summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/hid/amd-sfh-hid/amd_sfh_hid.h2
-rw-r--r--drivers/hid/bpf/hid_bpf_dispatch.c6
-rw-r--r--drivers/hid/hid-apple.c2
-rw-r--r--drivers/hid/hid-asus.c2
-rw-r--r--drivers/hid/hid-aureal.c2
-rw-r--r--drivers/hid/hid-bigbenff.c6
-rw-r--r--drivers/hid/hid-cherry.c2
-rw-r--r--drivers/hid/hid-chicony.c4
-rw-r--r--drivers/hid/hid-cmedia.c6
-rw-r--r--drivers/hid/hid-core.c39
-rw-r--r--drivers/hid/hid-corsair.c4
-rw-r--r--drivers/hid/hid-cougar.c4
-rw-r--r--drivers/hid/hid-cypress.c2
-rw-r--r--drivers/hid/hid-dr.c8
-rw-r--r--drivers/hid/hid-elecom.c2
-rw-r--r--drivers/hid/hid-gembird.c2
-rw-r--r--drivers/hid/hid-glorious.c2
-rw-r--r--drivers/hid/hid-google-hammer.c27
-rw-r--r--drivers/hid/hid-holtek-kbd.c6
-rw-r--r--drivers/hid/hid-holtek-mouse.c4
-rw-r--r--drivers/hid/hid-ids.h2
-rw-r--r--drivers/hid/hid-ite.c2
-rw-r--r--drivers/hid/hid-keytouch.c8
-rw-r--r--drivers/hid/hid-kye.c2
-rw-r--r--drivers/hid/hid-lenovo.c2
-rw-r--r--drivers/hid/hid-lg.c30
-rw-r--r--drivers/hid/hid-logitech-hidpp.c4
-rw-r--r--drivers/hid/hid-macally.c4
-rw-r--r--drivers/hid/hid-magicmouse.c4
-rw-r--r--drivers/hid/hid-maltron.c8
-rw-r--r--drivers/hid/hid-microsoft.c2
-rw-r--r--drivers/hid/hid-monterey.c2
-rw-r--r--drivers/hid/hid-multitouch.c30
-rw-r--r--drivers/hid/hid-nti.c2
-rw-r--r--drivers/hid/hid-ortek.c2
-rw-r--r--drivers/hid/hid-petalynx.c2
-rw-r--r--drivers/hid/hid-prodikeys.c2
-rw-r--r--drivers/hid/hid-pxrc.c6
-rw-r--r--drivers/hid/hid-redragon.c2
-rw-r--r--drivers/hid/hid-saitek.c2
-rw-r--r--drivers/hid/hid-samsung.c2
-rw-r--r--drivers/hid/hid-semitek.c4
-rw-r--r--drivers/hid/hid-sensor-custom.c2
-rw-r--r--drivers/hid/hid-sensor-hub.c2
-rw-r--r--drivers/hid/hid-sigmamicro.c4
-rw-r--r--drivers/hid/hid-sony.c14
-rw-r--r--drivers/hid/hid-steelseries.c8
-rw-r--r--drivers/hid/hid-sunplus.c2
-rw-r--r--drivers/hid/hid-topre.c4
-rw-r--r--drivers/hid/hid-uclogic-core.c4
-rw-r--r--drivers/hid/hid-uclogic-params.c4
-rw-r--r--drivers/hid/hid-uclogic-params.h10
-rw-r--r--drivers/hid/hid-uclogic-rdesc.c20
-rw-r--r--drivers/hid/hid-uclogic-rdesc.h20
-rw-r--r--drivers/hid/hid-viewsonic.c8
-rw-r--r--drivers/hid/hid-vrc2.c6
-rw-r--r--drivers/hid/hid-waltop.c30
-rw-r--r--drivers/hid/hid-winwing.c8
-rw-r--r--drivers/hid/hid-xiaomi.c8
-rw-r--r--drivers/hid/hid-zydacron.c2
-rw-r--r--drivers/hid/hidraw.c39
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-core.c42
-rw-r--r--drivers/hid/intel-ish-hid/ishtp/bus.h1
-rw-r--r--drivers/hid/intel-ish-hid/ishtp/client.h1
-rw-r--r--include/linux/hid.h12
-rw-r--r--include/linux/hid_bpf.h2
-rw-r--r--include/linux/hidraw.h1
-rw-r--r--include/uapi/linux/hidraw.h1
-rw-r--r--tools/testing/selftests/hid/.gitignore1
-rw-r--r--tools/testing/selftests/hid/Makefile2
-rw-r--r--tools/testing/selftests/hid/hid_bpf.c437
-rw-r--r--tools/testing/selftests/hid/hid_common.h436
-rw-r--r--tools/testing/selftests/hid/hidraw.c237
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);
+}