Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/hid: add test for assigning a given device to hid-generic

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>

+96 -2
+79 -1
tools/testing/selftests/hid/hid_bpf.c
··· 54 54 hid_bpf_teardown(_metadata, self, variant); \ 55 55 } while (0) 56 56 57 + struct specific_device { 58 + const char test_name[64]; 59 + __u16 bus; 60 + __u32 vid; 61 + __u32 pid; 62 + }; 63 + 57 64 FIXTURE_SETUP(hid_bpf) 58 65 { 66 + const struct specific_device *match = NULL; 59 67 int err; 60 68 61 - err = setup_uhid(_metadata, &self->hid, BUS_USB, 0x0001, 0x0a36, rdesc, sizeof(rdesc)); 69 + const struct specific_device devices[] = { 70 + { 71 + .test_name = "test_hid_driver_probe", 72 + .bus = BUS_BLUETOOTH, 73 + .vid = 0x05ac, /* USB_VENDOR_ID_APPLE */ 74 + .pid = 0x022c, /* USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI */ 75 + }, { 76 + .test_name = "*", 77 + .bus = BUS_USB, 78 + .vid = 0x0001, 79 + .pid = 0x0a36, 80 + }}; 81 + 82 + for (int i = 0; i < ARRAY_SIZE(devices); i++) { 83 + match = &devices[i]; 84 + if (!strncmp(_metadata->name, devices[i].test_name, sizeof(devices[i].test_name))) 85 + break; 86 + } 87 + 88 + ASSERT_OK_PTR(match); 89 + 90 + err = setup_uhid(_metadata, &self->hid, match->bus, match->vid, match->pid, 91 + rdesc, sizeof(rdesc)); 62 92 ASSERT_OK(err); 63 93 } 64 94 ··· 883 853 ASSERT_EQ(buf[1], 1); 884 854 ASSERT_EQ(buf[2], 2); 885 855 ASSERT_EQ(buf[3], 3); 856 + } 857 + 858 + static bool is_using_driver(struct __test_metadata *_metadata, struct uhid_device *hid, 859 + const char *driver) 860 + { 861 + char driver_line[512]; 862 + char uevent[1024]; 863 + char temp[512]; 864 + int fd, nread; 865 + bool found = false; 866 + 867 + sprintf(uevent, "/sys/bus/hid/devices/%04X:%04X:%04X.%04X/uevent", 868 + hid->bus, hid->vid, hid->pid, hid->hid_id); 869 + 870 + fd = open(uevent, O_RDONLY | O_NONBLOCK); 871 + if (fd < 0) { 872 + TH_LOG("couldn't open '%s': %d, %d", uevent, fd, errno); 873 + return false; 874 + } 875 + 876 + sprintf(driver_line, "DRIVER=%s", driver); 877 + 878 + nread = read(fd, temp, ARRAY_SIZE(temp)); 879 + if (nread > 0 && (strstr(temp, driver_line)) != NULL) 880 + found = true; 881 + 882 + close(fd); 883 + 884 + return found; 885 + } 886 + 887 + /* 888 + * Attach hid_driver_probe to the given uhid device, 889 + * check that the device is now using hid-generic. 890 + */ 891 + TEST_F(hid_bpf, test_hid_driver_probe) 892 + { 893 + const struct test_program progs[] = { 894 + { 895 + .name = "hid_test_driver_probe", 896 + }, 897 + }; 898 + 899 + ASSERT_TRUE(is_using_driver(_metadata, &self->hid, "apple")); 900 + 901 + LOAD_PROGRAMS(progs); 902 + 903 + ASSERT_TRUE(is_using_driver(_metadata, &self->hid, "hid-generic")); 886 904 } 887 905 888 906 /*
+12
tools/testing/selftests/hid/progs/hid.c
··· 598 598 struct hid_bpf_ops test_infinite_loop_input_report = { 599 599 .hid_device_event = (void *)hid_test_infinite_loop_input_report, 600 600 }; 601 + 602 + SEC("?struct_ops.s/hid_rdesc_fixup") 603 + int BPF_PROG(hid_test_driver_probe, struct hid_bpf_ctx *hid_ctx) 604 + { 605 + hid_ctx->hid->quirks |= HID_QUIRK_IGNORE_SPECIAL_DRIVER; 606 + return 0; 607 + } 608 + 609 + SEC(".struct_ops.link") 610 + struct hid_bpf_ops test_driver_probe = { 611 + .hid_rdesc_fixup = (void *)hid_test_driver_probe, 612 + };
+5 -1
tools/testing/selftests/hid/progs/hid_bpf_helpers.h
··· 84 84 struct hid_device *hdev; 85 85 }; 86 86 87 + #define BIT(n) (1U << n) 88 + 87 89 #ifndef BPF_F_BEFORE 88 - #define BPF_F_BEFORE (1U << 3) 90 + #define BPF_F_BEFORE BIT(3) 89 91 #endif 92 + 93 + #define HID_QUIRK_IGNORE_SPECIAL_DRIVER BIT(22) 90 94 91 95 /* following are kfuncs exported by HID for HID-BPF */ 92 96 extern __u8 *hid_bpf_get_data(struct hid_bpf_ctx *ctx,