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

HID: bpf: rescan the device for the group after a load/unload

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>

authored by

Benjamin Tissoires and committed by
Jiri Kosina
4c2c5ff9 4e411a3f

+21
+21
drivers/hid/hid-core.c
··· 944 944 hid->group = HID_GROUP_GENERIC; 945 945 946 946 /* 947 + * In case we are re-scanning after a BPF has been loaded, 948 + * we need to use the bpf report descriptor, not the original one. 949 + */ 950 + if (hid->bpf_rdesc && hid->bpf_rsize) { 951 + start = hid->bpf_rdesc; 952 + end = start + hid->bpf_rsize; 953 + } 954 + 955 + /* 947 956 * The parsing is simpler than the one in hid_open_report() as we should 948 957 * be robust against hid errors. Those errors will be raised by 949 958 * hid_open_report() anyway. ··· 2737 2728 int ret; 2738 2729 2739 2730 if (!hdev->bpf_rsize) { 2731 + /* we keep a reference to the currently scanned report descriptor */ 2732 + const __u8 *original_rdesc = hdev->bpf_rdesc; 2733 + 2734 + if (!original_rdesc) 2735 + original_rdesc = hdev->dev_rdesc; 2736 + 2740 2737 /* in case a bpf program gets detached, we need to free the old one */ 2741 2738 hid_free_bpf_rdesc(hdev); 2742 2739 ··· 2752 2737 /* call_hid_bpf_rdesc_fixup will always return a valid pointer */ 2753 2738 hdev->bpf_rdesc = call_hid_bpf_rdesc_fixup(hdev, hdev->dev_rdesc, 2754 2739 &hdev->bpf_rsize); 2740 + 2741 + /* the report descriptor changed, we need to re-scan it */ 2742 + if (original_rdesc != hdev->bpf_rdesc) { 2743 + hdev->group = 0; 2744 + hid_set_group(hdev); 2745 + } 2755 2746 } 2756 2747 2757 2748 if (!hid_check_device_match(hdev, hdrv, &id))