xref: /linux/drivers/hid/bpf/progs/Generic__touchpad.bpf.c (revision d97e7d7c304f87419921f740743f7baa99f40539)
1 // SPDX-License-Identifier: GPL-2.0-only
2 /* Copyright (c) 2025 Benjamin Tissoires
3  */
4 
5 #include "vmlinux.h"
6 #include "hid_bpf.h"
7 #include "hid_bpf_helpers.h"
8 #include "hid_report_helpers.h"
9 #include "hid_usages.h"
10 #include <bpf/bpf_tracing.h>
11 
12 HID_BPF_CONFIG(
13 	HID_DEVICE(BUS_ANY, HID_GROUP_MULTITOUCH_WIN_8, HID_VID_ANY, HID_PID_ANY),
14 );
15 
16 EXPORT_UDEV_PROP(HID_DIGITIZER_PAD_TYPE, 32);
17 
18 __u8 hw_req_buf[1024];
19 
20 /* to be filled by udev-hid-bpf */
21 struct hid_rdesc_descriptor HID_REPORT_DESCRIPTOR;
22 
23 SEC("syscall")
24 int probe(struct hid_bpf_probe_args *ctx)
25 {
26 	struct hid_rdesc_report *pad_type_feature = NULL;
27 	struct hid_rdesc_field *pad_type = NULL;
28 	struct hid_rdesc_report *feature;
29 	struct hid_bpf_ctx *hid_ctx;
30 	char *pad_type_str = "";
31 	int ret;
32 
33 	hid_bpf_for_each_feature_report(&HID_REPORT_DESCRIPTOR, feature) {
34 		struct hid_rdesc_field *field;
35 
36 		hid_bpf_for_each_field(feature, field) {
37 			if (field->usage_page == HidUsagePage_Digitizers &&
38 			    field->usage_id == HidUsage_Dig_PadType) {
39 				pad_type = field;
40 				pad_type_feature = feature;
41 				break;
42 			}
43 		}
44 		if (pad_type)
45 			break;
46 	}
47 
48 	if (!pad_type || !pad_type_feature) {
49 		ctx->retval = -EINVAL;
50 		return 0;
51 	}
52 
53 	hid_ctx = hid_bpf_allocate_context(ctx->hid);
54 
55 	if (!hid_ctx)
56 		return -1; /* EPERM check */
57 
58 	hw_req_buf[0] = pad_type_feature->report_id;
59 
60 	ret = hid_bpf_hw_request(hid_ctx, hw_req_buf, sizeof(hw_req_buf),
61 					HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
62 	hid_bpf_release_context(hid_ctx);
63 
64 	if (ret < 0) {
65 		ctx->retval = ret;
66 		return 0;
67 	}
68 
69 	ctx->retval = 0;
70 
71 	switch (EXTRACT_BITS(hw_req_buf, pad_type)) {
72 	case 0:
73 		pad_type_str = "Clickpad";
74 		break;
75 	case 1:
76 		pad_type_str = "Pressurepad";
77 		break;
78 	case 2:
79 		pad_type_str = "Discrete";
80 		break;
81 	default:
82 		pad_type_str = "Unknown";
83 	}
84 
85 	UDEV_PROP_SPRINTF(HID_DIGITIZER_PAD_TYPE, "%s", pad_type_str);
86 
87 	return 0;
88 }
89 
90 char _license[] SEC("license") = "GPL";
91