]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
HID: bpf: rescan the device for the group after a load/unload
authorBenjamin Tissoires <bentiss@kernel.org>
Thu, 21 Aug 2025 14:38:14 +0000 (16:38 +0200)
committerJiri Kosina <jkosina@suse.com>
Fri, 12 Sep 2025 15:11:55 +0000 (17:11 +0200)
When a BPF gets loaded, it was previously not possible to bind a
hid-generic device to hid-multitouch because the group was never
updated.

This change forces a rescan of the report descriptor after a bpf is
loaded/unloaded so we set up the proper group.

This was detected while Peter was trying to fix a Viewsonic device: the
HID device sending multiotuch data through a proprietary collection was
handled by hid-generic, and we don't have any way of attaching it to
hid-multitouch because the pre-scanning wasn't able to see the Contact
ID HID usage.

Suggested-by: Peter Hutterer <peter.hutterer@who-t.net>
Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net>
Signed-off-by: Benjamin Tissoires <bentiss@kernel.org>
Signed-off-by: Jiri Kosina <jkosina@suse.com>
drivers/hid/hid-core.c

index cf68fdffe0581eefb29a9d691f4acfc8f0d175d5..a5b3a8ca2fcbc868470dd50ec14e4c7829dd863b 100644 (file)
@@ -943,6 +943,15 @@ static int hid_scan_report(struct hid_device *hid)
        parser->device = hid;
        hid->group = HID_GROUP_GENERIC;
 
+       /*
+        * In case we are re-scanning after a BPF has been loaded,
+        * we need to use the bpf report descriptor, not the original one.
+        */
+       if (hid->bpf_rdesc && hid->bpf_rsize) {
+               start = hid->bpf_rdesc;
+               end = start + hid->bpf_rsize;
+       }
+
        /*
         * The parsing is simpler than the one in hid_open_report() as we should
         * be robust against hid errors. Those errors will be raised by
@@ -2728,6 +2737,12 @@ static int __hid_device_probe(struct hid_device *hdev, struct hid_driver *hdrv)
        int ret;
 
        if (!hdev->bpf_rsize) {
+               /* we keep a reference to the currently scanned report descriptor */
+               const __u8  *original_rdesc = hdev->bpf_rdesc;
+
+               if (!original_rdesc)
+                       original_rdesc = hdev->dev_rdesc;
+
                /* in case a bpf program gets detached, we need to free the old one */
                hid_free_bpf_rdesc(hdev);
 
@@ -2737,6 +2752,12 @@ static int __hid_device_probe(struct hid_device *hdev, struct hid_driver *hdrv)
                /* call_hid_bpf_rdesc_fixup will always return a valid pointer */
                hdev->bpf_rdesc = call_hid_bpf_rdesc_fixup(hdev, hdev->dev_rdesc,
                                                           &hdev->bpf_rsize);
+
+               /* the report descriptor changed, we need to re-scan it */
+               if (original_rdesc != hdev->bpf_rdesc) {
+                       hdev->group = 0;
+                       hid_set_group(hdev);
+               }
        }
 
        if (!hid_check_device_match(hdev, hdrv, &id))