1 | // SPDX-License-Identifier: GPL-2.0-only |
2 | /* Copyright (c) 2022 Benjamin Tissoires |
3 | */ |
4 | |
5 | #include "vmlinux.h" |
6 | #include <bpf/bpf_helpers.h> |
7 | #include <bpf/bpf_tracing.h> |
8 | #include "hid_bpf_helpers.h" |
9 | |
10 | #define HID_UP_BUTTON 0x0009 |
11 | #define HID_GD_WHEEL 0x0038 |
12 | |
13 | SEC("fmod_ret/hid_bpf_device_event" ) |
14 | int BPF_PROG(hid_event, struct hid_bpf_ctx *hctx) |
15 | { |
16 | __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */); |
17 | |
18 | if (!data) |
19 | return 0; /* EPERM check */ |
20 | |
21 | /* Touch */ |
22 | data[1] &= 0xfd; |
23 | |
24 | /* X */ |
25 | data[4] = 0; |
26 | data[5] = 0; |
27 | |
28 | /* Y */ |
29 | data[6] = 0; |
30 | data[7] = 0; |
31 | |
32 | return 0; |
33 | } |
34 | |
35 | /* 72 == 360 / 5 -> 1 report every 5 degrees */ |
36 | int resolution = 72; |
37 | int physical = 5; |
38 | |
39 | struct haptic_syscall_args { |
40 | unsigned int hid; |
41 | int retval; |
42 | }; |
43 | |
44 | static __u8 haptic_data[8]; |
45 | |
46 | SEC("syscall" ) |
47 | int set_haptic(struct haptic_syscall_args *args) |
48 | { |
49 | struct hid_bpf_ctx *ctx; |
50 | const size_t size = sizeof(haptic_data); |
51 | u16 *res; |
52 | int ret; |
53 | |
54 | if (size > sizeof(haptic_data)) |
55 | return -7; /* -E2BIG */ |
56 | |
57 | ctx = hid_bpf_allocate_context(args->hid); |
58 | if (!ctx) |
59 | return -1; /* EPERM check */ |
60 | |
61 | haptic_data[0] = 1; /* report ID */ |
62 | |
63 | ret = hid_bpf_hw_request(ctx, haptic_data, size, HID_FEATURE_REPORT, HID_REQ_GET_REPORT); |
64 | |
65 | bpf_printk("probed/remove event ret value: %d" , ret); |
66 | bpf_printk("buf: %02x %02x %02x" , |
67 | haptic_data[0], |
68 | haptic_data[1], |
69 | haptic_data[2]); |
70 | bpf_printk(" %02x %02x %02x" , |
71 | haptic_data[3], |
72 | haptic_data[4], |
73 | haptic_data[5]); |
74 | bpf_printk(" %02x %02x" , |
75 | haptic_data[6], |
76 | haptic_data[7]); |
77 | |
78 | /* whenever resolution multiplier is not 3600, we have the fixed report descriptor */ |
79 | res = (u16 *)&haptic_data[1]; |
80 | if (*res != 3600) { |
81 | // haptic_data[1] = 72; /* resolution multiplier */ |
82 | // haptic_data[2] = 0; /* resolution multiplier */ |
83 | // haptic_data[3] = 0; /* Repeat Count */ |
84 | haptic_data[4] = 3; /* haptic Auto Trigger */ |
85 | // haptic_data[5] = 5; /* Waveform Cutoff Time */ |
86 | // haptic_data[6] = 80; /* Retrigger Period */ |
87 | // haptic_data[7] = 0; /* Retrigger Period */ |
88 | } else { |
89 | haptic_data[4] = 0; |
90 | } |
91 | |
92 | ret = hid_bpf_hw_request(ctx, haptic_data, size, HID_FEATURE_REPORT, HID_REQ_SET_REPORT); |
93 | |
94 | bpf_printk("set haptic ret value: %d -> %d" , ret, haptic_data[4]); |
95 | |
96 | args->retval = ret; |
97 | |
98 | hid_bpf_release_context(ctx); |
99 | |
100 | return 0; |
101 | } |
102 | |
103 | /* Convert REL_DIAL into REL_WHEEL */ |
104 | SEC("fmod_ret/hid_bpf_rdesc_fixup" ) |
105 | int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx) |
106 | { |
107 | __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */); |
108 | __u16 *res, *phys; |
109 | |
110 | if (!data) |
111 | return 0; /* EPERM check */ |
112 | |
113 | /* Convert TOUCH into a button */ |
114 | data[31] = HID_UP_BUTTON; |
115 | data[33] = 2; |
116 | |
117 | /* Convert REL_DIAL into REL_WHEEL */ |
118 | data[45] = HID_GD_WHEEL; |
119 | |
120 | /* Change Resolution Multiplier */ |
121 | phys = (__u16 *)&data[61]; |
122 | *phys = physical; |
123 | res = (__u16 *)&data[66]; |
124 | *res = resolution; |
125 | |
126 | /* Convert X,Y from Abs to Rel */ |
127 | data[88] = 0x06; |
128 | data[98] = 0x06; |
129 | |
130 | return 0; |
131 | } |
132 | |
133 | char _license[] SEC("license" ) = "GPL" ; |
134 | u32 _version SEC("version" ) = 1; |
135 | |