diff options
73 files changed, 966 insertions, 658 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); 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/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..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) */ @@ -464,12 +464,12 @@ 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) { - 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; 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..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), */ @@ -199,13 +199,13 @@ 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) { 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; } diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 988d0acbdf04..30de92d0bf0f 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, @@ -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) @@ -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, @@ -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-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..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), */ @@ -228,14 +228,14 @@ 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: if (*rsize == PID0011_RDESC_ORIG_SIZE) { - rdesc = pid0011_rdesc_fixed; *rsize = sizeof(pid0011_rdesc_fixed); + return pid0011_rdesc_fixed; } break; } 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-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/drivers/hid/hid-holtek-kbd.c b/drivers/hid/hid-holtek-kbd.c index 1f014ac54e14..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), */ @@ -102,14 +102,14 @@ 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); 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; } 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-ids.h b/drivers/hid/hid-ids.h index 781c5aa29859..c935429ddb34 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 @@ -810,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-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..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, @@ -24,15 +24,13 @@ 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"); - rdesc = keytouch_fixed_rdesc; *rsize = sizeof(keytouch_fixed_rdesc); - - return rdesc; + return keytouch_fixed_rdesc; } static const struct hid_device_id keytouch_devices[] = { 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..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), */ @@ -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); @@ -453,8 +453,8 @@ static __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 __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 __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 __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 __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 __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 __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; 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..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) */ @@ -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..638e36c6d0f1 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, + }, { } }; @@ -1441,12 +1447,13 @@ 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 && (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( @@ -1811,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; @@ -2065,7 +2075,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, @@ -2113,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, @@ -2275,6 +2294,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) }, 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..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) @@ -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-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); 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..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; @@ -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..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), */ @@ -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) @@ -580,8 +580,8 @@ static __u8 *steelseries_srws1_report_fixup(struct hid_device *hdev, __u8 *rdesc 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; } 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..d8008933c052 100644 --- a/drivers/hid/hid-uclogic-core.c +++ b/drivers/hid/hid-uclogic-core.c @@ -50,14 +50,14 @@ 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); 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 <kunit/visibility.h> /* 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 */ diff --git a/drivers/hid/hid-viewsonic.c b/drivers/hid/hid-viewsonic.c index 668c2adb77b6..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), */ @@ -70,15 +70,15 @@ 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: 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; } diff --git a/drivers/hid/hid-vrc2.c b/drivers/hid/hid-vrc2.c index 80a2b7ef5e66..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) @@ -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..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), */ @@ -599,50 +599,50 @@ 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) { 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; } diff --git a/drivers/hid/hid-winwing.c b/drivers/hid/hid-winwing.c index 10a5d87ccb96..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, @@ -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..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), */ @@ -61,15 +61,15 @@ 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: 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; } 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/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/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); 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, diff --git a/include/linux/hid.h b/include/linux/hid.h index 1533c9dcd3a6..121d5b8bc867 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; }; @@ -600,9 +600,9 @@ struct hid_driver; struct hid_ll_driver; struct hid_device { /* device report descriptor */ - __u8 *dev_rdesc; + const __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 */ @@ -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, @@ -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); @@ -953,7 +955,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, 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, 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 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/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 <bpf/bpf.h> -#include <fcntl.h> -#include <fnmatch.h> -#include <dirent.h> -#include <poll.h> -#include <pthread.h> -#include <stdbool.h> -#include <linux/hidraw.h> -#include <linux/uhid.h> - -#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 <fcntl.h> +#include <fnmatch.h> +#include <dirent.h> +#include <poll.h> +#include <pthread.h> +#include <stdbool.h> +#include <linux/hidraw.h> +#include <linux/uhid.h> + +#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); +} diff --git a/tools/testing/selftests/hid/hidraw.c b/tools/testing/selftests/hid/hidraw.c new file mode 100644 index 000000000000..f8b4f7ff292c --- /dev/null +++ b/tools/testing/selftests/hid/hidraw.c @@ -0,0 +1,237 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2022-2024 Red Hat */ + +#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; + 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); +} + +/* + * 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); +} |