From d6ea2f88ac3659b799d8079a4fbda4f8faf6ff90 Mon Sep 17 00:00:00 2001 From: Raphael Assenat Date: Sat, 25 Apr 2015 16:30:32 -0400 Subject: HID: usbhid: Add a quirk for raphnet multi-gamepad adapters The raphnet.net 4nes4snes and 2nes2snes multi-joystick adapters use a single HID report descriptor with one report ID per controller. This has the effect that the inputs of otherwise independent game controllers get packed in one large joystick device. With this patch each controller gets its own /dev/input/jsX device, which is more natural and less confusing than having all inputs going to the same place. Signed-off-by: Raphael Assenat Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 41f167e..b24caf8 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -1038,4 +1038,11 @@ #define USB_VENDOR_ID_RISO_KAGAKU 0x1294 /* Riso Kagaku Corp. */ #define USB_DEVICE_ID_RI_KA_WEBMAIL 0x1320 /* Webmail Notifier */ +#define USB_VENDOR_ID_MULTIPLE_1781 0x1781 +#define USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD 0x0a8d + +#define USB_VENDOR_ID_DRACAL_RAPHNET 0x289b +#define USB_DEVICE_ID_RAPHNET_2NES2SNES 0x0002 +#define USB_DEVICE_ID_RAPHNET_4NES4SNES 0x0003 + #endif diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index a775143..09a22a7 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -140,6 +140,9 @@ static const struct hid_blacklist { { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP_V103, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_HOLTEK_ALT, USB_DEVICE_ID_HOLTEK_ALT_KEYBOARD_A096, HID_QUIRK_NO_INIT_INPUT_REPORTS }, + { USB_VENDOR_ID_MULTIPLE_1781, USB_DEVICE_ID_RAPHNET_4NES4SNES_OLD, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_2NES2SNES, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_DRACAL_RAPHNET, USB_DEVICE_ID_RAPHNET_4NES4SNES, HID_QUIRK_MULTI_INPUT }, { 0, 0 } }; -- cgit v0.10.2 From e03930620ae856a6ed79007207337d10011ecb36 Mon Sep 17 00:00:00 2001 From: Nicholas Mc Guire Date: Sat, 2 May 2015 17:55:15 +0200 Subject: HID: make timeout HZ independent wait_event_interruptible_timeout() expects a timeout in jiffies so the numeric constant becomes HZ dependent - put it through msecs_to_jiffies() to make it HZ independent. Signed-off-by: Nicholas Mc Guire Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index b86c18e..2671de9 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -700,7 +700,8 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) /* insert a little delay of 10 jiffies ~ 40ms */ wait_queue_head_t wait; init_waitqueue_head (&wait); - wait_event_interruptible_timeout(wait, 0, 10); + wait_event_interruptible_timeout(wait, 0, + msecs_to_jiffies(40)); /* Select random Address */ buf[1] = 0xB2; -- cgit v0.10.2 From c6f2104caaf00720a3a7a456af07f93a160693af Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Tue, 5 May 2015 10:09:53 +0200 Subject: HID: prodikeys: remove unused variable 'key' is set but never used in the first loop. So remove the set. And indent the re-set of pm->last_key properly. Signed-off-by: Jiri Slaby Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c index 91fab97..e3e98cc 100644 --- a/drivers/hid/hid-prodikeys.c +++ b/drivers/hid/hid-prodikeys.c @@ -395,11 +395,10 @@ static int pcmidi_handle_report4(struct pcmidi_snd *pm, u8 *data) /* break keys */ for (bit_index = 0; bit_index < 24; bit_index++) { - key = pm->last_key[bit_index]; if (!((0x01 << bit_index) & bit_mask)) { input_event(pm->input_ep82, EV_KEY, pm->last_key[bit_index], 0); - pm->last_key[bit_index] = 0; + pm->last_key[bit_index] = 0; } } -- cgit v0.10.2 From 2a552c30b2e44578b8d063e55b717ba94df84667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Mal=C3=BD?= Date: Wed, 8 Apr 2015 22:56:39 +0200 Subject: HID: hid-lg4ff: Remove double underscore prefix from numeric types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove double underscore prefix from numeric types. This code will never be used outside the kernel so the prefixes are unnecessary. Signed-off-by: Michal Malý Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 1232210..70e5ae6 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -72,12 +72,12 @@ static void hid_lg4ff_set_range_dfp(struct hid_device *hid, u16 range); static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range); struct lg4ff_device_entry { - __u32 product_id; - __u16 range; - __u16 min_range; - __u16 max_range; + u32 product_id; + u16 range; + u16 min_range; + u16 max_range; #ifdef CONFIG_LEDS_CLASS - __u8 led_state; + u8 led_state; struct led_classdev *led[5]; #endif u32 alternate_modes; @@ -95,16 +95,16 @@ static const signed short lg4ff_wheel_effects[] = { }; struct lg4ff_wheel { - const __u32 product_id; + const u32 product_id; const signed short *ff_effects; - const __u16 min_range; - const __u16 max_range; + const u16 min_range; + const u16 max_range; void (*set_range)(struct hid_device *hid, u16 range); }; struct lg4ff_compat_mode_switch { - const __u8 cmd_count; /* Number of commands to send */ - const __u8 cmd[]; + const u8 cmd_count; /* Number of commands to send */ + const u8 cmd[]; }; struct lg4ff_wheel_ident_info { @@ -245,10 +245,10 @@ static const struct lg4ff_compat_mode_switch lg4ff_mode_switch_ext16_g25 = { }; /* Recalculates X axis value accordingly to currently selected range */ -static __s32 lg4ff_adjust_dfp_x_axis(__s32 value, __u16 range) +static s32 lg4ff_adjust_dfp_x_axis(s32 value, u16 range) { - __u16 max_range; - __s32 new_value; + u16 max_range; + s32 new_value; if (range == 900) return value; @@ -269,10 +269,10 @@ static __s32 lg4ff_adjust_dfp_x_axis(__s32 value, __u16 range) } int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value, struct lg_drv_data *drv_data) + struct hid_usage *usage, s32 value, struct lg_drv_data *drv_data) { struct lg4ff_device_entry *entry = drv_data->device_props; - __s32 new_value = 0; + s32 new_value = 0; if (!entry) { hid_err(hid, "Device properties not found"); @@ -299,7 +299,7 @@ static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *e struct hid_device *hid = input_get_drvdata(dev); struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - __s32 *value = report->field[0]->value; + s32 *value = report->field[0]->value; int x; #define CLAMP(x) do { if (x < 0) x = 0; else if (x > 0xff) x = 0xff; } while (0) @@ -344,8 +344,8 @@ static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitud struct hid_device *hid = input_get_drvdata(dev); struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - __s32 *value = report->field[0]->value; - __u32 expand_a, expand_b; + s32 *value = report->field[0]->value; + u32 expand_a, expand_b; struct lg4ff_device_entry *entry; struct lg_drv_data *drv_data; @@ -421,7 +421,7 @@ static void hid_lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude) struct hid_device *hid = input_get_drvdata(dev); struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - __s32 *value = report->field[0]->value; + s32 *value = report->field[0]->value; magnitude = magnitude * 90 / 65535; value[0] = 0xfe; @@ -440,7 +440,7 @@ static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range) { struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - __s32 *value = report->field[0]->value; + s32 *value = report->field[0]->value; dbg_hid("G25/G27/DFGT: setting range to %u\n", range); @@ -456,12 +456,12 @@ static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range) } /* Sends commands to set range compatible with Driving Force Pro wheel */ -static void hid_lg4ff_set_range_dfp(struct hid_device *hid, __u16 range) +static void hid_lg4ff_set_range_dfp(struct hid_device *hid, u16 range) { struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); int start_left, start_right, full_range; - __s32 *value = report->field[0]->value; + s32 *value = report->field[0]->value; dbg_hid("Driving Force Pro: setting range to %u\n", range); @@ -571,7 +571,7 @@ static int lg4ff_switch_compatibility_mode(struct hid_device *hid, const struct { struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - __s32 *value = report->field[0]->value; + s32 *value = report->field[0]->value; u8 i; for (i = 0; i < s->cmd_count; i++) { @@ -754,7 +754,7 @@ static ssize_t range_store(struct device *dev, struct device_attribute *attr, struct hid_device *hid = to_hid_device(dev); struct lg4ff_device_entry *entry; struct lg_drv_data *drv_data; - __u16 range = simple_strtoul(buf, NULL, 10); + u16 range = simple_strtoul(buf, NULL, 10); drv_data = hid_get_drvdata(hid); if (!drv_data) { @@ -818,11 +818,11 @@ static ssize_t lg4ff_real_id_store(struct device *dev, struct device_attribute * static DEVICE_ATTR(real_id, S_IRUGO, lg4ff_real_id_show, lg4ff_real_id_store); #ifdef CONFIG_LEDS_CLASS -static void lg4ff_set_leds(struct hid_device *hid, __u8 leds) +static void lg4ff_set_leds(struct hid_device *hid, u8 leds) { struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - __s32 *value = report->field[0]->value; + s32 *value = report->field[0]->value; value[0] = 0xf8; value[1] = 0x12; diff --git a/drivers/hid/hid-lg4ff.h b/drivers/hid/hid-lg4ff.h index 5b6a508..66201af 100644 --- a/drivers/hid/hid-lg4ff.h +++ b/drivers/hid/hid-lg4ff.h @@ -5,12 +5,12 @@ extern int lg4ff_no_autoswitch; /* From hid-lg.c */ int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value, struct lg_drv_data *drv_data); + struct hid_usage *usage, s32 value, struct lg_drv_data *drv_data); int lg4ff_init(struct hid_device *hdev); int lg4ff_deinit(struct hid_device *hdev); #else static inline int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field, - struct hid_usage *usage, __s32 value, struct lg_drv_data *drv_data) { return 0; } + struct hid_usage *usage, s32 value, struct lg_drv_data *drv_data) { return 0; } static inline int lg4ff_init(struct hid_device *hdev) { return -1; } static inline int lg4ff_deinit(struct hid_device *hdev) { return -1; } #endif -- cgit v0.10.2 From d0afd84893ebdbbe6dc022514cd6b62fbc90a034 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Mal=C3=BD?= Date: Wed, 8 Apr 2015 22:56:40 +0200 Subject: HID: hid-lg4ff: Remove "hid_" prefix from some functions' names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove "hid_" prefix from some functions' names. All internal functions of hid-lg4ff should be prefixed with just "lg4ff_" Signed-off-by: Michal Malý Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 70e5ae6..9a0c0e5 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -68,8 +68,8 @@ #define LG4FF_FFEX_REV_MAJ 0x21 #define LG4FF_FFEX_REV_MIN 0x00 -static void hid_lg4ff_set_range_dfp(struct hid_device *hid, u16 range); -static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range); +static void lg4ff_set_range_dfp(struct hid_device *hid, u16 range); +static void lg4ff_set_range_g25(struct hid_device *hid, u16 range); struct lg4ff_device_entry { u32 product_id; @@ -134,10 +134,10 @@ struct lg4ff_alternate_mode { static const struct lg4ff_wheel lg4ff_devices[] = { {USB_DEVICE_ID_LOGITECH_WHEEL, lg4ff_wheel_effects, 40, 270, NULL}, {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL, lg4ff_wheel_effects, 40, 270, NULL}, - {USB_DEVICE_ID_LOGITECH_DFP_WHEEL, lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_dfp}, - {USB_DEVICE_ID_LOGITECH_G25_WHEEL, lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25}, - {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25}, - {USB_DEVICE_ID_LOGITECH_G27_WHEEL, lg4ff_wheel_effects, 40, 900, hid_lg4ff_set_range_g25}, + {USB_DEVICE_ID_LOGITECH_DFP_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_dfp}, + {USB_DEVICE_ID_LOGITECH_G25_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25}, + {USB_DEVICE_ID_LOGITECH_DFGT_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25}, + {USB_DEVICE_ID_LOGITECH_G27_WHEEL, lg4ff_wheel_effects, 40, 900, lg4ff_set_range_g25}, {USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2, lg4ff_wheel_effects, 40, 270, NULL}, {USB_DEVICE_ID_LOGITECH_WII_WHEEL, lg4ff_wheel_effects, 40, 270, NULL} }; @@ -294,7 +294,7 @@ int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field, } } -static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effect) +static int lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effect) { struct hid_device *hid = input_get_drvdata(dev); struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; @@ -339,7 +339,7 @@ static int hid_lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *e /* Sends default autocentering command compatible with * all wheels except Formula Force EX */ -static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude) +static void lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude) { struct hid_device *hid = input_get_drvdata(dev); struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; @@ -416,7 +416,7 @@ static void hid_lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitud } /* Sends autocentering command compatible with Formula Force EX */ -static void hid_lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude) +static void lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude) { struct hid_device *hid = input_get_drvdata(dev); struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; @@ -436,7 +436,7 @@ static void hid_lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude) } /* Sends command to set range compatible with G25/G27/Driving Force GT */ -static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range) +static void lg4ff_set_range_g25(struct hid_device *hid, u16 range) { struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); @@ -456,7 +456,7 @@ static void hid_lg4ff_set_range_g25(struct hid_device *hid, u16 range) } /* Sends commands to set range compatible with Driving Force Pro wheel */ -static void hid_lg4ff_set_range_dfp(struct hid_device *hid, u16 range) +static void lg4ff_set_range_dfp(struct hid_device *hid, u16 range) { struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); @@ -1043,7 +1043,7 @@ int lg4ff_init(struct hid_device *hid) for (j = 0; lg4ff_devices[i].ff_effects[j] >= 0; j++) set_bit(lg4ff_devices[i].ff_effects[j], dev->ffbit); - error = input_ff_create_memless(dev, NULL, hid_lg4ff_play); + error = input_ff_create_memless(dev, NULL, lg4ff_play); if (error) return error; @@ -1081,9 +1081,9 @@ int lg4ff_init(struct hid_device *hid) /* Formula Force EX expects different autocentering command */ if ((bcdDevice >> 8) == LG4FF_FFEX_REV_MAJ && (bcdDevice & 0xff) == LG4FF_FFEX_REV_MIN) - dev->ff->set_autocenter = hid_lg4ff_set_autocenter_ffex; + dev->ff->set_autocenter = lg4ff_set_autocenter_ffex; else - dev->ff->set_autocenter = hid_lg4ff_set_autocenter_default; + dev->ff->set_autocenter = lg4ff_set_autocenter_default; dev->ff->set_autocenter(dev, 0); } -- cgit v0.10.2 From fbf85e2ad1ade7bcc9efa0557c19bea5fffd192a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Mal=C3=BD?= Date: Wed, 8 Apr 2015 22:56:41 +0200 Subject: HID: hid-lg4ff: Replace DEVICE_ATTR_RW with DEVICE_ATTR to have all internal functions prefixed with "lg4ff_" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace DEVICE_ATTR_RW with DEVICE_ATTR to have all internal functions prefixed with "lg4ff_". All internal functions should be prefixed with just "lg4ff_". Usage of DEVICE_ATTR_RW breaks this scheme because it expects the functions' names to match the name of the respective sysfs entry. This partially reverts "2f1cec3250e38609bf9252db52dbbe61603c04a7" Signed-off-by: Michal Malý Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 9a0c0e5..cec84a5 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -721,9 +721,9 @@ static ssize_t lg4ff_alternate_modes_store(struct device *dev, struct device_att } static DEVICE_ATTR(alternate_modes, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, lg4ff_alternate_modes_show, lg4ff_alternate_modes_store); -/* Read current range and display it in terminal */ -static ssize_t range_show(struct device *dev, struct device_attribute *attr, - char *buf) +/* Export the currently set range of the wheel */ +static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *attr, + char *buf) { struct hid_device *hid = to_hid_device(dev); struct lg4ff_device_entry *entry; @@ -748,8 +748,8 @@ static ssize_t range_show(struct device *dev, struct device_attribute *attr, /* Set range to user specified value, call appropriate function * according to the type of the wheel */ -static ssize_t range_store(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) +static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) { struct hid_device *hid = to_hid_device(dev); struct lg4ff_device_entry *entry; @@ -780,7 +780,7 @@ static ssize_t range_store(struct device *dev, struct device_attribute *attr, return count; } -static DEVICE_ATTR_RW(range); +static DEVICE_ATTR(range, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH, lg4ff_range_show, lg4ff_range_store); static ssize_t lg4ff_real_id_show(struct device *dev, struct device_attribute *attr, char *buf) { -- cgit v0.10.2 From 0a33a7bcb5af29f8936b49dfe7b2b5bc932ad03d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Mal=C3=BD?= Date: Wed, 8 Apr 2015 22:56:42 +0200 Subject: HID: hid-lg4ff: Remove unused variable from the "lg4ff_device_entry" struct. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove unused variable from the "lg4ff_device_entry" struct. This is a leftover from times where hid_get|set_drvdata() was not available to hid-lg4ff so it had to keep track of the devices it managed by itself. Signed-off-by: Michal Malý Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index cec84a5..d1d5d45 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -84,7 +84,6 @@ struct lg4ff_device_entry { const char *real_tag; const char *real_name; u16 real_product_id; - struct list_head list; void (*set_range)(struct hid_device *hid, u16 range); }; -- cgit v0.10.2 From 371a1d9e1fed7dc4113386b23d92cccc3cfc6d8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Mal=C3=BD?= Date: Wed, 8 Apr 2015 22:56:43 +0200 Subject: HID: hid-lg4ff: Explicit casts from void * are not necessary MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Explicit casts from void * are not necessary. Signed-off-by: Michal Malý Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index d1d5d45..5a3b3be 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -847,7 +847,7 @@ static void lg4ff_led_set_brightness(struct led_classdev *led_cdev, return; } - entry = (struct lg4ff_device_entry *)drv_data->device_props; + entry = drv_data->device_props; if (!entry) { hid_err(hid, "Device properties not found."); @@ -882,7 +882,7 @@ static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cde return LED_OFF; } - entry = (struct lg4ff_device_entry *)drv_data->device_props; + entry = drv_data->device_props; if (!entry) { hid_err(hid, "Device properties not found."); -- cgit v0.10.2 From 9c2a6bd1133f7eae42b7b4e245d2aafecaf4a082 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Mal=C3=BD?= Date: Wed, 8 Apr 2015 22:56:44 +0200 Subject: HID: hid-lg4ff: Update a warning message MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update a warning message for a case where device is incorrectly flagged to be handled by hid-lg4ff in hid-lg. The original warning message was highly misleading. This warning can be triggered only if a device is flagged to be handled by hid-lg4ff in hid-lg but hid-lg4ff lacks support for such device. Signed-off-by: Michal Malý Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 5a3b3be..04822fb 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -1021,8 +1021,9 @@ int lg4ff_init(struct hid_device *hid) } if (i == ARRAY_SIZE(lg4ff_devices)) { - hid_err(hid, "Device is not supported by lg4ff driver. If you think it should be, consider reporting a bug to" - "LKML, Simon Wood or Michal Maly \n"); + hid_err(hid, "This device is flagged to be handled by the lg4ff module but this module does not know how to handle it. " + "Please report this as a bug to LKML, Simon Wood or " + "Michal Maly \n"); return -1; } -- cgit v0.10.2 From 2dbf635ea1c0b62a957438d72a162175680a3d4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Mal=C3=BD?= Date: Wed, 8 Apr 2015 22:56:45 +0200 Subject: HID: hid-lg: Check return values from lg[N]ff_init() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Check return values from lg[N]ff_init(). hid-lg did not check return values from the lg[N]_init() functions, possibly trying to work with a device whose initialization has failed. Signed-off-by: Michal Malý Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 2671de9..3f01da6 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -713,13 +713,16 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) } if (drv_data->quirks & LG_FF) - lgff_init(hdev); + ret = lgff_init(hdev); if (drv_data->quirks & LG_FF2) - lg2ff_init(hdev); + ret = lg2ff_init(hdev); if (drv_data->quirks & LG_FF3) - lg3ff_init(hdev); + ret = lg3ff_init(hdev); if (drv_data->quirks & LG_FF4) - lg4ff_init(hdev); + ret = lg4ff_init(hdev); + + if (ret) + goto err_free; return 0; err_free: -- cgit v0.10.2 From 72529c65a5399be02c619ed8592e38a3e5f049f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Mal=C3=BD?= Date: Wed, 8 Apr 2015 22:56:46 +0200 Subject: HID: hid-lg4ff: Make lg4ff_wheel_data a separate structure MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make lg4ff_wheel_data a separate structure stored within lg4ff_device_entry. Adjust the initialization process accordingly. Signed-off-by: Michal Malý Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 04822fb..0f8d726 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -71,7 +71,7 @@ static void lg4ff_set_range_dfp(struct hid_device *hid, u16 range); static void lg4ff_set_range_g25(struct hid_device *hid, u16 range); -struct lg4ff_device_entry { +struct lg4ff_wheel_data { u32 product_id; u16 range; u16 min_range; @@ -84,9 +84,14 @@ struct lg4ff_device_entry { const char *real_tag; const char *real_name; u16 real_product_id; + void (*set_range)(struct hid_device *hid, u16 range); }; +struct lg4ff_device_entry { + struct lg4ff_wheel_data wdata; +}; + static const signed short lg4ff_wheel_effects[] = { FF_CONSTANT, FF_AUTOCENTER, @@ -278,11 +283,11 @@ int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field, return 0; } - switch (entry->product_id) { + switch (entry->wdata.product_id) { case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: switch (usage->code) { case ABS_X: - new_value = lg4ff_adjust_dfp_x_axis(value, entry->range); + new_value = lg4ff_adjust_dfp_x_axis(value, entry->wdata.range); input_event(field->hidinput->input, usage->type, usage->code, new_value); return 1; default: @@ -383,7 +388,7 @@ static void lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude) } /* Adjust for non-MOMO wheels */ - switch (entry->product_id) { + switch (entry->wdata.product_id) { case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL: case USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2: break; @@ -605,23 +610,23 @@ static ssize_t lg4ff_alternate_modes_show(struct device *dev, struct device_attr return 0; } - if (!entry->real_name) { + if (!entry->wdata.real_name) { hid_err(hid, "NULL pointer to string\n"); return 0; } for (i = 0; i < LG4FF_MODE_MAX_IDX; i++) { - if (entry->alternate_modes & BIT(i)) { + if (entry->wdata.alternate_modes & BIT(i)) { /* Print tag and full name */ count += scnprintf(buf + count, PAGE_SIZE - count, "%s: %s", lg4ff_alternate_modes[i].tag, - !lg4ff_alternate_modes[i].product_id ? entry->real_name : lg4ff_alternate_modes[i].name); + !lg4ff_alternate_modes[i].product_id ? entry->wdata.real_name : lg4ff_alternate_modes[i].name); if (count >= PAGE_SIZE - 1) return count; /* Mark the currently active mode with an asterisk */ - if (lg4ff_alternate_modes[i].product_id == entry->product_id || - (lg4ff_alternate_modes[i].product_id == 0 && entry->product_id == entry->real_product_id)) + if (lg4ff_alternate_modes[i].product_id == entry->wdata.product_id || + (lg4ff_alternate_modes[i].product_id == 0 && entry->wdata.product_id == entry->wdata.real_product_id)) count += scnprintf(buf + count, PAGE_SIZE - count, " *\n"); else count += scnprintf(buf + count, PAGE_SIZE - count, "\n"); @@ -674,10 +679,10 @@ static ssize_t lg4ff_alternate_modes_store(struct device *dev, struct device_att const u16 mode_product_id = lg4ff_alternate_modes[i].product_id; const char *tag = lg4ff_alternate_modes[i].tag; - if (entry->alternate_modes & BIT(i)) { + if (entry->wdata.alternate_modes & BIT(i)) { if (!strcmp(tag, lbuf)) { if (!mode_product_id) - target_product_id = entry->real_product_id; + target_product_id = entry->wdata.real_product_id; else target_product_id = mode_product_id; break; @@ -692,24 +697,24 @@ static ssize_t lg4ff_alternate_modes_store(struct device *dev, struct device_att } kfree(lbuf); /* Not needed anymore */ - if (target_product_id == entry->product_id) /* Nothing to do */ + if (target_product_id == entry->wdata.product_id) /* Nothing to do */ return count; /* Automatic switching has to be disabled for the switch to DF-EX mode to work correctly */ if (target_product_id == USB_DEVICE_ID_LOGITECH_WHEEL && !lg4ff_no_autoswitch) { hid_info(hid, "\"%s\" cannot be switched to \"DF-EX\" mode. Load the \"hid_logitech\" module with \"lg4ff_no_autoswitch=1\" parameter set and try again\n", - entry->real_name); + entry->wdata.real_name); return -EINVAL; } /* Take care of hardware limitations */ - if ((entry->real_product_id == USB_DEVICE_ID_LOGITECH_DFP_WHEEL || entry->real_product_id == USB_DEVICE_ID_LOGITECH_G25_WHEEL) && - entry->product_id > target_product_id) { - hid_info(hid, "\"%s\" cannot be switched back into \"%s\" mode\n", entry->real_name, lg4ff_alternate_modes[i].name); + if ((entry->wdata.real_product_id == USB_DEVICE_ID_LOGITECH_DFP_WHEEL || entry->wdata.real_product_id == USB_DEVICE_ID_LOGITECH_G25_WHEEL) && + entry->wdata.product_id > target_product_id) { + hid_info(hid, "\"%s\" cannot be switched back into \"%s\" mode\n", entry->wdata.real_name, lg4ff_alternate_modes[i].name); return -EINVAL; } - s = lg4ff_get_mode_switch_command(entry->real_product_id, target_product_id); + s = lg4ff_get_mode_switch_command(entry->wdata.real_product_id, target_product_id); if (!s) { hid_err(hid, "Invalid target product ID %X\n", target_product_id); return -EINVAL; @@ -741,7 +746,7 @@ static ssize_t lg4ff_range_show(struct device *dev, struct device_attribute *att return 0; } - count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->range); + count = scnprintf(buf, PAGE_SIZE, "%u\n", entry->wdata.range); return count; } @@ -768,13 +773,13 @@ static ssize_t lg4ff_range_store(struct device *dev, struct device_attribute *at } if (range == 0) - range = entry->max_range; + range = entry->wdata.max_range; /* Check if the wheel supports range setting * and that the range is within limits for the wheel */ - if (entry->set_range != NULL && range >= entry->min_range && range <= entry->max_range) { - entry->set_range(hid, range); - entry->range = range; + if (entry->wdata.set_range && range >= entry->wdata.min_range && range <= entry->wdata.max_range) { + entry->wdata.set_range(hid, range); + entry->wdata.range = range; } return count; @@ -800,12 +805,12 @@ static ssize_t lg4ff_real_id_show(struct device *dev, struct device_attribute *a return 0; } - if (!entry->real_tag || !entry->real_name) { + if (!entry->wdata.real_tag || !entry->wdata.real_name) { hid_err(hid, "NULL pointer to string\n"); return 0; } - count = scnprintf(buf, PAGE_SIZE, "%s: %s\n", entry->real_tag, entry->real_name); + count = scnprintf(buf, PAGE_SIZE, "%s: %s\n", entry->wdata.real_tag, entry->wdata.real_name); return count; } @@ -855,15 +860,15 @@ static void lg4ff_led_set_brightness(struct led_classdev *led_cdev, } for (i = 0; i < 5; i++) { - if (led_cdev != entry->led[i]) + if (led_cdev != entry->wdata.led[i]) continue; - state = (entry->led_state >> i) & 1; + state = (entry->wdata.led_state >> i) & 1; if (value == LED_OFF && state) { - entry->led_state &= ~(1 << i); - lg4ff_set_leds(hid, entry->led_state); + entry->wdata.led_state &= ~(1 << i); + lg4ff_set_leds(hid, entry->wdata.led_state); } else if (value != LED_OFF && !state) { - entry->led_state |= 1 << i; - lg4ff_set_leds(hid, entry->led_state); + entry->wdata.led_state |= 1 << i; + lg4ff_set_leds(hid, entry->wdata.led_state); } break; } @@ -890,8 +895,8 @@ static enum led_brightness lg4ff_led_get_brightness(struct led_classdev *led_cde } for (i = 0; i < 5; i++) - if (led_cdev == entry->led[i]) { - value = (entry->led_state >> i) & 1; + if (led_cdev == entry->wdata.led[i]) { + value = (entry->wdata.led_state >> i) & 1; break; } @@ -1002,6 +1007,16 @@ int lg4ff_init(struct hid_device *hid) if (!hid_validate_values(hid, HID_OUTPUT_REPORT, 0, 0, 7)) return -1; + drv_data = hid_get_drvdata(hid); + if (!drv_data) { + hid_err(hid, "Cannot add device, private driver data not allocated\n"); + return -1; + } + entry = kzalloc(sizeof(*entry), GFP_KERNEL); + if (!entry) + return -ENOMEM; + drv_data->device_props = entry; + /* Check if a multimode wheel has been connected and * handle it appropriately */ mmode_ret = lg4ff_handle_multimode_wheel(hid, &real_product_id, bcdDevice); @@ -1011,6 +1026,11 @@ int lg4ff_init(struct hid_device *hid) */ if (mmode_ret == LG4FF_MMODE_SWITCHED) return 0; + else if (mmode_ret < 0) { + hid_err(hid, "Unable to switch device mode during initialization, errno %d\n", mmode_ret); + error = mmode_ret; + goto err_init; + } /* Check what wheel has been connected */ for (i = 0; i < ARRAY_SIZE(lg4ff_devices); i++) { @@ -1024,7 +1044,8 @@ int lg4ff_init(struct hid_device *hid) hid_err(hid, "This device is flagged to be handled by the lg4ff module but this module does not know how to handle it. " "Please report this as a bug to LKML, Simon Wood or " "Michal Maly \n"); - return -1; + error = -1; + goto err_init; } if (mmode_ret == LG4FF_MMODE_IS_MULTIMODE) { @@ -1035,7 +1056,8 @@ int lg4ff_init(struct hid_device *hid) if (mmode_idx == ARRAY_SIZE(lg4ff_multimode_wheels)) { hid_err(hid, "Device product ID %X is not listed as a multimode wheel", real_product_id); - return -1; + error = -1; + goto err_init; } } @@ -1046,33 +1068,18 @@ int lg4ff_init(struct hid_device *hid) error = input_ff_create_memless(dev, NULL, lg4ff_play); if (error) - return error; - - /* Get private driver data */ - drv_data = hid_get_drvdata(hid); - if (!drv_data) { - hid_err(hid, "Cannot add device, private driver data not allocated\n"); - return -1; - } + goto err_init; - /* Initialize device properties */ - entry = kzalloc(sizeof(struct lg4ff_device_entry), GFP_KERNEL); - if (!entry) { - hid_err(hid, "Cannot add device, insufficient memory to allocate device properties.\n"); - return -ENOMEM; - } - drv_data->device_props = entry; - - entry->product_id = lg4ff_devices[i].product_id; - entry->real_product_id = real_product_id; - entry->min_range = lg4ff_devices[i].min_range; - entry->max_range = lg4ff_devices[i].max_range; - entry->set_range = lg4ff_devices[i].set_range; + entry->wdata.product_id = lg4ff_devices[i].product_id; + entry->wdata.real_product_id = real_product_id; + entry->wdata.min_range = lg4ff_devices[i].min_range; + entry->wdata.max_range = lg4ff_devices[i].max_range; + entry->wdata.set_range = lg4ff_devices[i].set_range; if (mmode_ret == LG4FF_MMODE_IS_MULTIMODE) { BUG_ON(mmode_idx == -1); - entry->alternate_modes = lg4ff_multimode_wheels[mmode_idx].alternate_modes; - entry->real_tag = lg4ff_multimode_wheels[mmode_idx].real_tag; - entry->real_name = lg4ff_multimode_wheels[mmode_idx].real_name; + entry->wdata.alternate_modes = lg4ff_multimode_wheels[mmode_idx].alternate_modes; + entry->wdata.real_tag = lg4ff_multimode_wheels[mmode_idx].real_tag; + entry->wdata.real_name = lg4ff_multimode_wheels[mmode_idx].real_name; } /* Check if autocentering is available and @@ -1091,27 +1098,28 @@ int lg4ff_init(struct hid_device *hid) /* Create sysfs interface */ error = device_create_file(&hid->dev, &dev_attr_range); if (error) - return error; + goto err_init; if (mmode_ret == LG4FF_MMODE_IS_MULTIMODE) { error = device_create_file(&hid->dev, &dev_attr_real_id); if (error) - return error; + goto err_init; + error = device_create_file(&hid->dev, &dev_attr_alternate_modes); if (error) - return error; + goto err_init; } dbg_hid("sysfs interface created\n"); /* Set the maximum range to start with */ - entry->range = entry->max_range; - if (entry->set_range != NULL) - entry->set_range(hid, entry->range); + entry->wdata.range = entry->wdata.max_range; + if (entry->wdata.set_range) + entry->wdata.set_range(hid, entry->wdata.range); #ifdef CONFIG_LEDS_CLASS /* register led subsystem - G27 only */ - entry->led_state = 0; + entry->wdata.led_state = 0; for (j = 0; j < 5; j++) - entry->led[j] = NULL; + entry->wdata.led[j] = NULL; if (lg4ff_devices[i].product_id == USB_DEVICE_ID_LOGITECH_G27_WHEEL) { struct led_classdev *led; @@ -1126,7 +1134,7 @@ int lg4ff_init(struct hid_device *hid) led = kzalloc(sizeof(struct led_classdev)+name_sz, GFP_KERNEL); if (!led) { hid_err(hid, "can't allocate memory for LED %d\n", j); - goto err; + goto err_leds; } name = (void *)(&led[1]); @@ -1137,16 +1145,16 @@ int lg4ff_init(struct hid_device *hid) led->brightness_get = lg4ff_led_get_brightness; led->brightness_set = lg4ff_led_set_brightness; - entry->led[j] = led; + entry->wdata.led[j] = led; error = led_classdev_register(&hid->dev, led); if (error) { hid_err(hid, "failed to register LED %d. Aborting.\n", j); -err: +err_leds: /* Deregister LEDs (if any) */ for (j = 0; j < 5; j++) { - led = entry->led[j]; - entry->led[j] = NULL; + led = entry->wdata.led[j]; + entry->wdata.led[j] = NULL; if (!led) continue; led_classdev_unregister(led); @@ -1160,6 +1168,11 @@ out: #endif hid_info(hid, "Force feedback support for Logitech Gaming Wheels\n"); return 0; + +err_init: + drv_data->device_props = NULL; + kfree(entry); + return error; } int lg4ff_deinit(struct hid_device *hid) @@ -1176,14 +1189,13 @@ int lg4ff_deinit(struct hid_device *hid) if (!entry) goto out; /* Nothing more to do */ - device_remove_file(&hid->dev, &dev_attr_range); - /* Multimode devices will have at least the "MODE_NATIVE" bit set */ - if (entry->alternate_modes) { + if (entry->wdata.alternate_modes) { device_remove_file(&hid->dev, &dev_attr_real_id); device_remove_file(&hid->dev, &dev_attr_alternate_modes); } + device_remove_file(&hid->dev, &dev_attr_range); #ifdef CONFIG_LEDS_CLASS { int j; @@ -1192,8 +1204,8 @@ int lg4ff_deinit(struct hid_device *hid) /* Deregister LEDs (if any) */ for (j = 0; j < 5; j++) { - led = entry->led[j]; - entry->led[j] = NULL; + led = entry->wdata.led[j]; + entry->wdata.led[j] = NULL; if (!led) continue; led_classdev_unregister(led); @@ -1202,9 +1214,7 @@ int lg4ff_deinit(struct hid_device *hid) } #endif - /* Deallocate memory */ kfree(entry); - out: dbg_hid("Device successfully unregistered\n"); return 0; -- cgit v0.10.2 From b211a6388ca279a16a6627da2f3681a2cab18444 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Mal=C3=BD?= Date: Wed, 8 Apr 2015 22:56:47 +0200 Subject: HID: hid-lg4ff: Stop the hid device from lg4ff MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Stop the hid device from lg4ff. Originally hid-lg was responsible for stopping of the device. Signed-off-by: Michal Malý Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 3f01da6..d5022b3 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -735,8 +735,8 @@ static void lg_remove(struct hid_device *hdev) struct lg_drv_data *drv_data = hid_get_drvdata(hdev); if (drv_data->quirks & LG_FF4) lg4ff_deinit(hdev); - - hid_hw_stop(hdev); + else + hid_hw_stop(hdev); kfree(drv_data); } diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 0f8d726..031b8ab 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -1213,6 +1213,8 @@ int lg4ff_deinit(struct hid_device *hid) } } #endif + hid_hw_stop(hid); + drv_data->device_props = NULL; kfree(entry); out: -- cgit v0.10.2 From c918fe781fab6d8bdc35f1652dc4f95f2bf6950d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Mal=C3=BD?= Date: Wed, 8 Apr 2015 22:56:48 +0200 Subject: HID: hid-lg4ff: Protect concurrent access to output HID report MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Protect concurrent access to output HID report with a spinlock. The HID report structure used to submit commands to wheels is shared amongst all functions that need to do so and some of these functions can be executed in parallel. Additionally, lg4ff_play() can be called from interrupt context by ff-memless module. Locking is necessary to prevent sending bogus data to the wheels. Signed-off-by: Michal Malý Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index 031b8ab..f7f4eb6 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -89,6 +89,7 @@ struct lg4ff_wheel_data { }; struct lg4ff_device_entry { + spinlock_t report_lock; /* Protect output HID report */ struct lg4ff_wheel_data wdata; }; @@ -303,9 +304,24 @@ static int lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effec struct hid_device *hid = input_get_drvdata(dev); struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); + struct lg4ff_device_entry *entry; + struct lg_drv_data *drv_data; + unsigned long flags; s32 *value = report->field[0]->value; int x; + drv_data = hid_get_drvdata(hid); + if (!drv_data) { + hid_err(hid, "Private driver data not found!\n"); + return -EINVAL; + } + + entry = drv_data->device_props; + if (!entry) { + hid_err(hid, "Device properties not found!\n"); + return -EINVAL; + } + #define CLAMP(x) do { if (x < 0) x = 0; else if (x > 0xff) x = 0xff; } while (0) switch (effect->type) { @@ -313,6 +329,7 @@ static int lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effec x = effect->u.ramp.start_level + 0x80; /* 0x80 is no force */ CLAMP(x); + spin_lock_irqsave(&entry->report_lock, flags); if (x == 0x80) { /* De-activate force in slot-1*/ value[0] = 0x13; @@ -324,6 +341,7 @@ static int lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effec value[6] = 0x00; hid_hw_request(hid, report, HID_REQ_SET_REPORT); + spin_unlock_irqrestore(&entry->report_lock, flags); return 0; } @@ -336,6 +354,7 @@ static int lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effec value[6] = 0x00; hid_hw_request(hid, report, HID_REQ_SET_REPORT); + spin_unlock_irqrestore(&entry->report_lock, flags); break; } return 0; @@ -352,6 +371,7 @@ static void lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude) u32 expand_a, expand_b; struct lg4ff_device_entry *entry; struct lg_drv_data *drv_data; + unsigned long flags; drv_data = hid_get_drvdata(hid); if (!drv_data) { @@ -366,6 +386,7 @@ static void lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude) } /* De-activate Auto-Center */ + spin_lock_irqsave(&entry->report_lock, flags); if (magnitude == 0) { value[0] = 0xf5; value[1] = 0x00; @@ -376,6 +397,7 @@ static void lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude) value[6] = 0x00; hid_hw_request(hid, report, HID_REQ_SET_REPORT); + spin_unlock_irqrestore(&entry->report_lock, flags); return; } @@ -417,6 +439,7 @@ static void lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude) value[6] = 0x00; hid_hw_request(hid, report, HID_REQ_SET_REPORT); + spin_unlock_irqrestore(&entry->report_lock, flags); } /* Sends autocentering command compatible with Formula Force EX */ @@ -425,9 +448,25 @@ static void lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude) struct hid_device *hid = input_get_drvdata(dev); struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); + struct lg4ff_device_entry *entry; + struct lg_drv_data *drv_data; + unsigned long flags; s32 *value = report->field[0]->value; magnitude = magnitude * 90 / 65535; + drv_data = hid_get_drvdata(hid); + if (!drv_data) { + hid_err(hid, "Private driver data not found!\n"); + return; + } + + entry = drv_data->device_props; + if (!entry) { + hid_err(hid, "Device properties not found!\n"); + return; + } + + spin_lock_irqsave(&entry->report_lock, flags); value[0] = 0xfe; value[1] = 0x03; value[2] = magnitude >> 14; @@ -437,6 +476,7 @@ static void lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude) value[6] = 0x00; hid_hw_request(hid, report, HID_REQ_SET_REPORT); + spin_unlock_irqrestore(&entry->report_lock, flags); } /* Sends command to set range compatible with G25/G27/Driving Force GT */ @@ -444,10 +484,26 @@ static void lg4ff_set_range_g25(struct hid_device *hid, u16 range) { struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); + struct lg4ff_device_entry *entry; + struct lg_drv_data *drv_data; + unsigned long flags; s32 *value = report->field[0]->value; + drv_data = hid_get_drvdata(hid); + if (!drv_data) { + hid_err(hid, "Private driver data not found!\n"); + return; + } + + entry = drv_data->device_props; + if (!entry) { + hid_err(hid, "Device properties not found!\n"); + return; + } + dbg_hid("G25/G27/DFGT: setting range to %u\n", range); + spin_lock_irqsave(&entry->report_lock, flags); value[0] = 0xf8; value[1] = 0x81; value[2] = range & 0x00ff; @@ -457,6 +513,7 @@ static void lg4ff_set_range_g25(struct hid_device *hid, u16 range) value[6] = 0x00; hid_hw_request(hid, report, HID_REQ_SET_REPORT); + spin_unlock_irqrestore(&entry->report_lock, flags); } /* Sends commands to set range compatible with Driving Force Pro wheel */ @@ -465,11 +522,27 @@ static void lg4ff_set_range_dfp(struct hid_device *hid, u16 range) struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); int start_left, start_right, full_range; + struct lg4ff_device_entry *entry; + struct lg_drv_data *drv_data; + unsigned long flags; s32 *value = report->field[0]->value; + drv_data = hid_get_drvdata(hid); + if (!drv_data) { + hid_err(hid, "Private driver data not found!\n"); + return; + } + + entry = drv_data->device_props; + if (!entry) { + hid_err(hid, "Device properties not found!\n"); + return; + } + dbg_hid("Driving Force Pro: setting range to %u\n", range); /* Prepare "coarse" limit command */ + spin_lock_irqsave(&entry->report_lock, flags); value[0] = 0xf8; value[1] = 0x00; /* Set later */ value[2] = 0x00; @@ -498,6 +571,7 @@ static void lg4ff_set_range_dfp(struct hid_device *hid, u16 range) if (range == 200 || range == 900) { /* Do not apply any fine limit */ hid_hw_request(hid, report, HID_REQ_SET_REPORT); + spin_unlock_irqrestore(&entry->report_lock, flags); return; } @@ -512,6 +586,7 @@ static void lg4ff_set_range_dfp(struct hid_device *hid, u16 range) value[6] = 0xff; hid_hw_request(hid, report, HID_REQ_SET_REPORT); + spin_unlock_irqrestore(&entry->report_lock, flags); } static const struct lg4ff_compat_mode_switch *lg4ff_get_mode_switch_command(const u16 real_product_id, const u16 target_product_id) @@ -575,9 +650,25 @@ static int lg4ff_switch_compatibility_mode(struct hid_device *hid, const struct { struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); + struct lg4ff_device_entry *entry; + struct lg_drv_data *drv_data; + unsigned long flags; s32 *value = report->field[0]->value; u8 i; + drv_data = hid_get_drvdata(hid); + if (!drv_data) { + hid_err(hid, "Private driver data not found!\n"); + return -EINVAL; + } + + entry = drv_data->device_props; + if (!entry) { + hid_err(hid, "Device properties not found!\n"); + return -EINVAL; + } + + spin_lock_irqsave(&entry->report_lock, flags); for (i = 0; i < s->cmd_count; i++) { u8 j; @@ -586,6 +677,7 @@ static int lg4ff_switch_compatibility_mode(struct hid_device *hid, const struct hid_hw_request(hid, report, HID_REQ_SET_REPORT); } + spin_unlock_irqrestore(&entry->report_lock, flags); hid_hw_wait(hid); return 0; } @@ -826,8 +918,24 @@ static void lg4ff_set_leds(struct hid_device *hid, u8 leds) { struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); + struct lg_drv_data *drv_data; + struct lg4ff_device_entry *entry; + unsigned long flags; s32 *value = report->field[0]->value; + drv_data = hid_get_drvdata(hid); + if (!drv_data) { + hid_err(hid, "Private driver data not found!\n"); + return; + } + + entry = drv_data->device_props; + if (!entry) { + hid_err(hid, "Device properties not found!\n"); + return; + } + + spin_lock_irqsave(&entry->report_lock, flags); value[0] = 0xf8; value[1] = 0x12; value[2] = leds; @@ -836,6 +944,7 @@ static void lg4ff_set_leds(struct hid_device *hid, u8 leds) value[5] = 0x00; value[6] = 0x00; hid_hw_request(hid, report, HID_REQ_SET_REPORT); + spin_unlock_irqrestore(&entry->report_lock, flags); } static void lg4ff_led_set_brightness(struct led_classdev *led_cdev, @@ -1015,6 +1124,7 @@ int lg4ff_init(struct hid_device *hid) entry = kzalloc(sizeof(*entry), GFP_KERNEL); if (!entry) return -ENOMEM; + spin_lock_init(&entry->report_lock); drv_data->device_props = entry; /* Check if a multimode wheel has been connected and -- cgit v0.10.2 From c28abd8c423b85e2d8be8ed33984a3ad966f1c83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Mal=C3=BD?= Date: Wed, 8 Apr 2015 22:56:49 +0200 Subject: HID: hid-lg4ff: Store pointer to the output HID report struct in the device entry struct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Store pointer to the output HID report struct in the device entry struct. This eliminates the need to look the HID report struct up every time it is needed. Signed-off-by: Michal Malý Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index f7f4eb6..d27b210 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -90,6 +90,7 @@ struct lg4ff_wheel_data { struct lg4ff_device_entry { spinlock_t report_lock; /* Protect output HID report */ + struct hid_report *report; struct lg4ff_wheel_data wdata; }; @@ -302,12 +303,10 @@ int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field, static int lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effect) { struct hid_device *hid = input_get_drvdata(dev); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct hid_report *report = list_entry(report_list->next, struct hid_report, list); struct lg4ff_device_entry *entry; struct lg_drv_data *drv_data; unsigned long flags; - s32 *value = report->field[0]->value; + s32 *value; int x; drv_data = hid_get_drvdata(hid); @@ -321,6 +320,7 @@ static int lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effec hid_err(hid, "Device properties not found!\n"); return -EINVAL; } + value = entry->report->field[0]->value; #define CLAMP(x) do { if (x < 0) x = 0; else if (x > 0xff) x = 0xff; } while (0) @@ -340,7 +340,7 @@ static int lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effec value[5] = 0x00; value[6] = 0x00; - hid_hw_request(hid, report, HID_REQ_SET_REPORT); + hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); spin_unlock_irqrestore(&entry->report_lock, flags); return 0; } @@ -353,7 +353,7 @@ static int lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effec value[5] = 0x00; value[6] = 0x00; - hid_hw_request(hid, report, HID_REQ_SET_REPORT); + hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); spin_unlock_irqrestore(&entry->report_lock, flags); break; } @@ -384,6 +384,7 @@ static void lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude) hid_err(hid, "Device properties not found!\n"); return; } + value = entry->report->field[0]->value; /* De-activate Auto-Center */ spin_lock_irqsave(&entry->report_lock, flags); @@ -396,7 +397,7 @@ static void lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude) value[5] = 0x00; value[6] = 0x00; - hid_hw_request(hid, report, HID_REQ_SET_REPORT); + hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); spin_unlock_irqrestore(&entry->report_lock, flags); return; } @@ -427,7 +428,7 @@ static void lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude) value[5] = 0x00; value[6] = 0x00; - hid_hw_request(hid, report, HID_REQ_SET_REPORT); + hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); /* Activate Auto-Center */ value[0] = 0x14; @@ -438,7 +439,7 @@ static void lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude) value[5] = 0x00; value[6] = 0x00; - hid_hw_request(hid, report, HID_REQ_SET_REPORT); + hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); spin_unlock_irqrestore(&entry->report_lock, flags); } @@ -446,12 +447,10 @@ static void lg4ff_set_autocenter_default(struct input_dev *dev, u16 magnitude) static void lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude) { struct hid_device *hid = input_get_drvdata(dev); - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct hid_report *report = list_entry(report_list->next, struct hid_report, list); struct lg4ff_device_entry *entry; struct lg_drv_data *drv_data; unsigned long flags; - s32 *value = report->field[0]->value; + s32 *value; magnitude = magnitude * 90 / 65535; drv_data = hid_get_drvdata(hid); @@ -465,6 +464,7 @@ static void lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude) hid_err(hid, "Device properties not found!\n"); return; } + value = entry->report->field[0]->value; spin_lock_irqsave(&entry->report_lock, flags); value[0] = 0xfe; @@ -475,19 +475,17 @@ static void lg4ff_set_autocenter_ffex(struct input_dev *dev, u16 magnitude) value[5] = 0x00; value[6] = 0x00; - hid_hw_request(hid, report, HID_REQ_SET_REPORT); + hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); spin_unlock_irqrestore(&entry->report_lock, flags); } /* Sends command to set range compatible with G25/G27/Driving Force GT */ static void lg4ff_set_range_g25(struct hid_device *hid, u16 range) { - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct hid_report *report = list_entry(report_list->next, struct hid_report, list); struct lg4ff_device_entry *entry; struct lg_drv_data *drv_data; unsigned long flags; - s32 *value = report->field[0]->value; + s32 *value; drv_data = hid_get_drvdata(hid); if (!drv_data) { @@ -500,7 +498,7 @@ static void lg4ff_set_range_g25(struct hid_device *hid, u16 range) hid_err(hid, "Device properties not found!\n"); return; } - + value = entry->report->field[0]->value; dbg_hid("G25/G27/DFGT: setting range to %u\n", range); spin_lock_irqsave(&entry->report_lock, flags); @@ -512,20 +510,18 @@ static void lg4ff_set_range_g25(struct hid_device *hid, u16 range) value[5] = 0x00; value[6] = 0x00; - hid_hw_request(hid, report, HID_REQ_SET_REPORT); + hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); spin_unlock_irqrestore(&entry->report_lock, flags); } /* Sends commands to set range compatible with Driving Force Pro wheel */ static void lg4ff_set_range_dfp(struct hid_device *hid, u16 range) { - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct hid_report *report = list_entry(report_list->next, struct hid_report, list); - int start_left, start_right, full_range; struct lg4ff_device_entry *entry; struct lg_drv_data *drv_data; unsigned long flags; - s32 *value = report->field[0]->value; + int start_left, start_right, full_range; + s32 *value; drv_data = hid_get_drvdata(hid); if (!drv_data) { @@ -538,7 +534,7 @@ static void lg4ff_set_range_dfp(struct hid_device *hid, u16 range) hid_err(hid, "Device properties not found!\n"); return; } - + value = entry->report->field[0]->value; dbg_hid("Driving Force Pro: setting range to %u\n", range); /* Prepare "coarse" limit command */ @@ -552,13 +548,13 @@ static void lg4ff_set_range_dfp(struct hid_device *hid, u16 range) value[6] = 0x00; if (range > 200) { - report->field[0]->value[1] = 0x03; + value[1] = 0x03; full_range = 900; } else { - report->field[0]->value[1] = 0x02; + value[1] = 0x02; full_range = 200; } - hid_hw_request(hid, report, HID_REQ_SET_REPORT); + hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); /* Prepare "fine" limit command */ value[0] = 0x81; @@ -570,7 +566,7 @@ static void lg4ff_set_range_dfp(struct hid_device *hid, u16 range) value[6] = 0x00; if (range == 200 || range == 900) { /* Do not apply any fine limit */ - hid_hw_request(hid, report, HID_REQ_SET_REPORT); + hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); spin_unlock_irqrestore(&entry->report_lock, flags); return; } @@ -585,7 +581,7 @@ static void lg4ff_set_range_dfp(struct hid_device *hid, u16 range) value[5] = (start_right & 0xe) << 4 | (start_left & 0xe); value[6] = 0xff; - hid_hw_request(hid, report, HID_REQ_SET_REPORT); + hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); spin_unlock_irqrestore(&entry->report_lock, flags); } @@ -648,12 +644,10 @@ static const struct lg4ff_compat_mode_switch *lg4ff_get_mode_switch_command(cons static int lg4ff_switch_compatibility_mode(struct hid_device *hid, const struct lg4ff_compat_mode_switch *s) { - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct hid_report *report = list_entry(report_list->next, struct hid_report, list); struct lg4ff_device_entry *entry; struct lg_drv_data *drv_data; unsigned long flags; - s32 *value = report->field[0]->value; + s32 *value; u8 i; drv_data = hid_get_drvdata(hid); @@ -667,6 +661,7 @@ static int lg4ff_switch_compatibility_mode(struct hid_device *hid, const struct hid_err(hid, "Device properties not found!\n"); return -EINVAL; } + value = entry->report->field[0]->value; spin_lock_irqsave(&entry->report_lock, flags); for (i = 0; i < s->cmd_count; i++) { @@ -675,7 +670,7 @@ static int lg4ff_switch_compatibility_mode(struct hid_device *hid, const struct for (j = 0; j < 7; j++) value[j] = s->cmd[j + (7*i)]; - hid_hw_request(hid, report, HID_REQ_SET_REPORT); + hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); } spin_unlock_irqrestore(&entry->report_lock, flags); hid_hw_wait(hid); @@ -916,12 +911,10 @@ static DEVICE_ATTR(real_id, S_IRUGO, lg4ff_real_id_show, lg4ff_real_id_store); #ifdef CONFIG_LEDS_CLASS static void lg4ff_set_leds(struct hid_device *hid, u8 leds) { - struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; - struct hid_report *report = list_entry(report_list->next, struct hid_report, list); struct lg_drv_data *drv_data; struct lg4ff_device_entry *entry; unsigned long flags; - s32 *value = report->field[0]->value; + s32 *value; drv_data = hid_get_drvdata(hid); if (!drv_data) { @@ -934,6 +927,7 @@ static void lg4ff_set_leds(struct hid_device *hid, u8 leds) hid_err(hid, "Device properties not found!\n"); return; } + value = entry->report->field[0]->value; spin_lock_irqsave(&entry->report_lock, flags); value[0] = 0xf8; @@ -943,7 +937,7 @@ static void lg4ff_set_leds(struct hid_device *hid, u8 leds) value[4] = 0x00; value[5] = 0x00; value[6] = 0x00; - hid_hw_request(hid, report, HID_REQ_SET_REPORT); + hid_hw_request(hid, entry->report, HID_REQ_SET_REPORT); spin_unlock_irqrestore(&entry->report_lock, flags); } @@ -1104,6 +1098,8 @@ int lg4ff_init(struct hid_device *hid) { struct hid_input *hidinput = list_entry(hid->inputs.next, struct hid_input, list); struct input_dev *dev = hidinput->input; + struct list_head *report_list = &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct hid_report *report = list_entry(report_list->next, struct hid_report, list); const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor); const u16 bcdDevice = le16_to_cpu(udesc->bcdDevice); struct lg4ff_device_entry *entry; @@ -1125,6 +1121,7 @@ int lg4ff_init(struct hid_device *hid) if (!entry) return -ENOMEM; spin_lock_init(&entry->report_lock); + entry->report = report; drv_data->device_props = entry; /* Check if a multimode wheel has been connected and -- cgit v0.10.2 From 5d9d60ad308c867b271cc03233f2c93a0f5d80ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Mal=C3=BD?= Date: Wed, 8 Apr 2015 22:56:50 +0200 Subject: HID: hid-lg4ff: Constify members of lg4ff_device_entry MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Constify those members of lg4ff_device_entry struct whose value is not supposed to change. Signed-off-by: Michal Malý Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index d27b210..dcaf481 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -72,18 +72,18 @@ static void lg4ff_set_range_dfp(struct hid_device *hid, u16 range); static void lg4ff_set_range_g25(struct hid_device *hid, u16 range); struct lg4ff_wheel_data { - u32 product_id; + const u32 product_id; u16 range; - u16 min_range; - u16 max_range; + const u16 min_range; + const u16 max_range; #ifdef CONFIG_LEDS_CLASS u8 led_state; struct led_classdev *led[5]; #endif - u32 alternate_modes; - const char *real_tag; - const char *real_name; - u16 real_product_id; + const u32 alternate_modes; + const char * const real_tag; + const char * const real_name; + const u16 real_product_id; void (*set_range)(struct hid_device *hid, u16 range); }; @@ -300,6 +300,34 @@ int lg4ff_adjust_input_event(struct hid_device *hid, struct hid_field *field, } } +static void lg4ff_init_wheel_data(struct lg4ff_wheel_data * const wdata, const struct lg4ff_wheel *wheel, + const struct lg4ff_multimode_wheel *mmode_wheel, + const u16 real_product_id) +{ + u32 alternate_modes = 0; + const char *real_tag = NULL; + const char *real_name = NULL; + + if (mmode_wheel) { + alternate_modes = mmode_wheel->alternate_modes; + real_tag = mmode_wheel->real_tag; + real_name = mmode_wheel->real_name; + } + + { + struct lg4ff_wheel_data t_wdata = { .product_id = wheel->product_id, + .real_product_id = real_product_id, + .min_range = wheel->min_range, + .max_range = wheel->max_range, + .set_range = wheel->set_range, + .alternate_modes = alternate_modes, + .real_tag = real_tag, + .real_name = real_name }; + + memcpy(wdata, &t_wdata, sizeof(t_wdata)); + } +} + static int lg4ff_play(struct input_dev *dev, void *data, struct ff_effect *effect) { struct hid_device *hid = input_get_drvdata(dev); @@ -1102,6 +1130,7 @@ int lg4ff_init(struct hid_device *hid) struct hid_report *report = list_entry(report_list->next, struct hid_report, list); const struct usb_device_descriptor *udesc = &(hid_to_usb_dev(hid)->descriptor); const u16 bcdDevice = le16_to_cpu(udesc->bcdDevice); + const struct lg4ff_multimode_wheel *mmode_wheel = NULL; struct lg4ff_device_entry *entry; struct lg_drv_data *drv_data; int error, i, j; @@ -1177,17 +1206,12 @@ int lg4ff_init(struct hid_device *hid) if (error) goto err_init; - entry->wdata.product_id = lg4ff_devices[i].product_id; - entry->wdata.real_product_id = real_product_id; - entry->wdata.min_range = lg4ff_devices[i].min_range; - entry->wdata.max_range = lg4ff_devices[i].max_range; - entry->wdata.set_range = lg4ff_devices[i].set_range; + /* Initialize device properties */ if (mmode_ret == LG4FF_MMODE_IS_MULTIMODE) { BUG_ON(mmode_idx == -1); - entry->wdata.alternate_modes = lg4ff_multimode_wheels[mmode_idx].alternate_modes; - entry->wdata.real_tag = lg4ff_multimode_wheels[mmode_idx].real_tag; - entry->wdata.real_name = lg4ff_multimode_wheels[mmode_idx].real_name; + mmode_wheel = &lg4ff_multimode_wheels[mmode_idx]; } + lg4ff_init_wheel_data(&entry->wdata, &lg4ff_devices[i], mmode_wheel, real_product_id); /* Check if autocentering is available and * set the centering force to zero by default */ -- cgit v0.10.2 From d61a70ec93251d77608864e0f6daf6dd1bfd4a6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Mal=C3=BD?= Date: Wed, 8 Apr 2015 22:56:51 +0200 Subject: HID: hid-lg4ff: Allow the driver to continue without sysfs interface MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow the driver to continue without sysfs interface. Instead of bailing out allow the driver to continue in a degraded mode. Signed-off-by: Michal Malý Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-lg4ff.c b/drivers/hid/hid-lg4ff.c index dcaf481..02cec83 100644 --- a/drivers/hid/hid-lg4ff.c +++ b/drivers/hid/hid-lg4ff.c @@ -1229,15 +1229,14 @@ int lg4ff_init(struct hid_device *hid) /* Create sysfs interface */ error = device_create_file(&hid->dev, &dev_attr_range); if (error) - goto err_init; + hid_warn(hid, "Unable to create sysfs interface for \"range\", errno %d\n", error); if (mmode_ret == LG4FF_MMODE_IS_MULTIMODE) { error = device_create_file(&hid->dev, &dev_attr_real_id); if (error) - goto err_init; - + hid_warn(hid, "Unable to create sysfs interface for \"real_id\", errno %d\n", error); error = device_create_file(&hid->dev, &dev_attr_alternate_modes); if (error) - goto err_init; + hid_warn(hid, "Unable to create sysfs interface for \"alternate_modes\", errno %d\n", error); } dbg_hid("sysfs interface created\n"); -- cgit v0.10.2 From bbfd0ccc598ded2ec9f618f10b5bc54b1130f4d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Mal=C3=BD?= Date: Wed, 8 Apr 2015 22:56:52 +0200 Subject: HID: hid-lg4ff: Update respective sysfs interface documentation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update respective sysfs interface documentation - Refer to the sysfs interface for "range" using "/sys/bus/..." - Update contact email address Signed-off-by: Michal Malý Signed-off-by: Jiri Kosina diff --git a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff index b3f6a2a..db197a8 100644 --- a/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff +++ b/Documentation/ABI/testing/sysfs-driver-hid-logitech-lg4ff @@ -1,7 +1,7 @@ -What: /sys/module/hid_logitech/drivers/hid:logitech//range. +What: /sys/bus/hid/drivers/logitech//range Date: July 2011 KernelVersion: 3.2 -Contact: Michal Malý +Contact: Michal Malý Description: Display minimum, maximum and current range of the steering wheel. Writing a value within min and max boundaries sets the range of the wheel. @@ -9,7 +9,7 @@ Description: Display minimum, maximum and current range of the steering What: /sys/bus/hid/drivers/logitech//alternate_modes Date: Feb 2015 KernelVersion: 4.1 -Contact: Michal Malý +Contact: Michal Malý Description: Displays a set of alternate modes supported by a wheel. Each mode is listed as follows: Tag: Mode Name @@ -45,7 +45,7 @@ Description: Displays a set of alternate modes supported by a wheel. Each What: /sys/bus/hid/drivers/logitech//real_id Date: Feb 2015 KernelVersion: 4.1 -Contact: Michal Malý +Contact: Michal Malý Description: Displays the real model of the wheel regardless of any alternate mode the wheel might be switched to. It is a read-only value. -- cgit v0.10.2 From f4e1eb966256b15335054fac7b304f14e4965b5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Mal=C3=BD?= Date: Wed, 8 Apr 2015 22:56:53 +0200 Subject: HID: hid-lg: Only one of LG_FF flags can be set for a given device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only one of LG_FF flags can be set for a given device. Signed-off-by: Michal Malý Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index d5022b3..429340d 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -714,11 +714,11 @@ static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) if (drv_data->quirks & LG_FF) ret = lgff_init(hdev); - if (drv_data->quirks & LG_FF2) + else if (drv_data->quirks & LG_FF2) ret = lg2ff_init(hdev); - if (drv_data->quirks & LG_FF3) + else if (drv_data->quirks & LG_FF3) ret = lg3ff_init(hdev); - if (drv_data->quirks & LG_FF4) + else if (drv_data->quirks & LG_FF4) ret = lg4ff_init(hdev); if (ret) -- cgit v0.10.2 From d0091f5749eadfce87ce0436994584637a353e2c Mon Sep 17 00:00:00 2001 From: Sean Young Date: Fri, 8 May 2015 10:29:58 +0100 Subject: HID: core: remove phidgets from ignore list Once there were kernel drivers for some of the phidgets devices, and for those kernel drivers to work the hid system needed exceptions. Now the kernel drivers are long gone in favour of the user-space drivers. The user-space drivers support many more phidget devices and uses libusb. The udev rules set up permissions so that the kernel hid driver can be unbound from libusb, as it does for many devices not in hid_ignore_list. http://www.phidgets.com/docs/OS_-_Linux Signed-off-by: Sean Young Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 722a925..e880769 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2265,14 +2265,6 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0001) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0002) }, { HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH, 0x0004) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_4_PHIDGETSERVO_30) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_1_PHIDGETSERVO_30) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_0_4_IF_KIT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_16_16_IF_KIT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_8_8_8_IF_KIT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_7_IF_KIT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_0_8_8_IF_KIT) }, - { HID_USB_DEVICE(USB_VENDOR_ID_GLAB, USB_DEVICE_ID_PHIDGET_MOTORCONTROL) }, { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_SUPER_Q2) }, { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_GOGOPEN) }, { HID_USB_DEVICE(USB_VENDOR_ID_GOTOP, USB_DEVICE_ID_PENPOWER) }, @@ -2404,9 +2396,6 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) }, { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) }, { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_4_PHIDGETSERVO_20) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_1_PHIDGETSERVO_20) }, - { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_8_8_4_IF_KIT) }, { HID_USB_DEVICE(USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K) }, { HID_USB_DEVICE(USB_VENDOR_ID_RISO_KAGAKU, USB_DEVICE_ID_RI_KA_WEBMAIL) }, { } diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index b24caf8..cf0a537 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -362,16 +362,6 @@ #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A 0x010a #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100 0xe100 -#define USB_VENDOR_ID_GLAB 0x06c2 -#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038 -#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039 -#define USB_DEVICE_ID_0_0_4_IF_KIT 0x0040 -#define USB_DEVICE_ID_0_16_16_IF_KIT 0x0044 -#define USB_DEVICE_ID_8_8_8_IF_KIT 0x0045 -#define USB_DEVICE_ID_0_8_7_IF_KIT 0x0051 -#define USB_DEVICE_ID_0_8_8_IF_KIT 0x0053 -#define USB_DEVICE_ID_PHIDGET_MOTORCONTROL 0x0058 - #define USB_VENDOR_ID_GOODTOUCH 0x1aad #define USB_DEVICE_ID_GOODTOUCH_000f 0x000f @@ -982,9 +972,6 @@ #define USB_VENDOR_ID_WISEGROUP 0x0925 #define USB_DEVICE_ID_SMARTJOY_PLUS 0x0005 -#define USB_DEVICE_ID_1_PHIDGETSERVO_20 0x8101 -#define USB_DEVICE_ID_4_PHIDGETSERVO_20 0x8104 -#define USB_DEVICE_ID_8_8_4_IF_KIT 0x8201 #define USB_DEVICE_ID_SUPER_JOY_BOX_3 0x8888 #define USB_DEVICE_ID_QUAD_USB_JOYPAD 0x8800 #define USB_DEVICE_ID_DUAL_USB_JOYPAD 0x8866 -- cgit v0.10.2 From af43c4086cf24c3eb74a968195351163750c82b6 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 14 May 2015 11:32:56 +0300 Subject: HID: rmi: fix some harmless BIT() mistakes These defines are used like this: if (!(test_bit(RMI_STARTED, &hdata->flags))) So the intent was to use bits 0, 1 and 2 but because of the extra BIT() shifts we're actually using 1, 2 and 4. It's harmless because it's done consistently but static checkers will complain. Fixes: 9fb6bf02e3ad ('HID: rmi: introduce RMI driver for Synaptics touchpads') Signed-off-by: Dan Carpenter Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c index 368ffdf..2f3e51d 100644 --- a/drivers/hid/hid-rmi.c +++ b/drivers/hid/hid-rmi.c @@ -29,9 +29,9 @@ #define RMI_SET_RMI_MODE_REPORT_ID 0x0f /* Feature Report */ /* flags */ -#define RMI_READ_REQUEST_PENDING BIT(0) -#define RMI_READ_DATA_PENDING BIT(1) -#define RMI_STARTED BIT(2) +#define RMI_READ_REQUEST_PENDING 0 +#define RMI_READ_DATA_PENDING 1 +#define RMI_STARTED 2 /* device flags */ #define RMI_DEVICE BIT(0) -- cgit v0.10.2 From c8fd51dc12c6e22bb97d5e273babcf339770aba5 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 14 May 2015 11:33:30 +0300 Subject: HID: i2c-hid: fix harmless test_bit() issue These defines are used like this: if (test_bit(I2C_HID_STARTED, &ihid->flags)) The intent was to use bits 0, 1, and 2 but because of the extra shifts we're using bits 1, 2, and 4. It's harmless becuase it's done consistently but it's not the intent and static checkers will complain. Fixes: 4a200c3b9a40 ('HID: i2c-hid: introduce HID over i2c specification implementation') Signed-off-by: Dan Carpenter Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index ab4dd95..ea5ce75 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -42,9 +42,9 @@ #include /* flags */ -#define I2C_HID_STARTED (1 << 0) -#define I2C_HID_RESET_PENDING (1 << 1) -#define I2C_HID_READ_PENDING (1 << 2) +#define I2C_HID_STARTED 0 +#define I2C_HID_RESET_PENDING 1 +#define I2C_HID_READ_PENDING 2 #define I2C_HID_PWR_ON 0x00 #define I2C_HID_PWR_SLEEP 0x01 -- cgit v0.10.2 From 6e01d531c9603d591826e842298a539d17436fa8 Mon Sep 17 00:00:00 2001 From: Antonio Ospite Date: Tue, 28 Apr 2015 13:11:20 +0200 Subject: HID: Makefile: fix alignment of objs-* entries Most of the entries are aligned with TABs, fix those which are not. Signed-off-by: Antonio Ospite Signed-off-by: Jiri Kosina diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index e4a21df..2f8a41d 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -24,7 +24,7 @@ obj-$(CONFIG_HID_A4TECH) += hid-a4tech.o obj-$(CONFIG_HID_ACRUX) += hid-axff.o obj-$(CONFIG_HID_APPLE) += hid-apple.o obj-$(CONFIG_HID_APPLEIR) += hid-appleir.o -obj-$(CONFIG_HID_AUREAL) += hid-aureal.o +obj-$(CONFIG_HID_AUREAL) += hid-aureal.o obj-$(CONFIG_HID_BELKIN) += hid-belkin.o obj-$(CONFIG_HID_BETOP_FF) += hid-betopff.o obj-$(CONFIG_HID_CHERRY) += hid-cherry.o @@ -46,12 +46,12 @@ obj-$(CONFIG_HID_ICADE) += hid-icade.o obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o obj-$(CONFIG_HID_KYE) += hid-kye.o -obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o +obj-$(CONFIG_HID_LCPOWER) += hid-lcpower.o obj-$(CONFIG_HID_LENOVO) += hid-lenovo.o obj-$(CONFIG_HID_LOGITECH) += hid-logitech.o obj-$(CONFIG_HID_LOGITECH_DJ) += hid-logitech-dj.o obj-$(CONFIG_HID_LOGITECH_HIDPP) += hid-logitech-hidpp.o -obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o +obj-$(CONFIG_HID_MAGICMOUSE) += hid-magicmouse.o obj-$(CONFIG_HID_MICROSOFT) += hid-microsoft.o obj-$(CONFIG_HID_MONTEREY) += hid-monterey.o obj-$(CONFIG_HID_MULTITOUCH) += hid-multitouch.o -- cgit v0.10.2 From 09a5c34e8d6b05663ec4c3d22b1fbd9fec89aaf9 Mon Sep 17 00:00:00 2001 From: James C Boyd Date: Wed, 27 May 2015 17:09:06 -0500 Subject: HID: hid-input: Add parentheses to quell gcc warning GCC reports a -Wlogical-not-parentheses warning here; therefore add parentheses to shut it up and to express our intent more. Signed-off-by: James C Boyd Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 008e89b..714b758 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -1157,7 +1157,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct return; /* report the usage code as scancode if the key status has changed */ - if (usage->type == EV_KEY && !!test_bit(usage->code, input->key) != value) + if (usage->type == EV_KEY && (!!test_bit(usage->code, input->key)) != value) input_event(input, EV_MSC, MSC_SCAN, usage->hid); input_event(input, usage->type, usage->code, value); -- cgit v0.10.2 From 2c54c86a674979e2bd9dc3663d329ee56368a218 Mon Sep 17 00:00:00 2001 From: James C Boyd Date: Wed, 27 May 2015 17:09:07 -0500 Subject: HID: hid-input: Simplify conditional expression There are too many bangs in this conditional; therefore remove them while still maintaining the same logic. Signed-off-by: James C Boyd Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 714b758..abf4fc6 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -1157,7 +1157,7 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct return; /* report the usage code as scancode if the key status has changed */ - if (usage->type == EV_KEY && (!!test_bit(usage->code, input->key)) != value) + if (usage->type == EV_KEY && (!test_bit(usage->code, input->key)) == value) input_event(input, EV_MSC, MSC_SCAN, usage->hid); input_event(input, usage->type, usage->code, value); -- cgit v0.10.2 From 323ddaa84f003a0c1d49f3ce5d106bc3cef070d5 Mon Sep 17 00:00:00 2001 From: James C Boyd Date: Wed, 27 May 2015 17:09:08 -0500 Subject: HID: hid-input: Fix coding style issue This line is too long; split it up. Signed-off-by: James C Boyd Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index abf4fc6..3511bbab 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -1157,7 +1157,8 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct return; /* report the usage code as scancode if the key status has changed */ - if (usage->type == EV_KEY && (!test_bit(usage->code, input->key)) == value) + if (usage->type == EV_KEY && + (!test_bit(usage->code, input->key)) == value) input_event(input, EV_MSC, MSC_SCAN, usage->hid); input_event(input, usage->type, usage->code, value); -- cgit v0.10.2 From b721260085533a9bead1fd853c0aead7d82ce763 Mon Sep 17 00:00:00 2001 From: Alexey Khoroshilov Date: Fri, 29 May 2015 03:39:31 +0300 Subject: HID: lenovo: Remove sysfs group on failure path There is no sysfs_group_remove() on failure path in lenovo_probe_tpkbd(). Found by Linux Driver Verification project (linuxtesting.org). Signed-off-by: Alexey Khoroshilov Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c index c4c3f09..64ed3e3 100644 --- a/drivers/hid/hid-lenovo.c +++ b/drivers/hid/hid-lenovo.c @@ -599,7 +599,8 @@ static int lenovo_probe_tpkbd(struct hid_device *hdev) GFP_KERNEL); if (data_pointer == NULL) { hid_err(hdev, "Could not allocate memory for driver data\n"); - return -ENOMEM; + ret = -ENOMEM; + goto err; } // set same default values as windows driver @@ -610,7 +611,8 @@ static int lenovo_probe_tpkbd(struct hid_device *hdev) name_micmute = devm_kzalloc(&hdev->dev, name_sz, GFP_KERNEL); if (name_mute == NULL || name_micmute == NULL) { hid_err(hdev, "Could not allocate memory for led data\n"); - return -ENOMEM; + ret = -ENOMEM; + goto err; } snprintf(name_mute, name_sz, "%s:amber:mute", dev_name(dev)); snprintf(name_micmute, name_sz, "%s:amber:micmute", dev_name(dev)); @@ -634,6 +636,9 @@ static int lenovo_probe_tpkbd(struct hid_device *hdev) lenovo_features_set_tpkbd(hdev); return 0; +err: + sysfs_remove_group(&hdev->dev.kobj, &lenovo_attr_group_tpkbd); + return ret; } static int lenovo_probe_cptkbd(struct hid_device *hdev) -- cgit v0.10.2 From 04fba7864ffcceae8a5f78d88ae1fd8d682a5123 Mon Sep 17 00:00:00 2001 From: Goffredo Baroncelli Date: Sat, 30 May 2015 11:00:26 +0200 Subject: HID: Export hid_field_extract() Rename the function extract() to hid_field_extract(), make it external linkage to allow the use from other modules. Suggested-by: Jiri Kosina Signed-off-by: Goffredo Baroncelli Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 722a925..fe33f9e 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1061,13 +1061,13 @@ static u32 s32ton(__s32 value, unsigned n) * Search linux-kernel and linux-usb-devel archives for "hid-core extract". */ -static __u32 extract(const struct hid_device *hid, __u8 *report, +__u32 hid_field_extract(const struct hid_device *hid, __u8 *report, unsigned offset, unsigned n) { u64 x; if (n > 32) - hid_warn(hid, "extract() called with n (%d) > 32! (%s)\n", + hid_warn(hid, "hid_field_extract() called with n (%d) > 32! (%s)\n", n, current->comm); report += offset >> 3; /* adjust byte index */ @@ -1076,6 +1076,7 @@ static __u32 extract(const struct hid_device *hid, __u8 *report, x = (x >> offset) & ((1ULL << n) - 1); /* extract bit field */ return (u32) x; } +EXPORT_SYMBOL_GPL(hid_field_extract); /* * "implement" : set bits in a little endian bit stream. @@ -1221,9 +1222,9 @@ static void hid_input_field(struct hid_device *hid, struct hid_field *field, for (n = 0; n < count; n++) { value[n] = min < 0 ? - snto32(extract(hid, data, offset + n * size, size), - size) : - extract(hid, data, offset + n * size, size); + snto32(hid_field_extract(hid, data, offset + n * size, + size), size) : + hid_field_extract(hid, data, offset + n * size, size); /* Ignore report if ErrorRollOver */ if (!(field->flags & HID_MAIN_ITEM_VARIABLE) && diff --git a/include/linux/hid.h b/include/linux/hid.h index 176b436..f17980d 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -815,6 +815,8 @@ void hid_disconnect(struct hid_device *hid); const struct hid_device_id *hid_match_id(struct hid_device *hdev, const struct hid_device_id *id); s32 hid_snto32(__u32 value, unsigned n); +__u32 hid_field_extract(const struct hid_device *hid, __u8 *report, + unsigned offset, unsigned n); /** * hid_device_io_start - enable HID input during probe, remove -- cgit v0.10.2 From 8a09b4fadf320cef081e1539975a97793cfb9076 Mon Sep 17 00:00:00 2001 From: Goffredo Baroncelli Date: Sat, 30 May 2015 11:00:27 +0200 Subject: HID: hidpp: Add driver for mouse logitech M560 The Logitech M560 is a wireless mouse designed for windows 8 which uses the unifying receiver. Compared to a standard one, some buttons (the middle one and the two ones placed on the side) are bound to a key combination instead of a generating classic "mouse" button events. The device shows up as a mouse and keyboard combination: when the middle button is pressed it sends a key (as keyboard) combination, the same happens for the two side button. The left/right/wheel work as expected from a mouse. To complicate things further, the middle button sends different keys combinations between odd and even presses. In the "even" press it also sends a left click. But the worst thing is that no event is generated when the middle button is released. It is possible to re-configure the mouse sending a command (see function m560_send_config_command()). After this command the mouse sends some useful data when the buttons are pressed and/or released. [jkosina@suse.cz: fix build breakage due to leftover from previous patch version] Signed-off-by: Goffredo Baroncelli Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index b3cf6fd..394a6f4 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -40,8 +40,9 @@ MODULE_PARM_DESC(disable_raw_mode, #define HIDPP_REPORT_LONG_LENGTH 20 #define HIDPP_QUIRK_CLASS_WTP BIT(0) +#define HIDPP_QUIRK_CLASS_M560 BIT(1) -/* bits 1..20 are reserved for classes */ +/* bits 2..20 are reserved for classes */ #define HIDPP_QUIRK_DELAYED_INIT BIT(21) #define HIDPP_QUIRK_WTP_PHYSICAL_BUTTONS BIT(22) #define HIDPP_QUIRK_MULTI_INPUT BIT(23) @@ -941,6 +942,207 @@ static int wtp_connect(struct hid_device *hdev, bool connected) true, true); } +/* ------------------------------------------------------------------------- */ +/* Logitech M560 devices */ +/* ------------------------------------------------------------------------- */ + +/* + * Logitech M560 protocol overview + * + * The Logitech M560 mouse, is designed for windows 8. When the middle and/or + * the sides buttons are pressed, it sends some keyboard keys events + * instead of buttons ones. + * To complicate things further, the middle button keys sequence + * is different from the odd press and the even press. + * + * forward button -> Super_R + * backward button -> Super_L+'d' (press only) + * middle button -> 1st time: Alt_L+SuperL+XF86TouchpadOff (press only) + * 2nd time: left-click (press only) + * NB: press-only means that when the button is pressed, the + * KeyPress/ButtonPress and KeyRelease/ButtonRelease events are generated + * together sequentially; instead when the button is released, no event is + * generated ! + * + * With the command + * 100a 3500af03 (where is the mouse id), + * the mouse reacts differently: + * - it never sends a keyboard key event + * - for the three mouse button it sends: + * middle button press 110a 3500af00... + * side 1 button (forward) press 110a 3500b000... + * side 2 button (backward) press 110a 3500ae00... + * middle/side1/side2 button release 110a 35000000... + */ + +static const u8 m560_config_parameter[] = {0x00, 0xaf, 0x03}; + +struct m560_private_data { + struct input_dev *input; +}; + +/* how buttons are mapped in the report */ +#define M560_MOUSE_BTN_LEFT 0x01 +#define M560_MOUSE_BTN_RIGHT 0x02 +#define M560_MOUSE_BTN_WHEEL_LEFT 0x08 +#define M560_MOUSE_BTN_WHEEL_RIGHT 0x10 + +#define M560_SUB_ID 0x0a +#define M560_BUTTON_MODE_REGISTER 0x35 + +static int m560_send_config_command(struct hid_device *hdev, bool connected) +{ + struct hidpp_report response; + struct hidpp_device *hidpp_dev; + + hidpp_dev = hid_get_drvdata(hdev); + + if (!connected) + return -ENODEV; + + return hidpp_send_rap_command_sync( + hidpp_dev, + REPORT_ID_HIDPP_SHORT, + M560_SUB_ID, + M560_BUTTON_MODE_REGISTER, + (u8 *)m560_config_parameter, + sizeof(m560_config_parameter), + &response + ); +} + +static int m560_allocate(struct hid_device *hdev) +{ + struct hidpp_device *hidpp = hid_get_drvdata(hdev); + struct m560_private_data *d; + + d = devm_kzalloc(&hdev->dev, sizeof(struct m560_private_data), + GFP_KERNEL); + if (!d) + return -ENOMEM; + + hidpp->private_data = d; + + return 0; +}; + +static int m560_raw_event(struct hid_device *hdev, u8 *data, int size) +{ + struct hidpp_device *hidpp = hid_get_drvdata(hdev); + struct m560_private_data *mydata = hidpp->private_data; + + /* sanity check */ + if (!mydata || !mydata->input) { + hid_err(hdev, "error in parameter\n"); + return -EINVAL; + } + + if (size < 7) { + hid_err(hdev, "error in report\n"); + return 0; + } + + if (data[0] == REPORT_ID_HIDPP_LONG && + data[2] == M560_SUB_ID && data[6] == 0x00) { + /* + * m560 mouse report for middle, forward and backward button + * + * data[0] = 0x11 + * data[1] = device-id + * data[2] = 0x0a + * data[5] = 0xaf -> middle + * 0xb0 -> forward + * 0xae -> backward + * 0x00 -> release all + * data[6] = 0x00 + */ + + switch (data[5]) { + case 0xaf: + input_report_key(mydata->input, BTN_MIDDLE, 1); + break; + case 0xb0: + input_report_key(mydata->input, BTN_FORWARD, 1); + break; + case 0xae: + input_report_key(mydata->input, BTN_BACK, 1); + break; + case 0x00: + input_report_key(mydata->input, BTN_BACK, 0); + input_report_key(mydata->input, BTN_FORWARD, 0); + input_report_key(mydata->input, BTN_MIDDLE, 0); + break; + default: + hid_err(hdev, "error in report\n"); + return 0; + } + input_sync(mydata->input); + + } else if (data[0] == 0x02) { + /* + * Logitech M560 mouse report + * + * data[0] = type (0x02) + * data[1..2] = buttons + * data[3..5] = xy + * data[6] = wheel + */ + + int v; + + input_report_key(mydata->input, BTN_LEFT, + !!(data[1] & M560_MOUSE_BTN_LEFT)); + input_report_key(mydata->input, BTN_RIGHT, + !!(data[1] & M560_MOUSE_BTN_RIGHT)); + + if (data[1] & M560_MOUSE_BTN_WHEEL_LEFT) + input_report_rel(mydata->input, REL_HWHEEL, -1); + else if (data[1] & M560_MOUSE_BTN_WHEEL_RIGHT) + input_report_rel(mydata->input, REL_HWHEEL, 1); + + v = hid_snto32(hid_field_extract(hdev, data+3, 0, 12), 12); + input_report_rel(mydata->input, REL_X, v); + + v = hid_snto32(hid_field_extract(hdev, data+3, 12, 12), 12); + input_report_rel(mydata->input, REL_Y, v); + + v = hid_snto32(data[6], 8); + input_report_rel(mydata->input, REL_WHEEL, v); + + input_sync(mydata->input); + } + + return 1; +} + +static void m560_populate_input(struct hidpp_device *hidpp, + struct input_dev *input_dev, bool origin_is_hid_core) +{ + struct m560_private_data *mydata = hidpp->private_data; + + mydata->input = input_dev; + + __set_bit(EV_KEY, mydata->input->evbit); + __set_bit(BTN_MIDDLE, mydata->input->keybit); + __set_bit(BTN_RIGHT, mydata->input->keybit); + __set_bit(BTN_LEFT, mydata->input->keybit); + __set_bit(BTN_BACK, mydata->input->keybit); + __set_bit(BTN_FORWARD, mydata->input->keybit); + + __set_bit(EV_REL, mydata->input->evbit); + __set_bit(REL_X, mydata->input->relbit); + __set_bit(REL_Y, mydata->input->relbit); + __set_bit(REL_WHEEL, mydata->input->relbit); + __set_bit(REL_HWHEEL, mydata->input->relbit); +} + +static int m560_input_mapping(struct hid_device *hdev, struct hid_input *hi, + struct hid_field *field, struct hid_usage *usage, + unsigned long **bit, int *max) +{ + return -1; +} + /* -------------------------------------------------------------------------- */ /* Generic HID++ devices */ /* -------------------------------------------------------------------------- */ @@ -953,6 +1155,9 @@ static int hidpp_input_mapping(struct hid_device *hdev, struct hid_input *hi, if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) return wtp_input_mapping(hdev, hi, field, usage, bit, max); + else if (hidpp->quirks & HIDPP_QUIRK_CLASS_M560 && + field->application != HID_GD_MOUSE) + return m560_input_mapping(hdev, hi, field, usage, bit, max); return 0; } @@ -962,6 +1167,8 @@ static void hidpp_populate_input(struct hidpp_device *hidpp, { if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) wtp_populate_input(hidpp, input, origin_is_hid_core); + else if (hidpp->quirks & HIDPP_QUIRK_CLASS_M560) + m560_populate_input(hidpp, input, origin_is_hid_core); } static void hidpp_input_configured(struct hid_device *hdev, @@ -1049,6 +1256,8 @@ static int hidpp_raw_event(struct hid_device *hdev, struct hid_report *report, if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) return wtp_raw_event(hdev, data, size); + else if (hidpp->quirks & HIDPP_QUIRK_CLASS_M560) + return m560_raw_event(hdev, data, size); return 0; } @@ -1126,6 +1335,10 @@ static void hidpp_connect_event(struct hidpp_device *hidpp) ret = wtp_connect(hdev, connected); if (ret) return; + } else if (hidpp->quirks & HIDPP_QUIRK_CLASS_M560) { + ret = m560_send_config_command(hdev, connected); + if (ret) + return; } if (!connected || hidpp->delayed_input) @@ -1201,7 +1414,11 @@ static int hidpp_probe(struct hid_device *hdev, const struct hid_device_id *id) if (hidpp->quirks & HIDPP_QUIRK_CLASS_WTP) { ret = wtp_allocate(hdev, id); if (ret) - goto wtp_allocate_fail; + goto allocate_fail; + } else if (hidpp->quirks & HIDPP_QUIRK_CLASS_M560) { + ret = m560_allocate(hdev); + if (ret) + goto allocate_fail; } INIT_WORK(&hidpp->work, delayed_work_cb); @@ -1268,7 +1485,7 @@ hid_hw_start_fail: hid_parse_fail: cancel_work_sync(&hidpp->work); mutex_destroy(&hidpp->send_mutex); -wtp_allocate_fail: +allocate_fail: hid_set_drvdata(hdev, NULL); return ret; } @@ -1301,6 +1518,10 @@ static const struct hid_device_id hidpp_devices[] = { USB_VENDOR_ID_LOGITECH, 0x4102), .driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_MULTI_INPUT | HIDPP_QUIRK_CLASS_WTP }, + { /* Mouse logitech M560 */ + HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, + USB_VENDOR_ID_LOGITECH, 0x402d), + .driver_data = HIDPP_QUIRK_DELAYED_INIT | HIDPP_QUIRK_CLASS_M560 }, { HID_DEVICE(BUS_USB, HID_GROUP_LOGITECH_DJ_DEVICE, USB_VENDOR_ID_LOGITECH, HID_ANY_ID)}, -- cgit v0.10.2 From 0317a65b94770c953480970f67db0a716778c6a7 Mon Sep 17 00:00:00 2001 From: Dennis O'Brien Date: Sun, 31 May 2015 09:19:59 -0700 Subject: usb, HID: Remove Vernier devices from lsusb and hid_ignore_list Removes Vernier Software & Technology devices from the ldusb driver and the hid_ignore_list table of the usbhid driver in the Linux tree. These devices will now be supported via the hidraw driver. A user space driver for these devices will be found in the Go! Software Development Kit from Vernier at http://www.vernier.com/downloads/software-development-kits/go-sdk/. These devices are also be supported by the LabQuest2 standalone interface shown at http://www.vernier.com/products/interfaces/labq2/ and the LoggerPro for Linux software shown at http://www.vernier.com/downloads/logger-pro-linux/. Signed-off-by: Dennis O'Brien Acked-by: Greg Kroah-Hartman Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index e880769..2a0bd8e 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -2391,11 +2391,6 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_WTP) }, { HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DPAD) }, #endif - { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) }, - { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) }, - { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) }, - { HID_USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC) }, { HID_USB_DEVICE(USB_VENDOR_ID_YEALINK, USB_DEVICE_ID_YEALINK_P1K_P4K_B2K) }, { HID_USB_DEVICE(USB_VENDOR_ID_RISO_KAGAKU, USB_DEVICE_ID_RI_KA_WEBMAIL) }, { } diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index cf0a537..005335e 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -947,13 +947,6 @@ #define USB_DEVICE_ID_VELLEMAN_K8061_FIRST 0x8061 #define USB_DEVICE_ID_VELLEMAN_K8061_LAST 0x8068 -#define USB_VENDOR_ID_VERNIER 0x08f7 -#define USB_DEVICE_ID_VERNIER_LABPRO 0x0001 -#define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002 -#define USB_DEVICE_ID_VERNIER_SKIP 0x0003 -#define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004 -#define USB_DEVICE_ID_VERNIER_LCSPEC 0x0006 - #define USB_VENDOR_ID_VTL 0x0306 #define USB_DEVICE_ID_VTL_MULTITOUCH_FF3F 0xff3f diff --git a/drivers/usb/misc/ldusb.c b/drivers/usb/misc/ldusb.c index 82503a7..cce22ff 100644 --- a/drivers/usb/misc/ldusb.c +++ b/drivers/usb/misc/ldusb.c @@ -69,12 +69,6 @@ #define USB_DEVICE_ID_LD_HYBRID 0x2090 /* USB Product ID of Automotive Hybrid */ #define USB_DEVICE_ID_LD_HEATCONTROL 0x20A0 /* USB Product ID of Heat control */ -#define USB_VENDOR_ID_VERNIER 0x08f7 -#define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002 -#define USB_DEVICE_ID_VERNIER_SKIP 0x0003 -#define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004 -#define USB_DEVICE_ID_VERNIER_LCSPEC 0x0006 - #ifdef CONFIG_USB_DYNAMIC_MINORS #define USB_LD_MINOR_BASE 0 #else @@ -115,10 +109,6 @@ static const struct usb_device_id ld_usb_table[] = { { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MCT) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HYBRID) }, { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_HEATCONTROL) }, - { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) }, - { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) }, - { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) }, - { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LCSPEC) }, { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(usb, ld_usb_table); -- cgit v0.10.2 From 18eec2cd7e9746cd672ada102987534ae16f0f44 Mon Sep 17 00:00:00 2001 From: Raimund Roth Date: Mon, 8 Jun 2015 11:11:38 +0200 Subject: HID: microsoft: Add Surface Power Cover Adding support for the Microsoft Surface Pro Power Cover. Signed-off-by: Raimund Roth Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 2a0bd8e..d596a06 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -706,7 +706,8 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type) if (hid->vendor == USB_VENDOR_ID_MICROSOFT && (hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 || - hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3_JP) && + hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3_JP || + hid->product == USB_DEVICE_ID_MS_POWER_COVER) && hid->group == HID_GROUP_MULTITOUCH) hid->group = HID_GROUP_GENERIC; @@ -1901,6 +1902,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3_JP) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER) }, { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 005335e..4c81b07 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -662,6 +662,7 @@ #define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 #define USB_DEVICE_ID_MS_TYPE_COVER_3 0x07dc #define USB_DEVICE_ID_MS_TYPE_COVER_3_JP 0x07dd +#define USB_DEVICE_ID_MS_POWER_COVER 0x07da #define USB_VENDOR_ID_MOJO 0x8282 #define USB_DEVICE_ID_RETRO_ADAPTER 0x3201 diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index af935eb..32a596f 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -280,6 +280,8 @@ static const struct hid_device_id ms_devices[] = { .driver_data = MS_HIDINPUT }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3_JP), .driver_data = MS_HIDINPUT }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER), + .driver_data = MS_HIDINPUT }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT), .driver_data = MS_PRESENTER }, diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 09a22a7..70dbf61 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -88,6 +88,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3_JP, HID_QUIRK_NO_INIT_REPORTS }, + { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_POWER_COVER, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS }, -- cgit v0.10.2 From 74a3e0c719dcfc66333f43a8414a9c5bfc50bf95 Mon Sep 17 00:00:00 2001 From: Fabian Frederick Date: Wed, 10 Jun 2015 18:32:05 +0200 Subject: HID: cypress: use swap() in cp_report_fixup() Use kernel.h macro definition. Thanks to Julia Lawall for Coccinelle scripting support. Signed-off-by: Fabian Frederick Signed-off-by: Jiri Kosina diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c index c4ef3bc..1b764d1 100644 --- a/drivers/hid/hid-cypress.c +++ b/drivers/hid/hid-cypress.c @@ -41,13 +41,9 @@ static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, for (i = 0; i < *rsize - 4; i++) if (rdesc[i] == 0x29 && rdesc[i + 2] == 0x19) { - __u8 tmp; - rdesc[i] = 0x19; rdesc[i + 2] = 0x29; - tmp = rdesc[i + 3]; - rdesc[i + 3] = rdesc[i + 1]; - rdesc[i + 1] = tmp; + swap(rdesc[i + 3], rdesc[i + 1]); } return rdesc; } -- cgit v0.10.2