diff options
| -rw-r--r-- | Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff | 9 | ||||
| -rw-r--r-- | drivers/hid/hid-lg4ff.c | 58 |
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 | |||
| 54 | What: /sys/bus/hid/drivers/logitech/<dev>/combine_pedals | ||
| 55 | Date: Sep 2016 | ||
| 56 | KernelVersion: 4.9 | ||
| 57 | Contact: Simon Wood <simon@mungewell.org> | ||
| 58 | Description: 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 | ||
| 76 | struct lg4ff_wheel_data { | 76 | struct 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 | } |
| 886 | static DEVICE_ATTR(alternate_modes, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, lg4ff_alternate_modes_show, lg4ff_alternate_modes_store); | 888 | static DEVICE_ATTR(alternate_modes, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, lg4ff_alternate_modes_show, lg4ff_alternate_modes_store); |
| 887 | 889 | ||
| 890 | static 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 | |||
| 914 | static 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 | } | ||
| 940 | static 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 */ |
| 889 | static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr, | 943 | static 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 | { |
