xref: /linux/drivers/hid/bpf/progs/XPPen__Deco01V3.bpf.c (revision 24f171c7e145f43b9f187578e89b0982ce87e54c)
1*8ba327d5SBenjamin Tissoires // SPDX-License-Identifier: GPL-2.0-only
2*8ba327d5SBenjamin Tissoires /* Copyright (c) 2025 Red Hat
3*8ba327d5SBenjamin Tissoires  */
4*8ba327d5SBenjamin Tissoires 
5*8ba327d5SBenjamin Tissoires #include "vmlinux.h"
6*8ba327d5SBenjamin Tissoires #include "hid_bpf.h"
7*8ba327d5SBenjamin Tissoires #include "hid_bpf_helpers.h"
8*8ba327d5SBenjamin Tissoires #include "hid_report_helpers.h"
9*8ba327d5SBenjamin Tissoires #include <bpf/bpf_tracing.h>
10*8ba327d5SBenjamin Tissoires 
11*8ba327d5SBenjamin Tissoires #define VID_UGEE 0x28BD /* VID is shared with SinoWealth and Glorious and prob others */
12*8ba327d5SBenjamin Tissoires #define PID_DECO_01_V3 0x0947
13*8ba327d5SBenjamin Tissoires 
14*8ba327d5SBenjamin Tissoires HID_BPF_CONFIG(
15*8ba327d5SBenjamin Tissoires 	HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_UGEE, PID_DECO_01_V3),
16*8ba327d5SBenjamin Tissoires );
17*8ba327d5SBenjamin Tissoires 
18*8ba327d5SBenjamin Tissoires /*
19*8ba327d5SBenjamin Tissoires  * Default report descriptor reports:
20*8ba327d5SBenjamin Tissoires  * - a report descriptor for the pad buttons, reported as key sequences
21*8ba327d5SBenjamin Tissoires  * - a report descriptor for the pen
22*8ba327d5SBenjamin Tissoires  * - a vendor-specific report descriptor
23*8ba327d5SBenjamin Tissoires  *
24*8ba327d5SBenjamin Tissoires  * The Pad report descriptor, see
25*8ba327d5SBenjamin Tissoires  * https://gitlab.freedesktop.org/libevdev/udev-hid-bpf/-/issues/54
26*8ba327d5SBenjamin Tissoires  *
27*8ba327d5SBenjamin Tissoires  * # Report descriptor length: 102 bytes
28*8ba327d5SBenjamin Tissoires  * 0x05, 0x01,                    // Usage Page (Generic Desktop)              0
29*8ba327d5SBenjamin Tissoires  * 0x09, 0x02,                    // Usage (Mouse)                             2
30*8ba327d5SBenjamin Tissoires  * 0xa1, 0x01,                    // Collection (Application)                  4
31*8ba327d5SBenjamin Tissoires  * 0x85, 0x09,                    //   Report ID (9)                           6
32*8ba327d5SBenjamin Tissoires  * 0x09, 0x01,                    //   Usage (Pointer)                         8
33*8ba327d5SBenjamin Tissoires  * 0xa1, 0x00,                    //   Collection (Physical)                   10
34*8ba327d5SBenjamin Tissoires  * 0x05, 0x09,                    //     Usage Page (Button)                   12
35*8ba327d5SBenjamin Tissoires  * 0x19, 0x01,                    //     UsageMinimum (1)                      14
36*8ba327d5SBenjamin Tissoires  * 0x29, 0x03,                    //     UsageMaximum (3)                      16
37*8ba327d5SBenjamin Tissoires  * 0x15, 0x00,                    //     Logical Minimum (0)                   18
38*8ba327d5SBenjamin Tissoires  * 0x25, 0x01,                    //     Logical Maximum (1)                   20
39*8ba327d5SBenjamin Tissoires  * 0x95, 0x03,                    //     Report Count (3)                      22
40*8ba327d5SBenjamin Tissoires  * 0x75, 0x01,                    //     Report Size (1)                       24
41*8ba327d5SBenjamin Tissoires  * 0x81, 0x02,                    //     Input (Data,Var,Abs)                  26
42*8ba327d5SBenjamin Tissoires  * 0x95, 0x05,                    //     Report Count (5)                      28
43*8ba327d5SBenjamin Tissoires  * 0x81, 0x01,                    //     Input (Cnst,Arr,Abs)                  30
44*8ba327d5SBenjamin Tissoires  * 0x05, 0x01,                    //     Usage Page (Generic Desktop)          32
45*8ba327d5SBenjamin Tissoires  * 0x09, 0x30,                    //     Usage (X)                             34
46*8ba327d5SBenjamin Tissoires  * 0x09, 0x31,                    //     Usage (Y)                             36
47*8ba327d5SBenjamin Tissoires  * 0x26, 0xff, 0x7f,              //     Logical Maximum (32767)               38
48*8ba327d5SBenjamin Tissoires  * 0x95, 0x02,                    //     Report Count (2)                      41
49*8ba327d5SBenjamin Tissoires  * 0x75, 0x10,                    //     Report Size (16)                      43
50*8ba327d5SBenjamin Tissoires  * 0x81, 0x02,                    //     Input (Data,Var,Abs)                  45
51*8ba327d5SBenjamin Tissoires  * 0x05, 0x0d,                    //     Usage Page (Digitizers)               47
52*8ba327d5SBenjamin Tissoires  * 0x09, 0x30,                    //     Usage (Tip Pressure)                  49
53*8ba327d5SBenjamin Tissoires  * 0x26, 0xff, 0x07,              //     Logical Maximum (2047)                51
54*8ba327d5SBenjamin Tissoires  * 0x95, 0x01,                    //     Report Count (1)                      54
55*8ba327d5SBenjamin Tissoires  * 0x75, 0x10,                    //     Report Size (16)                      56
56*8ba327d5SBenjamin Tissoires  * 0x81, 0x02,                    //     Input (Data,Var,Abs)                  58
57*8ba327d5SBenjamin Tissoires  * 0xc0,                          //   End Collection                          60
58*8ba327d5SBenjamin Tissoires  * 0xc0,                          // End Collection                            61
59*8ba327d5SBenjamin Tissoires  * 0x05, 0x01,                    // Usage Page (Generic Desktop)              62
60*8ba327d5SBenjamin Tissoires  * 0x09, 0x06,                    // Usage (Keyboard)                          64
61*8ba327d5SBenjamin Tissoires  * 0xa1, 0x01,                    // Collection (Application)                  66
62*8ba327d5SBenjamin Tissoires  * 0x85, 0x06,                    //   Report ID (6)                           68
63*8ba327d5SBenjamin Tissoires  * 0x05, 0x07,                    //   Usage Page (Keyboard/Keypad)            70
64*8ba327d5SBenjamin Tissoires  * 0x19, 0xe0,                    //   UsageMinimum (224)                      72
65*8ba327d5SBenjamin Tissoires  * 0x29, 0xe7,                    //   UsageMaximum (231)                      74
66*8ba327d5SBenjamin Tissoires  * 0x15, 0x00,                    //   Logical Minimum (0)                     76
67*8ba327d5SBenjamin Tissoires  * 0x25, 0x01,                    //   Logical Maximum (1)                     78
68*8ba327d5SBenjamin Tissoires  * 0x75, 0x01,                    //   Report Size (1)                         80
69*8ba327d5SBenjamin Tissoires  * 0x95, 0x08,                    //   Report Count (8)                        82
70*8ba327d5SBenjamin Tissoires  * 0x81, 0x02,                    //   Input (Data,Var,Abs)                    84
71*8ba327d5SBenjamin Tissoires  * 0x05, 0x07,                    //   Usage Page (Keyboard/Keypad)            86
72*8ba327d5SBenjamin Tissoires  * 0x19, 0x00,                    //   UsageMinimum (0)                        88
73*8ba327d5SBenjamin Tissoires  * 0x29, 0xff,                    //   UsageMaximum (255)                      90
74*8ba327d5SBenjamin Tissoires  * 0x26, 0xff, 0x00,              //   Logical Maximum (255)                   92
75*8ba327d5SBenjamin Tissoires  * 0x75, 0x08,                    //   Report Size (8)                         95
76*8ba327d5SBenjamin Tissoires  * 0x95, 0x06,                    //   Report Count (6)                        97
77*8ba327d5SBenjamin Tissoires  * 0x81, 0x00,                    //   Input (Data,Arr,Abs)                    99
78*8ba327d5SBenjamin Tissoires  * 0xc0,                          // End Collection                            101
79*8ba327d5SBenjamin Tissoires  *
80*8ba327d5SBenjamin Tissoires  * And key events for buttons top->bottom are:
81*8ba327d5SBenjamin Tissoires  * Buttons released: 06 00 00 00 00 00 00 00
82*8ba327d5SBenjamin Tissoires  * Button1:          06 00 05 00 00 00 00 00 -> b
83*8ba327d5SBenjamin Tissoires  * Button2:          06 00 08 00 00 00 00 00 -> e
84*8ba327d5SBenjamin Tissoires  * Button3:          06 04 00 00 00 00 00 00 -> LAlt
85*8ba327d5SBenjamin Tissoires  * Button4:          06 00 2c 00 00 00 00 00 -> Space
86*8ba327d5SBenjamin Tissoires  * Button5:          06 01 16 00 00 00 00 00 -> LControl + s
87*8ba327d5SBenjamin Tissoires  * Button6:          06 01 1d 00 00 00 00 00 -> LControl + z
88*8ba327d5SBenjamin Tissoires  * Button7:          06 01 57 00 00 00 00 00 -> LControl + Keypad Plus
89*8ba327d5SBenjamin Tissoires  * Button8:          06 01 56 00 00 00 00 00 -> LControl + Keypad Dash
90*8ba327d5SBenjamin Tissoires  *
91*8ba327d5SBenjamin Tissoires  * When multiple buttons are pressed at the same time, the values used to
92*8ba327d5SBenjamin Tissoires  * identify the buttons are identical, but they appear in different bytes of the
93*8ba327d5SBenjamin Tissoires  * record. For example, when button 2 (0x08) and button 1 (0x05) are pressed,
94*8ba327d5SBenjamin Tissoires  * this is the report:
95*8ba327d5SBenjamin Tissoires  *
96*8ba327d5SBenjamin Tissoires  *   Buttons 2 and 1:  06 00 08 05 00 00 00 00 -> e + b
97*8ba327d5SBenjamin Tissoires  *
98*8ba327d5SBenjamin Tissoires  * Buttons 1, 2, 4, 5 and 6 can be matched by finding their values in the
99*8ba327d5SBenjamin Tissoires  * report.
100*8ba327d5SBenjamin Tissoires  *
101*8ba327d5SBenjamin Tissoires  * Button 3 is pressed when the 3rd bit is 1. For example, pressing buttons 3
102*8ba327d5SBenjamin Tissoires  * and 5 generates this report:
103*8ba327d5SBenjamin Tissoires  *
104*8ba327d5SBenjamin Tissoires  *   Buttons 3 and 5:  06 05 16 00 00 00 00 00 -> LControl + LAlt + s
105*8ba327d5SBenjamin Tissoires  *                        -- --
106*8ba327d5SBenjamin Tissoires  *                         |  |
107*8ba327d5SBenjamin Tissoires  *                         |  `- Button 5 (0x16)
108*8ba327d5SBenjamin Tissoires  *                         `- 0x05 = 0101. Button 3 is pressed
109*8ba327d5SBenjamin Tissoires  *                                    ^
110*8ba327d5SBenjamin Tissoires  *
111*8ba327d5SBenjamin Tissoires  * pad_buttons contains a list of buttons that can be matched in
112*8ba327d5SBenjamin Tissoires  * HID_BPF_DEVICE_EVENT. Button 3 as it has a dedicated bit.
113*8ba327d5SBenjamin Tissoires  *
114*8ba327d5SBenjamin Tissoires  *
115*8ba327d5SBenjamin Tissoires  * The Pen report descriptor announces a wrong tilt range:
116*8ba327d5SBenjamin Tissoires  *
117*8ba327d5SBenjamin Tissoires  * Report descriptor length: 109 bytes
118*8ba327d5SBenjamin Tissoires  * 0x05, 0x0d,                    // Usage Page (Digitizers)                   0
119*8ba327d5SBenjamin Tissoires  * 0x09, 0x02,                    // Usage (Pen)                               2
120*8ba327d5SBenjamin Tissoires  * 0xa1, 0x01,                    // Collection (Application)                  4
121*8ba327d5SBenjamin Tissoires  * 0x85, 0x07,                    //   Report ID (7)                           6
122*8ba327d5SBenjamin Tissoires  * 0x09, 0x20,                    //   Usage (Stylus)                          8
123*8ba327d5SBenjamin Tissoires  * 0xa1, 0x01,                    //   Collection (Application)                10
124*8ba327d5SBenjamin Tissoires  * 0x09, 0x42,                    //     Usage (Tip Switch)                    12
125*8ba327d5SBenjamin Tissoires  * 0x09, 0x44,                    //     Usage (Barrel Switch)                 14
126*8ba327d5SBenjamin Tissoires  * 0x09, 0x45,                    //     Usage (Eraser)                        16
127*8ba327d5SBenjamin Tissoires  * 0x09, 0x3c,                    //     Usage (Invert)                        18
128*8ba327d5SBenjamin Tissoires  * 0x15, 0x00,                    //     Logical Minimum (0)                   20
129*8ba327d5SBenjamin Tissoires  * 0x25, 0x01,                    //     Logical Maximum (1)                   22
130*8ba327d5SBenjamin Tissoires  * 0x75, 0x01,                    //     Report Size (1)                       24
131*8ba327d5SBenjamin Tissoires  * 0x95, 0x04,                    //     Report Count (4)                      26
132*8ba327d5SBenjamin Tissoires  * 0x81, 0x02,                    //     Input (Data,Var,Abs)                  28
133*8ba327d5SBenjamin Tissoires  * 0x95, 0x01,                    //     Report Count (1)                      30
134*8ba327d5SBenjamin Tissoires  * 0x81, 0x03,                    //     Input (Cnst,Var,Abs)                  32
135*8ba327d5SBenjamin Tissoires  * 0x09, 0x32,                    //     Usage (In Range)                      34
136*8ba327d5SBenjamin Tissoires  * 0x95, 0x01,                    //     Report Count (1)                      36
137*8ba327d5SBenjamin Tissoires  * 0x81, 0x02,                    //     Input (Data,Var,Abs)                  38
138*8ba327d5SBenjamin Tissoires  * 0x95, 0x02,                    //     Report Count (2)                      40
139*8ba327d5SBenjamin Tissoires  * 0x81, 0x03,                    //     Input (Cnst,Var,Abs)                  42
140*8ba327d5SBenjamin Tissoires  * 0x75, 0x10,                    //     Report Size (16)                      44
141*8ba327d5SBenjamin Tissoires  * 0x95, 0x01,                    //     Report Count (1)                      46
142*8ba327d5SBenjamin Tissoires  * 0x35, 0x00,                    //     Physical Minimum (0)                  48
143*8ba327d5SBenjamin Tissoires  * 0xa4,                          //     Push                                  50
144*8ba327d5SBenjamin Tissoires  * 0x05, 0x01,                    //     Usage Page (Generic Desktop)          51
145*8ba327d5SBenjamin Tissoires  * 0x09, 0x30,                    //     Usage (X)                             53
146*8ba327d5SBenjamin Tissoires  * 0x65, 0x13,                    //     Unit (EnglishLinear: in)              55
147*8ba327d5SBenjamin Tissoires  * 0x55, 0x0d,                    //     Unit Exponent (-3)                    57
148*8ba327d5SBenjamin Tissoires  * 0x46, 0x10, 0x27,              //     Physical Maximum (10000)              59
149*8ba327d5SBenjamin Tissoires  * 0x26, 0xff, 0x7f,              //     Logical Maximum (32767)               62
150*8ba327d5SBenjamin Tissoires  * 0x81, 0x02,                    //     Input (Data,Var,Abs)                  65
151*8ba327d5SBenjamin Tissoires  * 0x09, 0x31,                    //     Usage (Y)                             67
152*8ba327d5SBenjamin Tissoires  * 0x46, 0x6a, 0x18,              //     Physical Maximum (6250)               69
153*8ba327d5SBenjamin Tissoires  * 0x26, 0xff, 0x7f,              //     Logical Maximum (32767)               72
154*8ba327d5SBenjamin Tissoires  * 0x81, 0x02,                    //     Input (Data,Var,Abs)                  75
155*8ba327d5SBenjamin Tissoires  * 0xb4,                          //     Pop                                   77
156*8ba327d5SBenjamin Tissoires  * 0x09, 0x30,                    //     Usage (X)                             78
157*8ba327d5SBenjamin Tissoires  * 0x45, 0x00,                    //     Physical Maximum (0)                  80
158*8ba327d5SBenjamin Tissoires  * 0x26, 0xff, 0x3f,              //     Logical Maximum (16383)               82
159*8ba327d5SBenjamin Tissoires  * 0x81, 0x42,                    //     Input (Data,Var,Abs,Null)             85
160*8ba327d5SBenjamin Tissoires  * 0x09, 0x3d,                    //     Usage (Start)                         87
161*8ba327d5SBenjamin Tissoires  * 0x15, 0x81,                    //     Logical Minimum (-127)                89  <- Change from -127 to -60
162*8ba327d5SBenjamin Tissoires  * 0x25, 0x7f,                    //     Logical Maximum (127)                 91  <- Change from 127 to 60
163*8ba327d5SBenjamin Tissoires  * 0x75, 0x08,                    //     Report Size (8)                       93
164*8ba327d5SBenjamin Tissoires  * 0x95, 0x01,                    //     Report Count (1)                      95
165*8ba327d5SBenjamin Tissoires  * 0x81, 0x02,                    //     Input (Data,Var,Abs)                  97
166*8ba327d5SBenjamin Tissoires  * 0x09, 0x3e,                    //     Usage (Select)                        99
167*8ba327d5SBenjamin Tissoires  * 0x15, 0x81,                    //     Logical Minimum (-127)                101  <- Change from -127 to -60
168*8ba327d5SBenjamin Tissoires  * 0x25, 0x7f,                    //     Logical Maximum (127)                 103  <- Change from 127 to 60
169*8ba327d5SBenjamin Tissoires  * 0x81, 0x02,                    //     Input (Data,Var,Abs)                  105
170*8ba327d5SBenjamin Tissoires  * 0xc0,                          //   End Collection                          107
171*8ba327d5SBenjamin Tissoires  * 0xc0,                          // End Collection                            108
172*8ba327d5SBenjamin Tissoires  */
173*8ba327d5SBenjamin Tissoires 
174*8ba327d5SBenjamin Tissoires #define PEN_REPORT_DESCRIPTOR_LENGTH 109
175*8ba327d5SBenjamin Tissoires #define PAD_REPORT_DESCRIPTOR_LENGTH 102
176*8ba327d5SBenjamin Tissoires #define PAD_REPORT_LENGTH 8
177*8ba327d5SBenjamin Tissoires #define PAD_REPORT_ID 6
178*8ba327d5SBenjamin Tissoires #define PAD_NUM_BUTTONS 8
179*8ba327d5SBenjamin Tissoires 
180*8ba327d5SBenjamin Tissoires static const __u8 fixed_rdesc_pad[] = {
181*8ba327d5SBenjamin Tissoires 	UsagePage_GenericDesktop
182*8ba327d5SBenjamin Tissoires 	Usage_GD_Keypad
183*8ba327d5SBenjamin Tissoires 	CollectionApplication(
184*8ba327d5SBenjamin Tissoires 		// Byte 0 in report is the report ID
185*8ba327d5SBenjamin Tissoires 		ReportId(PAD_REPORT_ID)
186*8ba327d5SBenjamin Tissoires 		ReportCount(1)
187*8ba327d5SBenjamin Tissoires 		ReportSize(8)
188*8ba327d5SBenjamin Tissoires 		UsagePage_Digitizers
189*8ba327d5SBenjamin Tissoires 		Usage_Dig_TabletFunctionKeys
190*8ba327d5SBenjamin Tissoires 		CollectionPhysical(
191*8ba327d5SBenjamin Tissoires 			// Byte 1 is the button state
192*8ba327d5SBenjamin Tissoires 			UsagePage_Button
193*8ba327d5SBenjamin Tissoires 			UsageMinimum_i8(0x01)
194*8ba327d5SBenjamin Tissoires 			UsageMaximum_i8(PAD_NUM_BUTTONS)
195*8ba327d5SBenjamin Tissoires 			LogicalMinimum_i8(0x0)
196*8ba327d5SBenjamin Tissoires 			LogicalMaximum_i8(0x1)
197*8ba327d5SBenjamin Tissoires 			ReportCount(PAD_NUM_BUTTONS)
198*8ba327d5SBenjamin Tissoires 			ReportSize(1)
199*8ba327d5SBenjamin Tissoires 			Input(Var|Abs)
200*8ba327d5SBenjamin Tissoires 			// Byte 2 in report - just exists so we get to be a tablet pad
201*8ba327d5SBenjamin Tissoires 			UsagePage_Digitizers
202*8ba327d5SBenjamin Tissoires 			Usage_Dig_BarrelSwitch // BTN_STYLUS
203*8ba327d5SBenjamin Tissoires 			ReportCount(1)
204*8ba327d5SBenjamin Tissoires 			ReportSize(1)
205*8ba327d5SBenjamin Tissoires 			Input(Var|Abs)
206*8ba327d5SBenjamin Tissoires 			ReportCount(7) // padding
207*8ba327d5SBenjamin Tissoires 			Input(Const)
208*8ba327d5SBenjamin Tissoires 			// Bytes 3/4 in report - just exists so we get to be a tablet pad
209*8ba327d5SBenjamin Tissoires 			UsagePage_GenericDesktop
210*8ba327d5SBenjamin Tissoires 			Usage_GD_X
211*8ba327d5SBenjamin Tissoires 			Usage_GD_Y
212*8ba327d5SBenjamin Tissoires 			ReportCount(2)
213*8ba327d5SBenjamin Tissoires 			ReportSize(8)
214*8ba327d5SBenjamin Tissoires 			Input(Var|Abs)
215*8ba327d5SBenjamin Tissoires 			// Byte 5-7 are padding so we match the original report lengtth
216*8ba327d5SBenjamin Tissoires 			ReportCount(3)
217*8ba327d5SBenjamin Tissoires 			ReportSize(8)
218*8ba327d5SBenjamin Tissoires 			Input(Const)
219*8ba327d5SBenjamin Tissoires 		)
220*8ba327d5SBenjamin Tissoires 	)
221*8ba327d5SBenjamin Tissoires };
222*8ba327d5SBenjamin Tissoires 
223*8ba327d5SBenjamin Tissoires SEC(HID_BPF_RDESC_FIXUP)
224*8ba327d5SBenjamin Tissoires int BPF_PROG(xppen_deco01v3_rdesc_fixup, struct hid_bpf_ctx *hctx)
225*8ba327d5SBenjamin Tissoires {
226*8ba327d5SBenjamin Tissoires 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */);
227*8ba327d5SBenjamin Tissoires 
228*8ba327d5SBenjamin Tissoires 	const __u8 wrong_logical_range[] = {0x15, 0x81, 0x25, 0x7f};
229*8ba327d5SBenjamin Tissoires 	const __u8 correct_logical_range[] = {0x15, 0xc4, 0x25, 0x3c};
230*8ba327d5SBenjamin Tissoires 
231*8ba327d5SBenjamin Tissoires 	if (!data)
232*8ba327d5SBenjamin Tissoires 		return 0; /* EPERM check */
233*8ba327d5SBenjamin Tissoires 
234*8ba327d5SBenjamin Tissoires 	switch (hctx->size) {
235*8ba327d5SBenjamin Tissoires 	case PAD_REPORT_DESCRIPTOR_LENGTH:
236*8ba327d5SBenjamin Tissoires 		__builtin_memcpy(data, fixed_rdesc_pad, sizeof(fixed_rdesc_pad));
237*8ba327d5SBenjamin Tissoires 		return sizeof(fixed_rdesc_pad);
238*8ba327d5SBenjamin Tissoires 	case PEN_REPORT_DESCRIPTOR_LENGTH:
239*8ba327d5SBenjamin Tissoires 		if (__builtin_memcmp(&data[89], wrong_logical_range,
240*8ba327d5SBenjamin Tissoires 				     sizeof(wrong_logical_range)) == 0)
241*8ba327d5SBenjamin Tissoires 			__builtin_memcpy(&data[89], correct_logical_range,
242*8ba327d5SBenjamin Tissoires 					 sizeof(correct_logical_range));
243*8ba327d5SBenjamin Tissoires 		if (__builtin_memcmp(&data[101], wrong_logical_range,
244*8ba327d5SBenjamin Tissoires 				     sizeof(wrong_logical_range)) == 0)
245*8ba327d5SBenjamin Tissoires 			__builtin_memcpy(&data[101], correct_logical_range,
246*8ba327d5SBenjamin Tissoires 					 sizeof(correct_logical_range));
247*8ba327d5SBenjamin Tissoires 		break;
248*8ba327d5SBenjamin Tissoires 	}
249*8ba327d5SBenjamin Tissoires 
250*8ba327d5SBenjamin Tissoires 	return 0;
251*8ba327d5SBenjamin Tissoires }
252*8ba327d5SBenjamin Tissoires 
253*8ba327d5SBenjamin Tissoires SEC(HID_BPF_DEVICE_EVENT)
254*8ba327d5SBenjamin Tissoires int BPF_PROG(xppen_deco01v3_device_event, struct hid_bpf_ctx *hctx)
255*8ba327d5SBenjamin Tissoires {
256*8ba327d5SBenjamin Tissoires 	static const __u8 pad_buttons[] = { 0x05, 0x08, 0x00, 0x2c, 0x16, 0x1d, 0x57, 0x56 };
257*8ba327d5SBenjamin Tissoires 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, PAD_REPORT_LENGTH /* size */);
258*8ba327d5SBenjamin Tissoires 
259*8ba327d5SBenjamin Tissoires 	if (!data)
260*8ba327d5SBenjamin Tissoires 		return 0; /* EPERM check */
261*8ba327d5SBenjamin Tissoires 
262*8ba327d5SBenjamin Tissoires 	if (data[0] == PAD_REPORT_ID) {
263*8ba327d5SBenjamin Tissoires 		__u8 button_mask = 0;
264*8ba327d5SBenjamin Tissoires 		size_t d, b;
265*8ba327d5SBenjamin Tissoires 
266*8ba327d5SBenjamin Tissoires 		/* data[1] stores the status of BTN_2 in the 3rd bit*/
267*8ba327d5SBenjamin Tissoires 		if (data[1] & BIT(2))
268*8ba327d5SBenjamin Tissoires 			button_mask |= BIT(2);
269*8ba327d5SBenjamin Tissoires 
270*8ba327d5SBenjamin Tissoires 		/* The rest of the descriptor stores the buttons as in pad_buttons */
271*8ba327d5SBenjamin Tissoires 		for (d = 2; d < 8; d++) {
272*8ba327d5SBenjamin Tissoires 			for (b = 0; b < sizeof(pad_buttons); b++) {
273*8ba327d5SBenjamin Tissoires 				if (data[d] != 0 && data[d] == pad_buttons[b])
274*8ba327d5SBenjamin Tissoires 					button_mask |= BIT(b);
275*8ba327d5SBenjamin Tissoires 			}
276*8ba327d5SBenjamin Tissoires 		}
277*8ba327d5SBenjamin Tissoires 
278*8ba327d5SBenjamin Tissoires 		__u8 report[8] = {PAD_REPORT_ID, button_mask, 0x00};
279*8ba327d5SBenjamin Tissoires 
280*8ba327d5SBenjamin Tissoires 		__builtin_memcpy(data, report, sizeof(report));
281*8ba327d5SBenjamin Tissoires 	}
282*8ba327d5SBenjamin Tissoires 	return 0;
283*8ba327d5SBenjamin Tissoires }
284*8ba327d5SBenjamin Tissoires 
285*8ba327d5SBenjamin Tissoires HID_BPF_OPS(xppen_deco01v3) = {
286*8ba327d5SBenjamin Tissoires 	.hid_rdesc_fixup = (void *)xppen_deco01v3_rdesc_fixup,
287*8ba327d5SBenjamin Tissoires 	.hid_device_event = (void *)xppen_deco01v3_device_event,
288*8ba327d5SBenjamin Tissoires };
289*8ba327d5SBenjamin Tissoires 
290*8ba327d5SBenjamin Tissoires SEC("syscall")
291*8ba327d5SBenjamin Tissoires int probe(struct hid_bpf_probe_args *ctx)
292*8ba327d5SBenjamin Tissoires {
293*8ba327d5SBenjamin Tissoires 	switch (ctx->rdesc_size) {
294*8ba327d5SBenjamin Tissoires 	case PAD_REPORT_DESCRIPTOR_LENGTH:
295*8ba327d5SBenjamin Tissoires 	case PEN_REPORT_DESCRIPTOR_LENGTH:
296*8ba327d5SBenjamin Tissoires 		ctx->retval = 0;
297*8ba327d5SBenjamin Tissoires 		break;
298*8ba327d5SBenjamin Tissoires 	default:
299*8ba327d5SBenjamin Tissoires 		ctx->retval = -EINVAL;
300*8ba327d5SBenjamin Tissoires 	}
301*8ba327d5SBenjamin Tissoires 
302*8ba327d5SBenjamin Tissoires 	return 0;
303*8ba327d5SBenjamin Tissoires }
304*8ba327d5SBenjamin Tissoires 
305*8ba327d5SBenjamin Tissoires char _license[] SEC("license") = "GPL";
306