aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff9
-rw-r--r--drivers/hid/hid-lg4ff.c58
2 files changed, 67 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
index db197a879580..9cd7c5adeb7e 100644
--- a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
+++ b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff
@@ -50,3 +50,12 @@ Description: Displays the real model of the wheel regardless of any
50 alternate mode the wheel might be switched to. 50 alternate mode the wheel might be switched to.
51 It is a read-only value. 51 It is a read-only value.
52 This entry is not created for devices that have only one mode. 52 This entry is not created for devices that have only one mode.
53
54What: /sys/bus/hid/drivers/logitech/<dev>/combine_pedals
55Date: Sep 2016
56KernelVersion: 4.9
57Contact: Simon Wood <simon@mungewell.org>
58Description: Controls whether a combined value of accelerator and brake is
59 reported on the Y axis of the controller. Useful for older games
60 which can do not work with separate accelerator/brake axis.
61 Off ('0') by default, enabled by setting '1'.
diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c
index af3a8ec8a746..ca31ce4d2c24 100644
--- a/drivers/hid/hid-lg4ff.c
+++ b/drivers/hid/hid-lg4ff.c
@@ -75,6 +75,7 @@ static void lg4ff_set_range_g25(struct hid_device *hid, u16 range);
75 75
76struct lg4ff_wheel_data { 76struct lg4ff_wheel_data {
77 const u32 product_id; 77 const u32 product_id;
78 u16 combine;
78 u16 range; 79 u16 range;
79 const u16 min_range; 80 const u16 min_range;
80 const u16 max_range; 81 const u16 max_range;
@@ -345,6 +346,7 @@ static void lg4ff_init_wheel_data(struct lg4ff_wheel_data * const wdata, const s
345 { 346 {
346 struct lg4ff_wheel_data t_wdata = { .product_id = wheel->product_id, 347 struct lg4ff_wheel_data t_wdata = { .product_id = wheel->product_id,
347 .real_product_id = real_product_id, 348 .real_product_id = real_product_id,
349 .combine = 0,
348 .min_range = wheel->min_range, 350 .min_range = wheel->min_range,
349 .max_range = wheel->max_range, 351 .max_range = wheel->max_range,
350 .set_range = wheel->set_range, 352 .set_range = wheel->set_range,
@@ -885,6 +887,58 @@ static ssize_t lg4ff_alternate_modes_store(struct device *dev, struct device_att
885} 887}
886static DEVICE_ATTR(alternate_modes, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, lg4ff_alternate_modes_show, lg4ff_alternate_modes_store); 888static DEVICE_ATTR(alternate_modes, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, lg4ff_alternate_modes_show, lg4ff_alternate_modes_store);
887 889
890static ssize_t lg4ff_combine_show(struct device *dev, struct device_attribute *attr,
891 char *buf)
892{
893 struct hid_device *hid = to_hid_device(dev);
894 struct lg4ff_device_entry *entry;
895 struct lg_drv_data *drv_data;
896 size_t count;
897
898 drv_data = hid_get_drvdata(hid);
899 if (!drv_data) {
900 hid_err(hid, "Private driver data not found!\n");
901 return 0;
902 }
903
904 entry = drv_data->device_props;
905 if (!entry) {
906 hid_err(hid, "Device properties not found!\n");
907 return 0;
908 }
909
910 count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->wdata.combine);
911 return count;
912}
913
914static ssize_t lg4ff_combine_store(struct device *dev, struct device_attribute *attr,
915 const char *buf, size_t count)
916{
917 struct hid_device *hid = to_hid_device(dev);
918 struct lg4ff_device_entry *entry;
919 struct lg_drv_data *drv_data;
920 u16 combine = simple_strtoul(buf, NULL, 10);
921
922 drv_data = hid_get_drvdata(hid);
923 if (!drv_data) {
924 hid_err(hid, "Private driver data not found!\n");
925 return -EINVAL;
926 }
927
928 entry = drv_data->device_props;
929 if (!entry) {
930 hid_err(hid, "Device properties not found!\n");
931 return -EINVAL;
932 }
933
934 if (combine > 1)
935 combine = 1;
936
937 entry->wdata.combine = combine;
938 return count;
939}
940static DEVICE_ATTR(combine_pedals, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, lg4ff_combine_show, lg4ff_combine_store);
941
888/* Export the currently set range of the wheel */ 942/* Export the currently set range of the wheel */
889static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr, 943static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr,
890 char *buf) 944 char *buf)
@@ -1259,6 +1313,9 @@ int lg4ff_init(struct hid_device *hid)
1259 } 1313 }
1260 1314
1261 /* Create sysfs interface */ 1315 /* Create sysfs interface */
1316 error = device_create_file(&hid->dev, &dev_attr_combine_pedals);
1317 if (error)
1318 hid_warn(hid, "Unable to create sysfs interface for \"combine\", errno %d\n", error);
1262 error = device_create_file(&hid->dev, &dev_attr_range); 1319 error = device_create_file(&hid->dev, &dev_attr_range);
1263 if (error) 1320 if (error)
1264 hid_warn(hid, "Unable to create sysfs interface for \"range\", errno %d\n", error); 1321 hid_warn(hid, "Unable to create sysfs interface for \"range\", errno %d\n", error);
@@ -1358,6 +1415,7 @@ int lg4ff_deinit(struct hid_device *hid)
1358 device_remove_file(&hid->dev, &dev_attr_alternate_modes); 1415 device_remove_file(&hid->dev, &dev_attr_alternate_modes);
1359 } 1416 }
1360 1417
1418 device_remove_file(&hid->dev, &dev_attr_combine_pedals);
1361 device_remove_file(&hid->dev, &dev_attr_range); 1419 device_remove_file(&hid->dev, &dev_attr_range);
1362#ifdef CONFIG_LEDS_CLASS 1420#ifdef CONFIG_LEDS_CLASS
1363 { 1421 {