From b35e0dc548aa34eb39d80962e370e048dff7de88 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 5 Jul 2024 14:09:25 +0200 Subject: [PATCH 01/54] HID: samples: fix the 2 struct_ops definitions Turns out that this is not compiling anymore because the hid_bpf_ops struct_ops definition had a change during the revisions. Fixes: e342d6f6f7d8 ("HID: samples: convert the 2 HID-BPF samples into struct_ops") Link: https://patch.msgid.link/20240705-for-6-11-bpf-v1-1-1960e3165c9e@kernel.org Signed-off-by: Benjamin Tissoires --- samples/hid/hid_mouse.bpf.c | 8 ++++---- samples/hid/hid_surface_dial.bpf.c | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/samples/hid/hid_mouse.bpf.c b/samples/hid/hid_mouse.bpf.c index bd901fa855c9..f7f722dcf56d 100644 --- a/samples/hid/hid_mouse.bpf.c +++ b/samples/hid/hid_mouse.bpf.c @@ -67,7 +67,7 @@ static int hid_x_event(struct hid_bpf_ctx *hctx) return 0; } -SEC("struct_ops/device_event") +SEC("struct_ops/hid_device_event") int BPF_PROG(hid_event, struct hid_bpf_ctx *hctx, enum hid_report_type type) { int ret = hid_y_event(hctx); @@ -79,7 +79,7 @@ int BPF_PROG(hid_event, struct hid_bpf_ctx *hctx, enum hid_report_type type) } -SEC("struct_ops/rdesc_fixup") +SEC("struct_ops/hid_rdesc_fixup") int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx) { __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */); @@ -121,8 +121,8 @@ int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx) SEC(".struct_ops.link") struct hid_bpf_ops mouse_invert = { - .rdesc_fixup = (void *)hid_rdesc_fixup, - .device_event = (void *)hid_event, + .hid_rdesc_fixup = (void *)hid_rdesc_fixup, + .hid_device_event = (void *)hid_event, }; char _license[] SEC("license") = "GPL"; diff --git a/samples/hid/hid_surface_dial.bpf.c b/samples/hid/hid_surface_dial.bpf.c index d8d0fb07391f..527d584812ab 100644 --- a/samples/hid/hid_surface_dial.bpf.c +++ b/samples/hid/hid_surface_dial.bpf.c @@ -10,7 +10,7 @@ #define HID_UP_BUTTON 0x0009 #define HID_GD_WHEEL 0x0038 -SEC("struct_ops/device_event") +SEC("struct_ops/hid_device_event") int BPF_PROG(hid_event, struct hid_bpf_ctx *hctx) { __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */); @@ -101,7 +101,7 @@ int set_haptic(struct haptic_syscall_args *args) } /* Convert REL_DIAL into REL_WHEEL */ -SEC("struct_ops/rdesc_fixup") +SEC("struct_ops/hid_rdesc_fixup") int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx) { __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */); @@ -132,8 +132,8 @@ int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx) SEC(".struct_ops.link") struct hid_bpf_ops surface_dial = { - .rdesc_fixup = (void *)hid_rdesc_fixup, - .device_event = (void *)hid_event, + .hid_rdesc_fixup = (void *)hid_rdesc_fixup, + .hid_device_event = (void *)hid_event, }; char _license[] SEC("license") = "GPL"; From 6edb8cd87cca5dd4389d4ea2d84b66ea94341bbd Mon Sep 17 00:00:00 2001 From: Kerem Karabay Date: Fri, 5 Jul 2024 11:17:42 +0000 Subject: [PATCH 02/54] HID: core: add helper for finding a field with a certain usage This helper will allow HID drivers to easily determine if they should bind to a hid_device by checking for the prescence of a certain field when its ID is not enough, which can be the case on USB devices with multiple interfaces and/or configurations. Convert google-hammer driver to use it, and remove now superfluous hammer_has_usage(). [jkosina@suse.com: expand changelog with the information about google-hammer being added as user of this API ] Signed-off-by: Kerem Karabay Signed-off-by: Aditya Garg Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 25 +++++++++++++++++++++++++ drivers/hid/hid-google-hammer.c | 27 ++------------------------- include/linux/hid.h | 2 ++ 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 988d0acbdf04..caeba5487b69 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1912,6 +1912,31 @@ int hid_set_field(struct hid_field *field, unsigned offset, __s32 value) } EXPORT_SYMBOL_GPL(hid_set_field); +struct hid_field *hid_find_field(struct hid_device *hdev, unsigned int report_type, + unsigned int application, unsigned int usage) +{ + struct list_head *report_list = &hdev->report_enum[report_type].report_list; + struct hid_report *report; + int i, j; + + list_for_each_entry(report, report_list, list) { + if (report->application != application) + continue; + + for (i = 0; i < report->maxfield; i++) { + struct hid_field *field = report->field[i]; + + for (j = 0; j < field->maxusage; j++) { + if (field->usage[j].hid == usage) + return field; + } + } + } + + return NULL; +} +EXPORT_SYMBOL_GPL(hid_find_field); + static struct hid_report *hid_get_report(struct hid_report_enum *report_enum, const u8 *data) { diff --git a/drivers/hid/hid-google-hammer.c b/drivers/hid/hid-google-hammer.c index 6e4ebc349e45..4e79fafeeafa 100644 --- a/drivers/hid/hid-google-hammer.c +++ b/drivers/hid/hid-google-hammer.c @@ -418,38 +418,15 @@ static int hammer_event(struct hid_device *hid, struct hid_field *field, return 0; } -static bool hammer_has_usage(struct hid_device *hdev, unsigned int report_type, - unsigned application, unsigned usage) -{ - struct hid_report_enum *re = &hdev->report_enum[report_type]; - struct hid_report *report; - int i, j; - - list_for_each_entry(report, &re->report_list, list) { - if (report->application != application) - continue; - - for (i = 0; i < report->maxfield; i++) { - struct hid_field *field = report->field[i]; - - for (j = 0; j < field->maxusage; j++) - if (field->usage[j].hid == usage) - return true; - } - } - - return false; -} - static bool hammer_has_folded_event(struct hid_device *hdev) { - return hammer_has_usage(hdev, HID_INPUT_REPORT, + return !!hid_find_field(hdev, HID_INPUT_REPORT, HID_GD_KEYBOARD, HID_USAGE_KBD_FOLDED); } static bool hammer_has_backlight_control(struct hid_device *hdev) { - return hammer_has_usage(hdev, HID_OUTPUT_REPORT, + return !!hid_find_field(hdev, HID_OUTPUT_REPORT, HID_GD_KEYBOARD, HID_AD_BRIGHTNESS); } diff --git a/include/linux/hid.h b/include/linux/hid.h index 1533c9dcd3a6..2deff79f39a1 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -940,6 +940,8 @@ extern void hidinput_report_event(struct hid_device *hid, struct hid_report *rep extern int hidinput_connect(struct hid_device *hid, unsigned int force); extern void hidinput_disconnect(struct hid_device *); +struct hid_field *hid_find_field(struct hid_device *hdev, unsigned int report_type, + unsigned int application, unsigned int usage); int hid_set_field(struct hid_field *, unsigned, __s32); int hid_input_report(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 size, int interrupt); From 3152301ff28872255461484b3dc831e2bf0f28db Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Tue, 30 Jul 2024 08:51:56 -0700 Subject: [PATCH 03/54] HID: wacom: Improve warning for tablets falling back to default resolution When we encounter a usage mapped to ABS_X or ABS_Y which has a calculated resolution of 0, we want to warn the user of this before setting a default value. The previous language used the word "usage" but then printed out the value of a "code" instead. We can improve this. Signed-off-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 1f4564982b95..b753b2f111fb 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1904,8 +1904,8 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, if ((code == ABS_X || code == ABS_Y) && !resolution) { resolution = WACOM_INTUOS_RES; hid_warn(input, - "Wacom usage (%d) missing resolution \n", - code); + "Using default resolution for axis type 0x%x code 0x%x\n", + type, code); } input_abs_set_res(input, code, resolution); break; From 7525a0bd928e3a5d6dcea6a38cc5ce88f45d27a9 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Tue, 30 Jul 2024 08:51:57 -0700 Subject: [PATCH 04/54] HID: wacom: Support touchrings with relative motion If a touchring is configured to send relative events (e.g. +1 or -1 every time some bit of rotational distance is covered), we should similarly send relative events up to userspace. Previous non-HID tablets used REL_WHEEL to send this kind of information, so we opt to use this same axis since userspace (xf86-input-wacom and libinput) already expects this kind of behavior from the Wacom kernel driver. Signed-off-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index b753b2f111fb..798c26ddaeba 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1909,6 +1909,7 @@ static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, } input_abs_set_res(input, code, resolution); break; + case EV_REL: case EV_KEY: case EV_MSC: case EV_SW: @@ -2045,7 +2046,10 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev, features->device_type |= WACOM_DEVICETYPE_PAD; break; case WACOM_HID_WD_TOUCHRING: - wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0); + if (field->flags & HID_MAIN_ITEM_RELATIVE) + wacom_map_usage(input, usage, field, EV_REL, REL_WHEEL, 0); + else + wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0); features->device_type |= WACOM_DEVICETYPE_PAD; break; case WACOM_HID_WD_TOUCHRINGSTATUS: @@ -2110,7 +2114,10 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field return; if (wacom_equivalent_usage(field->physical) == HID_DG_TABLETFUNCTIONKEY) { - if (usage->hid != WACOM_HID_WD_TOUCHRING) + bool is_abs_touchring = usage->hid == WACOM_HID_WD_TOUCHRING && + !(field->flags & HID_MAIN_ITEM_RELATIVE); + + if (!is_abs_touchring) wacom_wac->hid_data.inrange_state |= value; } @@ -2163,6 +2170,15 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field hdev->product == 0x3AA) value = wacom_offset_rotation(input, usage, value, 1, 2); } + else if (field->flags & HID_MAIN_ITEM_RELATIVE) { + /* We must invert the sign for vertical + * relative scrolling. Clockwise rotation + * produces positive values from HW, but + * userspace treats positive REL_WHEEL as a + * scroll *up*! + */ + value = -value; + } else { value = wacom_offset_rotation(input, usage, value, 1, 4); } From 7ca234e3ae457f6941601d58db22736cd133ef4c Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Tue, 30 Jul 2024 08:51:58 -0700 Subject: [PATCH 05/54] HID: wacom: Add preliminary support for high-resolution wheel scrolling Modern userspace (i.e. libinput) will make use of high-resolution scrolling if supported. Hardware does not currently set a resolution multiplier needed for effective high-res scrolling, but we can still write code to support it in the future. Signed-off-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 24 ++++++++++++++++++++---- drivers/hid/wacom_wac.h | 1 + 2 files changed, 21 insertions(+), 4 deletions(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 798c26ddaeba..9e9cfc55b47b 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2046,10 +2046,12 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev, features->device_type |= WACOM_DEVICETYPE_PAD; break; case WACOM_HID_WD_TOUCHRING: - if (field->flags & HID_MAIN_ITEM_RELATIVE) - wacom_map_usage(input, usage, field, EV_REL, REL_WHEEL, 0); - else + if (field->flags & HID_MAIN_ITEM_RELATIVE) { + wacom_map_usage(input, usage, field, EV_REL, REL_WHEEL_HI_RES, 0); + set_bit(REL_WHEEL, input->relbit); + } else { wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0); + } features->device_type |= WACOM_DEVICETYPE_PAD; break; case WACOM_HID_WD_TOUCHRINGSTATUS: @@ -2177,7 +2179,21 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field * userspace treats positive REL_WHEEL as a * scroll *up*! */ - value = -value; + int hires_value = -value * 120 / usage->resolution_multiplier; + int *ring_value = &wacom_wac->hid_data.ring_value; + + value = hires_value; + *ring_value += hires_value; + + /* Emulate a legacy wheel click for every 120 + * units of hi-res travel. + */ + if (*ring_value >= 120 || *ring_value <= -120) { + int clicks = *ring_value / 120; + + input_event(input, usage->type, REL_WHEEL, clicks); + *ring_value -= clicks * 120; + } } else { value = wacom_offset_rotation(input, usage, value, 1, 4); diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 6ec499841f70..aeba2f3082f0 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -312,6 +312,7 @@ struct hid_data { int width; int height; int id; + int ring_value; int cc_report; int cc_index; int cc_value_index; From 19591e1a8a2e9e8ff53cc3121e6650bbf02f8403 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Tue, 30 Jul 2024 08:51:59 -0700 Subject: [PATCH 06/54] HID: wacom: Support devices with two touchrings If a device has more than one touchring, we want to be sure that userspace is able to distinguish them. Following previous standards, the first absolute ring will be reported as ABS_WHEEL and the second as ABS_THROTTLE. Relative rings will use REL_WHEEL_HI_RES / REL_WHEEL for the first and REL_HWHEEL_HI_RES / REL_HWHEEL for the second. Signed-off-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 58 ++++++++++++++++++++++++++++++++--------- drivers/hid/wacom_wac.h | 3 +++ 2 files changed, 49 insertions(+), 12 deletions(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 9e9cfc55b47b..36010c515f39 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2047,10 +2047,21 @@ static void wacom_wac_pad_usage_mapping(struct hid_device *hdev, break; case WACOM_HID_WD_TOUCHRING: if (field->flags & HID_MAIN_ITEM_RELATIVE) { - wacom_map_usage(input, usage, field, EV_REL, REL_WHEEL_HI_RES, 0); - set_bit(REL_WHEEL, input->relbit); + wacom_wac->relring_count++; + if (wacom_wac->relring_count == 1) { + wacom_map_usage(input, usage, field, EV_REL, REL_WHEEL_HI_RES, 0); + set_bit(REL_WHEEL, input->relbit); + } + else if (wacom_wac->relring_count == 2) { + wacom_map_usage(input, usage, field, EV_REL, REL_HWHEEL_HI_RES, 0); + set_bit(REL_HWHEEL, input->relbit); + } } else { - wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0); + wacom_wac->absring_count++; + if (wacom_wac->absring_count == 1) + wacom_map_usage(input, usage, field, EV_ABS, ABS_WHEEL, 0); + else if (wacom_wac->absring_count == 2) + wacom_map_usage(input, usage, field, EV_ABS, ABS_THROTTLE, 0); } features->device_type |= WACOM_DEVICETYPE_PAD; break; @@ -2173,14 +2184,37 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field value = wacom_offset_rotation(input, usage, value, 1, 2); } else if (field->flags & HID_MAIN_ITEM_RELATIVE) { - /* We must invert the sign for vertical - * relative scrolling. Clockwise rotation - * produces positive values from HW, but - * userspace treats positive REL_WHEEL as a - * scroll *up*! - */ - int hires_value = -value * 120 / usage->resolution_multiplier; - int *ring_value = &wacom_wac->hid_data.ring_value; + int hires_value = value * 120 / usage->resolution_multiplier; + int *ring_value; + int lowres_code; + + if (usage->code == REL_WHEEL_HI_RES) { + /* We must invert the sign for vertical + * relative scrolling. Clockwise + * rotation produces positive values + * from HW, but userspace treats + * positive REL_WHEEL as a scroll *up*! + */ + hires_value = -hires_value; + ring_value = &wacom_wac->hid_data.ring_value; + lowres_code = REL_WHEEL; + } + else if (usage->code == REL_HWHEEL_HI_RES) { + /* No need to invert the sign for + * horizontal relative scrolling. + * Clockwise rotation produces positive + * values from HW and userspace treats + * positive REL_HWHEEL as a scroll + * right. + */ + ring_value = &wacom_wac->hid_data.ring2_value; + lowres_code = REL_HWHEEL; + } + else { + hid_err(wacom->hdev, "unrecognized relative wheel with code %d\n", + usage->code); + break; + } value = hires_value; *ring_value += hires_value; @@ -2191,7 +2225,7 @@ static void wacom_wac_pad_event(struct hid_device *hdev, struct hid_field *field if (*ring_value >= 120 || *ring_value <= -120) { int clicks = *ring_value / 120; - input_event(input, usage->type, REL_WHEEL, clicks); + input_event(input, usage->type, lowres_code, clicks); *ring_value -= clicks * 120; } } diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index aeba2f3082f0..55e0c7a9fdcb 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -313,6 +313,7 @@ struct hid_data { int height; int id; int ring_value; + int ring2_value; int cc_report; int cc_index; int cc_value_index; @@ -356,6 +357,8 @@ struct wacom_wac { int num_contacts_left; u8 bt_features; u8 bt_high_speed; + u8 absring_count; + u8 relring_count; int mode_report; int mode_value; struct hid_data hid_data; From bcc31692a1d1e21f0d06c5f727c03ee299d2264e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 5 Aug 2024 16:51:47 +0200 Subject: [PATCH 07/54] HID: Ignore battery for all ELAN I2C-HID devices Before this change there were 16 vid:pid based quirks to ignore the battery reported by Elan I2C-HID touchscreens on various Asus and HP laptops. And a report has been received that the 04F3:2A00 I2C touchscreen on the HP ProBook x360 11 G5 EE/86CF also reports a non present battery. Since I2C-HID devices are always builtin to laptops they are not battery owered so it should be safe to just ignore the battery on all Elan I2C-HID devices, rather then adding a 17th quirk for the 04F3:2A00 touchscreen. As reported in the changelog of commit a3a5a37efba1 ("HID: Ignore battery for ELAN touchscreens 2F2C and 4116"), which added 2 new Elan touchscreen quirks about a month ago, the HID reported battery seems to be related to a stylus being used. But even when a stylus is in use it does not properly report the charge of the stylus battery, instead the reported battery charge jumps from 0% to 1%. So it is best to just ignore the HID battery. Closes: https://bugzilla.redhat.com/show_bug.cgi?id=2302776 Cc: Louis Dalibard Signed-off-by: Hans de Goede Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 16 ---------------- drivers/hid/hid-input.c | 37 +++++-------------------------------- 2 files changed, 5 insertions(+), 48 deletions(-) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 72d56ee7ce1b..72936a523c54 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -416,24 +416,8 @@ #define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401 #define USB_DEVICE_ID_HP_X2 0x074d #define USB_DEVICE_ID_HP_X2_10_COVER 0x0755 -#define I2C_DEVICE_ID_HP_ENVY_X360_15 0x2d05 -#define I2C_DEVICE_ID_HP_ENVY_X360_15T_DR100 0x29CF -#define I2C_DEVICE_ID_HP_ENVY_X360_EU0009NV 0x2CF9 -#define I2C_DEVICE_ID_HP_SPECTRE_X360_15 0x2817 -#define I2C_DEVICE_ID_HP_SPECTRE_X360_13_AW0020NG 0x29DF -#define I2C_DEVICE_ID_ASUS_TP420IA_TOUCHSCREEN 0x2BC8 -#define I2C_DEVICE_ID_ASUS_GV301RA_TOUCHSCREEN 0x2C82 -#define I2C_DEVICE_ID_ASUS_UX3402_TOUCHSCREEN 0x2F2C -#define I2C_DEVICE_ID_ASUS_UX6404_TOUCHSCREEN 0x4116 #define USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN 0x2544 #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706 -#define I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN 0x261A -#define I2C_DEVICE_ID_SURFACE_GO2_TOUCHSCREEN 0x2A1C -#define I2C_DEVICE_ID_LENOVO_YOGA_C630_TOUCHSCREEN 0x279F -#define I2C_DEVICE_ID_HP_SPECTRE_X360_13T_AW100 0x29F5 -#define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V1 0x2BED -#define I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V2 0x2BEE -#define I2C_DEVICE_ID_HP_ENVY_X360_15_EU0556NG 0x2D02 #define I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM 0x2F81 #define USB_VENDOR_ID_ELECOM 0x056e diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index c9094a4f281e..fda9dce3da99 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -373,14 +373,6 @@ static const struct hid_device_id hid_battery_quirks[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DINOVO_EDGE_KBD), HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_ASUS_TP420IA_TOUCHSCREEN), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_ASUS_GV301RA_TOUCHSCREEN), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_ASUS_UX3402_TOUCHSCREEN), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_ASUS_UX6404_TOUCHSCREEN), - HID_BATTERY_QUIRK_IGNORE }, { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN), HID_BATTERY_QUIRK_IGNORE }, { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN), @@ -391,32 +383,13 @@ static const struct hid_device_id hid_battery_quirks[] = { HID_BATTERY_QUIRK_AVOID_QUERY }, { HID_USB_DEVICE(USB_VENDOR_ID_UGEE, USB_DEVICE_ID_UGEE_XPPEN_TABLET_DECO_PRO_SW), HID_BATTERY_QUIRK_AVOID_QUERY }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15T_DR100), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_EU0009NV), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_15), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_13_AW0020NG), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO2_TOUCHSCREEN), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_LENOVO_YOGA_C630_TOUCHSCREEN), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_13T_AW100), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V1), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_14T_EA100_V2), - HID_BATTERY_QUIRK_IGNORE }, - { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_ENVY_X360_15_EU0556NG), - HID_BATTERY_QUIRK_IGNORE }, { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_CHROMEBOOK_TROGDOR_POMPOM), HID_BATTERY_QUIRK_AVOID_QUERY }, + /* + * Elan I2C-HID touchscreens seem to all report a non present battery, + * set HID_BATTERY_QUIRK_IGNORE for all Elan I2C-HID devices. + */ + { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, HID_ANY_ID), HID_BATTERY_QUIRK_IGNORE }, {} }; From c61f9a8388ee8a5d75b71476c01c165af75e4f3a Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Wed, 31 Jul 2024 18:31:22 +0800 Subject: [PATCH 08/54] HID: intel-ish-hid: Remove unused declarations Commit 3703f53b99e4 ("HID: intel_ish-hid: ISH Transport layer") declared ishtp_remove_all_clients()/ishtp_can_client_connect() but never implemented them. Signed-off-by: Yue Haibing Acked-by: Srinivas Pandruvada Signed-off-by: Jiri Kosina --- drivers/hid/intel-ish-hid/ishtp/bus.h | 1 - drivers/hid/intel-ish-hid/ishtp/client.h | 1 - 2 files changed, 2 deletions(-) diff --git a/drivers/hid/intel-ish-hid/ishtp/bus.h b/drivers/hid/intel-ish-hid/ishtp/bus.h index 5bb85c932e4c..53645ac89ee8 100644 --- a/drivers/hid/intel-ish-hid/ishtp/bus.h +++ b/drivers/hid/intel-ish-hid/ishtp/bus.h @@ -46,7 +46,6 @@ struct ishtp_cl_device { }; int ishtp_bus_new_client(struct ishtp_device *dev); -void ishtp_remove_all_clients(struct ishtp_device *dev); int ishtp_cl_device_bind(struct ishtp_cl *cl); void ishtp_cl_bus_rx_event(struct ishtp_cl_device *device); diff --git a/drivers/hid/intel-ish-hid/ishtp/client.h b/drivers/hid/intel-ish-hid/ishtp/client.h index fc62dd1495da..d9d398fadcf7 100644 --- a/drivers/hid/intel-ish-hid/ishtp/client.h +++ b/drivers/hid/intel-ish-hid/ishtp/client.h @@ -109,7 +109,6 @@ struct ishtp_cl { }; /* Client connection managenment internal functions */ -int ishtp_can_client_connect(struct ishtp_device *ishtp_dev, guid_t *uuid); int ishtp_fw_cl_by_id(struct ishtp_device *dev, uint8_t client_id); void ishtp_cl_send_msg(struct ishtp_device *dev, struct ishtp_cl *cl); void recv_ishtp_cl_msg(struct ishtp_device *dev, From a9ed31f18e08bf24fce9e4484d9da5712d4980d1 Mon Sep 17 00:00:00 2001 From: Yue Haibing Date: Wed, 31 Jul 2024 18:35:45 +0800 Subject: [PATCH 09/54] HID: amd_sfh: Remove unused declarations Commit 4b2c53d93a4b ("SFH:Transport Driver to add support of AMD Sensor Fusion Hub (SFH)") declared but never implemented them. Signed-off-by: Yue Haibing Acked-by: Basavaraj Natikar Signed-off-by: Jiri Kosina --- drivers/hid/amd-sfh-hid/amd_sfh_hid.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_hid.h b/drivers/hid/amd-sfh-hid/amd_sfh_hid.h index 97296f587bc7..1c91be8daedd 100644 --- a/drivers/hid/amd-sfh-hid/amd_sfh_hid.h +++ b/drivers/hid/amd-sfh-hid/amd_sfh_hid.h @@ -73,8 +73,6 @@ struct amdtp_hid_data { }; /* Interface functions between HID LL driver and AMD SFH client */ -void hid_amdtp_set_feature(struct hid_device *hid, char *buf, u32 len, int report_id); -void hid_amdtp_get_report(struct hid_device *hid, int report_id, int report_type); int amdtp_hid_probe(u32 cur_hid_dev, struct amdtp_cl_data *cli_data); void amdtp_hid_remove(struct amdtp_cl_data *cli_data); int amd_sfh_get_report(struct hid_device *hid, int report_id, int report_type); From 87de1615194eeb43b14cf5355ede3bd2115e0ff4 Mon Sep 17 00:00:00 2001 From: Zhang Lixu Date: Thu, 15 Aug 2024 10:09:59 +0800 Subject: [PATCH 10/54] Documentation: hid: intel-ish-hid: Add vendor custom firmware loading Add ISH firmware loading guidelines for vendor custom firmware. Signed-off-by: Zhang Lixu Acked-by: Srinivas Pandruvada Signed-off-by: Jiri Kosina --- Documentation/hid/intel-ish-hid.rst | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/Documentation/hid/intel-ish-hid.rst b/Documentation/hid/intel-ish-hid.rst index 55cbaa719a79..2adc174fb576 100644 --- a/Documentation/hid/intel-ish-hid.rst +++ b/Documentation/hid/intel-ish-hid.rst @@ -404,6 +404,35 @@ For more detailed information, please refer to the flow descriptions provided be | ISHTP Driver | | ISH Bootloader | +---------------+ +-----------------+ +Vendor Custom Firmware Loading +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The firmware running inside ISH can be provided by Intel or developed by vendors using the Firmware Development Kit (FDK) provided by Intel. +Intel will upstream the Intel-built firmware to the ``linux-firmware.git`` repository, located under the path ``intel/ish/``. For the Lunar Lake platform, the Intel-built ISH firmware will be named ``ish_lnlm.bin``. +Vendors who wish to upstream their custom firmware should follow these guidelines for naming their firmware files: + +- The firmware filename should use one of the following patterns: + + - ``ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_NAME_CRC32}_${PRODUCT_SKU_CRC32}.bin`` + - ``ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_SKU_CRC32}.bin`` + - ``ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_NAME_CRC32}.bin`` + - ``ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}.bin`` + +- ``${intel_plat_gen}`` indicates the Intel platform generation (e.g., ``lnlm`` for Lunar Lake) and must not exceed 8 characters in length. +- ``${SYS_VENDOR_CRC32}`` is the CRC32 checksum of the ``sys_vendor`` value from the DMI field ``DMI_SYS_VENDOR``. +- ``${PRODUCT_NAME_CRC32}`` is the CRC32 checksum of the ``product_name`` value from the DMI field ``DMI_PRODUCT_NAME``. +- ``${PRODUCT_SKU_CRC32}`` is the CRC32 checksum of the ``product_sku`` value from the DMI field ``DMI_PRODUCT_SKU``. + +During system boot, the ISH Linux driver will attempt to load the firmware in the following order, prioritizing custom firmware with more precise matching patterns: + +1. ``intel/ish/ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_NAME_CRC32}_${PRODUCT_SKU_CRC32}.bin`` +2. ``intel/ish/ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_SKU_CRC32}.bin`` +3. ``intel/ish/ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}_${PRODUCT_NAME_CRC32}.bin`` +4. ``intel/ish/ish_${intel_plat_gen}_${SYS_VENDOR_CRC32}.bin`` +5. ``intel/ish/ish_${intel_plat_gen}.bin`` + +The driver will load the first matching firmware and skip the rest. If no matching firmware is found, it will proceed to the next pattern in the specified order. If all searches fail, the default Intel firmware, listed last in the order above, will be loaded. + ISH Debugging ------------- From 641361538b68de29d97cc7bf535e50176dbdcfbf Mon Sep 17 00:00:00 2001 From: Zhang Lixu Date: Thu, 15 Aug 2024 10:10:00 +0800 Subject: [PATCH 11/54] HID: intel-ish-hid: Use CPU generation string in driver_data ISH allows vendors to customize ISH firmware. To differentiate different vendors and load the correct firmware, Intel defined a firmware file name format. As part of the filename, there is a "generation" string. To load correct format the driver must know the generation name to create file name. In the absence of any vendor specific firmware, default ISH firmware is loaded. Currently full ISH firmware file name is stored as part of driver data. This file name already includes the generation name. For example, for Lunar Lake, the name is ish_lnlm.bin, where "lnlm" is the generation. So instead of storing both generation name and ISH default firmware file name, just store generation name and create the default ISH firmware file name string during initialization. No functional changes are expected. Signed-off-by: Zhang Lixu Acked-by: Srinivas Pandruvada Signed-off-by: Jiri Kosina --- drivers/hid/intel-ish-hid/ipc/pci-ish.c | 8 ++++--- drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h | 8 ++++--- drivers/hid/intel-ish-hid/ishtp/loader.c | 23 ++++++++++++++++++--- 3 files changed, 30 insertions(+), 9 deletions(-) diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c index f82428d7f6c3..f20463082dc4 100644 --- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c +++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c @@ -28,11 +28,13 @@ enum ishtp_driver_data_index { ISHTP_DRIVER_DATA_LNL_M, }; -#define ISH_FW_FILENAME_LNL_M "intel/ish/ish_lnlm.bin" +#define ISH_FW_GEN_LNL_M "lnlm" + +#define ISH_FIRMWARE_PATH(gen) "intel/ish/ish_" gen ".bin" static struct ishtp_driver_data ishtp_driver_data[] = { [ISHTP_DRIVER_DATA_LNL_M] = { - .fw_filename = ISH_FW_FILENAME_LNL_M, + .fw_generation = ISH_FW_GEN_LNL_M, }, }; @@ -397,4 +399,4 @@ MODULE_AUTHOR("Srinivas Pandruvada "); MODULE_DESCRIPTION("Intel(R) Integrated Sensor Hub PCI Device Driver"); MODULE_LICENSE("GPL"); -MODULE_FIRMWARE(ISH_FW_FILENAME_LNL_M); +MODULE_FIRMWARE(ISH_FIRMWARE_PATH(ISH_FW_GEN_LNL_M)); diff --git a/drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h b/drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h index 181838c3d7ac..cdacce0a4c9d 100644 --- a/drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h +++ b/drivers/hid/intel-ish-hid/ishtp/ishtp-dev.h @@ -129,13 +129,15 @@ struct ishtp_hw_ops { * ISHTP device instance. It allows for the storage of data that is unique to * a particular driver or hardware variant. * - * @fw_filename: The firmware filename associated with a specific hardware + * @fw_generation: The generation name associated with a specific hardware * variant of the Intel Integrated Sensor Hub (ISH). This allows * the driver to load the correct firmware based on the device's - * hardware variant. + * hardware variant. For example, "lnlm" for the Lunar Lake-M + * platform. The generation name must not exceed 8 characters + * in length. */ struct ishtp_driver_data { - char *fw_filename; + char *fw_generation; }; /** diff --git a/drivers/hid/intel-ish-hid/ishtp/loader.c b/drivers/hid/intel-ish-hid/ishtp/loader.c index fcca070bdecb..ff11ee4e38ed 100644 --- a/drivers/hid/intel-ish-hid/ishtp/loader.c +++ b/drivers/hid/intel-ish-hid/ishtp/loader.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -192,6 +193,23 @@ static int prepare_dma_bufs(struct ishtp_device *dev, return 0; } +#define ISH_FW_FILE_DEFAULT_FMT "intel/ish/ish_%s.bin" + +#define ISH_FW_FILENAME_LEN_MAX 56 + +static int request_ish_firmware(const struct firmware **firmware_p, + struct device *dev) +{ + struct ishtp_device *ishtp = dev_get_drvdata(dev); + const char *gen; + char filename[ISH_FW_FILENAME_LEN_MAX]; + + gen = ishtp->driver_data->fw_generation; + snprintf(filename, sizeof(filename), ISH_FW_FILE_DEFAULT_FMT, gen); + + return request_firmware(firmware_p, filename, dev); +} + /** * ishtp_loader_work() - Load the ISHTP firmware * @work: The work structure @@ -220,7 +238,6 @@ void ishtp_loader_work(struct work_struct *work) struct loader_xfer_query query = { .header = cpu_to_le32(query_hdr.val32), }; struct loader_start start = { .header = cpu_to_le32(start_hdr.val32), }; union loader_recv_message recv_msg; - char *filename = dev->driver_data->fw_filename; const struct firmware *ish_fw; void *dma_bufs[FRAGMENT_MAX_NUM] = {}; u32 fragment_size; @@ -228,9 +245,9 @@ void ishtp_loader_work(struct work_struct *work) int retry = ISHTP_LOADER_RETRY_TIMES; int rv; - rv = request_firmware(&ish_fw, filename, dev->devc); + rv = request_ish_firmware(&ish_fw, dev->devc); if (rv < 0) { - dev_err(dev->devc, "request firmware %s failed:%d\n", filename, rv); + dev_err(dev->devc, "request ISH firmware failed:%d\n", rv); return; } From aa4674c525e1e9a27f77e29fa71a4a5779a52ee4 Mon Sep 17 00:00:00 2001 From: Zhang Lixu Date: Thu, 15 Aug 2024 10:10:01 +0800 Subject: [PATCH 12/54] hid: intel-ish-hid: Add support for vendor customized firmware loading Enhance the firmware loader to support the loading of vendor-specific customized firmware for the Intel Integrated Sensor Hub (ISH). The loader now constructs firmware file names based on the DMI_SYS_VENDOR, DMI_PRODUCT_NAME, and DMI_PRODUCT_SKU information in Desktop Management Interface (DMI). The loader will attempt to load the firmware files following a specific naming convention in sequence. If successful, it will skip the remaining files. For more details, please refer to Documentation/hid/intel-ish-hid.rst. Signed-off-by: Zhang Lixu Acked-by: Srinivas Pandruvada Signed-off-by: Jiri Kosina --- drivers/hid/intel-ish-hid/ipc/pci-ish.c | 2 + drivers/hid/intel-ish-hid/ishtp/loader.c | 104 ++++++++++++++++++++++- 2 files changed, 103 insertions(+), 3 deletions(-) diff --git a/drivers/hid/intel-ish-hid/ipc/pci-ish.c b/drivers/hid/intel-ish-hid/ipc/pci-ish.c index f20463082dc4..aae0d965b47b 100644 --- a/drivers/hid/intel-ish-hid/ipc/pci-ish.c +++ b/drivers/hid/intel-ish-hid/ipc/pci-ish.c @@ -31,6 +31,7 @@ enum ishtp_driver_data_index { #define ISH_FW_GEN_LNL_M "lnlm" #define ISH_FIRMWARE_PATH(gen) "intel/ish/ish_" gen ".bin" +#define ISH_FIRMWARE_PATH_ALL "intel/ish/ish_*.bin" static struct ishtp_driver_data ishtp_driver_data[] = { [ISHTP_DRIVER_DATA_LNL_M] = { @@ -400,3 +401,4 @@ MODULE_DESCRIPTION("Intel(R) Integrated Sensor Hub PCI Device Driver"); MODULE_LICENSE("GPL"); MODULE_FIRMWARE(ISH_FIRMWARE_PATH(ISH_FW_GEN_LNL_M)); +MODULE_FIRMWARE(ISH_FIRMWARE_PATH_ALL); diff --git a/drivers/hid/intel-ish-hid/ishtp/loader.c b/drivers/hid/intel-ish-hid/ishtp/loader.c index ff11ee4e38ed..f76c4437a1f5 100644 --- a/drivers/hid/intel-ish-hid/ishtp/loader.c +++ b/drivers/hid/intel-ish-hid/ishtp/loader.c @@ -35,8 +35,10 @@ #include #include +#include #include #include +#include #include #include #include @@ -193,21 +195,117 @@ static int prepare_dma_bufs(struct ishtp_device *dev, return 0; } +#define ISH_FW_FILE_VENDOR_NAME_SKU_FMT "intel/ish/ish_%s_%08x_%08x_%08x.bin" +#define ISH_FW_FILE_VENDOR_SKU_FMT "intel/ish/ish_%s_%08x_%08x.bin" +#define ISH_FW_FILE_VENDOR_NAME_FMT "intel/ish/ish_%s_%08x_%08x.bin" +#define ISH_FW_FILE_VENDOR_FMT "intel/ish/ish_%s_%08x.bin" #define ISH_FW_FILE_DEFAULT_FMT "intel/ish/ish_%s.bin" #define ISH_FW_FILENAME_LEN_MAX 56 +#define ISH_CRC_INIT (~0u) +#define ISH_CRC_XOROUT (~0u) + +static int _request_ish_firmware(const struct firmware **firmware_p, + const char *name, struct device *dev) +{ + int ret; + + dev_dbg(dev, "Try to load firmware: %s\n", name); + ret = firmware_request_nowarn(firmware_p, name, dev); + if (!ret) + dev_info(dev, "load firmware: %s\n", name); + + return ret; +} + +/** + * request_ish_firmware() - Request and load the ISH firmware. + * @firmware_p: Pointer to the firmware image. + * @dev: Device for which firmware is being requested. + * + * This function attempts to load the Integrated Sensor Hub (ISH) firmware + * for the given device in the following order, prioritizing custom firmware + * with more precise matching patterns: + * + * ish_${fw_generation}_${SYS_VENDOR_CRC32}_$(PRODUCT_NAME_CRC32)_${PRODUCT_SKU_CRC32}.bin + * ish_${fw_generation}_${SYS_VENDOR_CRC32}_${PRODUCT_SKU_CRC32}.bin + * ish_${fw_generation}_${SYS_VENDOR_CRC32}_$(PRODUCT_NAME_CRC32).bin + * ish_${fw_generation}_${SYS_VENDOR_CRC32}.bin + * ish_${fw_generation}.bin + * + * The driver will load the first matching firmware and skip the rest. If no + * matching firmware is found, it will proceed to the next pattern in the + * specified order. If all searches fail, the default Intel firmware, listed + * last in the order above, will be loaded. + * + * The firmware file name is constructed using CRC32 checksums of strings. + * This is done to create a valid file name that does not contain spaces + * or special characters which may be present in the original strings. + * + * The CRC-32 algorithm uses the following parameters: + * Poly: 0x04C11DB7 + * Init: 0xFFFFFFFF + * RefIn: true + * RefOut: true + * XorOut: 0xFFFFFFFF + * + * Return: 0 on success, negative error code on failure. + */ static int request_ish_firmware(const struct firmware **firmware_p, struct device *dev) { + const char *gen, *sys_vendor, *product_name, *product_sku; struct ishtp_device *ishtp = dev_get_drvdata(dev); - const char *gen; + u32 vendor_crc, name_crc, sku_crc; char filename[ISH_FW_FILENAME_LEN_MAX]; + int ret; gen = ishtp->driver_data->fw_generation; - snprintf(filename, sizeof(filename), ISH_FW_FILE_DEFAULT_FMT, gen); + sys_vendor = dmi_get_system_info(DMI_SYS_VENDOR); + product_name = dmi_get_system_info(DMI_PRODUCT_NAME); + product_sku = dmi_get_system_info(DMI_PRODUCT_SKU); - return request_firmware(firmware_p, filename, dev); + if (sys_vendor) + vendor_crc = crc32(ISH_CRC_INIT, sys_vendor, strlen(sys_vendor)) ^ ISH_CRC_XOROUT; + if (product_name) + name_crc = crc32(ISH_CRC_INIT, product_name, strlen(product_name)) ^ ISH_CRC_XOROUT; + if (product_sku) + sku_crc = crc32(ISH_CRC_INIT, product_sku, strlen(product_sku)) ^ ISH_CRC_XOROUT; + + if (sys_vendor && product_name && product_sku) { + snprintf(filename, sizeof(filename), ISH_FW_FILE_VENDOR_NAME_SKU_FMT, gen, + vendor_crc, name_crc, sku_crc); + ret = _request_ish_firmware(firmware_p, filename, dev); + if (!ret) + return 0; + } + + if (sys_vendor && product_sku) { + snprintf(filename, sizeof(filename), ISH_FW_FILE_VENDOR_SKU_FMT, gen, vendor_crc, + sku_crc); + ret = _request_ish_firmware(firmware_p, filename, dev); + if (!ret) + return 0; + } + + if (sys_vendor && product_name) { + snprintf(filename, sizeof(filename), ISH_FW_FILE_VENDOR_NAME_FMT, gen, vendor_crc, + name_crc); + ret = _request_ish_firmware(firmware_p, filename, dev); + if (!ret) + return 0; + } + + if (sys_vendor) { + snprintf(filename, sizeof(filename), ISH_FW_FILE_VENDOR_FMT, gen, vendor_crc); + ret = _request_ish_firmware(firmware_p, filename, dev); + if (!ret) + return 0; + } + + snprintf(filename, sizeof(filename), ISH_FW_FILE_DEFAULT_FMT, gen); + return _request_ish_firmware(firmware_p, filename, dev); } /** From 75e16c8ce283bb88e77704dc8fa041c577caac0f Mon Sep 17 00:00:00 2001 From: Charles Wang Date: Wed, 14 Aug 2024 10:45:12 +0800 Subject: [PATCH 13/54] HID: hid-goodix: Add Goodix HID-over-SPI driver This patch introduces a new driver to support the Goodix GT7986U touch controller. This device is not compatible with Microsoft's HID-over-SPI protocol and therefore needs to implement its own flavor. The data reported is packaged according to the HID protocol but uses SPI for communication to improve speed. This enables the device to transmit not only coordinate data but also corresponding raw data that can be accessed by user-space programs through the hidraw interface. The raw data can be utilized for functions like palm rejection, thereby improving the touch experience. Key features: - Device connection confirmation and initialization - IRQ-based event reporting to the input subsystem - Support for HIDRAW operations (GET_REPORT and SET_REPORT) Reviewed-by: Dmitry Torokhov Signed-off-by: Charles Wang Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 6 + drivers/hid/Makefile | 1 + drivers/hid/hid-goodix-spi.c | 810 +++++++++++++++++++++++++++++++++++ 3 files changed, 817 insertions(+) create mode 100644 drivers/hid/hid-goodix-spi.c diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 08446c89eff6..f8a56d631242 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -404,6 +404,12 @@ config HID_VIVALDI_COMMON option so that drivers can use common code to parse the HID descriptors for vivaldi function row keymap. +config HID_GOODIX_SPI + tristate "Goodix GT7986U SPI HID touchscreen" + depends on SPI_MASTER + help + Support for Goodix GT7986U SPI HID touchscreen device. + config HID_GOOGLE_HAMMER tristate "Google Hammer Keyboard" select HID_VIVALDI_COMMON diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index e40f1ddebbb7..496dab54c73a 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -54,6 +54,7 @@ obj-$(CONFIG_HID_GEMBIRD) += hid-gembird.o obj-$(CONFIG_HID_GFRM) += hid-gfrm.o obj-$(CONFIG_HID_GLORIOUS) += hid-glorious.o obj-$(CONFIG_HID_VIVALDI_COMMON) += hid-vivaldi-common.o +obj-$(CONFIG_HID_GOODIX_SPI) += hid-goodix-spi.o obj-$(CONFIG_HID_GOOGLE_HAMMER) += hid-google-hammer.o obj-$(CONFIG_HID_GOOGLE_STADIA_FF) += hid-google-stadiaff.o obj-$(CONFIG_HID_VIVALDI) += hid-vivaldi.o diff --git a/drivers/hid/hid-goodix-spi.c b/drivers/hid/hid-goodix-spi.c new file mode 100644 index 000000000000..5103bf0aada4 --- /dev/null +++ b/drivers/hid/hid-goodix-spi.c @@ -0,0 +1,810 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Goodix GT7986U SPI Driver Code for HID. + * + * Copyright (C) 2024 Godix, Inc. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define GOODIX_DEV_CONFIRM_ADDR 0x10000 +#define GOODIX_HID_DESC_ADDR 0x1058C +#define GOODIX_HID_REPORT_DESC_ADDR 0x105AA +#define GOODIX_HID_SIGN_ADDR 0x10D32 + +#define GOODIX_HID_GET_REPORT_CMD 0x02 +#define GOODIX_HID_SET_REPORT_CMD 0x03 + +#define GOODIX_HID_MAX_INBUF_SIZE 128 +#define GOODIX_HID_ACK_READY_FLAG 0x01 +#define GOODIX_HID_REPORT_READY_FLAG 0x80 + +#define GOODIX_DEV_CONFIRM_VAL 0xAA + +#define GOODIX_SPI_WRITE_FLAG 0xF0 +#define GOODIX_SPI_READ_FLAG 0xF1 +#define GOODIX_SPI_TRANS_PREFIX_LEN 1 +#define GOODIX_REGISTER_WIDTH 4 +#define GOODIX_SPI_READ_DUMMY_LEN 3 +#define GOODIX_SPI_READ_PREFIX_LEN (GOODIX_SPI_TRANS_PREFIX_LEN + \ + GOODIX_REGISTER_WIDTH + \ + GOODIX_SPI_READ_DUMMY_LEN) +#define GOODIX_SPI_WRITE_PREFIX_LEN (GOODIX_SPI_TRANS_PREFIX_LEN + \ + GOODIX_REGISTER_WIDTH) + +#define GOODIX_CHECKSUM_SIZE sizeof(u16) +#define GOODIX_NORMAL_RESET_DELAY_MS 150 + +struct goodix_hid_report_header { + u8 flag; + __le16 size; +} __packed; +#define GOODIX_HID_ACK_HEADER_SIZE sizeof(struct goodix_hid_report_header) + +struct goodix_hid_report_package { + __le16 size; + u8 data[]; +}; + +#define GOODIX_HID_PKG_LEN_SIZE sizeof(u16) +#define GOODIX_HID_COOR_DATA_LEN 82 +#define GOODIX_HID_COOR_PKG_LEN (GOODIX_HID_PKG_LEN_SIZE + \ + GOODIX_HID_COOR_DATA_LEN) + +/* power state */ +#define GOODIX_SPI_POWER_ON 0x00 +#define GOODIX_SPI_POWER_SLEEP 0x01 + +/* flags used to record the current device operating state */ +#define GOODIX_HID_STARTED 0 + +struct goodix_hid_report_event { + struct goodix_hid_report_header hdr; + u8 data[GOODIX_HID_COOR_PKG_LEN]; +} __packed; + +struct goodix_hid_desc { + __le16 desc_length; + __le16 bcd_version; + __le16 report_desc_length; + __le16 report_desc_register; + __le16 input_register; + __le16 max_input_length; + __le16 output_register; + __le16 max_output_length; + __le16 cmd_register; + __le16 data_register; + __le16 vendor_id; + __le16 product_id; + __le16 version_id; + __le32 reserved; +} __packed; + +struct goodix_ts_data { + struct device *dev; + struct spi_device *spi; + struct hid_device *hid; + struct goodix_hid_desc hid_desc; + + struct gpio_desc *reset_gpio; + u32 hid_report_addr; + + unsigned long flags; + /* lock for hid raw request operation */ + struct mutex hid_request_lock; + /* buffer used to store hid report event */ + u8 *event_buf; + u32 hid_max_event_sz; + /* buffer used to do spi data transfer */ + u8 xfer_buf[SZ_2K] ____cacheline_aligned; +}; + +static void *goodix_get_event_report(struct goodix_ts_data *ts, u32 addr, + u8 *data, size_t len) +{ + struct spi_device *spi = to_spi_device(&ts->spi->dev); + struct spi_transfer xfers; + struct spi_message spi_msg; + int error; + + /* buffer format: 0xF1 + addr(4bytes) + dummy(3bytes) + data */ + data[0] = GOODIX_SPI_READ_FLAG; + put_unaligned_be32(addr, data + GOODIX_SPI_TRANS_PREFIX_LEN); + + spi_message_init(&spi_msg); + memset(&xfers, 0, sizeof(xfers)); + xfers.tx_buf = data; + xfers.rx_buf = data; + xfers.len = GOODIX_SPI_READ_PREFIX_LEN + len; + spi_message_add_tail(&xfers, &spi_msg); + + error = spi_sync(spi, &spi_msg); + if (error) { + dev_err(ts->dev, "spi transfer error: %d", error); + return NULL; + } + + return data + GOODIX_SPI_READ_PREFIX_LEN; +} + +static int goodix_spi_read(struct goodix_ts_data *ts, u32 addr, + void *data, size_t len) +{ + struct spi_device *spi = to_spi_device(&ts->spi->dev); + struct spi_transfer xfers; + struct spi_message spi_msg; + int error; + + if (GOODIX_SPI_READ_PREFIX_LEN + len > sizeof(ts->xfer_buf)) { + dev_err(ts->dev, "read data len exceed limit %zu", + sizeof(ts->xfer_buf) - GOODIX_SPI_READ_PREFIX_LEN); + return -EINVAL; + } + + /* buffer format: 0xF1 + addr(4bytes) + dummy(3bytes) + data */ + ts->xfer_buf[0] = GOODIX_SPI_READ_FLAG; + put_unaligned_be32(addr, ts->xfer_buf + GOODIX_SPI_TRANS_PREFIX_LEN); + + spi_message_init(&spi_msg); + memset(&xfers, 0, sizeof(xfers)); + xfers.tx_buf = ts->xfer_buf; + xfers.rx_buf = ts->xfer_buf; + xfers.len = GOODIX_SPI_READ_PREFIX_LEN + len; + spi_message_add_tail(&xfers, &spi_msg); + + error = spi_sync(spi, &spi_msg); + if (error) + dev_err(ts->dev, "spi transfer error: %d", error); + else + memcpy(data, ts->xfer_buf + GOODIX_SPI_READ_PREFIX_LEN, len); + + return error; +} + +static int goodix_spi_write(struct goodix_ts_data *ts, u32 addr, + const void *data, size_t len) +{ + struct spi_device *spi = to_spi_device(&ts->spi->dev); + struct spi_transfer xfers; + struct spi_message spi_msg; + int error; + + if (GOODIX_SPI_WRITE_PREFIX_LEN + len > sizeof(ts->xfer_buf)) { + dev_err(ts->dev, "write data len exceed limit %zu", + sizeof(ts->xfer_buf) - GOODIX_SPI_WRITE_PREFIX_LEN); + return -EINVAL; + } + + /* buffer format: 0xF0 + addr(4bytes) + data */ + ts->xfer_buf[0] = GOODIX_SPI_WRITE_FLAG; + put_unaligned_be32(addr, ts->xfer_buf + GOODIX_SPI_TRANS_PREFIX_LEN); + memcpy(ts->xfer_buf + GOODIX_SPI_WRITE_PREFIX_LEN, data, len); + + spi_message_init(&spi_msg); + memset(&xfers, 0, sizeof(xfers)); + xfers.tx_buf = ts->xfer_buf; + xfers.len = GOODIX_SPI_WRITE_PREFIX_LEN + len; + spi_message_add_tail(&xfers, &spi_msg); + + error = spi_sync(spi, &spi_msg); + if (error) + dev_err(ts->dev, "spi transfer error: %d", error); + + return error; +} + +static int goodix_dev_confirm(struct goodix_ts_data *ts) +{ + u8 tx_buf[8], rx_buf[8]; + int retry = 3; + int error; + + gpiod_set_value_cansleep(ts->reset_gpio, 0); + usleep_range(4000, 4100); + + memset(tx_buf, GOODIX_DEV_CONFIRM_VAL, sizeof(tx_buf)); + while (retry--) { + error = goodix_spi_write(ts, GOODIX_DEV_CONFIRM_ADDR, + tx_buf, sizeof(tx_buf)); + if (error) + return error; + + error = goodix_spi_read(ts, GOODIX_DEV_CONFIRM_ADDR, + rx_buf, sizeof(rx_buf)); + if (error) + return error; + + if (!memcmp(tx_buf, rx_buf, sizeof(tx_buf))) + return 0; + + usleep_range(5000, 5100); + } + + dev_err(ts->dev, "device confirm failed, rx_buf: %*ph", 8, rx_buf); + return -EINVAL; +} + +/** + * goodix_hid_parse() - hid-core .parse() callback + * @hid: hid device instance + * + * This function gets called during call to hid_add_device + * + * Return: 0 on success and non zero on error + */ +static int goodix_hid_parse(struct hid_device *hid) +{ + struct goodix_ts_data *ts = hid->driver_data; + u16 rsize; + int error; + + rsize = le16_to_cpu(ts->hid_desc.report_desc_length); + if (!rsize || rsize > HID_MAX_DESCRIPTOR_SIZE) { + dev_err(ts->dev, "invalid report desc size, %d", rsize); + return -EINVAL; + } + + u8 *rdesc __free(kfree) = kzalloc(rsize, GFP_KERNEL); + if (!rdesc) + return -ENOMEM; + + error = goodix_spi_read(ts, GOODIX_HID_REPORT_DESC_ADDR, rdesc, rsize); + if (error) { + dev_err(ts->dev, "failed get report desc, %d", error); + return error; + } + + error = hid_parse_report(hid, rdesc, rsize); + if (error) { + dev_err(ts->dev, "failed parse report, %d", error); + return error; + } + + return 0; +} + +static int goodix_hid_get_report_length(struct hid_report *report) +{ + return ((report->size - 1) >> 3) + 1 + + report->device->report_enum[report->type].numbered + 2; +} + +static void goodix_hid_find_max_report(struct hid_device *hid, unsigned int type, + unsigned int *max) +{ + struct hid_report *report; + unsigned int size; + + list_for_each_entry(report, &hid->report_enum[type].report_list, list) { + size = goodix_hid_get_report_length(report); + if (*max < size) + *max = size; + } +} + +static int goodix_hid_start(struct hid_device *hid) +{ + struct goodix_ts_data *ts = hid->driver_data; + unsigned int bufsize = GOODIX_HID_COOR_PKG_LEN; + u32 report_size; + + goodix_hid_find_max_report(hid, HID_INPUT_REPORT, &bufsize); + goodix_hid_find_max_report(hid, HID_OUTPUT_REPORT, &bufsize); + goodix_hid_find_max_report(hid, HID_FEATURE_REPORT, &bufsize); + + report_size = GOODIX_SPI_READ_PREFIX_LEN + + GOODIX_HID_ACK_HEADER_SIZE + bufsize; + if (report_size <= ts->hid_max_event_sz) + return 0; + + ts->event_buf = devm_krealloc(ts->dev, ts->event_buf, + report_size, GFP_KERNEL); + if (!ts->event_buf) + return -ENOMEM; + + ts->hid_max_event_sz = report_size; + return 0; +} + +static void goodix_hid_stop(struct hid_device *hid) +{ + hid->claimed = 0; +} + +static int goodix_hid_open(struct hid_device *hid) +{ + struct goodix_ts_data *ts = hid->driver_data; + + set_bit(GOODIX_HID_STARTED, &ts->flags); + return 0; +} + +static void goodix_hid_close(struct hid_device *hid) +{ + struct goodix_ts_data *ts = hid->driver_data; + + clear_bit(GOODIX_HID_STARTED, &ts->flags); +} + +/* Return date length of response data */ +static int goodix_hid_check_ack_status(struct goodix_ts_data *ts) +{ + struct goodix_hid_report_header hdr; + int retry = 20; + int error; + + while (retry--) { + /* + * 3 bytes of hid request response data + * - byte 0: Ack flag, value of 1 for data ready + * - bytes 1-2: Response data length + */ + error = goodix_spi_read(ts, ts->hid_report_addr, + &hdr, sizeof(hdr)); + if (!error && (hdr.flag & GOODIX_HID_ACK_READY_FLAG)) + return le16_to_cpu(hdr.size); + + /* Wait 10ms for another try */ + usleep_range(10000, 11000); + } + + return -EINVAL; +} + +/** + * goodix_hid_get_raw_report() - Process hidraw GET REPORT operation + * @hid: hid device instance + * @reportnum: Report ID + * @buf: Buffer for store the report date + * @len: Length fo report data + * @report_type: Report type + * + * The function for hid_ll_driver.get_raw_report to handle the HIDRAW ioctl + * get report request. The transmitted data follows the standard i2c-hid + * protocol with a specified header. + * + * Return: The length of the data in the buf on success, negative error code + */ +static int goodix_hid_get_raw_report(struct hid_device *hid, + unsigned char reportnum, + u8 *buf, size_t len, + unsigned char report_type) +{ + struct goodix_ts_data *ts = hid->driver_data; + u16 data_register = le16_to_cpu(ts->hid_desc.data_register); + u16 cmd_register = le16_to_cpu(ts->hid_desc.cmd_register); + u8 tmp_buf[GOODIX_HID_MAX_INBUF_SIZE]; + int tx_len = 0, args_len = 0; + int response_data_len; + u8 args[3]; + int error; + + if (report_type == HID_OUTPUT_REPORT) + return -EINVAL; + + if (reportnum == 3) { + /* Get win8 signature data */ + error = goodix_spi_read(ts, GOODIX_HID_SIGN_ADDR, buf, len); + if (error) { + dev_err(ts->dev, "failed get win8 sign: %d", error); + return -EINVAL; + } + return len; + } + + if (reportnum >= 0x0F) + args[args_len++] = reportnum; + + put_unaligned_le16(data_register, args + args_len); + args_len += sizeof(data_register); + + /* Clean 3 bytes of hid ack header data */ + memset(tmp_buf, 0, GOODIX_HID_ACK_HEADER_SIZE); + tx_len += GOODIX_HID_ACK_HEADER_SIZE; + + put_unaligned_le16(cmd_register, tmp_buf + tx_len); + tx_len += sizeof(cmd_register); + + tmp_buf[tx_len] = (report_type == HID_FEATURE_REPORT ? 0x03 : 0x01) << 4; + tmp_buf[tx_len] |= reportnum >= 0x0F ? 0x0F : reportnum; + tx_len++; + + tmp_buf[tx_len++] = GOODIX_HID_GET_REPORT_CMD; + + memcpy(tmp_buf + tx_len, args, args_len); + tx_len += args_len; + + /* Step1: write report request info */ + error = goodix_spi_write(ts, ts->hid_report_addr, tmp_buf, tx_len); + if (error) { + dev_err(ts->dev, "failed send read feature cmd, %d", error); + return error; + } + + /* No need read response data */ + if (!len) + return 0; + + /* Step2: check response data status */ + response_data_len = goodix_hid_check_ack_status(ts); + if (response_data_len <= GOODIX_HID_PKG_LEN_SIZE) + return -EINVAL; + + len = min(len, response_data_len - GOODIX_HID_PKG_LEN_SIZE); + /* Step3: read response data(skip 2bytes of hid pkg length) */ + error = goodix_spi_read(ts, ts->hid_report_addr + + GOODIX_HID_ACK_HEADER_SIZE + + GOODIX_HID_PKG_LEN_SIZE, buf, len); + if (error) { + dev_err(ts->dev, "failed read hid response data, %d", error); + return error; + } + + if (buf[0] != reportnum) { + dev_err(ts->dev, "incorrect report (%d vs %d expected)", + buf[0], reportnum); + return -EINVAL; + } + return len; +} + +/** + * goodix_hid_set_raw_report() - process hidraw SET REPORT operation + * @hid: HID device + * @reportnum: Report ID + * @buf: Buffer for communication + * @len: Length of data in the buffer + * @report_type: Report type + * + * The function for hid_ll_driver.get_raw_report to handle the HIDRAW ioctl + * set report request. The transmitted data follows the standard i2c-hid + * protocol with a specified header. + * + * Return: The length of the data sent, negative error code on failure + */ +static int goodix_hid_set_raw_report(struct hid_device *hid, + unsigned char reportnum, + __u8 *buf, size_t len, + unsigned char report_type) +{ + struct goodix_ts_data *ts = hid->driver_data; + u16 data_register = le16_to_cpu(ts->hid_desc.data_register); + u16 cmd_register = le16_to_cpu(ts->hid_desc.cmd_register); + int tx_len = 0, args_len = 0; + u8 tmp_buf[GOODIX_HID_MAX_INBUF_SIZE]; + u8 args[5]; + int error; + + if (reportnum >= 0x0F) { + args[args_len++] = reportnum; + reportnum = 0x0F; + } + + put_unaligned_le16(data_register, args + args_len); + args_len += sizeof(data_register); + + put_unaligned_le16(GOODIX_HID_PKG_LEN_SIZE + len, args + args_len); + args_len += GOODIX_HID_PKG_LEN_SIZE; + + /* Clean 3 bytes of hid ack header data */ + memset(tmp_buf, 0, GOODIX_HID_ACK_HEADER_SIZE); + tx_len += GOODIX_HID_ACK_HEADER_SIZE; + + put_unaligned_le16(cmd_register, tmp_buf + tx_len); + tx_len += sizeof(cmd_register); + + tmp_buf[tx_len++] = ((report_type == HID_FEATURE_REPORT ? 0x03 : 0x02) << 4) | reportnum; + tmp_buf[tx_len++] = GOODIX_HID_SET_REPORT_CMD; + + memcpy(tmp_buf + tx_len, args, args_len); + tx_len += args_len; + + memcpy(tmp_buf + tx_len, buf, len); + tx_len += len; + + error = goodix_spi_write(ts, ts->hid_report_addr, tmp_buf, tx_len); + if (error) { + dev_err(ts->dev, "failed send report: %*ph", tx_len, tmp_buf); + return error; + } + return len; +} + +static int goodix_hid_raw_request(struct hid_device *hid, + unsigned char reportnum, + __u8 *buf, size_t len, + unsigned char rtype, int reqtype) +{ + struct goodix_ts_data *ts = hid->driver_data; + int error = -EINVAL; + + guard(mutex)(&ts->hid_request_lock); + switch (reqtype) { + case HID_REQ_GET_REPORT: + error = goodix_hid_get_raw_report(hid, reportnum, buf, + len, rtype); + break; + case HID_REQ_SET_REPORT: + if (buf[0] == reportnum) + error = goodix_hid_set_raw_report(hid, reportnum, + buf, len, rtype); + break; + default: + break; + } + + return error; +} + +static struct hid_ll_driver goodix_hid_ll_driver = { + .parse = goodix_hid_parse, + .start = goodix_hid_start, + .stop = goodix_hid_stop, + .open = goodix_hid_open, + .close = goodix_hid_close, + .raw_request = goodix_hid_raw_request +}; + +static irqreturn_t goodix_hid_irq(int irq, void *data) +{ + struct goodix_ts_data *ts = data; + struct goodix_hid_report_event *event; + struct goodix_hid_report_package *pkg; + u16 report_size; + + if (!test_bit(GOODIX_HID_STARTED, &ts->flags)) + return IRQ_HANDLED; + /* + * First, read buffer with space for header and coordinate package: + * - event header = 3 bytes + * - coordinate event = GOODIX_HID_COOR_PKG_LEN bytes + * + * If the data size info in the event header exceeds + * GOODIX_HID_COOR_PKG_LEN, it means that there are other packages + * besides the coordinate package. + */ + event = goodix_get_event_report(ts, ts->hid_report_addr, ts->event_buf, + GOODIX_HID_ACK_HEADER_SIZE + + GOODIX_HID_COOR_PKG_LEN); + if (!event) { + dev_err(ts->dev, "failed get coordinate data"); + return IRQ_HANDLED; + } + + /* Check coordinate data valid falg */ + if (event->hdr.flag != GOODIX_HID_REPORT_READY_FLAG) + return IRQ_HANDLED; + + pkg = (struct goodix_hid_report_package *)event->data; + if (le16_to_cpu(pkg->size) < GOODIX_HID_PKG_LEN_SIZE) { + dev_err(ts->dev, "invalid coordinate event package size, %d", + le16_to_cpu(pkg->size)); + return IRQ_HANDLED; + } + hid_input_report(ts->hid, HID_INPUT_REPORT, pkg->data, + le16_to_cpu(pkg->size) - GOODIX_HID_PKG_LEN_SIZE, 1); + + report_size = le16_to_cpu(event->hdr.size); + /* Check if there are other packages */ + if (report_size <= GOODIX_HID_COOR_PKG_LEN) + return IRQ_HANDLED; + + if (report_size >= ts->hid_max_event_sz) { + dev_err(ts->dev, "package size exceed limit %d vs %d", + report_size, ts->hid_max_event_sz); + return IRQ_HANDLED; + } + + /* Read the package behind the coordinate data */ + pkg = goodix_get_event_report(ts, ts->hid_report_addr + sizeof(*event), + ts->event_buf, + report_size - GOODIX_HID_COOR_PKG_LEN); + if (!pkg) { + dev_err(ts->dev, "failed read attachment data content"); + return IRQ_HANDLED; + } + + hid_input_report(ts->hid, HID_INPUT_REPORT, pkg->data, + le16_to_cpu(pkg->size) - GOODIX_HID_PKG_LEN_SIZE, 1); + + return IRQ_HANDLED; +} + +static int goodix_hid_init(struct goodix_ts_data *ts) +{ + struct hid_device *hid; + int error; + + /* Get hid descriptor */ + error = goodix_spi_read(ts, GOODIX_HID_DESC_ADDR, &ts->hid_desc, + sizeof(ts->hid_desc)); + if (error) { + dev_err(ts->dev, "failed get hid desc, %d", error); + return error; + } + + hid = hid_allocate_device(); + if (IS_ERR(hid)) + return PTR_ERR(hid); + + hid->driver_data = ts; + hid->ll_driver = &goodix_hid_ll_driver; + hid->bus = BUS_SPI; + hid->dev.parent = &ts->spi->dev; + + hid->version = le16_to_cpu(ts->hid_desc.bcd_version); + hid->vendor = le16_to_cpu(ts->hid_desc.vendor_id); + hid->product = le16_to_cpu(ts->hid_desc.product_id); + snprintf(hid->name, sizeof(hid->name), "%s %04X:%04X", "hid-gdix", + hid->vendor, hid->product); + + error = hid_add_device(hid); + if (error) { + dev_err(ts->dev, "failed add hid device, %d", error); + hid_destroy_device(hid); + return error; + } + + ts->hid = hid; + return 0; +} + +static int goodix_spi_probe(struct spi_device *spi) +{ + struct device *dev = &spi->dev; + struct goodix_ts_data *ts; + int error; + + /* init spi_device */ + spi->mode = SPI_MODE_0; + spi->bits_per_word = 8; + error = spi_setup(spi); + if (error) + return error; + + ts = devm_kzalloc(dev, sizeof(*ts), GFP_KERNEL); + if (!ts) + return -ENOMEM; + + mutex_init(&ts->hid_request_lock); + spi_set_drvdata(spi, ts); + ts->spi = spi; + ts->dev = dev; + ts->hid_max_event_sz = GOODIX_SPI_READ_PREFIX_LEN + + GOODIX_HID_ACK_HEADER_SIZE + GOODIX_HID_COOR_PKG_LEN; + ts->event_buf = devm_kmalloc(dev, ts->hid_max_event_sz, GFP_KERNEL); + if (!ts->event_buf) + return -ENOMEM; + + ts->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH); + if (IS_ERR(ts->reset_gpio)) + return dev_err_probe(dev, PTR_ERR(ts->reset_gpio), + "failed to request reset gpio\n"); + + error = device_property_read_u32(dev, "goodix,hid-report-addr", + &ts->hid_report_addr); + if (error) + return dev_err_probe(dev, error, + "failed get hid report addr\n"); + + error = goodix_dev_confirm(ts); + if (error) + return error; + + /* Waits 150ms for firmware to fully boot */ + msleep(GOODIX_NORMAL_RESET_DELAY_MS); + + error = goodix_hid_init(ts); + if (error) { + dev_err(dev, "failed init hid device"); + return error; + } + + error = devm_request_threaded_irq(&ts->spi->dev, ts->spi->irq, + NULL, goodix_hid_irq, IRQF_ONESHOT, + "goodix_spi_hid", ts); + if (error) { + dev_err(ts->dev, "could not register interrupt, irq = %d, %d", + ts->spi->irq, error); + goto err_destroy_hid; + } + + return 0; + +err_destroy_hid: + hid_destroy_device(ts->hid); + return error; +} + +static void goodix_spi_remove(struct spi_device *spi) +{ + struct goodix_ts_data *ts = spi_get_drvdata(spi); + + disable_irq(spi->irq); + hid_destroy_device(ts->hid); +} + +static int goodix_spi_set_power(struct goodix_ts_data *ts, int power_state) +{ + u8 power_control_cmd[] = {0x00, 0x00, 0x00, 0x87, 0x02, 0x00, 0x08}; + int error; + + /* value 0 for power on, 1 for power sleep */ + power_control_cmd[5] = power_state; + + guard(mutex)(&ts->hid_request_lock); + error = goodix_spi_write(ts, ts->hid_report_addr, power_control_cmd, + sizeof(power_control_cmd)); + if (error) { + dev_err(ts->dev, "failed set power mode: %s", + power_state == GOODIX_SPI_POWER_ON ? "on" : "sleep"); + return error; + } + return 0; +} + +static int goodix_spi_suspend(struct device *dev) +{ + struct goodix_ts_data *ts = dev_get_drvdata(dev); + + disable_irq(ts->spi->irq); + return goodix_spi_set_power(ts, GOODIX_SPI_POWER_SLEEP); +} + +static int goodix_spi_resume(struct device *dev) +{ + struct goodix_ts_data *ts = dev_get_drvdata(dev); + + enable_irq(ts->spi->irq); + return goodix_spi_set_power(ts, GOODIX_SPI_POWER_ON); +} + +static DEFINE_SIMPLE_DEV_PM_OPS(goodix_spi_pm_ops, + goodix_spi_suspend, goodix_spi_resume); + +#ifdef CONFIG_ACPI +static const struct acpi_device_id goodix_spi_acpi_match[] = { + { "GXTS7986" }, + { }, +}; +MODULE_DEVICE_TABLE(acpi, goodix_spi_acpi_match); +#endif + +#ifdef CONFIG_OF +static const struct of_device_id goodix_spi_of_match[] = { + { .compatible = "goodix,gt7986u", }, + { } +}; +MODULE_DEVICE_TABLE(of, goodix_spi_of_match); +#endif + +static const struct spi_device_id goodix_spi_ids[] = { + { "gt7986u" }, + { }, +}; +MODULE_DEVICE_TABLE(spi, goodix_spi_ids); + +static struct spi_driver goodix_spi_driver = { + .driver = { + .name = "goodix-spi-hid", + .acpi_match_table = ACPI_PTR(goodix_spi_acpi_match), + .of_match_table = of_match_ptr(goodix_spi_of_match), + .pm = pm_sleep_ptr(&goodix_spi_pm_ops), + }, + .probe = goodix_spi_probe, + .remove = goodix_spi_remove, + .id_table = goodix_spi_ids, +}; +module_spi_driver(goodix_spi_driver); + +MODULE_DESCRIPTION("Goodix SPI driver for HID touchscreen"); +MODULE_AUTHOR("Goodix, Inc."); +MODULE_LICENSE("GPL"); From 9184b17fbc232554f91e9a01d29cea3a47bca2ea Mon Sep 17 00:00:00 2001 From: Charles Wang Date: Wed, 14 Aug 2024 10:45:13 +0800 Subject: [PATCH 14/54] dt-bindings: input: Goodix SPI HID Touchscreen The Goodix GT7986U touch controller report touch data according to the HID protocol through the SPI bus. However, it is incompatible with Microsoft's HID-over-SPI protocol. Reviewed-by: Conor Dooley Signed-off-by: Charles Wang Signed-off-by: Jiri Kosina --- .../bindings/input/goodix,gt7986u.yaml | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 Documentation/devicetree/bindings/input/goodix,gt7986u.yaml diff --git a/Documentation/devicetree/bindings/input/goodix,gt7986u.yaml b/Documentation/devicetree/bindings/input/goodix,gt7986u.yaml new file mode 100644 index 000000000000..a7d42a5d6128 --- /dev/null +++ b/Documentation/devicetree/bindings/input/goodix,gt7986u.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/input/goodix,gt7986u.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: GOODIX GT7986U SPI HID Touchscreen + +maintainers: + - Charles Wang + +description: Supports the Goodix GT7986U touchscreen. + This touch controller reports data packaged according to the HID protocol, + but is incompatible with Microsoft's HID-over-SPI protocol. + +allOf: + - $ref: /schemas/spi/spi-peripheral-props.yaml# + +properties: + compatible: + enum: + - goodix,gt7986u + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + reset-gpios: + maxItems: 1 + + goodix,hid-report-addr: + $ref: /schemas/types.yaml#/definitions/uint32 + description: + The register address for retrieving HID report data. + This address is related to the device firmware and may + change after a firmware update. + + spi-max-frequency: true + +additionalProperties: false + +required: + - compatible + - reg + - interrupts + - reset-gpios + - goodix,hid-report-addr + +examples: + - | + #include + #include + + spi { + #address-cells = <1>; + #size-cells = <0>; + + touchscreen@0 { + compatible = "goodix,gt7986u"; + reg = <0>; + interrupt-parent = <&gpio>; + interrupts = <25 IRQ_TYPE_LEVEL_LOW>; + reset-gpios = <&gpio1 1 GPIO_ACTIVE_LOW>; + spi-max-frequency = <10000000>; + goodix,hid-report-addr = <0x22c8c>; + }; + }; + +... From 2933aa8b77be957d57d1a1ba71617e09cdaa2cbb Mon Sep 17 00:00:00 2001 From: Max Staudt Date: Sun, 11 Aug 2024 22:09:06 +0900 Subject: [PATCH 15/54] HID: hid-playstation: DS4: Update rumble and lightbar together Some 3rd party gamepads expect updates to rumble and lightbar together, and setting one may cancel the other. Let's maximise compatibility by always sending rumble and lightbar updates together, even when only one has been scheduled. Further background reading: - Apparently the PS4 always sends rumble and lightbar updates together: https://eleccelerator.com/wiki/index.php?title=DualShock_4#0x11_2 - 3rd party gamepads may not implement lightbar_blink, and may simply ignore updates with 0x07 set, according to: https://github.com/Ryochan7/DS4Windows/pull/1839 [jkosina@suse.com: fix shortlog] Acked-by: Roderick Colenbrander Signed-off-by: Max Staudt Signed-off-by: Jiri Kosina --- drivers/hid/hid-playstation.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/drivers/hid/hid-playstation.c b/drivers/hid/hid-playstation.c index e7c309cfe3a0..0d90d7ee693c 100644 --- a/drivers/hid/hid-playstation.c +++ b/drivers/hid/hid-playstation.c @@ -2143,6 +2143,26 @@ static void dualshock4_output_worker(struct work_struct *work) spin_lock_irqsave(&ds4->base.lock, flags); + /* + * Some 3rd party gamepads expect updates to rumble and lightbar + * together, and setting one may cancel the other. + * + * Let's maximise compatibility by always sending rumble and lightbar + * updates together, even when only one has been scheduled, resulting + * in: + * + * ds4->valid_flag0 >= 0x03 + * + * Hopefully this will maximise compatibility with third-party pads. + * + * Any further update bits, such as 0x04 for lightbar blinking, will + * be or'd on top of this like before. + */ + if (ds4->update_rumble || ds4->update_lightbar) { + ds4->update_rumble = true; /* 0x01 */ + ds4->update_lightbar = true; /* 0x02 */ + } + if (ds4->update_rumble) { /* Select classic rumble style haptics and enable it. */ common->valid_flag0 |= DS4_OUTPUT_VALID_FLAG0_MOTOR; From a707f85d47cad3978bef8fe90c7a79e3998e9d36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Sat, 3 Aug 2024 14:34:17 +0200 Subject: [PATCH 16/54] HID: bpf: constify parameter rdesc of call_hid_bpf_rdesc_fixup() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The parameter is never modified, so mark it as const. Also inline the return statement to avoid a type mismatch error. This is a prerequisite for constification changes in the HID core. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240803-hid-const-fixup-v2-1-f53d7a7b29d8@weissschuh.net Signed-off-by: Benjamin Tissoires --- drivers/hid/bpf/hid_bpf_dispatch.c | 6 ++---- include/linux/hid_bpf.h | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c index a272a086c950..8420c227e21b 100644 --- a/drivers/hid/bpf/hid_bpf_dispatch.c +++ b/drivers/hid/bpf/hid_bpf_dispatch.c @@ -148,7 +148,7 @@ out: } EXPORT_SYMBOL_GPL(dispatch_hid_bpf_output_report); -u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *size) +u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, const u8 *rdesc, unsigned int *size) { int ret; struct hid_bpf_ctx_kern ctx_kern = { @@ -179,9 +179,7 @@ u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *s *size = ret; } - rdesc = krealloc(ctx_kern.data, *size, GFP_KERNEL); - - return rdesc; + return krealloc(ctx_kern.data, *size, GFP_KERNEL); ignore_bpf: kfree(ctx_kern.data); diff --git a/include/linux/hid_bpf.h b/include/linux/hid_bpf.h index d4d063cf63b5..6a47223e6460 100644 --- a/include/linux/hid_bpf.h +++ b/include/linux/hid_bpf.h @@ -212,7 +212,7 @@ int hid_bpf_connect_device(struct hid_device *hdev); void hid_bpf_disconnect_device(struct hid_device *hdev); void hid_bpf_destroy_device(struct hid_device *hid); int hid_bpf_device_init(struct hid_device *hid); -u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *size); +u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, const u8 *rdesc, unsigned int *size); #else /* CONFIG_HID_BPF */ static inline u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, u8 *data, u32 *size, int interrupt, From 6737769ca0b6bfc82df53db5fd69068902d608db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Sat, 3 Aug 2024 14:34:18 +0200 Subject: [PATCH 17/54] HID: constify parameter rdesc of hid_parse_report() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The parameter is never modified, so mark it as const. This is a prerequisite for constification changes in the HID core. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240803-hid-const-fixup-v2-2-f53d7a7b29d8@weissschuh.net Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-core.c | 2 +- include/linux/hid.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 988d0acbdf04..0d2cbe491708 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -946,7 +946,7 @@ static int hid_scan_report(struct hid_device *hid) * Allocate the device report as read by the bus driver. This function should * only be called from parse() in ll drivers. */ -int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size) +int hid_parse_report(struct hid_device *hid, const __u8 *start, unsigned size) { hid->dev_rdesc = kmemdup(start, size, GFP_KERNEL); if (!hid->dev_rdesc) diff --git a/include/linux/hid.h b/include/linux/hid.h index 1533c9dcd3a6..e7a5d6f2f2eb 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -953,7 +953,7 @@ struct hid_device *hid_allocate_device(void); struct hid_report *hid_register_report(struct hid_device *device, enum hid_report_type type, unsigned int id, unsigned int application); -int hid_parse_report(struct hid_device *hid, __u8 *start, unsigned size); +int hid_parse_report(struct hid_device *hid, const __u8 *start, unsigned size); struct hid_report *hid_validate_values(struct hid_device *hid, enum hid_report_type type, unsigned int id, unsigned int field_index, From 24ddd0d7de7aaf50f537fd727f31616cb5a65a9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Sat, 3 Aug 2024 14:34:19 +0200 Subject: [PATCH 18/54] HID: constify hid_device::rdesc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Once a report descriptor has been created by the HID core it is not supposed to be modified anymore. Enforce this invariant through the type system. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240803-hid-const-fixup-v2-3-f53d7a7b29d8@weissschuh.net Signed-off-by: Benjamin Tissoires --- include/linux/hid.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/hid.h b/include/linux/hid.h index e7a5d6f2f2eb..dda34d8cad19 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -602,7 +602,7 @@ struct hid_ll_driver; struct hid_device { /* device report descriptor */ __u8 *dev_rdesc; unsigned dev_rsize; - __u8 *rdesc; + const __u8 *rdesc; unsigned rsize; struct hid_collection *collection; /* List of HID collections */ unsigned collection_size; /* Number of allocated hid_collections */ From 80cfb508f3fe4c7c6a567fc4aa863c9a38709cd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Sat, 3 Aug 2024 14:34:20 +0200 Subject: [PATCH 19/54] HID: constify params and return value of fetch_item() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit fetch_item() does not modify the descriptor it operates on. As a prerequisite for the constification of hid_driver::dev_rdesc, mark the parameters and return value of fetch_item() as const. Also adapt the variable types in the callers to match this constification. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240803-hid-const-fixup-v2-4-f53d7a7b29d8@weissschuh.net Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-core.c | 12 ++++++------ include/linux/hid.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 0d2cbe491708..311069588321 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -723,7 +723,7 @@ static void hid_device_release(struct device *dev) * items, though they are not used yet. */ -static u8 *fetch_item(__u8 *start, __u8 *end, struct hid_item *item) +static const u8 *fetch_item(const __u8 *start, const __u8 *end, struct hid_item *item) { u8 b; @@ -880,8 +880,8 @@ static int hid_scan_report(struct hid_device *hid) { struct hid_parser *parser; struct hid_item item; - __u8 *start = hid->dev_rdesc; - __u8 *end = start + hid->dev_rsize; + const __u8 *start = hid->dev_rdesc; + const __u8 *end = start + hid->dev_rsize; static int (*dispatch_type[])(struct hid_parser *parser, struct hid_item *item) = { hid_scan_main, @@ -1204,10 +1204,10 @@ int hid_open_report(struct hid_device *device) struct hid_parser *parser; struct hid_item item; unsigned int size; - __u8 *start; + const __u8 *start; __u8 *buf; - __u8 *end; - __u8 *next; + const __u8 *end; + const __u8 *next; int ret; int i; static int (*dispatch_type[])(struct hid_parser *parser, diff --git a/include/linux/hid.h b/include/linux/hid.h index dda34d8cad19..502bbc6f078c 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -46,7 +46,7 @@ struct hid_item { __s16 s16; __u32 u32; __s32 s32; - __u8 *longdata; + const __u8 *longdata; } data; }; From 3593630c89d7d3963c42262694f8aa8b4727a0ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Sat, 3 Aug 2024 14:34:21 +0200 Subject: [PATCH 20/54] HID: constify hid_device::dev_rdesc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Once a report descriptor has been created by the HID core it is not supposed to be modified anymore. Enforce this invariant through the type system. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240803-hid-const-fixup-v2-5-f53d7a7b29d8@weissschuh.net Signed-off-by: Benjamin Tissoires --- include/linux/hid.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/hid.h b/include/linux/hid.h index 502bbc6f078c..c5fb43db0f2e 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -600,7 +600,7 @@ struct hid_driver; struct hid_ll_driver; struct hid_device { /* device report descriptor */ - __u8 *dev_rdesc; + const __u8 *dev_rdesc; unsigned dev_rsize; const __u8 *rdesc; unsigned rsize; From fe73965d078670406acee0218f118c0870d6a58b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Sat, 3 Aug 2024 14:34:22 +0200 Subject: [PATCH 21/54] HID: change return type of report_fixup() to const MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit By allowing the drivers to return a "const *" they can constify their static report arrays. This makes it clear to driver authors that the HID core will not modify those reports and they can be reused for multiple devices. Furthermore security is slightly improved as those reports are protected against accidental or malicious modifications. [bentiss: fixup hid-cougar.c and hid-multitouch.c for latest version of the master branch] Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240803-hid-const-fixup-v2-6-f53d7a7b29d8@weissschuh.net Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-apple.c | 2 +- drivers/hid/hid-asus.c | 2 +- drivers/hid/hid-aureal.c | 2 +- drivers/hid/hid-bigbenff.c | 2 +- drivers/hid/hid-cherry.c | 2 +- drivers/hid/hid-chicony.c | 4 ++-- drivers/hid/hid-cmedia.c | 2 +- drivers/hid/hid-corsair.c | 4 ++-- drivers/hid/hid-cougar.c | 4 ++-- drivers/hid/hid-cypress.c | 2 +- drivers/hid/hid-dr.c | 4 ++-- drivers/hid/hid-elecom.c | 2 +- drivers/hid/hid-gembird.c | 2 +- drivers/hid/hid-glorious.c | 2 +- drivers/hid/hid-holtek-kbd.c | 2 +- drivers/hid/hid-holtek-mouse.c | 4 ++-- drivers/hid/hid-ite.c | 2 +- drivers/hid/hid-keytouch.c | 2 +- drivers/hid/hid-kye.c | 2 +- drivers/hid/hid-lenovo.c | 2 +- drivers/hid/hid-lg.c | 2 +- drivers/hid/hid-logitech-hidpp.c | 4 ++-- drivers/hid/hid-macally.c | 4 ++-- drivers/hid/hid-magicmouse.c | 4 ++-- drivers/hid/hid-maltron.c | 4 ++-- drivers/hid/hid-microsoft.c | 2 +- drivers/hid/hid-monterey.c | 2 +- drivers/hid/hid-multitouch.c | 2 +- drivers/hid/hid-nti.c | 2 +- drivers/hid/hid-ortek.c | 2 +- drivers/hid/hid-petalynx.c | 2 +- drivers/hid/hid-prodikeys.c | 2 +- drivers/hid/hid-pxrc.c | 4 ++-- drivers/hid/hid-redragon.c | 2 +- drivers/hid/hid-saitek.c | 2 +- drivers/hid/hid-samsung.c | 2 +- drivers/hid/hid-semitek.c | 4 ++-- drivers/hid/hid-sensor-hub.c | 2 +- drivers/hid/hid-sigmamicro.c | 4 ++-- drivers/hid/hid-sony.c | 2 +- drivers/hid/hid-steelseries.c | 4 ++-- drivers/hid/hid-sunplus.c | 2 +- drivers/hid/hid-topre.c | 4 ++-- drivers/hid/hid-uclogic-core.c | 2 +- drivers/hid/hid-viewsonic.c | 4 ++-- drivers/hid/hid-vrc2.c | 4 ++-- drivers/hid/hid-waltop.c | 2 +- drivers/hid/hid-winwing.c | 2 +- drivers/hid/hid-xiaomi.c | 4 ++-- drivers/hid/hid-zydacron.c | 2 +- include/linux/hid.h | 2 +- 51 files changed, 68 insertions(+), 68 deletions(-) diff --git a/drivers/hid/hid-apple.c b/drivers/hid/hid-apple.c index af5cf94f9dea..7e1ae2a2bcc2 100644 --- a/drivers/hid/hid-apple.c +++ b/drivers/hid/hid-apple.c @@ -620,7 +620,7 @@ static void apple_battery_timer_tick(struct timer_list *t) * MacBook JIS keyboard has wrong logical maximum * Magic Keyboard JIS has wrong logical maximum */ -static __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *apple_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { struct apple_sc *asc = hid_get_drvdata(hdev); diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c index a282388b7aa5..28a958bc4723 100644 --- a/drivers/hid/hid-asus.c +++ b/drivers/hid/hid-asus.c @@ -1119,7 +1119,7 @@ static const __u8 asus_g752_fixed_rdesc[] = { 0x2A, 0xFF, 0x00, /* Usage Maximum (0xFF) */ }; -static __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *asus_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { struct asus_drvdata *drvdata = hid_get_drvdata(hdev); diff --git a/drivers/hid/hid-aureal.c b/drivers/hid/hid-aureal.c index cf1a562d8523..896304148a87 100644 --- a/drivers/hid/hid-aureal.c +++ b/drivers/hid/hid-aureal.c @@ -18,7 +18,7 @@ #include "hid-ids.h" -static __u8 *aureal_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *aureal_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { if (*rsize >= 54 && rdesc[52] == 0x25 && rdesc[53] == 0x01) { diff --git a/drivers/hid/hid-bigbenff.c b/drivers/hid/hid-bigbenff.c index be17af3d9c0c..a2ff60dd834c 100644 --- a/drivers/hid/hid-bigbenff.c +++ b/drivers/hid/hid-bigbenff.c @@ -464,7 +464,7 @@ error_hw_stop: return error; } -static __u8 *bigben_report_fixup(struct hid_device *hid, __u8 *rdesc, +static const __u8 *bigben_report_fixup(struct hid_device *hid, __u8 *rdesc, unsigned int *rsize) { if (*rsize == PID0902_RDESC_ORIG_SIZE) { diff --git a/drivers/hid/hid-cherry.c b/drivers/hid/hid-cherry.c index 549c73b05b8d..a504632febfc 100644 --- a/drivers/hid/hid-cherry.c +++ b/drivers/hid/hid-cherry.c @@ -22,7 +22,7 @@ * Cherry Cymotion keyboard have an invalid HID report descriptor, * that needs fixing before we can parse it. */ -static __u8 *ch_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *ch_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { if (*rsize >= 18 && rdesc[11] == 0x3c && rdesc[12] == 0x02) { diff --git a/drivers/hid/hid-chicony.c b/drivers/hid/hid-chicony.c index 99954c6b3242..5776ec2e7159 100644 --- a/drivers/hid/hid-chicony.c +++ b/drivers/hid/hid-chicony.c @@ -88,8 +88,8 @@ static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi, return 1; } -static __u8 *ch_switch12_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) +static const __u8 *ch_switch12_report_fixup(struct hid_device *hdev, + __u8 *rdesc, unsigned int *rsize) { struct usb_interface *intf = to_usb_interface(hdev->dev.parent); diff --git a/drivers/hid/hid-cmedia.c b/drivers/hid/hid-cmedia.c index cab42047bc99..01009c95613c 100644 --- a/drivers/hid/hid-cmedia.c +++ b/drivers/hid/hid-cmedia.c @@ -199,7 +199,7 @@ static struct hid_driver cmhid_driver = { .input_mapping = cmhid_input_mapping, }; -static __u8 *cmhid_hs100b_report_fixup(struct hid_device *hid, __u8 *rdesc, +static const __u8 *cmhid_hs100b_report_fixup(struct hid_device *hid, __u8 *rdesc, unsigned int *rsize) { if (*rsize == HS100B_RDESC_ORIG_SIZE) { diff --git a/drivers/hid/hid-corsair.c b/drivers/hid/hid-corsair.c index 702f50e9841d..62b99f5c3cf8 100644 --- a/drivers/hid/hid-corsair.c +++ b/drivers/hid/hid-corsair.c @@ -690,8 +690,8 @@ static int corsair_input_mapping(struct hid_device *dev, * - USB ID 1b1c:1b3e, sold as Scimitar RGB Pro Gaming mouse */ -static __u8 *corsair_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) +static const __u8 *corsair_mouse_report_fixup(struct hid_device *hdev, + __u8 *rdesc, unsigned int *rsize) { struct usb_interface *intf = to_usb_interface(hdev->dev.parent); diff --git a/drivers/hid/hid-cougar.c b/drivers/hid/hid-cougar.c index 0fa785f52707..5596dd940322 100644 --- a/drivers/hid/hid-cougar.c +++ b/drivers/hid/hid-cougar.c @@ -103,8 +103,8 @@ static void cougar_fix_g6_mapping(void) /* * Constant-friendly rdesc fixup for mouse interface */ -static __u8 *cougar_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) +static const __u8 *cougar_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { if (*rsize >= 117 && rdesc[2] == 0x09 && rdesc[3] == 0x02 && (rdesc[115] | rdesc[116] << 8) >= HID_MAX_USAGES) { diff --git a/drivers/hid/hid-cypress.c b/drivers/hid/hid-cypress.c index b952b235e70a..98548201feec 100644 --- a/drivers/hid/hid-cypress.c +++ b/drivers/hid/hid-cypress.c @@ -67,7 +67,7 @@ static __u8 *va_logical_boundary_fixup(struct hid_device *hdev, __u8 *rdesc, return rdesc; } -static __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *cp_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); diff --git a/drivers/hid/hid-dr.c b/drivers/hid/hid-dr.c index c88224a96e9e..b24f9bc743e1 100644 --- a/drivers/hid/hid-dr.c +++ b/drivers/hid/hid-dr.c @@ -228,8 +228,8 @@ static __u8 pid0011_rdesc_fixed[] = { 0xC0 /* End Collection */ }; -static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) +static const __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { switch (hdev->product) { case 0x0011: diff --git a/drivers/hid/hid-elecom.c b/drivers/hid/hid-elecom.c index 5973a3bab29f..defcf91fdd14 100644 --- a/drivers/hid/hid-elecom.c +++ b/drivers/hid/hid-elecom.c @@ -53,7 +53,7 @@ static void mouse_button_fixup(struct hid_device *hdev, rdesc[padding_bit + 1] = MOUSE_BUTTONS_MAX - nbuttons; } -static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { switch (hdev->product) { diff --git a/drivers/hid/hid-gembird.c b/drivers/hid/hid-gembird.c index c42593fe7116..20a8de766e56 100644 --- a/drivers/hid/hid-gembird.c +++ b/drivers/hid/hid-gembird.c @@ -57,7 +57,7 @@ static const __u8 gembird_jpd_fixed_rdesc[] = { 0x81, 0x02, /* Input (Data,Var,Abs) */ }; -static __u8 *gembird_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *gembird_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { __u8 *new_rdesc; diff --git a/drivers/hid/hid-glorious.c b/drivers/hid/hid-glorious.c index 281b3a7187ce..5bbd81248053 100644 --- a/drivers/hid/hid-glorious.c +++ b/drivers/hid/hid-glorious.c @@ -26,7 +26,7 @@ MODULE_DESCRIPTION("HID driver for Glorious PC Gaming Race mice"); * keyboard HID report, causing keycodes to be misinterpreted. * Fix this by setting Usage Minimum to 0 in that report. */ -static __u8 *glorious_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *glorious_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { if (*rsize == 213 && diff --git a/drivers/hid/hid-holtek-kbd.c b/drivers/hid/hid-holtek-kbd.c index 1f014ac54e14..794d609c2e31 100644 --- a/drivers/hid/hid-holtek-kbd.c +++ b/drivers/hid/hid-holtek-kbd.c @@ -102,7 +102,7 @@ static __u8 holtek_kbd_rdesc_fixed[] = { 0xC0, /* End Collection */ }; -static __u8 *holtek_kbd_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *holtek_kbd_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { struct usb_interface *intf = to_usb_interface(hdev->dev.parent); diff --git a/drivers/hid/hid-holtek-mouse.c b/drivers/hid/hid-holtek-mouse.c index 343730c28e2d..b618a1646c13 100644 --- a/drivers/hid/hid-holtek-mouse.c +++ b/drivers/hid/hid-holtek-mouse.c @@ -29,8 +29,8 @@ * - USB ID 04d9:a0c2, sold as ETEKCITY Scroll T-140 Gaming Mouse */ -static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) +static const __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, + __u8 *rdesc, unsigned int *rsize) { struct usb_interface *intf = to_usb_interface(hdev->dev.parent); diff --git a/drivers/hid/hid-ite.c b/drivers/hid/hid-ite.c index 6a7281bc27c9..8e42780a2663 100644 --- a/drivers/hid/hid-ite.c +++ b/drivers/hid/hid-ite.c @@ -13,7 +13,7 @@ #define QUIRK_TOUCHPAD_ON_OFF_REPORT BIT(0) -static __u8 *ite_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) +static const __u8 *ite_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); diff --git a/drivers/hid/hid-keytouch.c b/drivers/hid/hid-keytouch.c index a972943baaea..6e3033bb80dd 100644 --- a/drivers/hid/hid-keytouch.c +++ b/drivers/hid/hid-keytouch.c @@ -24,7 +24,7 @@ static __u8 keytouch_fixed_rdesc[] = { 0x26, 0xff, 0x00, 0x05, 0x07, 0x19, 0x00, 0x2a, 0xff, 0x00, 0x81, 0x00, 0xc0 }; -static __u8 *keytouch_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *keytouch_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { hid_info(hdev, "fixing up Keytouch IEC report descriptor\n"); diff --git a/drivers/hid/hid-kye.c b/drivers/hid/hid-kye.c index ca2ba3da2458..32344331282f 100644 --- a/drivers/hid/hid-kye.c +++ b/drivers/hid/hid-kye.c @@ -466,7 +466,7 @@ static __u8 *kye_tablet_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int return rdesc; } -static __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *kye_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { switch (hdev->product) { diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c index e5e72aa5260a..3b0c779ce8f7 100644 --- a/drivers/hid/hid-lenovo.c +++ b/drivers/hid/hid-lenovo.c @@ -133,7 +133,7 @@ static const __u8 lenovo_tpIIbtkbd_need_fixup_collection[] = { 0x81, 0x01, /* Input (Const,Array,Abs,No Wrap,Linear,Preferred State,No Null Position) */ }; -static __u8 *lenovo_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *lenovo_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { switch (hdev->product) { diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index cfe2f4f6e93f..a9be918e2b5c 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -427,7 +427,7 @@ static __u8 fg_rdesc_fixed[] = { * above the logical maximum described in descriptor. This extends * the original value of 0x28c of logical maximum to 0x104d */ -static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { struct lg_drv_data *drv_data = hid_get_drvdata(hdev); diff --git a/drivers/hid/hid-logitech-hidpp.c b/drivers/hid/hid-logitech-hidpp.c index 400d70e6dbe2..0e33fa0eb8db 100644 --- a/drivers/hid/hid-logitech-hidpp.c +++ b/drivers/hid/hid-logitech-hidpp.c @@ -3767,8 +3767,8 @@ static int hidpp_initialize_hires_scroll(struct hidpp_device *hidpp) /* Generic HID++ devices */ /* -------------------------------------------------------------------------- */ -static u8 *hidpp_report_fixup(struct hid_device *hdev, u8 *rdesc, - unsigned int *rsize) +static const u8 *hidpp_report_fixup(struct hid_device *hdev, u8 *rdesc, + unsigned int *rsize) { struct hidpp_device *hidpp = hid_get_drvdata(hdev); diff --git a/drivers/hid/hid-macally.c b/drivers/hid/hid-macally.c index aea46e522008..fe7576458afa 100644 --- a/drivers/hid/hid-macally.c +++ b/drivers/hid/hid-macally.c @@ -18,8 +18,8 @@ MODULE_LICENSE("GPL"); * The Macally ikey keyboard says that its logical and usage maximums are both * 101, but the power key is 102 and the equals key is 103 */ -static __u8 *macally_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) +static const __u8 *macally_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { if (*rsize >= 60 && rdesc[53] == 0x65 && rdesc[59] == 0x65) { hid_info(hdev, diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index 2eb285b97fc0..8a73b59e0827 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -907,8 +907,8 @@ static void magicmouse_remove(struct hid_device *hdev) hid_hw_stop(hdev); } -static __u8 *magicmouse_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) +static const __u8 *magicmouse_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { /* * Change the usage from: diff --git a/drivers/hid/hid-maltron.c b/drivers/hid/hid-maltron.c index caba0def938c..374c64dd82c2 100644 --- a/drivers/hid/hid-maltron.c +++ b/drivers/hid/hid-maltron.c @@ -137,8 +137,8 @@ static u8 maltron_rdesc[] = { 0xC0 /* End Collection */ }; -static __u8 *maltron_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) +static const __u8 *maltron_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { if (*rsize == sizeof(maltron_rdesc_o) && !memcmp(maltron_rdesc_o, rdesc, sizeof(maltron_rdesc_o))) { diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 4cf0fcddb379..18ac21c0bcb2 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -56,7 +56,7 @@ struct xb1s_ff_report { __u8 loop_count; } __packed; -static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { struct ms_data *ms = hid_get_drvdata(hdev); diff --git a/drivers/hid/hid-monterey.c b/drivers/hid/hid-monterey.c index 989681f73d77..3089be990afe 100644 --- a/drivers/hid/hid-monterey.c +++ b/drivers/hid/hid-monterey.c @@ -18,7 +18,7 @@ #include "hid-ids.h" -static __u8 *mr_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *mr_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { if (*rsize >= 31 && rdesc[29] == 0x05 && rdesc[30] == 0x09) { diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 99812c0f830b..5d4e916166c1 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1441,7 +1441,7 @@ static int mt_event(struct hid_device *hid, struct hid_field *field, return 0; } -static __u8 *mt_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *mt_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *size) { if (hdev->vendor == I2C_VENDOR_ID_GOODIX && diff --git a/drivers/hid/hid-nti.c b/drivers/hid/hid-nti.c index 1952e9ca5f45..03f7dd491228 100644 --- a/drivers/hid/hid-nti.c +++ b/drivers/hid/hid-nti.c @@ -29,7 +29,7 @@ MODULE_DESCRIPTION("HID driver for Network Technologies USB-SUN keyboard adapter /* * NTI Sun keyboard adapter has wrong logical maximum in report descriptor */ -static __u8 *nti_usbsun_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *nti_usbsun_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { if (*rsize >= 60 && rdesc[53] == 0x65 && rdesc[59] == 0x65) { diff --git a/drivers/hid/hid-ortek.c b/drivers/hid/hid-ortek.c index 99e3b06a8331..f27297269a7f 100644 --- a/drivers/hid/hid-ortek.c +++ b/drivers/hid/hid-ortek.c @@ -22,7 +22,7 @@ #include "hid-ids.h" -static __u8 *ortek_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *ortek_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { if (*rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x01) { diff --git a/drivers/hid/hid-petalynx.c b/drivers/hid/hid-petalynx.c index 5e47634bb07d..1a986f077ce1 100644 --- a/drivers/hid/hid-petalynx.c +++ b/drivers/hid/hid-petalynx.c @@ -19,7 +19,7 @@ #include "hid-ids.h" /* Petalynx Maxter Remote has maximum for consumer page set too low */ -static __u8 *pl_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *pl_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { if (*rsize >= 62 && rdesc[39] == 0x2a && rdesc[40] == 0xf5 && diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c index 757361593e52..3d08c190a935 100644 --- a/drivers/hid/hid-prodikeys.c +++ b/drivers/hid/hid-prodikeys.c @@ -728,7 +728,7 @@ static int pcmidi_snd_terminate(struct pcmidi_snd *pm) /* * PC-MIDI report descriptor for report id is wrong. */ -static __u8 *pk_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *pk_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { if (*rsize == 178 && diff --git a/drivers/hid/hid-pxrc.c b/drivers/hid/hid-pxrc.c index b0e517f9cde7..ef38730e78ab 100644 --- a/drivers/hid/hid-pxrc.c +++ b/drivers/hid/hid-pxrc.c @@ -42,8 +42,8 @@ static __u8 pxrc_rdesc_fixed[] = { 0xC0, // End Collection }; -static __u8 *pxrc_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) +static const __u8 *pxrc_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { hid_info(hdev, "fixing up PXRC report descriptor\n"); *rsize = sizeof(pxrc_rdesc_fixed); diff --git a/drivers/hid/hid-redragon.c b/drivers/hid/hid-redragon.c index 07d803513f27..20d28ed75c1e 100644 --- a/drivers/hid/hid-redragon.c +++ b/drivers/hid/hid-redragon.c @@ -33,7 +33,7 @@ * key codes are generated. */ -static __u8 *redragon_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *redragon_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { if (*rsize >= 102 && rdesc[100] == 0x81 && rdesc[101] == 0x00) { diff --git a/drivers/hid/hid-saitek.c b/drivers/hid/hid-saitek.c index 85ac8def368f..6fe7c087c594 100644 --- a/drivers/hid/hid-saitek.c +++ b/drivers/hid/hid-saitek.c @@ -66,7 +66,7 @@ static int saitek_probe(struct hid_device *hdev, return 0; } -static __u8 *saitek_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *saitek_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { struct saitek_sc *ssc = hid_get_drvdata(hdev); diff --git a/drivers/hid/hid-samsung.c b/drivers/hid/hid-samsung.c index d4e27142245c..f3908a9e04e6 100644 --- a/drivers/hid/hid-samsung.c +++ b/drivers/hid/hid-samsung.c @@ -469,7 +469,7 @@ static int samsung_universal_kbd_input_mapping(struct hid_device *hdev, return 1; } -static __u8 *samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *samsung_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { if (hdev->product == USB_DEVICE_ID_SAMSUNG_IR_REMOTE && hid_is_usb(hdev)) diff --git a/drivers/hid/hid-semitek.c b/drivers/hid/hid-semitek.c index 710766f6839d..4fbec5fd87ce 100644 --- a/drivers/hid/hid-semitek.c +++ b/drivers/hid/hid-semitek.c @@ -11,8 +11,8 @@ #include "hid-ids.h" -static __u8 *semitek_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) +static const __u8 *semitek_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { /* In the report descriptor for interface 2, fix the incorrect description of report ID 0x04 (the report contains a diff --git a/drivers/hid/hid-sensor-hub.c b/drivers/hid/hid-sensor-hub.c index 26e93a331a51..7bd86eef6ec7 100644 --- a/drivers/hid/hid-sensor-hub.c +++ b/drivers/hid/hid-sensor-hub.c @@ -580,7 +580,7 @@ void sensor_hub_device_close(struct hid_sensor_hub_device *hsdev) } EXPORT_SYMBOL_GPL(sensor_hub_device_close); -static __u8 *sensor_hub_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *sensor_hub_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { /* diff --git a/drivers/hid/hid-sigmamicro.c b/drivers/hid/hid-sigmamicro.c index 2e7058ac0e9d..c87276d7ba0d 100644 --- a/drivers/hid/hid-sigmamicro.c +++ b/drivers/hid/hid-sigmamicro.c @@ -99,8 +99,8 @@ static const __u8 sm_0059_rdesc[] = { 0xc0, /* End Collection 166 */ }; -static __u8 *sm_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) +static const __u8 *sm_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { if (*rsize == sizeof(sm_0059_rdesc) && !memcmp(sm_0059_rdesc, rdesc, *rsize)) { diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index eac75f98f08a..8e2e914bd236 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -743,7 +743,7 @@ static int sixaxis_mapping(struct hid_device *hdev, struct hid_input *hi, return -1; } -static u8 *sony_report_fixup(struct hid_device *hdev, u8 *rdesc, +static const u8 *sony_report_fixup(struct hid_device *hdev, u8 *rdesc, unsigned int *rsize) { struct sony_sc *sc = hid_get_drvdata(hdev); diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c index 2154e14f55f1..895da49e8ead 100644 --- a/drivers/hid/hid-steelseries.c +++ b/drivers/hid/hid-steelseries.c @@ -570,8 +570,8 @@ static void steelseries_remove(struct hid_device *hdev) hid_hw_stop(hdev); } -static __u8 *steelseries_srws1_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) +static const __u8 *steelseries_srws1_report_fixup(struct hid_device *hdev, + __u8 *rdesc, unsigned int *rsize) { if (hdev->vendor != USB_VENDOR_ID_STEELSERIES || hdev->product != USB_DEVICE_ID_STEELSERIES_SRWS1) diff --git a/drivers/hid/hid-sunplus.c b/drivers/hid/hid-sunplus.c index f32e60d4420f..64e4cff8ca1d 100644 --- a/drivers/hid/hid-sunplus.c +++ b/drivers/hid/hid-sunplus.c @@ -18,7 +18,7 @@ #include "hid-ids.h" -static __u8 *sp_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *sp_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { if (*rsize >= 112 && rdesc[104] == 0x26 && rdesc[105] == 0x80 && diff --git a/drivers/hid/hid-topre.c b/drivers/hid/hid-topre.c index d1d5ca310ead..848361f6225d 100644 --- a/drivers/hid/hid-topre.c +++ b/drivers/hid/hid-topre.c @@ -21,8 +21,8 @@ MODULE_LICENSE("GPL"); * events it's actually sending. It claims to send array events but is instead * sending variable events. */ -static __u8 *topre_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) +static const __u8 *topre_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { if (*rsize >= 119 && rdesc[69] == 0x29 && rdesc[70] == 0xe7 && rdesc[71] == 0x81 && rdesc[72] == 0x00) { diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index b176f9c0dd52..f6a1572b3728 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -50,7 +50,7 @@ static void uclogic_inrange_timeout(struct timer_list *t) input_sync(input); } -static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); diff --git a/drivers/hid/hid-viewsonic.c b/drivers/hid/hid-viewsonic.c index 668c2adb77b6..86f41e3fcb95 100644 --- a/drivers/hid/hid-viewsonic.c +++ b/drivers/hid/hid-viewsonic.c @@ -70,8 +70,8 @@ static __u8 pd1011_rdesc_fixed[] = { 0xC0 /* End Collection */ }; -static __u8 *viewsonic_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) +static const __u8 *viewsonic_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { switch (hdev->product) { case USB_DEVICE_ID_VIEWSONIC_PD1011: diff --git a/drivers/hid/hid-vrc2.c b/drivers/hid/hid-vrc2.c index 80a2b7ef5e66..9a4840b524ba 100644 --- a/drivers/hid/hid-vrc2.c +++ b/drivers/hid/hid-vrc2.c @@ -38,8 +38,8 @@ static __u8 vrc2_rdesc_fixed[] = { 0xC0, // End Collection }; -static __u8 *vrc2_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) +static const __u8 *vrc2_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { hid_info(hdev, "fixing up VRC-2 report descriptor\n"); *rsize = sizeof(vrc2_rdesc_fixed); diff --git a/drivers/hid/hid-waltop.c b/drivers/hid/hid-waltop.c index 1e590c61eef5..137a682ef5fb 100644 --- a/drivers/hid/hid-waltop.c +++ b/drivers/hid/hid-waltop.c @@ -599,7 +599,7 @@ static __u8 sirius_battery_free_tablet_rdesc_fixed[] = { 0xC0 /* End Collection */ }; -static __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { switch (hdev->product) { diff --git a/drivers/hid/hid-winwing.c b/drivers/hid/hid-winwing.c index 10a5d87ccb96..86b64c0ced12 100644 --- a/drivers/hid/hid-winwing.c +++ b/drivers/hid/hid-winwing.c @@ -165,7 +165,7 @@ static __u8 original_rdesc_buttons[] = { * This module skips numbers 32-63, unused on some throttle grips. */ -static __u8 *winwing_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *winwing_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { int sig_length = sizeof(original_rdesc_buttons); diff --git a/drivers/hid/hid-xiaomi.c b/drivers/hid/hid-xiaomi.c index a97a90afad33..035733fce2e1 100644 --- a/drivers/hid/hid-xiaomi.c +++ b/drivers/hid/hid-xiaomi.c @@ -61,8 +61,8 @@ static __u8 mi_silent_mouse_rdesc_fixed[] = { 0xC0 /* End Collection */ }; -static __u8 *xiaomi_report_fixup(struct hid_device *hdev, __u8 *rdesc, - unsigned int *rsize) +static const __u8 *xiaomi_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) { switch (hdev->product) { case USB_DEVICE_ID_MI_SILENT_MOUSE: diff --git a/drivers/hid/hid-zydacron.c b/drivers/hid/hid-zydacron.c index 998a3db19c1f..3bdb26f45592 100644 --- a/drivers/hid/hid-zydacron.c +++ b/drivers/hid/hid-zydacron.c @@ -24,7 +24,7 @@ struct zc_device { * Zydacron remote control has an invalid HID report descriptor, * that needs fixing before we can parse it. */ -static __u8 *zc_report_fixup(struct hid_device *hdev, __u8 *rdesc, +static const __u8 *zc_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { if (*rsize >= 253 && diff --git a/include/linux/hid.h b/include/linux/hid.h index c5fb43db0f2e..3a998fa3812d 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -822,7 +822,7 @@ struct hid_driver { struct hid_usage *usage, __s32 value); void (*report)(struct hid_device *hdev, struct hid_report *report); - __u8 *(*report_fixup)(struct hid_device *hdev, __u8 *buf, + const __u8 *(*report_fixup)(struct hid_device *hdev, __u8 *buf, unsigned int *size); int (*input_mapping)(struct hid_device *hdev, From e6de161b5ab4315405f4001736c25a070def61c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Sat, 3 Aug 2024 14:34:23 +0200 Subject: [PATCH 22/54] HID: cmedia: constify fixed up report descriptor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The HID core now allows static report descriptors to be read-only, make use of it. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240803-hid-const-fixup-v2-7-f53d7a7b29d8@weissschuh.net Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-cmedia.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-cmedia.c b/drivers/hid/hid-cmedia.c index 01009c95613c..528d7f361215 100644 --- a/drivers/hid/hid-cmedia.c +++ b/drivers/hid/hid-cmedia.c @@ -26,7 +26,7 @@ MODULE_LICENSE("GPL"); /* Fixed report descriptor of HS-100B audio chip * Bit 4 is an abolute Microphone mute usage instead of being unassigned. */ -static __u8 hs100b_rdesc_fixed[] = { +static const __u8 hs100b_rdesc_fixed[] = { 0x05, 0x0C, /* Usage Page (Consumer), */ 0x09, 0x01, /* Usage (Consumer Control), */ 0xA1, 0x01, /* Collection (Application), */ @@ -204,8 +204,8 @@ static const __u8 *cmhid_hs100b_report_fixup(struct hid_device *hid, __u8 *rdesc { if (*rsize == HS100B_RDESC_ORIG_SIZE) { hid_info(hid, "Fixing CMedia HS-100B report descriptor\n"); - rdesc = hs100b_rdesc_fixed; *rsize = sizeof(hs100b_rdesc_fixed); + return hs100b_rdesc_fixed; } return rdesc; } From c1f9eff7b270861005c7ec8146b6ad398c40940b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Sun, 4 Aug 2024 18:29:37 +0200 Subject: [PATCH 23/54] HID: winwing: constify read-only structs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These structs are never modified, so mark them as const. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240804-hid-const-winwing-v1-1-5a6c714753b1@weissschuh.net Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-winwing.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/hid/hid-winwing.c b/drivers/hid/hid-winwing.c index 86b64c0ced12..831b760c66ea 100644 --- a/drivers/hid/hid-winwing.c +++ b/drivers/hid/hid-winwing.c @@ -27,7 +27,7 @@ struct winwing_led_info { const char *led_name; }; -static struct winwing_led_info led_info[3] = { +static const struct winwing_led_info led_info[3] = { { 0, 255, "backlight" }, { 1, 1, "a-a" }, { 2, 1, "a-g" }, @@ -94,7 +94,7 @@ static int winwing_init_led(struct hid_device *hdev, return -ENOMEM; for (i = 0; i < 3; i += 1) { - struct winwing_led_info *info = &led_info[i]; + const struct winwing_led_info *info = &led_info[i]; led = &data->leds[i]; led->hdev = hdev; @@ -150,7 +150,7 @@ static int winwing_input_configured(struct hid_device *hdev, return ret; } -static __u8 original_rdesc_buttons[] = { +static const __u8 original_rdesc_buttons[] = { 0x05, 0x09, 0x19, 0x01, 0x29, 0x6F, 0x15, 0x00, 0x25, 0x01, 0x35, 0x00, 0x45, 0x01, 0x75, 0x01, 0x95, 0x6F, From b31c9d9dc343146b9f4ce67b4eee748c49296e99 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 27 Aug 2024 17:19:29 +0900 Subject: [PATCH 24/54] HID: hidraw: add HIDIOCREVOKE ioctl There is a need for userspace applications to open HID devices directly. Use-cases include configuration of gaming mice or direct access to joystick devices. The latter is currently handled by the uaccess tag in systemd, other devices include more custom/local configurations or just sudo. A better approach is what we already have for evdev devices: give the application a file descriptor and revoke it when it may no longer access that device. This patch is the hidraw equivalent to the EVIOCREVOKE ioctl, see commit c7dc65737c9a ("Input: evdev - add EVIOCREVOKE ioctl") for full details. An MR for systemd-logind has been filed here: https://github.com/systemd/systemd/pull/33970 Signed-off-by: Peter Hutterer Link: https://patch.msgid.link/20240827-hidraw-revoke-v5-1-d004a7451aea@kernel.org Signed-off-by: Benjamin Tissoires --- drivers/hid/hidraw.c | 39 +++++++++++++++++++++++++++++++++---- include/linux/hidraw.h | 1 + include/uapi/linux/hidraw.h | 1 + 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index 716294e40e8a..c887f48756f4 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c @@ -38,12 +38,20 @@ static const struct class hidraw_class = { static struct hidraw *hidraw_table[HIDRAW_MAX_DEVICES]; static DECLARE_RWSEM(minors_rwsem); +static inline bool hidraw_is_revoked(struct hidraw_list *list) +{ + return list->revoked; +} + static ssize_t hidraw_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos) { struct hidraw_list *list = file->private_data; int ret = 0, len; DECLARE_WAITQUEUE(wait, current); + if (hidraw_is_revoked(list)) + return -ENODEV; + mutex_lock(&list->read_mutex); while (ret == 0) { @@ -161,9 +169,13 @@ out: static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) { + struct hidraw_list *list = file->private_data; ssize_t ret; down_read(&minors_rwsem); - ret = hidraw_send_report(file, buffer, count, HID_OUTPUT_REPORT); + if (hidraw_is_revoked(list)) + ret = -ENODEV; + else + ret = hidraw_send_report(file, buffer, count, HID_OUTPUT_REPORT); up_read(&minors_rwsem); return ret; } @@ -256,7 +268,7 @@ static __poll_t hidraw_poll(struct file *file, poll_table *wait) poll_wait(file, &list->hidraw->wait, wait); if (list->head != list->tail) mask |= EPOLLIN | EPOLLRDNORM; - if (!list->hidraw->exist) + if (!list->hidraw->exist || hidraw_is_revoked(list)) mask |= EPOLLERR | EPOLLHUP; return mask; } @@ -320,6 +332,9 @@ static int hidraw_fasync(int fd, struct file *file, int on) { struct hidraw_list *list = file->private_data; + if (hidraw_is_revoked(list)) + return -ENODEV; + return fasync_helper(fd, file, on, &list->fasync); } @@ -372,6 +387,13 @@ static int hidraw_release(struct inode * inode, struct file * file) return 0; } +static int hidraw_revoke(struct hidraw_list *list) +{ + list->revoked = true; + + return 0; +} + static long hidraw_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { @@ -379,11 +401,12 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, unsigned int minor = iminor(inode); long ret = 0; struct hidraw *dev; + struct hidraw_list *list = file->private_data; void __user *user_arg = (void __user*) arg; down_read(&minors_rwsem); dev = hidraw_table[minor]; - if (!dev || !dev->exist) { + if (!dev || !dev->exist || hidraw_is_revoked(list)) { ret = -ENODEV; goto out; } @@ -421,6 +444,14 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, ret = -EFAULT; break; } + case HIDIOCREVOKE: + { + if (user_arg) + ret = -EINVAL; + else + ret = hidraw_revoke(list); + break; + } default: { struct hid_device *hid = dev->hid; @@ -527,7 +558,7 @@ int hidraw_report_event(struct hid_device *hid, u8 *data, int len) list_for_each_entry(list, &dev->list, node) { int new_head = (list->head + 1) & (HIDRAW_BUFFER_SIZE - 1); - if (new_head == list->tail) + if (hidraw_is_revoked(list) || new_head == list->tail) continue; if (!(list->buffer[list->head].value = kmemdup(data, len, GFP_ATOMIC))) { diff --git a/include/linux/hidraw.h b/include/linux/hidraw.h index cd67f4ca5599..18fd30a288de 100644 --- a/include/linux/hidraw.h +++ b/include/linux/hidraw.h @@ -32,6 +32,7 @@ struct hidraw_list { struct hidraw *hidraw; struct list_head node; struct mutex read_mutex; + bool revoked; }; #ifdef CONFIG_HIDRAW diff --git a/include/uapi/linux/hidraw.h b/include/uapi/linux/hidraw.h index 33ebad81720a..d5ee269864e0 100644 --- a/include/uapi/linux/hidraw.h +++ b/include/uapi/linux/hidraw.h @@ -46,6 +46,7 @@ struct hidraw_devinfo { /* The first byte of SOUTPUT and GOUTPUT is the report number */ #define HIDIOCSOUTPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0B, len) #define HIDIOCGOUTPUT(len) _IOC(_IOC_WRITE|_IOC_READ, 'H', 0x0C, len) +#define HIDIOCREVOKE _IOW('H', 0x0D, int) /* Revoke device access */ #define HIDRAW_FIRST_MINOR 0 #define HIDRAW_MAX_DEVICES 64 From 375e9bde9fc0fdb9e8d2339b06be5c2c2a5cb701 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Tue, 27 Aug 2024 17:19:30 +0900 Subject: [PATCH 25/54] selftests/hid: extract the utility part of hid_bpf.c into its own header When adding new tests programs, we need the same mechanics to create new virtual devices, and read from their matching hidraw node. Extract the common part into its own header so we can easily add new tests C-files. Link: https://patch.msgid.link/20240827-hidraw-revoke-v5-2-d004a7451aea@kernel.org Signed-off-by: Benjamin Tissoires --- tools/testing/selftests/hid/hid_bpf.c | 437 +---------------------- tools/testing/selftests/hid/hid_common.h | 436 ++++++++++++++++++++++ 2 files changed, 438 insertions(+), 435 deletions(-) create mode 100644 tools/testing/selftests/hid/hid_common.h diff --git a/tools/testing/selftests/hid/hid_bpf.c b/tools/testing/selftests/hid/hid_bpf.c index 75b7b4ef6cfa..d10cf6883683 100644 --- a/tools/testing/selftests/hid/hid_bpf.c +++ b/tools/testing/selftests/hid/hid_bpf.c @@ -1,93 +1,8 @@ // SPDX-License-Identifier: GPL-2.0 -/* Copyright (c) 2022 Red Hat */ +/* Copyright (c) 2022-2024 Red Hat */ #include "hid.skel.h" - -#include "../kselftest_harness.h" - +#include "hid_common.h" #include -#include -#include -#include -#include -#include -#include -#include -#include - -#define SHOW_UHID_DEBUG 0 - -#define min(a, b) \ - ({ __typeof__(a) _a = (a); \ - __typeof__(b) _b = (b); \ - _a < _b ? _a : _b; }) - -static unsigned char rdesc[] = { - 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */ - 0x09, 0x21, /* Usage (Vendor Usage 0x21) */ - 0xa1, 0x01, /* COLLECTION (Application) */ - 0x09, 0x01, /* Usage (Vendor Usage 0x01) */ - 0xa1, 0x00, /* COLLECTION (Physical) */ - 0x85, 0x02, /* REPORT_ID (2) */ - 0x19, 0x01, /* USAGE_MINIMUM (1) */ - 0x29, 0x08, /* USAGE_MAXIMUM (3) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ - 0x95, 0x08, /* REPORT_COUNT (8) */ - 0x75, 0x08, /* REPORT_SIZE (8) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0xc0, /* END_COLLECTION */ - 0x09, 0x01, /* Usage (Vendor Usage 0x01) */ - 0xa1, 0x00, /* COLLECTION (Physical) */ - 0x85, 0x01, /* REPORT_ID (1) */ - 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */ - 0x19, 0x01, /* USAGE_MINIMUM (1) */ - 0x29, 0x03, /* USAGE_MAXIMUM (3) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x95, 0x03, /* REPORT_COUNT (3) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x81, 0x02, /* INPUT (Data,Var,Abs) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x05, /* REPORT_SIZE (5) */ - 0x81, 0x01, /* INPUT (Cnst,Var,Abs) */ - 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ - 0x09, 0x30, /* USAGE (X) */ - 0x09, 0x31, /* USAGE (Y) */ - 0x15, 0x81, /* LOGICAL_MINIMUM (-127) */ - 0x25, 0x7f, /* LOGICAL_MAXIMUM (127) */ - 0x75, 0x10, /* REPORT_SIZE (16) */ - 0x95, 0x02, /* REPORT_COUNT (2) */ - 0x81, 0x06, /* INPUT (Data,Var,Rel) */ - - 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */ - 0x19, 0x01, /* USAGE_MINIMUM (1) */ - 0x29, 0x03, /* USAGE_MAXIMUM (3) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x95, 0x03, /* REPORT_COUNT (3) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0x91, 0x02, /* Output (Data,Var,Abs) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x05, /* REPORT_SIZE (5) */ - 0x91, 0x01, /* Output (Cnst,Var,Abs) */ - - 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */ - 0x19, 0x06, /* USAGE_MINIMUM (6) */ - 0x29, 0x08, /* USAGE_MAXIMUM (8) */ - 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ - 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ - 0x95, 0x03, /* REPORT_COUNT (3) */ - 0x75, 0x01, /* REPORT_SIZE (1) */ - 0xb1, 0x02, /* Feature (Data,Var,Abs) */ - 0x95, 0x01, /* REPORT_COUNT (1) */ - 0x75, 0x05, /* REPORT_SIZE (5) */ - 0x91, 0x01, /* Output (Cnst,Var,Abs) */ - - 0xc0, /* END_COLLECTION */ - 0xc0, /* END_COLLECTION */ -}; - -static __u8 feature_data[] = { 1, 2 }; struct attach_prog_args { int prog_fd; @@ -105,354 +20,6 @@ struct hid_hw_request_syscall_args { __u8 request_type; }; -#define ASSERT_OK(data) ASSERT_FALSE(data) -#define ASSERT_OK_PTR(ptr) ASSERT_NE(NULL, ptr) - -#define UHID_LOG(fmt, ...) do { \ - if (SHOW_UHID_DEBUG) \ - TH_LOG(fmt, ##__VA_ARGS__); \ -} while (0) - -static pthread_mutex_t uhid_started_mtx = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t uhid_started = PTHREAD_COND_INITIALIZER; - -static pthread_mutex_t uhid_output_mtx = PTHREAD_MUTEX_INITIALIZER; -static pthread_cond_t uhid_output_cond = PTHREAD_COND_INITIALIZER; -static unsigned char output_report[10]; - -/* no need to protect uhid_stopped, only one thread accesses it */ -static bool uhid_stopped; - -static int uhid_write(struct __test_metadata *_metadata, int fd, const struct uhid_event *ev) -{ - ssize_t ret; - - ret = write(fd, ev, sizeof(*ev)); - if (ret < 0) { - TH_LOG("Cannot write to uhid: %m"); - return -errno; - } else if (ret != sizeof(*ev)) { - TH_LOG("Wrong size written to uhid: %zd != %zu", - ret, sizeof(ev)); - return -EFAULT; - } else { - return 0; - } -} - -static int uhid_create(struct __test_metadata *_metadata, int fd, int rand_nb) -{ - struct uhid_event ev; - char buf[25]; - - sprintf(buf, "test-uhid-device-%d", rand_nb); - - memset(&ev, 0, sizeof(ev)); - ev.type = UHID_CREATE; - strcpy((char *)ev.u.create.name, buf); - ev.u.create.rd_data = rdesc; - ev.u.create.rd_size = sizeof(rdesc); - ev.u.create.bus = BUS_USB; - ev.u.create.vendor = 0x0001; - ev.u.create.product = 0x0a37; - ev.u.create.version = 0; - ev.u.create.country = 0; - - sprintf(buf, "%d", rand_nb); - strcpy((char *)ev.u.create.phys, buf); - - return uhid_write(_metadata, fd, &ev); -} - -static void uhid_destroy(struct __test_metadata *_metadata, int fd) -{ - struct uhid_event ev; - - memset(&ev, 0, sizeof(ev)); - ev.type = UHID_DESTROY; - - uhid_write(_metadata, fd, &ev); -} - -static int uhid_event(struct __test_metadata *_metadata, int fd) -{ - struct uhid_event ev, answer; - ssize_t ret; - - memset(&ev, 0, sizeof(ev)); - ret = read(fd, &ev, sizeof(ev)); - if (ret == 0) { - UHID_LOG("Read HUP on uhid-cdev"); - return -EFAULT; - } else if (ret < 0) { - UHID_LOG("Cannot read uhid-cdev: %m"); - return -errno; - } else if (ret != sizeof(ev)) { - UHID_LOG("Invalid size read from uhid-dev: %zd != %zu", - ret, sizeof(ev)); - return -EFAULT; - } - - switch (ev.type) { - case UHID_START: - pthread_mutex_lock(&uhid_started_mtx); - pthread_cond_signal(&uhid_started); - pthread_mutex_unlock(&uhid_started_mtx); - - UHID_LOG("UHID_START from uhid-dev"); - break; - case UHID_STOP: - uhid_stopped = true; - - UHID_LOG("UHID_STOP from uhid-dev"); - break; - case UHID_OPEN: - UHID_LOG("UHID_OPEN from uhid-dev"); - break; - case UHID_CLOSE: - UHID_LOG("UHID_CLOSE from uhid-dev"); - break; - case UHID_OUTPUT: - UHID_LOG("UHID_OUTPUT from uhid-dev"); - - pthread_mutex_lock(&uhid_output_mtx); - memcpy(output_report, - ev.u.output.data, - min(ev.u.output.size, sizeof(output_report))); - pthread_cond_signal(&uhid_output_cond); - pthread_mutex_unlock(&uhid_output_mtx); - break; - case UHID_GET_REPORT: - UHID_LOG("UHID_GET_REPORT from uhid-dev"); - - answer.type = UHID_GET_REPORT_REPLY; - answer.u.get_report_reply.id = ev.u.get_report.id; - answer.u.get_report_reply.err = ev.u.get_report.rnum == 1 ? 0 : -EIO; - answer.u.get_report_reply.size = sizeof(feature_data); - memcpy(answer.u.get_report_reply.data, feature_data, sizeof(feature_data)); - - uhid_write(_metadata, fd, &answer); - - break; - case UHID_SET_REPORT: - UHID_LOG("UHID_SET_REPORT from uhid-dev"); - break; - default: - TH_LOG("Invalid event from uhid-dev: %u", ev.type); - } - - return 0; -} - -struct uhid_thread_args { - int fd; - struct __test_metadata *_metadata; -}; -static void *uhid_read_events_thread(void *arg) -{ - struct uhid_thread_args *args = (struct uhid_thread_args *)arg; - struct __test_metadata *_metadata = args->_metadata; - struct pollfd pfds[1]; - int fd = args->fd; - int ret = 0; - - pfds[0].fd = fd; - pfds[0].events = POLLIN; - - uhid_stopped = false; - - while (!uhid_stopped) { - ret = poll(pfds, 1, 100); - if (ret < 0) { - TH_LOG("Cannot poll for fds: %m"); - break; - } - if (pfds[0].revents & POLLIN) { - ret = uhid_event(_metadata, fd); - if (ret) - break; - } - } - - return (void *)(long)ret; -} - -static int uhid_start_listener(struct __test_metadata *_metadata, pthread_t *tid, int uhid_fd) -{ - struct uhid_thread_args args = { - .fd = uhid_fd, - ._metadata = _metadata, - }; - int err; - - pthread_mutex_lock(&uhid_started_mtx); - err = pthread_create(tid, NULL, uhid_read_events_thread, (void *)&args); - ASSERT_EQ(0, err) { - TH_LOG("Could not start the uhid thread: %d", err); - pthread_mutex_unlock(&uhid_started_mtx); - close(uhid_fd); - return -EIO; - } - pthread_cond_wait(&uhid_started, &uhid_started_mtx); - pthread_mutex_unlock(&uhid_started_mtx); - - return 0; -} - -static int uhid_send_event(struct __test_metadata *_metadata, int fd, __u8 *buf, size_t size) -{ - struct uhid_event ev; - - if (size > sizeof(ev.u.input.data)) - return -E2BIG; - - memset(&ev, 0, sizeof(ev)); - ev.type = UHID_INPUT2; - ev.u.input2.size = size; - - memcpy(ev.u.input2.data, buf, size); - - return uhid_write(_metadata, fd, &ev); -} - -static int setup_uhid(struct __test_metadata *_metadata, int rand_nb) -{ - int fd; - const char *path = "/dev/uhid"; - int ret; - - fd = open(path, O_RDWR | O_CLOEXEC); - ASSERT_GE(fd, 0) TH_LOG("open uhid-cdev failed; %d", fd); - - ret = uhid_create(_metadata, fd, rand_nb); - ASSERT_EQ(0, ret) { - TH_LOG("create uhid device failed: %d", ret); - close(fd); - } - - return fd; -} - -static bool match_sysfs_device(int dev_id, const char *workdir, struct dirent *dir) -{ - const char *target = "0003:0001:0A37.*"; - char phys[512]; - char uevent[1024]; - char temp[512]; - int fd, nread; - bool found = false; - - if (fnmatch(target, dir->d_name, 0)) - return false; - - /* we found the correct VID/PID, now check for phys */ - sprintf(uevent, "%s/%s/uevent", workdir, dir->d_name); - - fd = open(uevent, O_RDONLY | O_NONBLOCK); - if (fd < 0) - return false; - - sprintf(phys, "PHYS=%d", dev_id); - - nread = read(fd, temp, ARRAY_SIZE(temp)); - if (nread > 0 && (strstr(temp, phys)) != NULL) - found = true; - - close(fd); - - return found; -} - -static int get_hid_id(int dev_id) -{ - const char *workdir = "/sys/devices/virtual/misc/uhid"; - const char *str_id; - DIR *d; - struct dirent *dir; - int found = -1, attempts = 3; - - /* it would be nice to be able to use nftw, but the no_alu32 target doesn't support it */ - - while (found < 0 && attempts > 0) { - attempts--; - d = opendir(workdir); - if (d) { - while ((dir = readdir(d)) != NULL) { - if (!match_sysfs_device(dev_id, workdir, dir)) - continue; - - str_id = dir->d_name + sizeof("0003:0001:0A37."); - found = (int)strtol(str_id, NULL, 16); - - break; - } - closedir(d); - } - if (found < 0) - usleep(100000); - } - - return found; -} - -static int get_hidraw(int dev_id) -{ - const char *workdir = "/sys/devices/virtual/misc/uhid"; - char sysfs[1024]; - DIR *d, *subd; - struct dirent *dir, *subdir; - int i, found = -1; - - /* retry 5 times in case the system is loaded */ - for (i = 5; i > 0; i--) { - usleep(10); - d = opendir(workdir); - - if (!d) - continue; - - while ((dir = readdir(d)) != NULL) { - if (!match_sysfs_device(dev_id, workdir, dir)) - continue; - - sprintf(sysfs, "%s/%s/hidraw", workdir, dir->d_name); - - subd = opendir(sysfs); - if (!subd) - continue; - - while ((subdir = readdir(subd)) != NULL) { - if (fnmatch("hidraw*", subdir->d_name, 0)) - continue; - - found = atoi(subdir->d_name + strlen("hidraw")); - } - - closedir(subd); - - if (found > 0) - break; - } - closedir(d); - } - - return found; -} - -static int open_hidraw(int dev_id) -{ - int hidraw_number; - char hidraw_path[64] = { 0 }; - - hidraw_number = get_hidraw(dev_id); - if (hidraw_number < 0) - return hidraw_number; - - /* open hidraw node to check the other side of the pipe */ - sprintf(hidraw_path, "/dev/hidraw%d", hidraw_number); - return open(hidraw_path, O_RDWR | O_NONBLOCK); -} - FIXTURE(hid_bpf) { int dev_id; int uhid_fd; diff --git a/tools/testing/selftests/hid/hid_common.h b/tools/testing/selftests/hid/hid_common.h new file mode 100644 index 000000000000..f151f151a1ed --- /dev/null +++ b/tools/testing/selftests/hid/hid_common.h @@ -0,0 +1,436 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* Copyright (c) 2022-2024 Red Hat */ + +#include "../kselftest_harness.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#define SHOW_UHID_DEBUG 0 + +#define min(a, b) \ + ({ __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a < _b ? _a : _b; }) + +static unsigned char rdesc[] = { + 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */ + 0x09, 0x21, /* Usage (Vendor Usage 0x21) */ + 0xa1, 0x01, /* COLLECTION (Application) */ + 0x09, 0x01, /* Usage (Vendor Usage 0x01) */ + 0xa1, 0x00, /* COLLECTION (Physical) */ + 0x85, 0x02, /* REPORT_ID (2) */ + 0x19, 0x01, /* USAGE_MINIMUM (1) */ + 0x29, 0x08, /* USAGE_MAXIMUM (3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0xff, /* LOGICAL_MAXIMUM (255) */ + 0x95, 0x08, /* REPORT_COUNT (8) */ + 0x75, 0x08, /* REPORT_SIZE (8) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + 0xc0, /* END_COLLECTION */ + 0x09, 0x01, /* Usage (Vendor Usage 0x01) */ + 0xa1, 0x00, /* COLLECTION (Physical) */ + 0x85, 0x01, /* REPORT_ID (1) */ + 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */ + 0x19, 0x01, /* USAGE_MINIMUM (1) */ + 0x29, 0x03, /* USAGE_MAXIMUM (3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x03, /* REPORT_COUNT (3) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x81, 0x02, /* INPUT (Data,Var,Abs) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x05, /* REPORT_SIZE (5) */ + 0x81, 0x01, /* INPUT (Cnst,Var,Abs) */ + 0x05, 0x01, /* USAGE_PAGE (Generic Desktop) */ + 0x09, 0x30, /* USAGE (X) */ + 0x09, 0x31, /* USAGE (Y) */ + 0x15, 0x81, /* LOGICAL_MINIMUM (-127) */ + 0x25, 0x7f, /* LOGICAL_MAXIMUM (127) */ + 0x75, 0x10, /* REPORT_SIZE (16) */ + 0x95, 0x02, /* REPORT_COUNT (2) */ + 0x81, 0x06, /* INPUT (Data,Var,Rel) */ + + 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */ + 0x19, 0x01, /* USAGE_MINIMUM (1) */ + 0x29, 0x03, /* USAGE_MAXIMUM (3) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x03, /* REPORT_COUNT (3) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0x91, 0x02, /* Output (Data,Var,Abs) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x05, /* REPORT_SIZE (5) */ + 0x91, 0x01, /* Output (Cnst,Var,Abs) */ + + 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */ + 0x19, 0x06, /* USAGE_MINIMUM (6) */ + 0x29, 0x08, /* USAGE_MAXIMUM (8) */ + 0x15, 0x00, /* LOGICAL_MINIMUM (0) */ + 0x25, 0x01, /* LOGICAL_MAXIMUM (1) */ + 0x95, 0x03, /* REPORT_COUNT (3) */ + 0x75, 0x01, /* REPORT_SIZE (1) */ + 0xb1, 0x02, /* Feature (Data,Var,Abs) */ + 0x95, 0x01, /* REPORT_COUNT (1) */ + 0x75, 0x05, /* REPORT_SIZE (5) */ + 0x91, 0x01, /* Output (Cnst,Var,Abs) */ + + 0xc0, /* END_COLLECTION */ + 0xc0, /* END_COLLECTION */ +}; + +static __u8 feature_data[] = { 1, 2 }; + +#define ASSERT_OK(data) ASSERT_FALSE(data) +#define ASSERT_OK_PTR(ptr) ASSERT_NE(NULL, ptr) + +#define UHID_LOG(fmt, ...) do { \ + if (SHOW_UHID_DEBUG) \ + TH_LOG(fmt, ##__VA_ARGS__); \ +} while (0) + +static pthread_mutex_t uhid_started_mtx = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t uhid_started = PTHREAD_COND_INITIALIZER; + +static pthread_mutex_t uhid_output_mtx = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t uhid_output_cond = PTHREAD_COND_INITIALIZER; +static unsigned char output_report[10]; + +/* no need to protect uhid_stopped, only one thread accesses it */ +static bool uhid_stopped; + +static int uhid_write(struct __test_metadata *_metadata, int fd, const struct uhid_event *ev) +{ + ssize_t ret; + + ret = write(fd, ev, sizeof(*ev)); + if (ret < 0) { + TH_LOG("Cannot write to uhid: %m"); + return -errno; + } else if (ret != sizeof(*ev)) { + TH_LOG("Wrong size written to uhid: %zd != %zu", + ret, sizeof(ev)); + return -EFAULT; + } else { + return 0; + } +} + +static int uhid_create(struct __test_metadata *_metadata, int fd, int rand_nb) +{ + struct uhid_event ev; + char buf[25]; + + sprintf(buf, "test-uhid-device-%d", rand_nb); + + memset(&ev, 0, sizeof(ev)); + ev.type = UHID_CREATE; + strcpy((char *)ev.u.create.name, buf); + ev.u.create.rd_data = rdesc; + ev.u.create.rd_size = sizeof(rdesc); + ev.u.create.bus = BUS_USB; + ev.u.create.vendor = 0x0001; + ev.u.create.product = 0x0a37; + ev.u.create.version = 0; + ev.u.create.country = 0; + + sprintf(buf, "%d", rand_nb); + strcpy((char *)ev.u.create.phys, buf); + + return uhid_write(_metadata, fd, &ev); +} + +static void uhid_destroy(struct __test_metadata *_metadata, int fd) +{ + struct uhid_event ev; + + memset(&ev, 0, sizeof(ev)); + ev.type = UHID_DESTROY; + + uhid_write(_metadata, fd, &ev); +} + +static int uhid_event(struct __test_metadata *_metadata, int fd) +{ + struct uhid_event ev, answer; + ssize_t ret; + + memset(&ev, 0, sizeof(ev)); + ret = read(fd, &ev, sizeof(ev)); + if (ret == 0) { + UHID_LOG("Read HUP on uhid-cdev"); + return -EFAULT; + } else if (ret < 0) { + UHID_LOG("Cannot read uhid-cdev: %m"); + return -errno; + } else if (ret != sizeof(ev)) { + UHID_LOG("Invalid size read from uhid-dev: %zd != %zu", + ret, sizeof(ev)); + return -EFAULT; + } + + switch (ev.type) { + case UHID_START: + pthread_mutex_lock(&uhid_started_mtx); + pthread_cond_signal(&uhid_started); + pthread_mutex_unlock(&uhid_started_mtx); + + UHID_LOG("UHID_START from uhid-dev"); + break; + case UHID_STOP: + uhid_stopped = true; + + UHID_LOG("UHID_STOP from uhid-dev"); + break; + case UHID_OPEN: + UHID_LOG("UHID_OPEN from uhid-dev"); + break; + case UHID_CLOSE: + UHID_LOG("UHID_CLOSE from uhid-dev"); + break; + case UHID_OUTPUT: + UHID_LOG("UHID_OUTPUT from uhid-dev"); + + pthread_mutex_lock(&uhid_output_mtx); + memcpy(output_report, + ev.u.output.data, + min(ev.u.output.size, sizeof(output_report))); + pthread_cond_signal(&uhid_output_cond); + pthread_mutex_unlock(&uhid_output_mtx); + break; + case UHID_GET_REPORT: + UHID_LOG("UHID_GET_REPORT from uhid-dev"); + + answer.type = UHID_GET_REPORT_REPLY; + answer.u.get_report_reply.id = ev.u.get_report.id; + answer.u.get_report_reply.err = ev.u.get_report.rnum == 1 ? 0 : -EIO; + answer.u.get_report_reply.size = sizeof(feature_data); + memcpy(answer.u.get_report_reply.data, feature_data, sizeof(feature_data)); + + uhid_write(_metadata, fd, &answer); + + break; + case UHID_SET_REPORT: + UHID_LOG("UHID_SET_REPORT from uhid-dev"); + break; + default: + TH_LOG("Invalid event from uhid-dev: %u", ev.type); + } + + return 0; +} + +struct uhid_thread_args { + int fd; + struct __test_metadata *_metadata; +}; +static void *uhid_read_events_thread(void *arg) +{ + struct uhid_thread_args *args = (struct uhid_thread_args *)arg; + struct __test_metadata *_metadata = args->_metadata; + struct pollfd pfds[1]; + int fd = args->fd; + int ret = 0; + + pfds[0].fd = fd; + pfds[0].events = POLLIN; + + uhid_stopped = false; + + while (!uhid_stopped) { + ret = poll(pfds, 1, 100); + if (ret < 0) { + TH_LOG("Cannot poll for fds: %m"); + break; + } + if (pfds[0].revents & POLLIN) { + ret = uhid_event(_metadata, fd); + if (ret) + break; + } + } + + return (void *)(long)ret; +} + +static int uhid_start_listener(struct __test_metadata *_metadata, pthread_t *tid, int uhid_fd) +{ + struct uhid_thread_args args = { + .fd = uhid_fd, + ._metadata = _metadata, + }; + int err; + + pthread_mutex_lock(&uhid_started_mtx); + err = pthread_create(tid, NULL, uhid_read_events_thread, (void *)&args); + ASSERT_EQ(0, err) { + TH_LOG("Could not start the uhid thread: %d", err); + pthread_mutex_unlock(&uhid_started_mtx); + close(uhid_fd); + return -EIO; + } + pthread_cond_wait(&uhid_started, &uhid_started_mtx); + pthread_mutex_unlock(&uhid_started_mtx); + + return 0; +} + +static int uhid_send_event(struct __test_metadata *_metadata, int fd, __u8 *buf, size_t size) +{ + struct uhid_event ev; + + if (size > sizeof(ev.u.input.data)) + return -E2BIG; + + memset(&ev, 0, sizeof(ev)); + ev.type = UHID_INPUT2; + ev.u.input2.size = size; + + memcpy(ev.u.input2.data, buf, size); + + return uhid_write(_metadata, fd, &ev); +} + +static int setup_uhid(struct __test_metadata *_metadata, int rand_nb) +{ + int fd; + const char *path = "/dev/uhid"; + int ret; + + fd = open(path, O_RDWR | O_CLOEXEC); + ASSERT_GE(fd, 0) TH_LOG("open uhid-cdev failed; %d", fd); + + ret = uhid_create(_metadata, fd, rand_nb); + ASSERT_EQ(0, ret) { + TH_LOG("create uhid device failed: %d", ret); + close(fd); + } + + return fd; +} + +static bool match_sysfs_device(int dev_id, const char *workdir, struct dirent *dir) +{ + const char *target = "0003:0001:0A37.*"; + char phys[512]; + char uevent[1024]; + char temp[512]; + int fd, nread; + bool found = false; + + if (fnmatch(target, dir->d_name, 0)) + return false; + + /* we found the correct VID/PID, now check for phys */ + sprintf(uevent, "%s/%s/uevent", workdir, dir->d_name); + + fd = open(uevent, O_RDONLY | O_NONBLOCK); + if (fd < 0) + return false; + + sprintf(phys, "PHYS=%d", dev_id); + + nread = read(fd, temp, ARRAY_SIZE(temp)); + if (nread > 0 && (strstr(temp, phys)) != NULL) + found = true; + + close(fd); + + return found; +} + +static int get_hid_id(int dev_id) +{ + const char *workdir = "/sys/devices/virtual/misc/uhid"; + const char *str_id; + DIR *d; + struct dirent *dir; + int found = -1, attempts = 3; + + /* it would be nice to be able to use nftw, but the no_alu32 target doesn't support it */ + + while (found < 0 && attempts > 0) { + attempts--; + d = opendir(workdir); + if (d) { + while ((dir = readdir(d)) != NULL) { + if (!match_sysfs_device(dev_id, workdir, dir)) + continue; + + str_id = dir->d_name + sizeof("0003:0001:0A37."); + found = (int)strtol(str_id, NULL, 16); + + break; + } + closedir(d); + } + if (found < 0) + usleep(100000); + } + + return found; +} + +static int get_hidraw(int dev_id) +{ + const char *workdir = "/sys/devices/virtual/misc/uhid"; + char sysfs[1024]; + DIR *d, *subd; + struct dirent *dir, *subdir; + int i, found = -1; + + /* retry 5 times in case the system is loaded */ + for (i = 5; i > 0; i--) { + usleep(10); + d = opendir(workdir); + + if (!d) + continue; + + while ((dir = readdir(d)) != NULL) { + if (!match_sysfs_device(dev_id, workdir, dir)) + continue; + + sprintf(sysfs, "%s/%s/hidraw", workdir, dir->d_name); + + subd = opendir(sysfs); + if (!subd) + continue; + + while ((subdir = readdir(subd)) != NULL) { + if (fnmatch("hidraw*", subdir->d_name, 0)) + continue; + + found = atoi(subdir->d_name + strlen("hidraw")); + } + + closedir(subd); + + if (found > 0) + break; + } + closedir(d); + } + + return found; +} + +static int open_hidraw(int dev_id) +{ + int hidraw_number; + char hidraw_path[64] = { 0 }; + + hidraw_number = get_hidraw(dev_id); + if (hidraw_number < 0) + return hidraw_number; + + /* open hidraw node to check the other side of the pipe */ + sprintf(hidraw_path, "/dev/hidraw%d", hidraw_number); + return open(hidraw_path, O_RDWR | O_NONBLOCK); +} From 8163892a629ca544af575ce54955bf275a3250cd Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Tue, 27 Aug 2024 17:19:31 +0900 Subject: [PATCH 26/54] selftests/hid: Add initial hidraw tests skeleton Largely inspired from hid_bpf.c for the fixture setup. Create a couple of tests for hidraw: - create a uhid device and check if the fixture is working properly - inject one uhid event and read it through hidraw These tests are not that useful for now, but will be once we start adding the ioctl and BPFs to revoke the hidraw node. Reviewed-by: Peter Hutterer Link: https://patch.msgid.link/20240827-hidraw-revoke-v5-3-d004a7451aea@kernel.org Signed-off-by: Benjamin Tissoires --- tools/testing/selftests/hid/.gitignore | 1 + tools/testing/selftests/hid/Makefile | 2 +- tools/testing/selftests/hid/hidraw.c | 90 ++++++++++++++++++++++++++ 3 files changed, 92 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/hid/hidraw.c diff --git a/tools/testing/selftests/hid/.gitignore b/tools/testing/selftests/hid/.gitignore index 995af0670f69..746c62361f77 100644 --- a/tools/testing/selftests/hid/.gitignore +++ b/tools/testing/selftests/hid/.gitignore @@ -2,4 +2,5 @@ bpftool *.skel.h /tools hid_bpf +hidraw results diff --git a/tools/testing/selftests/hid/Makefile b/tools/testing/selftests/hid/Makefile index 2b5ea18bde38..72be55ac4bdf 100644 --- a/tools/testing/selftests/hid/Makefile +++ b/tools/testing/selftests/hid/Makefile @@ -32,7 +32,7 @@ CFLAGS += -Wno-unused-command-line-argument endif # Order correspond to 'make run_tests' order -TEST_GEN_PROGS = hid_bpf +TEST_GEN_PROGS = hid_bpf hidraw # Emit succinct information message describing current building step # $1 - generic step name (e.g., CC, LINK, etc); diff --git a/tools/testing/selftests/hid/hidraw.c b/tools/testing/selftests/hid/hidraw.c new file mode 100644 index 000000000000..37372709130c --- /dev/null +++ b/tools/testing/selftests/hid/hidraw.c @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2022-2024 Red Hat */ + +#include "hid_common.h" + +FIXTURE(hidraw) { + int dev_id; + int uhid_fd; + int hidraw_fd; + int hid_id; + pthread_t tid; +}; +static void close_hidraw(FIXTURE_DATA(hidraw) * self) +{ + if (self->hidraw_fd) + close(self->hidraw_fd); + self->hidraw_fd = 0; +} + +FIXTURE_TEARDOWN(hidraw) { + void *uhid_err; + + uhid_destroy(_metadata, self->uhid_fd); + + close_hidraw(self); + pthread_join(self->tid, &uhid_err); +} +#define TEARDOWN_LOG(fmt, ...) do { \ + TH_LOG(fmt, ##__VA_ARGS__); \ + hidraw_teardown(_metadata, self, variant); \ +} while (0) + +FIXTURE_SETUP(hidraw) +{ + time_t t; + int err; + + /* initialize random number generator */ + srand((unsigned int)time(&t)); + + self->dev_id = rand() % 1024; + + self->uhid_fd = setup_uhid(_metadata, self->dev_id); + + /* locate the uev, self, variant);ent file of the created device */ + self->hid_id = get_hid_id(self->dev_id); + ASSERT_GT(self->hid_id, 0) + TEARDOWN_LOG("Could not locate uhid device id: %d", self->hid_id); + + err = uhid_start_listener(_metadata, &self->tid, self->uhid_fd); + ASSERT_EQ(0, err) TEARDOWN_LOG("could not start udev listener: %d", err); + + self->hidraw_fd = open_hidraw(self->dev_id); + ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw"); +} + +/* + * A simple test to see if the fixture is working fine. + * If this fails, none of the other tests will pass. + */ +TEST_F(hidraw, test_create_uhid) +{ +} + +/* + * Inject one event in the uhid device, + * check that we get the same data through hidraw + */ +TEST_F(hidraw, raw_event) +{ + __u8 buf[10] = {0}; + int err; + + /* inject one event */ + buf[0] = 1; + buf[1] = 42; + uhid_send_event(_metadata, self->uhid_fd, buf, 6); + + /* read the data from hidraw */ + memset(buf, 0, sizeof(buf)); + err = read(self->hidraw_fd, buf, sizeof(buf)); + ASSERT_EQ(err, 6) TH_LOG("read_hidraw"); + ASSERT_EQ(buf[0], 1); + ASSERT_EQ(buf[1], 42); +} + +int main(int argc, char **argv) +{ + return test_harness_run(argc, argv); +} From 321f7798cfb8d834ae0ed0d467c8bf46804243f9 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Tue, 27 Aug 2024 17:19:32 +0900 Subject: [PATCH 27/54] selftests/hid: Add HIDIOCREVOKE tests Add 4 tests for the new revoke ioctl, for read/write/ioctl and poll. Reviewed-by: Peter Hutterer Link: https://patch.msgid.link/20240827-hidraw-revoke-v5-4-d004a7451aea@kernel.org Signed-off-by: Benjamin Tissoires --- tools/testing/selftests/hid/hidraw.c | 147 +++++++++++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/tools/testing/selftests/hid/hidraw.c b/tools/testing/selftests/hid/hidraw.c index 37372709130c..f8b4f7ff292c 100644 --- a/tools/testing/selftests/hid/hidraw.c +++ b/tools/testing/selftests/hid/hidraw.c @@ -3,6 +3,11 @@ #include "hid_common.h" +/* for older kernels */ +#ifndef HIDIOCREVOKE +#define HIDIOCREVOKE _IOW('H', 0x0D, int) /* Revoke device access */ +#endif /* HIDIOCREVOKE */ + FIXTURE(hidraw) { int dev_id; int uhid_fd; @@ -84,6 +89,148 @@ TEST_F(hidraw, raw_event) ASSERT_EQ(buf[1], 42); } +/* + * After initial opening/checks of hidraw, revoke the hidraw + * node and check that we can not read any more data. + */ +TEST_F(hidraw, raw_event_revoked) +{ + __u8 buf[10] = {0}; + int err; + + /* inject one event */ + buf[0] = 1; + buf[1] = 42; + uhid_send_event(_metadata, self->uhid_fd, buf, 6); + + /* read the data from hidraw */ + memset(buf, 0, sizeof(buf)); + err = read(self->hidraw_fd, buf, sizeof(buf)); + ASSERT_EQ(err, 6) TH_LOG("read_hidraw"); + ASSERT_EQ(buf[0], 1); + ASSERT_EQ(buf[1], 42); + + /* call the revoke ioctl */ + err = ioctl(self->hidraw_fd, HIDIOCREVOKE, NULL); + ASSERT_OK(err) TH_LOG("couldn't revoke the hidraw fd"); + + /* inject one other event */ + buf[0] = 1; + buf[1] = 43; + uhid_send_event(_metadata, self->uhid_fd, buf, 6); + + /* read the data from hidraw */ + memset(buf, 0, sizeof(buf)); + err = read(self->hidraw_fd, buf, sizeof(buf)); + ASSERT_EQ(err, -1) TH_LOG("read_hidraw"); + ASSERT_EQ(errno, ENODEV) TH_LOG("unexpected error code while reading the hidraw node: %d", + errno); +} + +/* + * Revoke the hidraw node and check that we can not do any ioctl. + */ +TEST_F(hidraw, ioctl_revoked) +{ + int err, desc_size = 0; + + /* call the revoke ioctl */ + err = ioctl(self->hidraw_fd, HIDIOCREVOKE, NULL); + ASSERT_OK(err) TH_LOG("couldn't revoke the hidraw fd"); + + /* do an ioctl */ + err = ioctl(self->hidraw_fd, HIDIOCGRDESCSIZE, &desc_size); + ASSERT_EQ(err, -1) TH_LOG("ioctl_hidraw"); + ASSERT_EQ(errno, ENODEV) TH_LOG("unexpected error code while doing an ioctl: %d", + errno); +} + +/* + * Setup polling of the fd, and check that revoke works properly. + */ +TEST_F(hidraw, poll_revoked) +{ + struct pollfd pfds[1]; + __u8 buf[10] = {0}; + int err, ready; + + /* setup polling */ + pfds[0].fd = self->hidraw_fd; + pfds[0].events = POLLIN; + + /* inject one event */ + buf[0] = 1; + buf[1] = 42; + uhid_send_event(_metadata, self->uhid_fd, buf, 6); + + while (true) { + ready = poll(pfds, 1, 5000); + ASSERT_EQ(ready, 1) TH_LOG("poll return value"); + + if (pfds[0].revents & POLLIN) { + memset(buf, 0, sizeof(buf)); + err = read(self->hidraw_fd, buf, sizeof(buf)); + ASSERT_EQ(err, 6) TH_LOG("read_hidraw"); + ASSERT_EQ(buf[0], 1); + ASSERT_EQ(buf[1], 42); + + /* call the revoke ioctl */ + err = ioctl(self->hidraw_fd, HIDIOCREVOKE, NULL); + ASSERT_OK(err) TH_LOG("couldn't revoke the hidraw fd"); + } else { + break; + } + } + + ASSERT_TRUE(pfds[0].revents & POLLHUP); +} + +/* + * After initial opening/checks of hidraw, revoke the hidraw + * node and check that we can not read any more data. + */ +TEST_F(hidraw, write_event_revoked) +{ + struct timespec time_to_wait; + __u8 buf[10] = {0}; + int err; + + /* inject one event from hidraw */ + buf[0] = 1; /* report ID */ + buf[1] = 2; + buf[2] = 42; + + pthread_mutex_lock(&uhid_output_mtx); + + memset(output_report, 0, sizeof(output_report)); + clock_gettime(CLOCK_REALTIME, &time_to_wait); + time_to_wait.tv_sec += 2; + + err = write(self->hidraw_fd, buf, 3); + ASSERT_EQ(err, 3) TH_LOG("unexpected error while writing to hidraw node: %d", err); + + err = pthread_cond_timedwait(&uhid_output_cond, &uhid_output_mtx, &time_to_wait); + ASSERT_OK(err) TH_LOG("error while calling waiting for the condition"); + + ASSERT_EQ(output_report[0], 1); + ASSERT_EQ(output_report[1], 2); + ASSERT_EQ(output_report[2], 42); + + /* call the revoke ioctl */ + err = ioctl(self->hidraw_fd, HIDIOCREVOKE, NULL); + ASSERT_OK(err) TH_LOG("couldn't revoke the hidraw fd"); + + /* inject one other event */ + buf[0] = 1; + buf[1] = 43; + err = write(self->hidraw_fd, buf, 3); + ASSERT_LT(err, 0) TH_LOG("unexpected success while writing to hidraw node: %d", err); + ASSERT_EQ(errno, ENODEV) TH_LOG("unexpected error code while writing to hidraw node: %d", + errno); + + pthread_mutex_unlock(&uhid_output_mtx); +} + int main(int argc, char **argv) { return test_harness_run(argc, argv); From 252ed1f7f7c657812ee864a9dad0a935f7bed08b Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 29 Aug 2024 22:30:39 +0300 Subject: [PATCH 28/54] HID: hid-goodix: Fix type promotion bug in goodix_hid_get_raw_report() The issue is GOODIX_HID_PKG_LEN_SIZE is defined as sizeof(u16) which is type size_t. However, goodix_hid_check_ack_status() returns negative error codes or potentially a positive but invalid length which is too small. So when we compare "if ((response_data_len <= GOODIX_HID_PKG_LEN_SIZE)" then negative error codes are type promoted to size_t and counted as a positive large value and treated as valid. It would have been easy enough to add some casting to avoid the type promotion, however this patch takes a more thourough approach and moves the length check into goodix_hid_check_ack_status(). Now the function only return negative error codes or zero on success and the length pointer is never set to an invalid length. Fixes: 75e16c8ce283 ("HID: hid-goodix: Add Goodix HID-over-SPI driver") Signed-off-by: Dan Carpenter Reviewed-by: Dmitry Torokhov Signed-off-by: Jiri Kosina --- drivers/hid/hid-goodix-spi.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/drivers/hid/hid-goodix-spi.c b/drivers/hid/hid-goodix-spi.c index 5103bf0aada4..de655f745d3f 100644 --- a/drivers/hid/hid-goodix-spi.c +++ b/drivers/hid/hid-goodix-spi.c @@ -335,11 +335,12 @@ static void goodix_hid_close(struct hid_device *hid) } /* Return date length of response data */ -static int goodix_hid_check_ack_status(struct goodix_ts_data *ts) +static int goodix_hid_check_ack_status(struct goodix_ts_data *ts, u32 *resp_len) { struct goodix_hid_report_header hdr; int retry = 20; int error; + int len; while (retry--) { /* @@ -349,8 +350,15 @@ static int goodix_hid_check_ack_status(struct goodix_ts_data *ts) */ error = goodix_spi_read(ts, ts->hid_report_addr, &hdr, sizeof(hdr)); - if (!error && (hdr.flag & GOODIX_HID_ACK_READY_FLAG)) - return le16_to_cpu(hdr.size); + if (!error && (hdr.flag & GOODIX_HID_ACK_READY_FLAG)) { + len = le16_to_cpu(hdr.size); + if (len < GOODIX_HID_PKG_LEN_SIZE) { + dev_err(ts->dev, "hrd.size too short: %d", len); + return -EINVAL; + } + *resp_len = len; + return 0; + } /* Wait 10ms for another try */ usleep_range(10000, 11000); @@ -383,7 +391,7 @@ static int goodix_hid_get_raw_report(struct hid_device *hid, u16 cmd_register = le16_to_cpu(ts->hid_desc.cmd_register); u8 tmp_buf[GOODIX_HID_MAX_INBUF_SIZE]; int tx_len = 0, args_len = 0; - int response_data_len; + u32 response_data_len; u8 args[3]; int error; @@ -434,9 +442,9 @@ static int goodix_hid_get_raw_report(struct hid_device *hid, return 0; /* Step2: check response data status */ - response_data_len = goodix_hid_check_ack_status(ts); - if (response_data_len <= GOODIX_HID_PKG_LEN_SIZE) - return -EINVAL; + error = goodix_hid_check_ack_status(ts, &response_data_len); + if (error) + return error; len = min(len, response_data_len - GOODIX_HID_PKG_LEN_SIZE); /* Step3: read response data(skip 2bytes of hid pkg length) */ From e0808d7a63b8c03ea4f55b31b5cef4221eae9f34 Mon Sep 17 00:00:00 2001 From: Zhaoxiong Lv Date: Mon, 22 Jul 2024 15:31:35 +0800 Subject: [PATCH 29/54] dt-bindings: HID: i2c-hid: elan: Introduce Elan ekth6a12nay The Elan ekth6a12nay touch screen chip same as Elan eKTH6915 controller has a reset gpio. The difference is that they have different post_power_delay_ms. Acked-by: Rob Herring (Arm) Signed-off-by: Zhaoxiong Lv Signed-off-by: Jiri Kosina --- Documentation/devicetree/bindings/input/elan,ekth6915.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/input/elan,ekth6915.yaml b/Documentation/devicetree/bindings/input/elan,ekth6915.yaml index a62916d07a08..cb3e1801b0d3 100644 --- a/Documentation/devicetree/bindings/input/elan,ekth6915.yaml +++ b/Documentation/devicetree/bindings/input/elan,ekth6915.yaml @@ -23,7 +23,9 @@ properties: - enum: - elan,ekth5015m - const: elan,ekth6915 - - const: elan,ekth6915 + - enum: + - elan,ekth6915 + - elan,ekth6a12nay reg: const: 0x10 From d06651bebf99e51259ecfe9e63c42179abc1288c Mon Sep 17 00:00:00 2001 From: Zhaoxiong Lv Date: Mon, 22 Jul 2024 15:31:36 +0800 Subject: [PATCH 30/54] HID: i2c-hid: elan: Add elan-ekth6a12nay timing Elan-ekth6a12nay requires reset to pull down time greater than 10ms, so the configuration post_power_delay_ms is 10, and the chipset initial time is required to be greater than 300ms, so the post_gpio_reset_on_delay_ms is set to 300. Reviewed-by: Douglas Anderson Signed-off-by: Zhaoxiong Lv Signed-off-by: Jiri Kosina --- drivers/hid/i2c-hid/i2c-hid-of-elan.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/hid/i2c-hid/i2c-hid-of-elan.c b/drivers/hid/i2c-hid/i2c-hid-of-elan.c index 091e37933225..3fcff6daa0d3 100644 --- a/drivers/hid/i2c-hid/i2c-hid-of-elan.c +++ b/drivers/hid/i2c-hid/i2c-hid-of-elan.c @@ -152,6 +152,13 @@ static const struct elan_i2c_hid_chip_data elan_ekth6915_chip_data = { .main_supply_name = "vcc33", }; +static const struct elan_i2c_hid_chip_data elan_ekth6a12nay_chip_data = { + .post_power_delay_ms = 10, + .post_gpio_reset_on_delay_ms = 300, + .hid_descriptor_address = 0x0001, + .main_supply_name = "vcc33", +}; + static const struct elan_i2c_hid_chip_data ilitek_ili9882t_chip_data = { .post_power_delay_ms = 1, .post_gpio_reset_on_delay_ms = 200, @@ -174,6 +181,7 @@ static const struct elan_i2c_hid_chip_data ilitek_ili2901_chip_data = { static const struct of_device_id elan_i2c_hid_of_match[] = { { .compatible = "elan,ekth6915", .data = &elan_ekth6915_chip_data }, + { .compatible = "elan,ekth6a12nay", .data = &elan_ekth6a12nay_chip_data }, { .compatible = "ilitek,ili9882t", .data = &ilitek_ili9882t_chip_data }, { .compatible = "ilitek,ili2901", .data = &ilitek_ili2901_chip_data }, { } From 8417b265e1e6cf5101edc3a1a0fb219db20f554e Mon Sep 17 00:00:00 2001 From: Chen Ni Date: Tue, 3 Sep 2024 10:44:02 +0800 Subject: [PATCH 31/54] HID: amd_sfh: Convert comma to semicolon Replace a comma between expression statements by a semicolon. Signed-off-by: Chen Ni Acked-by: Basavaraj Natikar Signed-off-by: Jiri Kosina --- drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c index 621793d92464..db36d87d5634 100644 --- a/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c +++ b/drivers/hid/amd-sfh-hid/sfh1_1/amd_sfh_init.c @@ -299,8 +299,8 @@ static void amd_sfh_set_ops(struct amd_mp2_dev *mp2) sfh_interface_init(mp2); mp2_ops = mp2->mp2_ops; - mp2_ops->clear_intr = amd_sfh_clear_intr_v2, - mp2_ops->init_intr = amd_sfh_irq_init_v2, + mp2_ops->clear_intr = amd_sfh_clear_intr_v2; + mp2_ops->init_intr = amd_sfh_irq_init_v2; mp2_ops->suspend = amd_sfh_suspend; mp2_ops->resume = amd_sfh_resume; mp2_ops->remove = amd_mp2_pci_remove; From 251efae73bd46b097deec4f9986d926813aed744 Mon Sep 17 00:00:00 2001 From: He Lugang Date: Tue, 27 Aug 2024 10:56:05 +0800 Subject: [PATCH 32/54] HID: multitouch: Add support for lenovo Y9000P Touchpad The 2024 Lenovo Y9000P which use GT7868Q chip also needs a fixup. The information of the chip is as follows: I2C HID v1.00 Mouse [GXTP5100:00 27C6:01E0] Signed-off-by: He Lugang Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-multitouch.c | 8 ++++++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 781c5aa29859..cb804b630653 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -521,6 +521,7 @@ #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100 0xe100 #define I2C_VENDOR_ID_GOODIX 0x27c6 +#define I2C_DEVICE_ID_GOODIX_01E0 0x01e0 #define I2C_DEVICE_ID_GOODIX_01E8 0x01e8 #define I2C_DEVICE_ID_GOODIX_01E9 0x01e9 #define I2C_DEVICE_ID_GOODIX_01F0 0x01f0 diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 99812c0f830b..0faaa2c23d2e 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -1446,7 +1446,8 @@ static __u8 *mt_report_fixup(struct hid_device *hdev, __u8 *rdesc, { if (hdev->vendor == I2C_VENDOR_ID_GOODIX && (hdev->product == I2C_DEVICE_ID_GOODIX_01E8 || - hdev->product == I2C_DEVICE_ID_GOODIX_01E9)) { + hdev->product == I2C_DEVICE_ID_GOODIX_01E9 || + hdev->product == I2C_DEVICE_ID_GOODIX_01E0)) { if (rdesc[607] == 0x15) { rdesc[607] = 0x25; dev_info( @@ -2065,7 +2066,10 @@ static const struct hid_device_id mt_devices[] = { I2C_DEVICE_ID_GOODIX_01E8) }, { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT_NSMU, HID_DEVICE(BUS_I2C, HID_GROUP_ANY, I2C_VENDOR_ID_GOODIX, - I2C_DEVICE_ID_GOODIX_01E8) }, + I2C_DEVICE_ID_GOODIX_01E9) }, + { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT_NSMU, + HID_DEVICE(BUS_I2C, HID_GROUP_ANY, I2C_VENDOR_ID_GOODIX, + I2C_DEVICE_ID_GOODIX_01E0) }, /* GoodTouch panels */ { .driver_data = MT_CLS_NSMU, From de07af0ab02edcd4665deafc7373c5b13fb82db1 Mon Sep 17 00:00:00 2001 From: tammy tseng Date: Tue, 6 Aug 2024 16:25:32 +0800 Subject: [PATCH 33/54] HID: add patch for sis multitouch format The patch is to add proper quirks for sis multitouch format Signed-off-by: tammy tseng Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 0faaa2c23d2e..35a6d3f29f59 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -212,6 +212,7 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app); #define MT_CLS_GOOGLE 0x0111 #define MT_CLS_RAZER_BLADE_STEALTH 0x0112 #define MT_CLS_SMART_TECH 0x0113 +#define MT_CLS_SIS 0x0457 #define MT_DEFAULT_MAXCONTACT 10 #define MT_MAX_MAXCONTACT 250 @@ -396,6 +397,11 @@ static const struct mt_class mt_classes[] = { MT_QUIRK_CONTACT_CNT_ACCURATE | MT_QUIRK_SEPARATE_APP_REPORT, }, + { .name = MT_CLS_SIS, + .quirks = MT_QUIRK_NOT_SEEN_MEANS_UP | + MT_QUIRK_ALWAYS_VALID | + MT_QUIRK_CONTACT_CNT_ACCURATE, + }, { } }; @@ -1812,6 +1818,9 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) if (mtclass->quirks & MT_QUIRK_FIX_CONST_CONTACT_ID) mt_fix_const_fields(hdev, HID_DG_CONTACTID); + if (hdev->vendor == USB_VENDOR_ID_SIS_TOUCH) + hdev->quirks |= HID_QUIRK_NOGET; + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); if (ret) return ret; @@ -2279,6 +2288,11 @@ static const struct hid_device_id mt_devices[] = { HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8, USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_WHISKERS) }, + /* sis */ + { .driver_data = MT_CLS_SIS, + HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_SIS_TOUCH, + HID_ANY_ID) }, + /* Generic MT device */ { HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) }, From d11cfda966c18d8bf4f0e3f6d82a09c0771c955a Mon Sep 17 00:00:00 2001 From: Chen Ni Date: Tue, 3 Sep 2024 10:50:10 +0800 Subject: [PATCH 34/54] HID: hid-sensor-custom: Convert comma to semicolon Replace a comma between expression statements by a semicolon. Signed-off-by: Chen Ni Signed-off-by: Jiri Kosina --- drivers/hid/hid-sensor-custom.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-sensor-custom.c index bd400f6b472b..66f0675df24b 100644 --- a/drivers/hid/hid-sensor-custom.c +++ b/drivers/hid/hid-sensor-custom.c @@ -732,7 +732,7 @@ static int hid_sensor_custom_dev_if_add(struct hid_sensor_custom *sensor_inst) sensor_inst->custom_dev.minor = MISC_DYNAMIC_MINOR; sensor_inst->custom_dev.name = dev_name(&sensor_inst->pdev->dev); - sensor_inst->custom_dev.fops = &hid_sensor_custom_fops, + sensor_inst->custom_dev.fops = &hid_sensor_custom_fops; ret = misc_register(&sensor_inst->custom_dev); if (ret) { kfifo_free(&sensor_inst->data_fifo); From 28a7eeb9eb40fcfeec4f663cabe8d25bb2d9bd6a Mon Sep 17 00:00:00 2001 From: Thomas Zimmermann Date: Wed, 31 Jul 2024 15:09:50 +0200 Subject: [PATCH 35/54] HID: picoLCD: Use backlight power constants Replace FB_BLANK_ constants with their counterparts from the backlight subsystem. The values are identical, so there's no change in functionality or semantics. Signed-off-by: Thomas Zimmermann Signed-off-by: Jiri Kosina --- drivers/hid/hid-picolcd_backlight.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-picolcd_backlight.c b/drivers/hid/hid-picolcd_backlight.c index 08d16917eb60..4b43b64537a3 100644 --- a/drivers/hid/hid-picolcd_backlight.c +++ b/drivers/hid/hid-picolcd_backlight.c @@ -31,7 +31,8 @@ static int picolcd_set_brightness(struct backlight_device *bdev) data->lcd_brightness = bdev->props.brightness & 0x0ff; data->lcd_power = bdev->props.power; spin_lock_irqsave(&data->lock, flags); - hid_set_field(report->field[0], 0, data->lcd_power == FB_BLANK_UNBLANK ? data->lcd_brightness : 0); + hid_set_field(report->field[0], 0, + data->lcd_power == BACKLIGHT_POWER_ON ? data->lcd_brightness : 0); if (!(data->status & PICOLCD_FAILED)) hid_hw_request(data->hdev, report, HID_REQ_SET_REPORT); spin_unlock_irqrestore(&data->lock, flags); @@ -94,7 +95,7 @@ void picolcd_suspend_backlight(struct picolcd_data *data) if (!data->backlight) return; - data->backlight->props.power = FB_BLANK_POWERDOWN; + data->backlight->props.power = BACKLIGHT_POWER_OFF; picolcd_set_brightness(data->backlight); data->lcd_power = data->backlight->props.power = bl_power; } From 00f6f65bd1162dee2e30ef11864892afcbbf2352 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Wed, 28 Aug 2024 09:33:20 +0200 Subject: [PATCH 36/54] HID: bigbenff: constify fixed up report descriptor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the HID core can handle const report descriptors, constify them where possible. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240828-hid-const-fixup-2-v1-1-663b9210eb69@weissschuh.net Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-bigbenff.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-bigbenff.c b/drivers/hid/hid-bigbenff.c index a2ff60dd834c..9f05465358d9 100644 --- a/drivers/hid/hid-bigbenff.c +++ b/drivers/hid/hid-bigbenff.c @@ -99,7 +99,7 @@ * - map previously unused analog trigger data to Z/RZ * - simplify feature and output descriptor */ -static __u8 pid0902_rdesc_fixed[] = { +static const __u8 pid0902_rdesc_fixed[] = { 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */ 0x09, 0x05, /* Usage (Game Pad) */ 0xA1, 0x01, /* Collection (Application) */ @@ -468,8 +468,8 @@ static const __u8 *bigben_report_fixup(struct hid_device *hid, __u8 *rdesc, unsigned int *rsize) { if (*rsize == PID0902_RDESC_ORIG_SIZE) { - rdesc = pid0902_rdesc_fixed; *rsize = sizeof(pid0902_rdesc_fixed); + return pid0902_rdesc_fixed; } else hid_warn(hid, "unexpected rdesc, please submit for review\n"); return rdesc; From 49e00b5ca0bbf26cc0c7ff22415ede58b71937f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Wed, 28 Aug 2024 09:33:21 +0200 Subject: [PATCH 37/54] HID: dr: constify fixed up report descriptor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the HID core can handle const report descriptors, constify them where possible. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240828-hid-const-fixup-2-v1-2-663b9210eb69@weissschuh.net Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-dr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-dr.c b/drivers/hid/hid-dr.c index b24f9bc743e1..84e1e90a266b 100644 --- a/drivers/hid/hid-dr.c +++ b/drivers/hid/hid-dr.c @@ -199,7 +199,7 @@ static inline int drff_init(struct hid_device *hid) #define PID0011_RDESC_ORIG_SIZE 101 /* Fixed report descriptor for PID 0x011 joystick */ -static __u8 pid0011_rdesc_fixed[] = { +static const __u8 pid0011_rdesc_fixed[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x04, /* Usage (Joystick), */ 0xA1, 0x01, /* Collection (Application), */ @@ -234,8 +234,8 @@ static const __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc, switch (hdev->product) { case 0x0011: if (*rsize == PID0011_RDESC_ORIG_SIZE) { - rdesc = pid0011_rdesc_fixed; *rsize = sizeof(pid0011_rdesc_fixed); + return pid0011_rdesc_fixed; } break; } From 3ce7edfa4f096a6e6c802bc3c6b04b1d691a2612 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Wed, 28 Aug 2024 09:33:22 +0200 Subject: [PATCH 38/54] HID: holtek-kbd: constify fixed up report descriptor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the HID core can handle const report descriptors, constify them where possible. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240828-hid-const-fixup-2-v1-3-663b9210eb69@weissschuh.net Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-holtek-kbd.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-holtek-kbd.c b/drivers/hid/hid-holtek-kbd.c index 794d609c2e31..d13543517a6c 100644 --- a/drivers/hid/hid-holtek-kbd.c +++ b/drivers/hid/hid-holtek-kbd.c @@ -27,7 +27,7 @@ * to the boot interface. */ -static __u8 holtek_kbd_rdesc_fixed[] = { +static const __u8 holtek_kbd_rdesc_fixed[] = { /* Original report descriptor, with reduced number of consumer usages */ 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x80, /* Usage (Sys Control), */ @@ -108,8 +108,8 @@ static const __u8 *holtek_kbd_report_fixup(struct hid_device *hdev, __u8 *rdesc, struct usb_interface *intf = to_usb_interface(hdev->dev.parent); if (intf->cur_altsetting->desc.bInterfaceNumber == 1) { - rdesc = holtek_kbd_rdesc_fixed; *rsize = sizeof(holtek_kbd_rdesc_fixed); + return holtek_kbd_rdesc_fixed; } return rdesc; } From b299944af770e36cf5e04e908ca056b72d6f6b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Wed, 28 Aug 2024 09:33:23 +0200 Subject: [PATCH 39/54] HID: keytouch: constify fixed up report descriptor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the HID core can handle const report descriptors, constify them where possible. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240828-hid-const-fixup-2-v1-4-663b9210eb69@weissschuh.net Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-keytouch.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/hid/hid-keytouch.c b/drivers/hid/hid-keytouch.c index 6e3033bb80dd..b9abd53a5864 100644 --- a/drivers/hid/hid-keytouch.c +++ b/drivers/hid/hid-keytouch.c @@ -16,7 +16,7 @@ /* Replace the broken report descriptor of this device with rather * a default one */ -static __u8 keytouch_fixed_rdesc[] = { +static const __u8 keytouch_fixed_rdesc[] = { 0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07, 0x19, 0xe0, 0x29, 0xe7, 0x15, 0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01, 0x75, 0x08, 0x81, 0x01, 0x95, 0x03, 0x75, 0x01, 0x05, 0x08, 0x19, 0x01, 0x29, 0x03, 0x91, @@ -29,10 +29,8 @@ static const __u8 *keytouch_report_fixup(struct hid_device *hdev, __u8 *rdesc, { hid_info(hdev, "fixing up Keytouch IEC report descriptor\n"); - rdesc = keytouch_fixed_rdesc; *rsize = sizeof(keytouch_fixed_rdesc); - - return rdesc; + return keytouch_fixed_rdesc; } static const struct hid_device_id keytouch_devices[] = { From d8b21af666013ae275675a101facaf1222719203 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Wed, 28 Aug 2024 09:33:24 +0200 Subject: [PATCH 40/54] HID: maltron: constify fixed up report descriptor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the HID core can handle const report descriptors, constify them where possible. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240828-hid-const-fixup-2-v1-5-663b9210eb69@weissschuh.net Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-maltron.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-maltron.c b/drivers/hid/hid-maltron.c index 374c64dd82c2..f0aad1ba2e6d 100644 --- a/drivers/hid/hid-maltron.c +++ b/drivers/hid/hid-maltron.c @@ -22,7 +22,7 @@ #include "hid-ids.h" /* The original buggy USB descriptor */ -static u8 maltron_rdesc_o[] = { +static const u8 maltron_rdesc_o[] = { 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */ 0x09, 0x80, /* Usage (Sys Control) */ 0xA1, 0x01, /* Collection (Application) */ @@ -79,7 +79,7 @@ static u8 maltron_rdesc_o[] = { }; /* The patched descriptor, allowing media key events to be accepted as valid */ -static u8 maltron_rdesc[] = { +static const u8 maltron_rdesc[] = { 0x05, 0x01, /* Usage Page (Generic Desktop Ctrls) */ 0x09, 0x80, /* Usage (Sys Control) */ 0xA1, 0x01, /* Collection (Application) */ From c06df4c57af89f07713adc7088ad875409a91462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Wed, 28 Aug 2024 09:33:25 +0200 Subject: [PATCH 41/54] HID: xiaomi: constify fixed up report descriptor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the HID core can handle const report descriptors, constify them where possible. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240828-hid-const-fixup-2-v1-6-663b9210eb69@weissschuh.net Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-xiaomi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-xiaomi.c b/drivers/hid/hid-xiaomi.c index 035733fce2e1..ef6598550a40 100644 --- a/drivers/hid/hid-xiaomi.c +++ b/drivers/hid/hid-xiaomi.c @@ -14,7 +14,7 @@ /* Fixed Mi Silent Mouse report descriptor */ /* Button's Usage Maximum changed from 3 to 5 to make side buttons work */ #define MI_SILENT_MOUSE_ORIG_RDESC_LENGTH 87 -static __u8 mi_silent_mouse_rdesc_fixed[] = { +static const __u8 mi_silent_mouse_rdesc_fixed[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x02, /* Usage (Mouse), */ 0xA1, 0x01, /* Collection (Application), */ @@ -68,8 +68,8 @@ static const __u8 *xiaomi_report_fixup(struct hid_device *hdev, __u8 *rdesc, case USB_DEVICE_ID_MI_SILENT_MOUSE: if (*rsize == MI_SILENT_MOUSE_ORIG_RDESC_LENGTH) { hid_info(hdev, "fixing up Mi Silent Mouse report descriptor\n"); - rdesc = mi_silent_mouse_rdesc_fixed; *rsize = sizeof(mi_silent_mouse_rdesc_fixed); + return mi_silent_mouse_rdesc_fixed; } break; } From 49cf20b878faf1678b25cbc26df6f0e6bff372f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Wed, 28 Aug 2024 09:33:26 +0200 Subject: [PATCH 42/54] HID: vrc2: constify fixed up report descriptor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the HID core can handle const report descriptors, constify them where possible. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240828-hid-const-fixup-2-v1-7-663b9210eb69@weissschuh.net Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-vrc2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-vrc2.c b/drivers/hid/hid-vrc2.c index 9a4840b524ba..7dc41e92f488 100644 --- a/drivers/hid/hid-vrc2.c +++ b/drivers/hid/hid-vrc2.c @@ -16,7 +16,7 @@ #define USB_VENDOR_ID_VRC2 (0x07c0) #define USB_DEVICE_ID_VRC2 (0x1125) -static __u8 vrc2_rdesc_fixed[] = { +static const __u8 vrc2_rdesc_fixed[] = { 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x04, // Usage (Joystick) 0xA1, 0x01, // Collection (Application) From 4f3ff3a275f9ab016cde5561bc1b53c581fc8734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Wed, 28 Aug 2024 09:33:27 +0200 Subject: [PATCH 43/54] HID: viewsonic: constify fixed up report descriptor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the HID core can handle const report descriptors, constify them where possible. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240828-hid-const-fixup-2-v1-8-663b9210eb69@weissschuh.net Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-viewsonic.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-viewsonic.c b/drivers/hid/hid-viewsonic.c index 86f41e3fcb95..532bed88bdf8 100644 --- a/drivers/hid/hid-viewsonic.c +++ b/drivers/hid/hid-viewsonic.c @@ -22,7 +22,7 @@ #define PD1011_RDESC_ORIG_SIZE 408 /* Fixed report descriptor of PD1011 signature pad */ -static __u8 pd1011_rdesc_fixed[] = { +static const __u8 pd1011_rdesc_fixed[] = { 0x05, 0x0D, /* Usage Page (Digitizer), */ 0x09, 0x01, /* Usage (Digitizer), */ 0xA1, 0x01, /* Collection (Application), */ @@ -77,8 +77,8 @@ static const __u8 *viewsonic_report_fixup(struct hid_device *hdev, __u8 *rdesc, case USB_DEVICE_ID_VIEWSONIC_PD1011: case USB_DEVICE_ID_SIGNOTEC_VIEWSONIC_PD1011: if (*rsize == PD1011_RDESC_ORIG_SIZE) { - rdesc = pd1011_rdesc_fixed; *rsize = sizeof(pd1011_rdesc_fixed); + return pd1011_rdesc_fixed; } break; } From 88ae9ffc7c85c1b6b845f51e5fd850d092e75cd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Wed, 28 Aug 2024 09:33:28 +0200 Subject: [PATCH 44/54] HID: steelseries: constify fixed up report descriptor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the HID core can handle const report descriptors, constify them where possible. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240828-hid-const-fixup-2-v1-9-663b9210eb69@weissschuh.net Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-steelseries.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/hid/hid-steelseries.c b/drivers/hid/hid-steelseries.c index 895da49e8ead..7e83fee1ffa0 100644 --- a/drivers/hid/hid-steelseries.c +++ b/drivers/hid/hid-steelseries.c @@ -51,7 +51,7 @@ struct steelseries_srws1_data { * appear in the 'Generic Desktop' usage. */ -static __u8 steelseries_srws1_rdesc_fixed[] = { +static const __u8 steelseries_srws1_rdesc_fixed[] = { 0x05, 0x01, /* Usage Page (Desktop) */ 0x09, 0x08, /* Usage (MultiAxis), Changed */ 0xA1, 0x01, /* Collection (Application), */ @@ -580,8 +580,8 @@ static const __u8 *steelseries_srws1_report_fixup(struct hid_device *hdev, if (*rsize >= 115 && rdesc[11] == 0x02 && rdesc[13] == 0xc8 && rdesc[29] == 0xbb && rdesc[40] == 0xc5) { hid_info(hdev, "Fixing up Steelseries SRW-S1 report descriptor\n"); - rdesc = steelseries_srws1_rdesc_fixed; *rsize = sizeof(steelseries_srws1_rdesc_fixed); + return steelseries_srws1_rdesc_fixed; } return rdesc; } From 4211f9b112167f107c96e1c18cd0e5da71b0680a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Wed, 28 Aug 2024 09:33:29 +0200 Subject: [PATCH 45/54] HID: pxrc: constify fixed up report descriptor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the HID core can handle const report descriptors, constify them where possible. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240828-hid-const-fixup-2-v1-10-663b9210eb69@weissschuh.net Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-pxrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/hid-pxrc.c b/drivers/hid/hid-pxrc.c index ef38730e78ab..71fe0c06ddcd 100644 --- a/drivers/hid/hid-pxrc.c +++ b/drivers/hid/hid-pxrc.c @@ -17,7 +17,7 @@ struct pxrc_priv { bool alternate; }; -static __u8 pxrc_rdesc_fixed[] = { +static const __u8 pxrc_rdesc_fixed[] = { 0x05, 0x01, // Usage Page (Generic Desktop Ctrls) 0x09, 0x04, // Usage (Joystick) 0xA1, 0x01, // Collection (Application) From d4781a27add1a881b92cd71d1ce6190c121d042b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Wed, 28 Aug 2024 09:33:30 +0200 Subject: [PATCH 46/54] HID: sony: constify fixed up report descriptor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the HID core can handle const report descriptors, constify them where possible. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240828-hid-const-fixup-2-v1-11-663b9210eb69@weissschuh.net Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-sony.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 8e2e914bd236..df29c614e490 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -99,7 +99,7 @@ static const char ghl_ps4_magic_data[] = { }; /* PS/3 Motion controller */ -static u8 motion_rdesc[] = { +static const u8 motion_rdesc[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x04, /* Usage (Joystick), */ 0xA1, 0x01, /* Collection (Application), */ @@ -195,7 +195,7 @@ static u8 motion_rdesc[] = { 0xC0 /* End Collection */ }; -static u8 ps3remote_rdesc[] = { +static const u8 ps3remote_rdesc[] = { 0x05, 0x01, /* GUsagePage Generic Desktop */ 0x09, 0x05, /* LUsage 0x05 [Game Pad] */ 0xA1, 0x01, /* MCollection Application (mouse, keyboard) */ @@ -599,15 +599,15 @@ static int guitar_mapping(struct hid_device *hdev, struct hid_input *hi, return 0; } -static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc, - unsigned int *rsize) +static const u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc, + unsigned int *rsize) { *rsize = sizeof(motion_rdesc); return motion_rdesc; } -static u8 *ps3remote_fixup(struct hid_device *hdev, u8 *rdesc, - unsigned int *rsize) +static const u8 *ps3remote_fixup(struct hid_device *hdev, u8 *rdesc, + unsigned int *rsize) { *rsize = sizeof(ps3remote_rdesc); return ps3remote_rdesc; From 24b3c515c69bcb87e4af696883eaaecece26ff60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Wed, 28 Aug 2024 09:33:31 +0200 Subject: [PATCH 47/54] HID: waltop: constify fixed up report descriptor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the HID core can handle const report descriptors, constify them where possible. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240828-hid-const-fixup-2-v1-12-663b9210eb69@weissschuh.net Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-waltop.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/hid/hid-waltop.c b/drivers/hid/hid-waltop.c index 137a682ef5fb..be34be27d4d5 100644 --- a/drivers/hid/hid-waltop.c +++ b/drivers/hid/hid-waltop.c @@ -43,7 +43,7 @@ #define SLIM_TABLET_5_8_INCH_RDESC_ORIG_SIZE 222 /* Fixed Slim Tablet 5.8 inch descriptor */ -static __u8 slim_tablet_5_8_inch_rdesc_fixed[] = { +static const __u8 slim_tablet_5_8_inch_rdesc_fixed[] = { 0x05, 0x0D, /* Usage Page (Digitizer), */ 0x09, 0x02, /* Usage (Pen), */ 0xA1, 0x01, /* Collection (Application), */ @@ -94,7 +94,7 @@ static __u8 slim_tablet_5_8_inch_rdesc_fixed[] = { #define SLIM_TABLET_12_1_INCH_RDESC_ORIG_SIZE 269 /* Fixed Slim Tablet 12.1 inch descriptor */ -static __u8 slim_tablet_12_1_inch_rdesc_fixed[] = { +static const __u8 slim_tablet_12_1_inch_rdesc_fixed[] = { 0x05, 0x0D, /* Usage Page (Digitizer), */ 0x09, 0x02, /* Usage (Pen), */ 0xA1, 0x01, /* Collection (Application), */ @@ -145,7 +145,7 @@ static __u8 slim_tablet_12_1_inch_rdesc_fixed[] = { #define Q_PAD_RDESC_ORIG_SIZE 241 /* Fixed Q Pad descriptor */ -static __u8 q_pad_rdesc_fixed[] = { +static const __u8 q_pad_rdesc_fixed[] = { 0x05, 0x0D, /* Usage Page (Digitizer), */ 0x09, 0x02, /* Usage (Pen), */ 0xA1, 0x01, /* Collection (Application), */ @@ -198,7 +198,7 @@ static __u8 q_pad_rdesc_fixed[] = { /* * Fixed report descriptor for tablet with PID 0038. */ -static __u8 pid_0038_rdesc_fixed[] = { +static const __u8 pid_0038_rdesc_fixed[] = { 0x05, 0x0D, /* Usage Page (Digitizer), */ 0x09, 0x02, /* Usage (Pen), */ 0xA1, 0x01, /* Collection (Application), */ @@ -249,7 +249,7 @@ static __u8 pid_0038_rdesc_fixed[] = { #define MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE 300 /* Fixed Media Tablet 10.6 inch descriptor */ -static __u8 media_tablet_10_6_inch_rdesc_fixed[] = { +static const __u8 media_tablet_10_6_inch_rdesc_fixed[] = { 0x05, 0x0D, /* Usage Page (Digitizer), */ 0x09, 0x02, /* Usage (Pen), */ 0xA1, 0x01, /* Collection (Application), */ @@ -362,7 +362,7 @@ static __u8 media_tablet_10_6_inch_rdesc_fixed[] = { #define MEDIA_TABLET_14_1_INCH_RDESC_ORIG_SIZE 309 /* Fixed Media Tablet 14.1 inch descriptor */ -static __u8 media_tablet_14_1_inch_rdesc_fixed[] = { +static const __u8 media_tablet_14_1_inch_rdesc_fixed[] = { 0x05, 0x0D, /* Usage Page (Digitizer), */ 0x09, 0x02, /* Usage (Pen), */ 0xA1, 0x01, /* Collection (Application), */ @@ -473,7 +473,7 @@ static __u8 media_tablet_14_1_inch_rdesc_fixed[] = { #define SIRIUS_BATTERY_FREE_TABLET_RDESC_ORIG_SIZE 335 /* Fixed Sirius Battery Free Tablet descriptor */ -static __u8 sirius_battery_free_tablet_rdesc_fixed[] = { +static const __u8 sirius_battery_free_tablet_rdesc_fixed[] = { 0x05, 0x0D, /* Usage Page (Digitizer), */ 0x09, 0x02, /* Usage (Pen), */ 0xA1, 0x01, /* Collection (Application), */ @@ -605,44 +605,44 @@ static const __u8 *waltop_report_fixup(struct hid_device *hdev, __u8 *rdesc, switch (hdev->product) { case USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH: if (*rsize == SLIM_TABLET_5_8_INCH_RDESC_ORIG_SIZE) { - rdesc = slim_tablet_5_8_inch_rdesc_fixed; *rsize = sizeof(slim_tablet_5_8_inch_rdesc_fixed); + return slim_tablet_5_8_inch_rdesc_fixed; } break; case USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH: if (*rsize == SLIM_TABLET_12_1_INCH_RDESC_ORIG_SIZE) { - rdesc = slim_tablet_12_1_inch_rdesc_fixed; *rsize = sizeof(slim_tablet_12_1_inch_rdesc_fixed); + return slim_tablet_12_1_inch_rdesc_fixed; } break; case USB_DEVICE_ID_WALTOP_Q_PAD: if (*rsize == Q_PAD_RDESC_ORIG_SIZE) { - rdesc = q_pad_rdesc_fixed; *rsize = sizeof(q_pad_rdesc_fixed); + return q_pad_rdesc_fixed; } break; case USB_DEVICE_ID_WALTOP_PID_0038: if (*rsize == PID_0038_RDESC_ORIG_SIZE) { - rdesc = pid_0038_rdesc_fixed; *rsize = sizeof(pid_0038_rdesc_fixed); + return pid_0038_rdesc_fixed; } break; case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH: if (*rsize == MEDIA_TABLET_10_6_INCH_RDESC_ORIG_SIZE) { - rdesc = media_tablet_10_6_inch_rdesc_fixed; *rsize = sizeof(media_tablet_10_6_inch_rdesc_fixed); + return media_tablet_10_6_inch_rdesc_fixed; } break; case USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH: if (*rsize == MEDIA_TABLET_14_1_INCH_RDESC_ORIG_SIZE) { - rdesc = media_tablet_14_1_inch_rdesc_fixed; *rsize = sizeof(media_tablet_14_1_inch_rdesc_fixed); + return media_tablet_14_1_inch_rdesc_fixed; } break; case USB_DEVICE_ID_WALTOP_SIRIUS_BATTERY_FREE_TABLET: if (*rsize == SIRIUS_BATTERY_FREE_TABLET_RDESC_ORIG_SIZE) { - rdesc = sirius_battery_free_tablet_rdesc_fixed; *rsize = sizeof(sirius_battery_free_tablet_rdesc_fixed); + return sirius_battery_free_tablet_rdesc_fixed; } break; } From 03f8dc1d0a3823229a761f202bc1a6e63d5b4ba0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Wed, 28 Aug 2024 09:33:33 +0200 Subject: [PATCH 48/54] HID: uclogic: constify fixed up report descriptor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the HID core can handle const report descriptors, constify them where possible. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240828-hid-const-fixup-2-v1-14-663b9210eb69@weissschuh.net Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-uclogic-core.c | 2 +- drivers/hid/hid-uclogic-params.c | 4 ++-- drivers/hid/hid-uclogic-params.h | 10 +++++----- drivers/hid/hid-uclogic-rdesc.c | 20 ++++++++++---------- drivers/hid/hid-uclogic-rdesc.h | 20 ++++++++++---------- 5 files changed, 28 insertions(+), 28 deletions(-) diff --git a/drivers/hid/hid-uclogic-core.c b/drivers/hid/hid-uclogic-core.c index f6a1572b3728..d8008933c052 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -56,8 +56,8 @@ static const __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, struct uclogic_drvdata *drvdata = hid_get_drvdata(hdev); if (drvdata->desc_ptr != NULL) { - rdesc = drvdata->desc_ptr; *rsize = drvdata->desc_size; + return drvdata->desc_ptr; } return rdesc; } diff --git a/drivers/hid/hid-uclogic-params.c b/drivers/hid/hid-uclogic-params.c index 5bab006ec165..87fd4eb76c70 100644 --- a/drivers/hid/hid-uclogic-params.c +++ b/drivers/hid/hid-uclogic-params.c @@ -681,7 +681,7 @@ void uclogic_params_cleanup(struct uclogic_params *params) * -ENOMEM, if failed to allocate memory. */ int uclogic_params_get_desc(const struct uclogic_params *params, - __u8 **pdesc, + const __u8 **pdesc, unsigned int *psize) { int rc = -ENOMEM; @@ -769,7 +769,7 @@ static void uclogic_params_init_invalid(struct uclogic_params *params) static int uclogic_params_init_with_opt_desc(struct uclogic_params *params, struct hid_device *hdev, unsigned int orig_desc_size, - __u8 *desc_ptr, + const __u8 *desc_ptr, unsigned int desc_size) { __u8 *desc_copy_ptr = NULL; diff --git a/drivers/hid/hid-uclogic-params.h b/drivers/hid/hid-uclogic-params.h index d6ffadb2f601..35ff062d09b5 100644 --- a/drivers/hid/hid-uclogic-params.h +++ b/drivers/hid/hid-uclogic-params.h @@ -79,7 +79,7 @@ struct uclogic_params_pen { * Pointer to report descriptor part describing the pen inputs. * Allocated with kmalloc. NULL if the part is not specified. */ - __u8 *desc_ptr; + const __u8 *desc_ptr; /* * Size of the report descriptor. * Only valid, if "desc_ptr" is not NULL. @@ -118,7 +118,7 @@ struct uclogic_params_frame { * Pointer to report descriptor part describing the frame inputs. * Allocated with kmalloc. NULL if the part is not specified. */ - __u8 *desc_ptr; + const __u8 *desc_ptr; /* * Size of the report descriptor. * Only valid, if "desc_ptr" is not NULL. @@ -212,7 +212,7 @@ struct uclogic_params { * allocated with kmalloc. NULL if no common part is needed. * Only valid, if "invalid" is false. */ - __u8 *desc_ptr; + const __u8 *desc_ptr; /* * Size of the common part of the replacement report descriptor. * Only valid, if "desc_ptr" is valid and not NULL. @@ -239,7 +239,7 @@ struct uclogic_drvdata { /* Interface parameters */ struct uclogic_params params; /* Pointer to the replacement report descriptor. NULL if none. */ - __u8 *desc_ptr; + const __u8 *desc_ptr; /* * Size of the replacement report descriptor. * Only valid if desc_ptr is not NULL @@ -261,7 +261,7 @@ extern int uclogic_params_init(struct uclogic_params *params, /* Get a replacement report descriptor for a tablet's interface. */ extern int uclogic_params_get_desc(const struct uclogic_params *params, - __u8 **pdesc, + const __u8 **pdesc, unsigned int *psize); /* Free resources used by tablet interface's parameters */ diff --git a/drivers/hid/hid-uclogic-rdesc.c b/drivers/hid/hid-uclogic-rdesc.c index acfa591ab52f..964d17e08f26 100644 --- a/drivers/hid/hid-uclogic-rdesc.c +++ b/drivers/hid/hid-uclogic-rdesc.c @@ -20,7 +20,7 @@ #include /* Fixed WP4030U report descriptor */ -__u8 uclogic_rdesc_wp4030u_fixed_arr[] = { +const __u8 uclogic_rdesc_wp4030u_fixed_arr[] = { 0x05, 0x0D, /* Usage Page (Digitizer), */ 0x09, 0x01, /* Usage (Digitizer), */ 0xA1, 0x01, /* Collection (Application), */ @@ -65,7 +65,7 @@ const size_t uclogic_rdesc_wp4030u_fixed_size = sizeof(uclogic_rdesc_wp4030u_fixed_arr); /* Fixed WP5540U report descriptor */ -__u8 uclogic_rdesc_wp5540u_fixed_arr[] = { +const __u8 uclogic_rdesc_wp5540u_fixed_arr[] = { 0x05, 0x0D, /* Usage Page (Digitizer), */ 0x09, 0x01, /* Usage (Digitizer), */ 0xA1, 0x01, /* Collection (Application), */ @@ -142,7 +142,7 @@ const size_t uclogic_rdesc_wp5540u_fixed_size = sizeof(uclogic_rdesc_wp5540u_fixed_arr); /* Fixed WP8060U report descriptor */ -__u8 uclogic_rdesc_wp8060u_fixed_arr[] = { +const __u8 uclogic_rdesc_wp8060u_fixed_arr[] = { 0x05, 0x0D, /* Usage Page (Digitizer), */ 0x09, 0x01, /* Usage (Digitizer), */ 0xA1, 0x01, /* Collection (Application), */ @@ -219,7 +219,7 @@ const size_t uclogic_rdesc_wp8060u_fixed_size = sizeof(uclogic_rdesc_wp8060u_fixed_arr); /* Fixed WP1062 report descriptor */ -__u8 uclogic_rdesc_wp1062_fixed_arr[] = { +const __u8 uclogic_rdesc_wp1062_fixed_arr[] = { 0x05, 0x0D, /* Usage Page (Digitizer), */ 0x09, 0x01, /* Usage (Digitizer), */ 0xA1, 0x01, /* Collection (Application), */ @@ -267,7 +267,7 @@ const size_t uclogic_rdesc_wp1062_fixed_size = sizeof(uclogic_rdesc_wp1062_fixed_arr); /* Fixed PF1209 report descriptor */ -__u8 uclogic_rdesc_pf1209_fixed_arr[] = { +const __u8 uclogic_rdesc_pf1209_fixed_arr[] = { 0x05, 0x0D, /* Usage Page (Digitizer), */ 0x09, 0x01, /* Usage (Digitizer), */ 0xA1, 0x01, /* Collection (Application), */ @@ -344,7 +344,7 @@ const size_t uclogic_rdesc_pf1209_fixed_size = sizeof(uclogic_rdesc_pf1209_fixed_arr); /* Fixed PID 0522 tablet report descriptor, interface 0 (stylus) */ -__u8 uclogic_rdesc_twhl850_fixed0_arr[] = { +const __u8 uclogic_rdesc_twhl850_fixed0_arr[] = { 0x05, 0x0D, /* Usage Page (Digitizer), */ 0x09, 0x01, /* Usage (Digitizer), */ 0xA1, 0x01, /* Collection (Application), */ @@ -390,7 +390,7 @@ const size_t uclogic_rdesc_twhl850_fixed0_size = sizeof(uclogic_rdesc_twhl850_fixed0_arr); /* Fixed PID 0522 tablet report descriptor, interface 1 (mouse) */ -__u8 uclogic_rdesc_twhl850_fixed1_arr[] = { +const __u8 uclogic_rdesc_twhl850_fixed1_arr[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x02, /* Usage (Mouse), */ 0xA1, 0x01, /* Collection (Application), */ @@ -430,7 +430,7 @@ const size_t uclogic_rdesc_twhl850_fixed1_size = sizeof(uclogic_rdesc_twhl850_fixed1_arr); /* Fixed PID 0522 tablet report descriptor, interface 2 (frame buttons) */ -__u8 uclogic_rdesc_twhl850_fixed2_arr[] = { +const __u8 uclogic_rdesc_twhl850_fixed2_arr[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x06, /* Usage (Keyboard), */ 0xA1, 0x01, /* Collection (Application), */ @@ -456,7 +456,7 @@ const size_t uclogic_rdesc_twhl850_fixed2_size = sizeof(uclogic_rdesc_twhl850_fixed2_arr); /* Fixed TWHA60 report descriptor, interface 0 (stylus) */ -__u8 uclogic_rdesc_twha60_fixed0_arr[] = { +const __u8 uclogic_rdesc_twha60_fixed0_arr[] = { 0x05, 0x0D, /* Usage Page (Digitizer), */ 0x09, 0x01, /* Usage (Digitizer), */ 0xA1, 0x01, /* Collection (Application), */ @@ -505,7 +505,7 @@ const size_t uclogic_rdesc_twha60_fixed0_size = sizeof(uclogic_rdesc_twha60_fixed0_arr); /* Fixed TWHA60 report descriptor, interface 1 (frame buttons) */ -__u8 uclogic_rdesc_twha60_fixed1_arr[] = { +const __u8 uclogic_rdesc_twha60_fixed1_arr[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x06, /* Usage (Keyboard), */ 0xA1, 0x01, /* Collection (Application), */ diff --git a/drivers/hid/hid-uclogic-rdesc.h b/drivers/hid/hid-uclogic-rdesc.h index 906d068f50a9..3878a0e8c464 100644 --- a/drivers/hid/hid-uclogic-rdesc.h +++ b/drivers/hid/hid-uclogic-rdesc.h @@ -23,15 +23,15 @@ #define UCLOGIC_RDESC_WPXXXXU_ORIG_SIZE 212 /* Fixed WP4030U report descriptor */ -extern __u8 uclogic_rdesc_wp4030u_fixed_arr[]; +extern const __u8 uclogic_rdesc_wp4030u_fixed_arr[]; extern const size_t uclogic_rdesc_wp4030u_fixed_size; /* Fixed WP5540U report descriptor */ -extern __u8 uclogic_rdesc_wp5540u_fixed_arr[]; +extern const __u8 uclogic_rdesc_wp5540u_fixed_arr[]; extern const size_t uclogic_rdesc_wp5540u_fixed_size; /* Fixed WP8060U report descriptor */ -extern __u8 uclogic_rdesc_wp8060u_fixed_arr[]; +extern const __u8 uclogic_rdesc_wp8060u_fixed_arr[]; extern const size_t uclogic_rdesc_wp8060u_fixed_size; /* Size of the original descriptor of the new WP5540U tablet */ @@ -41,14 +41,14 @@ extern const size_t uclogic_rdesc_wp8060u_fixed_size; #define UCLOGIC_RDESC_WP1062_ORIG_SIZE 254 /* Fixed WP1062 report descriptor */ -extern __u8 uclogic_rdesc_wp1062_fixed_arr[]; +extern const __u8 uclogic_rdesc_wp1062_fixed_arr[]; extern const size_t uclogic_rdesc_wp1062_fixed_size; /* Size of the original descriptor of PF1209 tablet */ #define UCLOGIC_RDESC_PF1209_ORIG_SIZE 234 /* Fixed PF1209 report descriptor */ -extern __u8 uclogic_rdesc_pf1209_fixed_arr[]; +extern const __u8 uclogic_rdesc_pf1209_fixed_arr[]; extern const size_t uclogic_rdesc_pf1209_fixed_size; /* Size of the original descriptors of TWHL850 tablet */ @@ -57,15 +57,15 @@ extern const size_t uclogic_rdesc_pf1209_fixed_size; #define UCLOGIC_RDESC_TWHL850_ORIG2_SIZE 92 /* Fixed PID 0522 tablet report descriptor, interface 0 (stylus) */ -extern __u8 uclogic_rdesc_twhl850_fixed0_arr[]; +extern const __u8 uclogic_rdesc_twhl850_fixed0_arr[]; extern const size_t uclogic_rdesc_twhl850_fixed0_size; /* Fixed PID 0522 tablet report descriptor, interface 1 (mouse) */ -extern __u8 uclogic_rdesc_twhl850_fixed1_arr[]; +extern const __u8 uclogic_rdesc_twhl850_fixed1_arr[]; extern const size_t uclogic_rdesc_twhl850_fixed1_size; /* Fixed PID 0522 tablet report descriptor, interface 2 (frame buttons) */ -extern __u8 uclogic_rdesc_twhl850_fixed2_arr[]; +extern const __u8 uclogic_rdesc_twhl850_fixed2_arr[]; extern const size_t uclogic_rdesc_twhl850_fixed2_size; /* Size of the original descriptors of TWHA60 tablet */ @@ -73,11 +73,11 @@ extern const size_t uclogic_rdesc_twhl850_fixed2_size; #define UCLOGIC_RDESC_TWHA60_ORIG1_SIZE 139 /* Fixed TWHA60 report descriptor, interface 0 (stylus) */ -extern __u8 uclogic_rdesc_twha60_fixed0_arr[]; +extern const __u8 uclogic_rdesc_twha60_fixed0_arr[]; extern const size_t uclogic_rdesc_twha60_fixed0_size; /* Fixed TWHA60 report descriptor, interface 1 (frame buttons) */ -extern __u8 uclogic_rdesc_twha60_fixed1_arr[]; +extern const __u8 uclogic_rdesc_twha60_fixed1_arr[]; extern const size_t uclogic_rdesc_twha60_fixed1_size; /* Report descriptor template placeholder head */ From 9f5305ed80108a7849b3b27e1a889a7afff46a51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= Date: Thu, 5 Sep 2024 17:48:38 +0200 Subject: [PATCH 49/54] HID: lg: constify fixed up report descriptor MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Now that the HID core can handle const report descriptors, constify them where possible. Signed-off-by: Thomas Weißschuh Link: https://patch.msgid.link/20240905-hid-const-fixup-2-v2-1-70915e0cc1c7@weissschuh.net Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-lg.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index a9be918e2b5c..9a2cfa018bd3 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -58,7 +58,7 @@ * These descriptors remove the combined Y axis and instead report * separate throttle (Y) and brake (RZ). */ -static __u8 df_rdesc_fixed[] = { +static const __u8 df_rdesc_fixed[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x04, /* Usage (Joystick), */ 0xA1, 0x01, /* Collection (Application), */ @@ -124,7 +124,7 @@ static __u8 df_rdesc_fixed[] = { 0xC0 /* End Collection */ }; -static __u8 dfp_rdesc_fixed[] = { +static const __u8 dfp_rdesc_fixed[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x04, /* Usage (Joystick), */ 0xA1, 0x01, /* Collection (Application), */ @@ -172,7 +172,7 @@ static __u8 dfp_rdesc_fixed[] = { 0xC0 /* End Collection */ }; -static __u8 fv_rdesc_fixed[] = { +static const __u8 fv_rdesc_fixed[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x04, /* Usage (Joystick), */ 0xA1, 0x01, /* Collection (Application), */ @@ -239,7 +239,7 @@ static __u8 fv_rdesc_fixed[] = { 0xC0 /* End Collection */ }; -static __u8 momo_rdesc_fixed[] = { +static const __u8 momo_rdesc_fixed[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x04, /* Usage (Joystick), */ 0xA1, 0x01, /* Collection (Application), */ @@ -285,7 +285,7 @@ static __u8 momo_rdesc_fixed[] = { 0xC0 /* End Collection */ }; -static __u8 momo2_rdesc_fixed[] = { +static const __u8 momo2_rdesc_fixed[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x04, /* Usage (Joystick), */ 0xA1, 0x01, /* Collection (Application), */ @@ -333,7 +333,7 @@ static __u8 momo2_rdesc_fixed[] = { 0xC0 /* End Collection */ }; -static __u8 ffg_rdesc_fixed[] = { +static const __u8 ffg_rdesc_fixed[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x04, /* Usage (Joystik), */ 0xA1, 0x01, /* Collection (Application), */ @@ -379,7 +379,7 @@ static __u8 ffg_rdesc_fixed[] = { 0xC0 /* End Collection */ }; -static __u8 fg_rdesc_fixed[] = { +static const __u8 fg_rdesc_fixed[] = { 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x04, /* Usage (Joystik), */ 0xA1, 0x01, /* Collection (Application), */ @@ -453,8 +453,8 @@ static const __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, if (*rsize == FG_RDESC_ORIG_SIZE) { hid_info(hdev, "fixing up Logitech Wingman Formula GP report descriptor\n"); - rdesc = fg_rdesc_fixed; *rsize = sizeof(fg_rdesc_fixed); + return fg_rdesc_fixed; } else { hid_info(hdev, "rdesc size test failed for formula gp\n"); @@ -466,8 +466,8 @@ static const __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, if (*rsize == FFG_RDESC_ORIG_SIZE) { hid_info(hdev, "fixing up Logitech Wingman Formula Force GP report descriptor\n"); - rdesc = ffg_rdesc_fixed; *rsize = sizeof(ffg_rdesc_fixed); + return ffg_rdesc_fixed; } break; @@ -476,8 +476,8 @@ static const __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, if (*rsize == DF_RDESC_ORIG_SIZE) { hid_info(hdev, "fixing up Logitech Driving Force report descriptor\n"); - rdesc = df_rdesc_fixed; *rsize = sizeof(df_rdesc_fixed); + return df_rdesc_fixed; } break; @@ -485,8 +485,8 @@ static const __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, if (*rsize == MOMO_RDESC_ORIG_SIZE) { hid_info(hdev, "fixing up Logitech Momo Force (Red) report descriptor\n"); - rdesc = momo_rdesc_fixed; *rsize = sizeof(momo_rdesc_fixed); + return momo_rdesc_fixed; } break; @@ -494,8 +494,8 @@ static const __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, if (*rsize == MOMO2_RDESC_ORIG_SIZE) { hid_info(hdev, "fixing up Logitech Momo Racing Force (Black) report descriptor\n"); - rdesc = momo2_rdesc_fixed; *rsize = sizeof(momo2_rdesc_fixed); + return momo2_rdesc_fixed; } break; @@ -503,8 +503,8 @@ static const __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, if (*rsize == FV_RDESC_ORIG_SIZE) { hid_info(hdev, "fixing up Logitech Formula Vibration report descriptor\n"); - rdesc = fv_rdesc_fixed; *rsize = sizeof(fv_rdesc_fixed); + return fv_rdesc_fixed; } break; @@ -512,8 +512,8 @@ static const __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, if (*rsize == DFP_RDESC_ORIG_SIZE) { hid_info(hdev, "fixing up Logitech Driving Force Pro report descriptor\n"); - rdesc = dfp_rdesc_fixed; *rsize = sizeof(dfp_rdesc_fixed); + return dfp_rdesc_fixed; } break; From 359673ea3a203611b4f6d0f28922a4b9d2cfbcc8 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Mon, 9 Sep 2024 13:32:07 -0700 Subject: [PATCH 50/54] HID: wacom: Support sequence numbers smaller than 16-bit The current dropped packet reporting assumes that all sequence numbers are 16 bits in length. This results in misleading "Dropped" messages if the hardware uses fewer bits. For example, if a tablet uses only 8 bits to store its sequence number, once it rolls over from 255 -> 0, the driver will still be expecting a packet "256". This patch adjusts the logic to reset the next expected packet to logical_minimum whenever it overflows beyond logical_maximum. Signed-off-by: Jason Gerecke Tested-by: Joshua Dickens Fixes: 6d09085b38e5 ("HID: wacom: Adding Support for new usages") Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 36010c515f39..22b0d281ff5c 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2510,9 +2510,14 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field wacom_wac->hid_data.barrelswitch3 = value; return; case WACOM_HID_WD_SEQUENCENUMBER: - if (wacom_wac->hid_data.sequence_number != value) - hid_warn(hdev, "Dropped %hu packets", (unsigned short)(value - wacom_wac->hid_data.sequence_number)); + if (wacom_wac->hid_data.sequence_number != value) { + int sequence_size = field->logical_maximum - field->logical_minimum + 1; + int drop_count = (value - wacom_wac->hid_data.sequence_number) % sequence_size; + hid_warn(hdev, "Dropped %d packets", drop_count); + } wacom_wac->hid_data.sequence_number = value + 1; + if (wacom_wac->hid_data.sequence_number > field->logical_maximum) + wacom_wac->hid_data.sequence_number = field->logical_minimum; return; } From 84aecf2d251a3359bc78b7c8e58f54b9fc966e89 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Mon, 9 Sep 2024 13:32:08 -0700 Subject: [PATCH 51/54] HID: wacom: Do not warn about dropped packets for first packet The driver currently assumes that the first sequence number it will see is going to be 0. This is not a realiable assumption and can break if, for example, the tablet has already been running for some time prior to the kernel driver connecting to the device. This commit initializes the expected sequence number to -1 and will only print the "Dropped" warning the it has been updated to a non-negative value. Signed-off-by: Jason Gerecke Tested-by: Joshua Dickens Fixes: 6d09085b38e5 ("HID: wacom: Adding Support for new usages") Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 6 +++++- drivers/hid/wacom_wac.h | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 22b0d281ff5c..b7129cc7c6bf 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2386,6 +2386,9 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, wacom_map_usage(input, usage, field, EV_KEY, BTN_STYLUS3, 0); features->quirks &= ~WACOM_QUIRK_PEN_BUTTON3; break; + case WACOM_HID_WD_SEQUENCENUMBER: + wacom_wac->hid_data.sequence_number = -1; + break; } } @@ -2510,7 +2513,8 @@ static void wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field wacom_wac->hid_data.barrelswitch3 = value; return; case WACOM_HID_WD_SEQUENCENUMBER: - if (wacom_wac->hid_data.sequence_number != value) { + if (wacom_wac->hid_data.sequence_number != value && + wacom_wac->hid_data.sequence_number >= 0) { int sequence_size = field->logical_maximum - field->logical_minimum + 1; int drop_count = (value - wacom_wac->hid_data.sequence_number) % sequence_size; hid_warn(hdev, "Dropped %d packets", drop_count); diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 55e0c7a9fdcb..c8803d5c6a71 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -326,7 +326,7 @@ struct hid_data { int bat_connected; int ps_connected; bool pad_input_event_flag; - unsigned short sequence_number; + int sequence_number; ktime_t time_delayed; }; From 65b72ea91a257a5f0cb5a26b01194d3dd4b85298 Mon Sep 17 00:00:00 2001 From: Vishnu Sankar Date: Sun, 18 Aug 2024 16:27:29 +0900 Subject: [PATCH 52/54] HID: multitouch: Add support for Thinkpad X12 Gen 2 Kbd Portfolio This applies similar quirks used by previous generation device, so that Trackpoint and buttons on the touchpad works. New USB KBD PID 0x61AE for Thinkpad X12 Tab is added. Signed-off-by: Vishnu Sankar Reviewed-by: Mark Pearson Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-multitouch.c | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index cb804b630653..c935429ddb34 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -811,6 +811,7 @@ #define USB_DEVICE_ID_LENOVO_X1_TAB 0x60a3 #define USB_DEVICE_ID_LENOVO_X1_TAB3 0x60b5 #define USB_DEVICE_ID_LENOVO_X12_TAB 0x60fe +#define USB_DEVICE_ID_LENOVO_X12_TAB2 0x61ae #define USB_DEVICE_ID_LENOVO_OPTICAL_USB_MOUSE_600E 0x600e #define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_608D 0x608d #define USB_DEVICE_ID_LENOVO_PIXART_USB_MOUSE_6019 0x6019 diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 35a6d3f29f59..15bcafa220e4 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -2126,6 +2126,12 @@ static const struct hid_device_id mt_devices[] = { USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_X12_TAB) }, + /* Lenovo X12 TAB Gen 2 */ + { .driver_data = MT_CLS_WIN_8_FORCE_MULTI_INPUT_NSMU, + HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8, + USB_VENDOR_ID_LENOVO, + USB_DEVICE_ID_LENOVO_X12_TAB2) }, + /* Logitech devices */ { .driver_data = MT_CLS_NSMU, HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_MULTITOUCH_WIN_8, From b4ed18a3d56eabd18cfd9841ff05111e3cfbe8f9 Mon Sep 17 00:00:00 2001 From: Dmitry Torokhov Date: Mon, 9 Sep 2024 13:37:40 -0700 Subject: [PATCH 53/54] HID: i2c-hid: ensure various commands do not interfere with each other i2c-hid uses 2 shared buffers: command and "raw" input buffer for sending requests to peripherals and read data from peripherals when executing variety of commands. Such commands include reading of HID registers, requesting particular power mode, getting and setting reports and so on. Because all such requests use the same 2 buffers they should not execute simultaneously. Fix this by introducing "cmd_lock" mutex and acquire it whenever we needs to access ihid->cmdbuf or idid->rawbuf. Signed-off-by: Dmitry Torokhov Reviewed-by: Hans de Goede Signed-off-by: Jiri Kosina --- drivers/hid/i2c-hid/i2c-hid-core.c | 42 +++++++++++++++++++----------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c index 632eaf9e11a6..2f8a9d3f1e86 100644 --- a/drivers/hid/i2c-hid/i2c-hid-core.c +++ b/drivers/hid/i2c-hid/i2c-hid-core.c @@ -105,6 +105,7 @@ struct i2c_hid { wait_queue_head_t wait; /* For waiting the interrupt */ + struct mutex cmd_lock; /* protects cmdbuf and rawbuf */ struct mutex reset_lock; struct i2chid_ops *ops; @@ -220,6 +221,8 @@ static int i2c_hid_xfer(struct i2c_hid *ihid, static int i2c_hid_read_register(struct i2c_hid *ihid, __le16 reg, void *buf, size_t len) { + guard(mutex)(&ihid->cmd_lock); + *(__le16 *)ihid->cmdbuf = reg; return i2c_hid_xfer(ihid, ihid->cmdbuf, sizeof(__le16), buf, len); @@ -252,6 +255,8 @@ static int i2c_hid_get_report(struct i2c_hid *ihid, i2c_hid_dbg(ihid, "%s\n", __func__); + guard(mutex)(&ihid->cmd_lock); + /* Command register goes first */ *(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister; length += sizeof(__le16); @@ -342,6 +347,8 @@ static int i2c_hid_set_or_send_report(struct i2c_hid *ihid, if (!do_set && le16_to_cpu(ihid->hdesc.wMaxOutputLength) == 0) return -ENOSYS; + guard(mutex)(&ihid->cmd_lock); + if (do_set) { /* Command register goes first */ *(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister; @@ -384,6 +391,8 @@ static int i2c_hid_set_power_command(struct i2c_hid *ihid, int power_state) { size_t length; + guard(mutex)(&ihid->cmd_lock); + /* SET_POWER uses command register */ *(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister; length = sizeof(__le16); @@ -440,25 +449,27 @@ static int i2c_hid_start_hwreset(struct i2c_hid *ihid) if (ret) return ret; - /* Prepare reset command. Command register goes first. */ - *(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister; - length += sizeof(__le16); - /* Next is RESET command itself */ - length += i2c_hid_encode_command(ihid->cmdbuf + length, - I2C_HID_OPCODE_RESET, 0, 0); + scoped_guard(mutex, &ihid->cmd_lock) { + /* Prepare reset command. Command register goes first. */ + *(__le16 *)ihid->cmdbuf = ihid->hdesc.wCommandRegister; + length += sizeof(__le16); + /* Next is RESET command itself */ + length += i2c_hid_encode_command(ihid->cmdbuf + length, + I2C_HID_OPCODE_RESET, 0, 0); - set_bit(I2C_HID_RESET_PENDING, &ihid->flags); + set_bit(I2C_HID_RESET_PENDING, &ihid->flags); - ret = i2c_hid_xfer(ihid, ihid->cmdbuf, length, NULL, 0); - if (ret) { - dev_err(&ihid->client->dev, - "failed to reset device: %d\n", ret); - goto err_clear_reset; + ret = i2c_hid_xfer(ihid, ihid->cmdbuf, length, NULL, 0); + if (ret) { + dev_err(&ihid->client->dev, + "failed to reset device: %d\n", ret); + break; + } + + return 0; } - return 0; - -err_clear_reset: + /* Clean up if sending reset command failed */ clear_bit(I2C_HID_RESET_PENDING, &ihid->flags); i2c_hid_set_power(ihid, I2C_HID_PWR_SLEEP); return ret; @@ -1200,6 +1211,7 @@ int i2c_hid_core_probe(struct i2c_client *client, struct i2chid_ops *ops, ihid->is_panel_follower = drm_is_panel_follower(&client->dev); init_waitqueue_head(&ihid->wait); + mutex_init(&ihid->cmd_lock); mutex_init(&ihid->reset_lock); INIT_WORK(&ihid->panel_follower_prepare_work, ihid_core_panel_prepare_work); From e9a081c80cb377b84ead0ba46e8ec892184318bd Mon Sep 17 00:00:00 2001 From: Jinjie Ruan Date: Fri, 13 Sep 2024 15:46:32 +0800 Subject: [PATCH 54/54] hid: cp2112: Use irq_get_trigger_type() helper Use irq_get_trigger_type() to replace irq_get_irq_data() and then irqd_get_trigger_type(), if the irq data is NULL it will return 0. No functional changed. Signed-off-by: Jinjie Ruan Link: https://patch.msgid.link/20240913074632.3779321-1-ruanjinjie@huawei.com Signed-off-by: Benjamin Tissoires --- drivers/hid/hid-cp2112.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c index 20a0d1315d90..dae2b84a1490 100644 --- a/drivers/hid/hid-cp2112.c +++ b/drivers/hid/hid-cp2112.c @@ -1094,7 +1094,6 @@ static void cp2112_gpio_poll_callback(struct work_struct *work) { struct cp2112_device *dev = container_of(work, struct cp2112_device, gpio_poll_worker.work); - struct irq_data *d; u8 gpio_mask; u32 irq_type; int irq, virq, ret; @@ -1111,12 +1110,10 @@ static void cp2112_gpio_poll_callback(struct work_struct *work) if (!irq) continue; - d = irq_get_irq_data(irq); - if (!d) + irq_type = irq_get_trigger_type(irq); + if (!irq_type) continue; - irq_type = irqd_get_trigger_type(d); - if (gpio_mask & BIT(virq)) { /* Level High */