aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/tools
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2024-11-20 13:57:40 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2024-11-20 13:57:40 -0800
commitb57807cbbf36f17448cdb42e69a949aa76605440 (patch)
tree0d5dd84ac53af24003c213a6b9d7dd3240a4a338 /tools
parentMerge tag 'devicetree-for-6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/robh/linux (diff)
parentMerge branch 'for-6.13/bpf' into for-linus (diff)
downloadwireguard-linux-b57807cbbf36f17448cdb42e69a949aa76605440.tar.xz
wireguard-linux-b57807cbbf36f17448cdb42e69a949aa76605440.zip
Merge tag 'hid-for-linus-2024111801' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID updates from Jiri Kosina: - improvement in the way hid-bpf coexists with specific drivers (others than hid-generic) that are already bound to devices (Benjamin Tissoires) - removal of three way-too-aggressive BUG_ON()s from HID drivers (He Lugang) - assorted cleanups and small code fixes to HID core (Dmitry Torokhov, Yan Zhen, Nathan Chancellor, Andy Shevchenko) - support for Corsair Void headset family (Stuart Hayhurst) - Support for Goodix GT7986U SPI (Charles Wang) - initial vendor-specific driver for Kysona, currently adding support for Kysona M600 (Lode Willems) - other assorted code cleanups and small bugfixes all over the place * tag 'hid-for-linus-2024111801' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: (40 commits) HID: multitouch: make mt_set_mode() less cryptic HID: hid-goodix-spi: Add OF supports dt-bindings: input: Goodix GT7986U SPI HID Touchscreen HID: hyperv: streamline driver probe to avoid devres issues HID: magicmouse: Apple Magic Trackpad 2 USB-C driver support HID: rmi: Add select RMI4_F3A in Kconfig HID: wacom: Interpret tilt data from Intuos Pro BT as signed values HID: steelseries: Add capacity_level mapping HID: steelseries: Fix battery requests stopping after some time HID: hid-goodix: Fix HID get/set feature operation overwritten problem HID: hid-goodix: Return 0 when receiving an empty HID feature package HID: bpf: drop use of Logical|Physical|UsageRange HID: bpf: Fix Rapoo M50 Plus Silent side buttons HID: bpf: Fix NKRO on Mistel MD770 HID: replace BUG_ON() with WARN_ON() HID: wacom: Set eraser status when either 'Eraser' or 'Invert' usage is set HID: Kysona: add basic online status HID: Kysona: check battery status every 5s using a workqueue HID: Kysona: Add basic battery reporting for Kysona M600 HID: Add IDs for Kysona ...
Diffstat (limited to '')
-rw-r--r--tools/testing/selftests/hid/Makefile2
-rw-r--r--tools/testing/selftests/hid/hid_bpf.c151
-rw-r--r--tools/testing/selftests/hid/hid_common.h112
-rw-r--r--tools/testing/selftests/hid/hidraw.c36
-rw-r--r--tools/testing/selftests/hid/progs/hid.c12
-rw-r--r--tools/testing/selftests/hid/progs/hid_bpf_helpers.h6
6 files changed, 206 insertions, 113 deletions
diff --git a/tools/testing/selftests/hid/Makefile b/tools/testing/selftests/hid/Makefile
index 662209f5fabc..0336353bd15f 100644
--- a/tools/testing/selftests/hid/Makefile
+++ b/tools/testing/selftests/hid/Makefile
@@ -232,7 +232,7 @@ $(BPF_SKELS): %.skel.h: %.bpf.o $(BPFTOOL) | $(OUTPUT)
$(Q)$(BPFTOOL) gen object $(<:.o=.linked1.o) $<
$(Q)$(BPFTOOL) gen skeleton $(<:.o=.linked1.o) name $(notdir $(<:.bpf.o=)) > $@
-$(OUTPUT)/%.o: %.c $(BPF_SKELS)
+$(OUTPUT)/%.o: %.c $(BPF_SKELS) hid_common.h
$(call msg,CC,,$@)
$(Q)$(CC) $(CFLAGS) -c $(filter %.c,$^) $(LDLIBS) -o $@
diff --git a/tools/testing/selftests/hid/hid_bpf.c b/tools/testing/selftests/hid/hid_bpf.c
index 86f4d66379f7..ca58bfa3ca65 100644
--- a/tools/testing/selftests/hid/hid_bpf.c
+++ b/tools/testing/selftests/hid/hid_bpf.c
@@ -4,13 +4,6 @@
#include "hid_common.h"
#include <bpf/bpf.h>
-struct attach_prog_args {
- int prog_fd;
- unsigned int hid;
- int retval;
- int insert_head;
-};
-
struct hid_hw_request_syscall_args {
__u8 data[10];
unsigned int hid;
@@ -21,11 +14,8 @@ struct hid_hw_request_syscall_args {
};
FIXTURE(hid_bpf) {
- int dev_id;
- int uhid_fd;
+ struct uhid_device hid;
int hidraw_fd;
- int hid_id;
- pthread_t tid;
struct hid *skel;
struct bpf_link *hid_links[3]; /* max number of programs loaded in a single test */
};
@@ -54,35 +44,52 @@ static void detach_bpf(FIXTURE_DATA(hid_bpf) * self)
FIXTURE_TEARDOWN(hid_bpf) {
void *uhid_err;
- uhid_destroy(_metadata, self->uhid_fd);
+ uhid_destroy(_metadata, &self->hid);
detach_bpf(self);
- pthread_join(self->tid, &uhid_err);
+ pthread_join(self->hid.tid, &uhid_err);
}
#define TEARDOWN_LOG(fmt, ...) do { \
TH_LOG(fmt, ##__VA_ARGS__); \
hid_bpf_teardown(_metadata, self, variant); \
} while (0)
+struct specific_device {
+ const char test_name[64];
+ __u16 bus;
+ __u32 vid;
+ __u32 pid;
+};
+
FIXTURE_SETUP(hid_bpf)
{
- time_t t;
+ const struct specific_device *match = NULL;
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);
+ const struct specific_device devices[] = {
+ {
+ .test_name = "test_hid_driver_probe",
+ .bus = BUS_BLUETOOTH,
+ .vid = 0x05ac, /* USB_VENDOR_ID_APPLE */
+ .pid = 0x022c, /* USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI */
+ }, {
+ .test_name = "*",
+ .bus = BUS_USB,
+ .vid = 0x0001,
+ .pid = 0x0a36,
+ }};
+
+ for (int i = 0; i < ARRAY_SIZE(devices); i++) {
+ match = &devices[i];
+ if (!strncmp(_metadata->name, devices[i].test_name, sizeof(devices[i].test_name)))
+ break;
+ }
- /* 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);
+ ASSERT_OK_PTR(match);
- err = uhid_start_listener(_metadata, &self->tid, self->uhid_fd);
- ASSERT_EQ(0, err) TEARDOWN_LOG("could not start udev listener: %d", err);
+ err = setup_uhid(_metadata, &self->hid, match->bus, match->vid, match->pid,
+ rdesc, sizeof(rdesc));
+ ASSERT_OK(err);
}
struct test_program {
@@ -129,7 +136,7 @@ static void load_programs(const struct test_program programs[],
ops_hid_id = bpf_map__initial_value(map, NULL);
ASSERT_OK_PTR(ops_hid_id) TH_LOG("unable to retrieve struct_ops data");
- *ops_hid_id = self->hid_id;
+ *ops_hid_id = self->hid.hid_id;
}
/* we disable the auto-attach feature of all maps because we
@@ -157,7 +164,7 @@ static void load_programs(const struct test_program programs[],
hid__attach(self->skel);
- self->hidraw_fd = open_hidraw(self->dev_id);
+ self->hidraw_fd = open_hidraw(&self->hid);
ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw");
}
@@ -192,7 +199,7 @@ TEST_F(hid_bpf, raw_event)
/* inject one event */
buf[0] = 1;
buf[1] = 42;
- uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+ uhid_send_event(_metadata, &self->hid, buf, 6);
/* check that hid_first_event() was executed */
ASSERT_EQ(self->skel->data->callback_check, 42) TH_LOG("callback_check1");
@@ -208,7 +215,7 @@ TEST_F(hid_bpf, raw_event)
memset(buf, 0, sizeof(buf));
buf[0] = 1;
buf[1] = 47;
- uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+ uhid_send_event(_metadata, &self->hid, buf, 6);
/* check that hid_first_event() was executed */
ASSERT_EQ(self->skel->data->callback_check, 47) TH_LOG("callback_check1");
@@ -239,7 +246,7 @@ TEST_F(hid_bpf, subprog_raw_event)
/* inject one event */
buf[0] = 1;
buf[1] = 42;
- uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+ uhid_send_event(_metadata, &self->hid, buf, 6);
/* read the data from hidraw */
memset(buf, 0, sizeof(buf));
@@ -252,7 +259,7 @@ TEST_F(hid_bpf, subprog_raw_event)
memset(buf, 0, sizeof(buf));
buf[0] = 1;
buf[1] = 47;
- uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+ uhid_send_event(_metadata, &self->hid, buf, 6);
/* read the data from hidraw */
memset(buf, 0, sizeof(buf));
@@ -303,7 +310,7 @@ TEST_F(hid_bpf, test_attach_detach)
/* inject one event */
buf[0] = 1;
buf[1] = 42;
- uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+ uhid_send_event(_metadata, &self->hid, buf, 6);
/* read the data from hidraw */
memset(buf, 0, sizeof(buf));
@@ -326,14 +333,14 @@ TEST_F(hid_bpf, test_attach_detach)
/* detach the program */
detach_bpf(self);
- self->hidraw_fd = open_hidraw(self->dev_id);
+ self->hidraw_fd = open_hidraw(&self->hid);
ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw");
/* inject another event */
memset(buf, 0, sizeof(buf));
buf[0] = 1;
buf[1] = 47;
- uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+ uhid_send_event(_metadata, &self->hid, buf, 6);
/* read the data from hidraw */
memset(buf, 0, sizeof(buf));
@@ -352,7 +359,7 @@ TEST_F(hid_bpf, test_attach_detach)
memset(buf, 0, sizeof(buf));
buf[0] = 1;
buf[1] = 42;
- uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+ uhid_send_event(_metadata, &self->hid, buf, 6);
/* read the data from hidraw */
memset(buf, 0, sizeof(buf));
@@ -382,7 +389,7 @@ TEST_F(hid_bpf, test_hid_change_report)
/* inject one event */
buf[0] = 1;
buf[1] = 42;
- uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+ uhid_send_event(_metadata, &self->hid, buf, 6);
/* read the data from hidraw */
memset(buf, 0, sizeof(buf));
@@ -412,7 +419,7 @@ TEST_F(hid_bpf, test_hid_user_input_report_call)
LOAD_BPF;
- args.hid = self->hid_id;
+ args.hid = self->hid.hid_id;
args.data[0] = 1; /* report ID */
args.data[1] = 2; /* report ID */
args.data[2] = 42; /* report ID */
@@ -458,7 +465,7 @@ TEST_F(hid_bpf, test_hid_user_output_report_call)
LOAD_BPF;
- args.hid = self->hid_id;
+ args.hid = self->hid.hid_id;
args.data[0] = 1; /* report ID */
args.data[1] = 2; /* report ID */
args.data[2] = 42; /* report ID */
@@ -506,7 +513,7 @@ TEST_F(hid_bpf, test_hid_user_raw_request_call)
LOAD_BPF;
- args.hid = self->hid_id;
+ args.hid = self->hid.hid_id;
args.data[0] = 1; /* report ID */
prog_fd = bpf_program__fd(self->skel->progs.hid_user_raw_request);
@@ -539,7 +546,7 @@ TEST_F(hid_bpf, test_hid_filter_raw_request_call)
/* inject one event */
buf[0] = 1;
buf[1] = 42;
- uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+ uhid_send_event(_metadata, &self->hid, buf, 6);
/* read the data from hidraw */
memset(buf, 0, sizeof(buf));
@@ -565,7 +572,7 @@ TEST_F(hid_bpf, test_hid_filter_raw_request_call)
/* detach the program */
detach_bpf(self);
- self->hidraw_fd = open_hidraw(self->dev_id);
+ self->hidraw_fd = open_hidraw(&self->hid);
ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw");
err = ioctl(self->hidraw_fd, HIDIOCGFEATURE(sizeof(buf)), buf);
@@ -641,7 +648,7 @@ TEST_F(hid_bpf, test_hid_filter_output_report_call)
/* inject one event */
buf[0] = 1;
buf[1] = 42;
- uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+ uhid_send_event(_metadata, &self->hid, buf, 6);
/* read the data from hidraw */
memset(buf, 0, sizeof(buf));
@@ -667,7 +674,7 @@ TEST_F(hid_bpf, test_hid_filter_output_report_call)
/* detach the program */
detach_bpf(self);
- self->hidraw_fd = open_hidraw(self->dev_id);
+ self->hidraw_fd = open_hidraw(&self->hid);
ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw");
err = write(self->hidraw_fd, buf, 3);
@@ -742,7 +749,7 @@ TEST_F(hid_bpf, test_multiply_events_wq)
/* inject one event */
buf[0] = 1;
buf[1] = 42;
- uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+ uhid_send_event(_metadata, &self->hid, buf, 6);
/* read the data from hidraw */
memset(buf, 0, sizeof(buf));
@@ -780,7 +787,7 @@ TEST_F(hid_bpf, test_multiply_events)
/* inject one event */
buf[0] = 1;
buf[1] = 42;
- uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+ uhid_send_event(_metadata, &self->hid, buf, 6);
/* read the data from hidraw */
memset(buf, 0, sizeof(buf));
@@ -816,7 +823,7 @@ TEST_F(hid_bpf, test_hid_infinite_loop_input_report_call)
buf[1] = 2;
buf[2] = 42;
- uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+ uhid_send_event(_metadata, &self->hid, buf, 6);
/* read the data from hidraw */
memset(buf, 0, sizeof(buf));
@@ -867,7 +874,7 @@ TEST_F(hid_bpf, test_hid_attach_flags)
/* inject one event */
buf[0] = 1;
- uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+ uhid_send_event(_metadata, &self->hid, buf, 6);
/* read the data from hidraw */
memset(buf, 0, sizeof(buf));
@@ -878,6 +885,54 @@ TEST_F(hid_bpf, test_hid_attach_flags)
ASSERT_EQ(buf[3], 3);
}
+static bool is_using_driver(struct __test_metadata *_metadata, struct uhid_device *hid,
+ const char *driver)
+{
+ char driver_line[512];
+ char uevent[1024];
+ char temp[512];
+ int fd, nread;
+ bool found = false;
+
+ sprintf(uevent, "/sys/bus/hid/devices/%04X:%04X:%04X.%04X/uevent",
+ hid->bus, hid->vid, hid->pid, hid->hid_id);
+
+ fd = open(uevent, O_RDONLY | O_NONBLOCK);
+ if (fd < 0) {
+ TH_LOG("couldn't open '%s': %d, %d", uevent, fd, errno);
+ return false;
+ }
+
+ sprintf(driver_line, "DRIVER=%s", driver);
+
+ nread = read(fd, temp, ARRAY_SIZE(temp));
+ if (nread > 0 && (strstr(temp, driver_line)) != NULL)
+ found = true;
+
+ close(fd);
+
+ return found;
+}
+
+/*
+ * Attach hid_driver_probe to the given uhid device,
+ * check that the device is now using hid-generic.
+ */
+TEST_F(hid_bpf, test_hid_driver_probe)
+{
+ const struct test_program progs[] = {
+ {
+ .name = "hid_test_driver_probe",
+ },
+ };
+
+ ASSERT_TRUE(is_using_driver(_metadata, &self->hid, "apple"));
+
+ LOAD_PROGRAMS(progs);
+
+ ASSERT_TRUE(is_using_driver(_metadata, &self->hid, "hid-generic"));
+}
+
/*
* Attach hid_rdesc_fixup to the given uhid device,
* retrieve and open the matching hidraw node,
diff --git a/tools/testing/selftests/hid/hid_common.h b/tools/testing/selftests/hid/hid_common.h
index f151f151a1ed..f77f69c6657d 100644
--- a/tools/testing/selftests/hid/hid_common.h
+++ b/tools/testing/selftests/hid/hid_common.h
@@ -19,6 +19,16 @@
__typeof__(b) _b = (b); \
_a < _b ? _a : _b; })
+struct uhid_device {
+ int dev_id; /* uniq (random) number to identify the device */
+ int uhid_fd;
+ int hid_id; /* HID device id in the system */
+ __u16 bus;
+ __u32 vid;
+ __u32 pid;
+ pthread_t tid; /* thread for reading uhid events */
+};
+
static unsigned char rdesc[] = {
0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */
0x09, 0x21, /* Usage (Vendor Usage 0x21) */
@@ -122,7 +132,9 @@ static int uhid_write(struct __test_metadata *_metadata, int fd, const struct uh
}
}
-static int uhid_create(struct __test_metadata *_metadata, int fd, int rand_nb)
+static int uhid_create(struct __test_metadata *_metadata, int fd, int rand_nb,
+ __u16 bus, __u32 vid, __u32 pid, __u8 *rdesc,
+ size_t rdesc_size)
{
struct uhid_event ev;
char buf[25];
@@ -133,10 +145,10 @@ static int uhid_create(struct __test_metadata *_metadata, int fd, int rand_nb)
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.rd_size = rdesc_size;
+ ev.u.create.bus = bus;
+ ev.u.create.vendor = vid;
+ ev.u.create.product = pid;
ev.u.create.version = 0;
ev.u.create.country = 0;
@@ -146,14 +158,14 @@ static int uhid_create(struct __test_metadata *_metadata, int fd, int rand_nb)
return uhid_write(_metadata, fd, &ev);
}
-static void uhid_destroy(struct __test_metadata *_metadata, int fd)
+static void uhid_destroy(struct __test_metadata *_metadata, struct uhid_device *hid)
{
struct uhid_event ev;
memset(&ev, 0, sizeof(ev));
ev.type = UHID_DESTROY;
- uhid_write(_metadata, fd, &ev);
+ uhid_write(_metadata, hid->uhid_fd, &ev);
}
static int uhid_event(struct __test_metadata *_metadata, int fd)
@@ -281,7 +293,8 @@ static int uhid_start_listener(struct __test_metadata *_metadata, pthread_t *tid
return 0;
}
-static int uhid_send_event(struct __test_metadata *_metadata, int fd, __u8 *buf, size_t size)
+static int uhid_send_event(struct __test_metadata *_metadata, struct uhid_device *hid,
+ __u8 *buf, size_t size)
{
struct uhid_event ev;
@@ -294,36 +307,20 @@ static int uhid_send_event(struct __test_metadata *_metadata, int fd, __u8 *buf,
memcpy(ev.u.input2.data, buf, size);
- return uhid_write(_metadata, fd, &ev);
+ return uhid_write(_metadata, hid->uhid_fd, &ev);
}
-static int setup_uhid(struct __test_metadata *_metadata, int rand_nb)
+static bool match_sysfs_device(struct uhid_device *hid, const char *workdir, struct dirent *dir)
{
- 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 target[20] = "";
char phys[512];
char uevent[1024];
char temp[512];
int fd, nread;
bool found = false;
+ snprintf(target, sizeof(target), "%04X:%04X:%04X.*", hid->bus, hid->vid, hid->pid);
+
if (fnmatch(target, dir->d_name, 0))
return false;
@@ -334,7 +331,7 @@ static bool match_sysfs_device(int dev_id, const char *workdir, struct dirent *d
if (fd < 0)
return false;
- sprintf(phys, "PHYS=%d", dev_id);
+ sprintf(phys, "PHYS=%d", hid->dev_id);
nread = read(fd, temp, ARRAY_SIZE(temp));
if (nread > 0 && (strstr(temp, phys)) != NULL)
@@ -345,7 +342,7 @@ static bool match_sysfs_device(int dev_id, const char *workdir, struct dirent *d
return found;
}
-static int get_hid_id(int dev_id)
+static int get_hid_id(struct uhid_device *hid)
{
const char *workdir = "/sys/devices/virtual/misc/uhid";
const char *str_id;
@@ -360,10 +357,10 @@ static int get_hid_id(int dev_id)
d = opendir(workdir);
if (d) {
while ((dir = readdir(d)) != NULL) {
- if (!match_sysfs_device(dev_id, workdir, dir))
+ if (!match_sysfs_device(hid, workdir, dir))
continue;
- str_id = dir->d_name + sizeof("0003:0001:0A37.");
+ str_id = dir->d_name + sizeof("0000:0000:0000.");
found = (int)strtol(str_id, NULL, 16);
break;
@@ -377,7 +374,7 @@ static int get_hid_id(int dev_id)
return found;
}
-static int get_hidraw(int dev_id)
+static int get_hidraw(struct uhid_device *hid)
{
const char *workdir = "/sys/devices/virtual/misc/uhid";
char sysfs[1024];
@@ -394,7 +391,7 @@ static int get_hidraw(int dev_id)
continue;
while ((dir = readdir(d)) != NULL) {
- if (!match_sysfs_device(dev_id, workdir, dir))
+ if (!match_sysfs_device(hid, workdir, dir))
continue;
sprintf(sysfs, "%s/%s/hidraw", workdir, dir->d_name);
@@ -421,12 +418,12 @@ static int get_hidraw(int dev_id)
return found;
}
-static int open_hidraw(int dev_id)
+static int open_hidraw(struct uhid_device *hid)
{
int hidraw_number;
char hidraw_path[64] = { 0 };
- hidraw_number = get_hidraw(dev_id);
+ hidraw_number = get_hidraw(hid);
if (hidraw_number < 0)
return hidraw_number;
@@ -434,3 +431,44 @@ static int open_hidraw(int dev_id)
sprintf(hidraw_path, "/dev/hidraw%d", hidraw_number);
return open(hidraw_path, O_RDWR | O_NONBLOCK);
}
+
+static int setup_uhid(struct __test_metadata *_metadata, struct uhid_device *hid,
+ __u16 bus, __u32 vid, __u32 pid, const __u8 *rdesc, size_t rdesc_size)
+{
+ const char *path = "/dev/uhid";
+ time_t t;
+ int ret;
+
+ /* initialize random number generator */
+ srand((unsigned int)time(&t));
+
+ hid->dev_id = rand() % 1024;
+ hid->bus = bus;
+ hid->vid = vid;
+ hid->pid = pid;
+
+ hid->uhid_fd = open(path, O_RDWR | O_CLOEXEC);
+ ASSERT_GE(hid->uhid_fd, 0) TH_LOG("open uhid-cdev failed; %d", hid->uhid_fd);
+
+ ret = uhid_create(_metadata, hid->uhid_fd, hid->dev_id, bus, vid, pid,
+ (__u8 *)rdesc, rdesc_size);
+ ASSERT_EQ(0, ret) {
+ TH_LOG("create uhid device failed: %d", ret);
+ close(hid->uhid_fd);
+ return ret;
+ }
+
+ /* locate the uevent file of the created device */
+ hid->hid_id = get_hid_id(hid);
+ ASSERT_GT(hid->hid_id, 0)
+ TH_LOG("Could not locate uhid device id: %d", hid->hid_id);
+
+ ret = uhid_start_listener(_metadata, &hid->tid, hid->uhid_fd);
+ ASSERT_EQ(0, ret) {
+ TH_LOG("could not start udev listener: %d", ret);
+ close(hid->uhid_fd);
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/tools/testing/selftests/hid/hidraw.c b/tools/testing/selftests/hid/hidraw.c
index f8b4f7ff292c..821db37ba4bb 100644
--- a/tools/testing/selftests/hid/hidraw.c
+++ b/tools/testing/selftests/hid/hidraw.c
@@ -9,11 +9,8 @@
#endif /* HIDIOCREVOKE */
FIXTURE(hidraw) {
- int dev_id;
- int uhid_fd;
+ struct uhid_device hid;
int hidraw_fd;
- int hid_id;
- pthread_t tid;
};
static void close_hidraw(FIXTURE_DATA(hidraw) * self)
{
@@ -25,10 +22,10 @@ static void close_hidraw(FIXTURE_DATA(hidraw) * self)
FIXTURE_TEARDOWN(hidraw) {
void *uhid_err;
- uhid_destroy(_metadata, self->uhid_fd);
+ uhid_destroy(_metadata, &self->hid);
close_hidraw(self);
- pthread_join(self->tid, &uhid_err);
+ pthread_join(self->hid.tid, &uhid_err);
}
#define TEARDOWN_LOG(fmt, ...) do { \
TH_LOG(fmt, ##__VA_ARGS__); \
@@ -37,25 +34,12 @@ FIXTURE_TEARDOWN(hidraw) {
FIXTURE_SETUP(hidraw)
{
- time_t t;
int err;
- /* initialize random number generator */
- srand((unsigned int)time(&t));
+ err = setup_uhid(_metadata, &self->hid, BUS_USB, 0x0001, 0x0a37, rdesc, sizeof(rdesc));
+ ASSERT_OK(err);
- 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);
+ self->hidraw_fd = open_hidraw(&self->hid);
ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw");
}
@@ -79,7 +63,7 @@ TEST_F(hidraw, raw_event)
/* inject one event */
buf[0] = 1;
buf[1] = 42;
- uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+ uhid_send_event(_metadata, &self->hid, buf, 6);
/* read the data from hidraw */
memset(buf, 0, sizeof(buf));
@@ -101,7 +85,7 @@ TEST_F(hidraw, raw_event_revoked)
/* inject one event */
buf[0] = 1;
buf[1] = 42;
- uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+ uhid_send_event(_metadata, &self->hid, buf, 6);
/* read the data from hidraw */
memset(buf, 0, sizeof(buf));
@@ -117,7 +101,7 @@ TEST_F(hidraw, raw_event_revoked)
/* inject one other event */
buf[0] = 1;
buf[1] = 43;
- uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+ uhid_send_event(_metadata, &self->hid, buf, 6);
/* read the data from hidraw */
memset(buf, 0, sizeof(buf));
@@ -161,7 +145,7 @@ TEST_F(hidraw, poll_revoked)
/* inject one event */
buf[0] = 1;
buf[1] = 42;
- uhid_send_event(_metadata, self->uhid_fd, buf, 6);
+ uhid_send_event(_metadata, &self->hid, buf, 6);
while (true) {
ready = poll(pfds, 1, 5000);
diff --git a/tools/testing/selftests/hid/progs/hid.c b/tools/testing/selftests/hid/progs/hid.c
index 5ecc845ef792..9b22e9a0e658 100644
--- a/tools/testing/selftests/hid/progs/hid.c
+++ b/tools/testing/selftests/hid/progs/hid.c
@@ -598,3 +598,15 @@ SEC(".struct_ops.link")
struct hid_bpf_ops test_infinite_loop_input_report = {
.hid_device_event = (void *)hid_test_infinite_loop_input_report,
};
+
+SEC("?struct_ops.s/hid_rdesc_fixup")
+int BPF_PROG(hid_test_driver_probe, struct hid_bpf_ctx *hid_ctx)
+{
+ hid_ctx->hid->quirks |= HID_QUIRK_IGNORE_SPECIAL_DRIVER;
+ return 0;
+}
+
+SEC(".struct_ops.link")
+struct hid_bpf_ops test_driver_probe = {
+ .hid_rdesc_fixup = (void *)hid_test_driver_probe,
+};
diff --git a/tools/testing/selftests/hid/progs/hid_bpf_helpers.h b/tools/testing/selftests/hid/progs/hid_bpf_helpers.h
index e5db897586bb..1a645684a117 100644
--- a/tools/testing/selftests/hid/progs/hid_bpf_helpers.h
+++ b/tools/testing/selftests/hid/progs/hid_bpf_helpers.h
@@ -84,10 +84,14 @@ struct hid_bpf_ops {
struct hid_device *hdev;
};
+#define BIT(n) (1U << n)
+
#ifndef BPF_F_BEFORE
-#define BPF_F_BEFORE (1U << 3)
+#define BPF_F_BEFORE BIT(3)
#endif
+#define HID_QUIRK_IGNORE_SPECIAL_DRIVER BIT(22)
+
/* following are kfuncs exported by HID for HID-BPF */
extern __u8 *hid_bpf_get_data(struct hid_bpf_ctx *ctx,
unsigned int offset,