File Index
Files and directories
Sign in
FILE

Huion__Kamvas-Pro-19.bpf.c

File preview with syntax highlighting.

linux-6.19.14/drivers/hid/bpf/progs/Huion__Kamvas-Pro-19.bpf.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/* Copyright (c) 2024 Benjamin Tissoires
  3 */
  4
  5#include "vmlinux.h"
  6#include "hid_bpf.h"
  7#include "hid_bpf_helpers.h"
  8#include <bpf/bpf_tracing.h>
  9
 10#define VID_HUION 0x256C
 11#define PID_KAMVAS_PRO_19 0x006B
 12#define PID_KAMVAS_PRO_27 0x006c
 13#define NAME_KAMVAS_PRO_19 "HUION Huion Tablet_GT1902"
 14#define NAME_KAMVAS_PRO_27 "HUION Huion Tablet_GT2701"
 15
 16#define TEST_PREFIX "uhid test "
 17
 18HID_BPF_CONFIG(
 19	HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8, VID_HUION, PID_KAMVAS_PRO_19),
 20	HID_DEVICE(BUS_USB, HID_GROUP_MULTITOUCH_WIN_8, VID_HUION, PID_KAMVAS_PRO_27),
 21);
 22
 23bool prev_was_out_of_range;
 24bool in_eraser_mode;
 25
 26/*
 27 * We need to amend the report descriptor for the following:
 28 * - the second button is reported through Secondary Tip Switch instead of Secondary Barrel Switch
 29 * - the third button is reported through Invert, and we need some room to report it.
 30 *
 31 */
 32static const __u8 fixed_rdesc[] = {
 33	0x05, 0x0d,                    // Usage Page (Digitizers)             0
 34	0x09, 0x02,                    // Usage (Pen)                         2
 35	0xa1, 0x01,                    // Collection (Application)            4
 36	0x85, 0x0a,                    //  Report ID (10)                     6
 37	0x09, 0x20,                    //  Usage (Stylus)                     8
 38	0xa1, 0x01,                    //  Collection (Application)           10
 39	0x09, 0x42,                    //   Usage (Tip Switch)                12
 40	0x09, 0x44,                    //   Usage (Barrel Switch)             14
 41	0x09, 0x5a,                    //   Usage (Secondary Barrel Switch)   16 /* changed from Secondary Tip Switch */
 42	0x09, 0x3c,                    //   Usage (Invert)                    18
 43	0x09, 0x45,                    //   Usage (Eraser)                    20
 44	0x15, 0x00,                    //   Logical Minimum (0)               22
 45	0x25, 0x01,                    //   Logical Maximum (1)               24
 46	0x75, 0x01,                    //   Report Size (1)                   26
 47	0x95, 0x05,                    //   Report Count (5)                  28 /* changed (was 6) */
 48	0x81, 0x02,                    //   Input (Data,Var,Abs)              30
 49	0x05, 0x09,                    //   Usage Page (Button)                  /* inserted */
 50	0x09, 0x4a,                    //   Usage (0x4a)                         /* inserted to be translated as input usage 0x149: BTN_STYLUS3 */
 51	0x95, 0x01,                    //   Report Count (1)                     /* inserted */
 52	0x81, 0x02,                    //   Input (Data,Var,Abs)                 /* inserted */
 53	0x05, 0x0d,                    //   Usage Page (Digitizers)              /* inserted */
 54	0x09, 0x32,                    //   Usage (In Range)                  32
 55	0x75, 0x01,                    //   Report Size (1)                   34
 56	0x95, 0x01,                    //   Report Count (1)                  36
 57	0x81, 0x02,                    //   Input (Data,Var,Abs)              38
 58	0x81, 0x03,                    //   Input (Cnst,Var,Abs)              40
 59	0x05, 0x01,                    //   Usage Page (Generic Desktop)      42
 60	0x09, 0x30,                    //   Usage (X)                         44
 61	0x09, 0x31,                    //   Usage (Y)                         46
 62	0x55, 0x0d,                    //   Unit Exponent (-3)                48
 63	0x65, 0x33,                    //   Unit (EnglishLinear: in³)         50
 64	0x26, 0xff, 0x7f,              //   Logical Maximum (32767)           52
 65	0x35, 0x00,                    //   Physical Minimum (0)              55
 66	0x46, 0x00, 0x08,              //   Physical Maximum (2048)           57
 67	0x75, 0x10,                    //   Report Size (16)                  60
 68	0x95, 0x02,                    //   Report Count (2)                  62
 69	0x81, 0x02,                    //   Input (Data,Var,Abs)              64
 70	0x05, 0x0d,                    //   Usage Page (Digitizers)           66
 71	0x09, 0x30,                    //   Usage (Tip Pressure)              68
 72	0x26, 0xff, 0x3f,              //   Logical Maximum (16383)           70
 73	0x75, 0x10,                    //   Report Size (16)                  73
 74	0x95, 0x01,                    //   Report Count (1)                  75
 75	0x81, 0x02,                    //   Input (Data,Var,Abs)              77
 76	0x09, 0x3d,                    //   Usage (X Tilt)                    79
 77	0x09, 0x3e,                    //   Usage (Y Tilt)                    81
 78	0x15, 0xa6,                    //   Logical Minimum (-90)             83
 79	0x25, 0x5a,                    //   Logical Maximum (90)              85
 80	0x75, 0x08,                    //   Report Size (8)                   87
 81	0x95, 0x02,                    //   Report Count (2)                  89
 82	0x81, 0x02,                    //   Input (Data,Var,Abs)              91
 83	0xc0,                          //  End Collection                     93
 84	0xc0,                          // End Collection                      94
 85	0x05, 0x0d,                    // Usage Page (Digitizers)             95
 86	0x09, 0x04,                    // Usage (Touch Screen)                97
 87	0xa1, 0x01,                    // Collection (Application)            99
 88	0x85, 0x04,                    //  Report ID (4)                      101
 89	0x09, 0x22,                    //  Usage (Finger)                     103
 90	0xa1, 0x02,                    //  Collection (Logical)               105
 91	0x05, 0x0d,                    //   Usage Page (Digitizers)           107
 92	0x95, 0x01,                    //   Report Count (1)                  109
 93	0x75, 0x06,                    //   Report Size (6)                   111
 94	0x09, 0x51,                    //   Usage (Contact Id)                113
 95	0x15, 0x00,                    //   Logical Minimum (0)               115
 96	0x25, 0x3f,                    //   Logical Maximum (63)              117
 97	0x81, 0x02,                    //   Input (Data,Var,Abs)              119
 98	0x09, 0x42,                    //   Usage (Tip Switch)                121
 99	0x25, 0x01,                    //   Logical Maximum (1)               123
100	0x75, 0x01,                    //   Report Size (1)                   125
101	0x95, 0x01,                    //   Report Count (1)                  127
102	0x81, 0x02,                    //   Input (Data,Var,Abs)              129
103	0x75, 0x01,                    //   Report Size (1)                   131
104	0x95, 0x01,                    //   Report Count (1)                  133
105	0x81, 0x03,                    //   Input (Cnst,Var,Abs)              135
106	0x05, 0x01,                    //   Usage Page (Generic Desktop)      137
107	0x75, 0x10,                    //   Report Size (16)                  139
108	0x55, 0x0e,                    //   Unit Exponent (-2)                141
109	0x65, 0x11,                    //   Unit (SILinear: cm)               143
110	0x09, 0x30,                    //   Usage (X)                         145
111	0x26, 0xff, 0x7f,              //   Logical Maximum (32767)           147
112	0x35, 0x00,                    //   Physical Minimum (0)              150
113	0x46, 0x15, 0x0c,              //   Physical Maximum (3093)           152
114	0x81, 0x42,                    //   Input (Data,Var,Abs,Null)         155
115	0x09, 0x31,                    //   Usage (Y)                         157
116	0x26, 0xff, 0x7f,              //   Logical Maximum (32767)           159
117	0x46, 0xcb, 0x06,              //   Physical Maximum (1739)           162
118	0x81, 0x42,                    //   Input (Data,Var,Abs,Null)         165
119	0x05, 0x0d,                    //   Usage Page (Digitizers)           167
120	0x09, 0x30,                    //   Usage (Tip Pressure)              169
121	0x26, 0xff, 0x1f,              //   Logical Maximum (8191)            171
122	0x75, 0x10,                    //   Report Size (16)                  174
123	0x95, 0x01,                    //   Report Count (1)                  176
124	0x81, 0x02,                    //   Input (Data,Var,Abs)              178
125	0xc0,                          //  End Collection                     180
126	0x05, 0x0d,                    //  Usage Page (Digitizers)            181
127	0x09, 0x22,                    //  Usage (Finger)                     183
128	0xa1, 0x02,                    //  Collection (Logical)               185
129	0x05, 0x0d,                    //   Usage Page (Digitizers)           187
130	0x95, 0x01,                    //   Report Count (1)                  189
131	0x75, 0x06,                    //   Report Size (6)                   191
132	0x09, 0x51,                    //   Usage (Contact Id)                193
133	0x15, 0x00,                    //   Logical Minimum (0)               195
134	0x25, 0x3f,                    //   Logical Maximum (63)              197
135	0x81, 0x02,                    //   Input (Data,Var,Abs)              199
136	0x09, 0x42,                    //   Usage (Tip Switch)                201
137	0x25, 0x01,                    //   Logical Maximum (1)               203
138	0x75, 0x01,                    //   Report Size (1)                   205
139	0x95, 0x01,                    //   Report Count (1)                  207
140	0x81, 0x02,                    //   Input (Data,Var,Abs)              209
141	0x75, 0x01,                    //   Report Size (1)                   211
142	0x95, 0x01,                    //   Report Count (1)                  213
143	0x81, 0x03,                    //   Input (Cnst,Var,Abs)              215
144	0x05, 0x01,                    //   Usage Page (Generic Desktop)      217
145	0x75, 0x10,                    //   Report Size (16)                  219
146	0x55, 0x0e,                    //   Unit Exponent (-2)                221
147	0x65, 0x11,                    //   Unit (SILinear: cm)               223
148	0x09, 0x30,                    //   Usage (X)                         225
149	0x26, 0xff, 0x7f,              //   Logical Maximum (32767)           227
150	0x35, 0x00,                    //   Physical Minimum (0)              230
151	0x46, 0x15, 0x0c,              //   Physical Maximum (3093)           232
152	0x81, 0x42,                    //   Input (Data,Var,Abs,Null)         235
153	0x09, 0x31,                    //   Usage (Y)                         237
154	0x26, 0xff, 0x7f,              //   Logical Maximum (32767)           239
155	0x46, 0xcb, 0x06,              //   Physical Maximum (1739)           242
156	0x81, 0x42,                    //   Input (Data,Var,Abs,Null)         245
157	0x05, 0x0d,                    //   Usage Page (Digitizers)           247
158	0x09, 0x30,                    //   Usage (Tip Pressure)              249
159	0x26, 0xff, 0x1f,              //   Logical Maximum (8191)            251
160	0x75, 0x10,                    //   Report Size (16)                  254
161	0x95, 0x01,                    //   Report Count (1)                  256
162	0x81, 0x02,                    //   Input (Data,Var,Abs)              258
163	0xc0,                          //  End Collection                     260
164	0x05, 0x0d,                    //  Usage Page (Digitizers)            261
165	0x09, 0x56,                    //  Usage (Scan Time)                  263
166	0x55, 0x00,                    //  Unit Exponent (0)                  265
167	0x65, 0x00,                    //  Unit (None)                        267
168	0x27, 0xff, 0xff, 0xff, 0x7f,  //  Logical Maximum (2147483647)       269
169	0x95, 0x01,                    //  Report Count (1)                   274
170	0x75, 0x20,                    //  Report Size (32)                   276
171	0x81, 0x02,                    //  Input (Data,Var,Abs)               278
172	0x09, 0x54,                    //  Usage (Contact Count)              280
173	0x25, 0x7f,                    //  Logical Maximum (127)              282
174	0x95, 0x01,                    //  Report Count (1)                   284
175	0x75, 0x08,                    //  Report Size (8)                    286
176	0x81, 0x02,                    //  Input (Data,Var,Abs)               288
177	0x75, 0x08,                    //  Report Size (8)                    290
178	0x95, 0x08,                    //  Report Count (8)                   292
179	0x81, 0x03,                    //  Input (Cnst,Var,Abs)               294
180	0x85, 0x05,                    //  Report ID (5)                      296
181	0x09, 0x55,                    //  Usage (Contact Max)                298
182	0x25, 0x0a,                    //  Logical Maximum (10)               300
183	0x75, 0x08,                    //  Report Size (8)                    302
184	0x95, 0x01,                    //  Report Count (1)                   304
185	0xb1, 0x02,                    //  Feature (Data,Var,Abs)             306
186	0x06, 0x00, 0xff,              //  Usage Page (Vendor Defined Page 1) 308
187	0x09, 0xc5,                    //  Usage (Vendor Usage 0xc5)          311
188	0x85, 0x06,                    //  Report ID (6)                      313
189	0x15, 0x00,                    //  Logical Minimum (0)                315
190	0x26, 0xff, 0x00,              //  Logical Maximum (255)              317
191	0x75, 0x08,                    //  Report Size (8)                    320
192	0x96, 0x00, 0x01,              //  Report Count (256)                 322
193	0xb1, 0x02,                    //  Feature (Data,Var,Abs)             325
194	0xc0,                          // End Collection                      327
195	/* New in Firmware Version: HUION_M220_240524 */
196	0x05, 0x01,                    // Usage Page (Generic Desktop)            328
197	0x09, 0x01,                    // Usage (Pointer)                         330
198	0xa1, 0x01,                    // Collection (Application)                332
199	0x09, 0x01,                    //   Usage (Pointer)                       334
200	0xa1, 0x00,                    //   Collection (Physical)                 336
201	0x05, 0x09,                    //     Usage Page (Button)                 338
202	0x19, 0x01,                    //     UsageMinimum (1)                    340
203	0x29, 0x03,                    //     UsageMaximum (3)                    342
204	0x15, 0x00,                    //     Logical Minimum (0)                 344
205	0x25, 0x01,                    //     Logical Maximum (1)                 346
206	0x85, 0x02,                    //     Report ID (2)                       348
207	0x95, 0x03,                    //     Report Count (3)                    350
208	0x75, 0x01,                    //     Report Size (1)                     352
209	0x81, 0x02,                    //     Input (Data,Var,Abs)                354
210	0x95, 0x01,                    //     Report Count (1)                    356
211	0x75, 0x05,                    //     Report Size (5)                     358
212	0x81, 0x01,                    //     Input (Cnst,Arr,Abs)                360
213	0x05, 0x01,                    //     Usage Page (Generic Desktop)        362
214	0x09, 0x30,                    //     Usage (X)                           364
215	0x09, 0x31,                    //     Usage (Y)                           366
216	0x15, 0x81,                    //     Logical Minimum (-127)              368
217	0x25, 0x7f,                    //     Logical Maximum (127)               370
218	0x75, 0x08,                    //     Report Size (8)                     372
219	0x95, 0x02,                    //     Report Count (2)                    374
220	0x81, 0x06,                    //     Input (Data,Var,Rel)                376
221	0x95, 0x04,                    //     Report Count (4)                    378
222	0x75, 0x08,                    //     Report Size (8)                     380
223	0x81, 0x01,                    //     Input (Cnst,Arr,Abs)                382
224	0xc0,                          //   End Collection                        384
225	0xc0,                          // End Collection                          385
226	0x05, 0x0d,                    // Usage Page (Digitizers)                 386
227	0x09, 0x05,                    // Usage (Touch Pad)                       388
228	0xa1, 0x01,                    // Collection (Application)                390
229	0x06, 0x00, 0xff,              //   Usage Page (Vendor Defined Page FF00) 392
230	0x09, 0x0c,                    //   Usage (Vendor Usage 0x0c)             395
231	0x15, 0x00,                    //   Logical Minimum (0)                   397
232	0x26, 0xff, 0x00,              //   Logical Maximum (255)                 399
233	0x75, 0x08,                    //   Report Size (8)                       402
234	0x95, 0x10,                    //   Report Count (16)                     404
235	0x85, 0x3f,                    //   Report ID (63)                        406
236	0x81, 0x22,                    //   Input (Data,Var,Abs,NoPref)           408
237	0xc0,                          // End Collection                          410
238	0x06, 0x00, 0xff,              // Usage Page (Vendor Defined Page FF00)   411
239	0x09, 0x0c,                    // Usage (Vendor Usage 0x0c)               414
240	0xa1, 0x01,                    // Collection (Application)                416
241	0x06, 0x00, 0xff,              //   Usage Page (Vendor Defined Page FF00) 418
242	0x09, 0x0c,                    //   Usage (Vendor Usage 0x0c)             421
243	0x15, 0x00,                    //   Logical Minimum (0)                   423
244	0x26, 0xff, 0x00,              //   Logical Maximum (255)                 425
245	0x85, 0x44,                    //   Report ID (68)                        428
246	0x75, 0x08,                    //   Report Size (8)                       430
247	0x96, 0x6b, 0x05,              //   Report Count (1387)                   432
248	0x81, 0x00,                    //   Input (Data,Arr,Abs)                  435
249	0xc0,                          // End Collection                          437
250};
251
252#define PRE_240524_RDESC_SIZE 328
253#define PRE_240524_RDESC_FIXED_SIZE 338 /* The original bits of the descriptor */
254#define FW_240524_RDESC_SIZE 438
255#define FW_240524_RDESC_FIXED_SIZE sizeof(fixed_rdesc)
256
257SEC(HID_BPF_RDESC_FIXUP)
258int BPF_PROG(hid_fix_rdesc_huion_kamvas_pro_19, struct hid_bpf_ctx *hctx)
259{
260	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */);
261
262	if (!data)
263		return 0; /* EPERM check */
264
265	if (hctx->size == FW_240524_RDESC_SIZE) {
266		__builtin_memcpy(data, fixed_rdesc, FW_240524_RDESC_FIXED_SIZE);
267		return sizeof(fixed_rdesc);
268	}
269
270	__builtin_memcpy(data, fixed_rdesc, PRE_240524_RDESC_FIXED_SIZE);
271
272	return PRE_240524_RDESC_FIXED_SIZE;
273}
274
275/*
276 * This tablet reports the 3rd button through invert, but this conflict
277 * with the normal eraser mode.
278 * Fortunately, before entering eraser mode, (so Invert = 1),
279 * the tablet always sends an out-of-proximity event.
280 * So we can detect that single event and:
281 * - if there was none but the invert bit was toggled: this is the
282 *   third button
283 * - if there was this out-of-proximity event, we are entering
284 *   eraser mode, and we will until the next out-of-proximity.
285 */
286SEC(HID_BPF_DEVICE_EVENT)
287int BPF_PROG(kamvas_pro_19_fix_3rd_button, struct hid_bpf_ctx *hctx)
288{
289	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
290
291	if (!data)
292		return 0; /* EPERM check */
293
294	if (data[0] != 0x0a) /* not the pen report ID */
295		return 0;
296
297	/* stylus is out of range */
298	if (!(data[1] & 0x40)) {
299		prev_was_out_of_range = true;
300		in_eraser_mode = false;
301		return 0;
302	}
303
304	/* going into eraser mode (Invert = 1) only happens after an
305	 * out of range event
306	 */
307	if (prev_was_out_of_range && (data[1] & 0x18))
308		in_eraser_mode = true;
309
310	/* eraser mode works fine */
311	if (in_eraser_mode)
312		return 0;
313
314	/* copy the Invert bit reported for the 3rd button in bit 7 */
315	if (data[1] & 0x08)
316		data[1] |= 0x20;
317
318	/* clear Invert bit now that it was copied */
319	data[1] &= 0xf7;
320
321	prev_was_out_of_range = false;
322
323	return 0;
324}
325
326HID_BPF_OPS(huion_Kamvas_pro_19) = {
327	.hid_rdesc_fixup = (void *)hid_fix_rdesc_huion_kamvas_pro_19,
328	.hid_device_event = (void *)kamvas_pro_19_fix_3rd_button,
329};
330
331SEC("syscall")
332int probe(struct hid_bpf_probe_args *ctx)
333{
334
335	ctx->retval = !((ctx->rdesc_size == PRE_240524_RDESC_SIZE) ||
336			(ctx->rdesc_size == FW_240524_RDESC_SIZE));
337	if (ctx->retval)
338		ctx->retval = -EINVAL;
339
340	/* ensure the kernel isn't fixed already */
341	if (ctx->rdesc[17] != 0x43) /* Secondary Tip Switch */
342		ctx->retval = -EINVAL;
343
344	struct hid_bpf_ctx *hctx = hid_bpf_allocate_context(ctx->hid);
345
346	if (!hctx) {
347		return ctx->retval = -EINVAL;
348		return 0;
349	}
350
351	const char *name = hctx->hid->name;
352
353	/* strip out TEST_PREFIX */
354	if (!__builtin_memcmp(name, TEST_PREFIX, sizeof(TEST_PREFIX) - 1))
355		name += sizeof(TEST_PREFIX) - 1;
356
357	if (__builtin_memcmp(name, NAME_KAMVAS_PRO_19, sizeof(NAME_KAMVAS_PRO_19)) &&
358	    __builtin_memcmp(name, NAME_KAMVAS_PRO_27, sizeof(NAME_KAMVAS_PRO_27)))
359		ctx->retval = -EINVAL;
360
361	hid_bpf_release_context(hctx);
362
363	return 0;
364}
365
366char _license[] SEC("license") = "GPL";
~/ Read-only file preview.