]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
selftests/hid: add test for assigning a given device to hid-generic
authorBenjamin Tissoires <bentiss@kernel.org>
Tue, 1 Oct 2024 14:30:13 +0000 (16:30 +0200)
committerBenjamin Tissoires <bentiss@kernel.org>
Fri, 4 Oct 2024 14:10:49 +0000 (16:10 +0200)
We use a well known VID/PID on a driver that doesn't need to talk to
the device, ensures we created the device against the target driver,
then load our program and ensure we have unbound to this driver and use
hid-generic instead.

Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Acked-by: Shuah Khan <skhan@linuxfoundation.org>
Link: https://patch.msgid.link/20241001-hid-bpf-hid-generic-v3-9-2ef1019468df@kernel.org
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
tools/testing/selftests/hid/hid_bpf.c
tools/testing/selftests/hid/progs/hid.c
tools/testing/selftests/hid/progs/hid_bpf_helpers.h

index 1e979fb3542bab79803ae2c772e048d93927df33..ca58bfa3ca656df06b835291dac4ffc918c226ca 100644 (file)
@@ -54,11 +54,41 @@ FIXTURE_TEARDOWN(hid_bpf) {
        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)
 {
+       const struct specific_device *match = NULL;
        int err;
 
-       err = setup_uhid(_metadata, &self->hid, BUS_USB, 0x0001, 0x0a36, rdesc, sizeof(rdesc));
+       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;
+       }
+
+       ASSERT_OK_PTR(match);
+
+       err = setup_uhid(_metadata, &self->hid, match->bus, match->vid, match->pid,
+                        rdesc, sizeof(rdesc));
        ASSERT_OK(err);
 }
 
@@ -855,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,
index 5ecc845ef79216d42e141e42167289109ea79267..9b22e9a0e658f2d679ae47e940f190d085504053 100644 (file)
@@ -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,
+};
index e5db897586bbfe010d8799f6f52fc5c418344e6b..1a645684a1179909c2c3cbf74b8e55d2ed3ab9a0 100644 (file)
@@ -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,