File Index
Files and directories
Sign in
FILE

Huion__Inspiroy-2-M.bpf.c

File preview with syntax highlighting.

linux-6.19.14/drivers/hid/bpf/progs/Huion__Inspiroy-2-M.bpf.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/* Copyright (c) 2024 Red Hat, Inc
  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 <bpf/bpf_tracing.h>
 10
 11#define VID_HUION 0x256C
 12#define PID_INSPIROY_2_M 0x0067
 13
 14HID_BPF_CONFIG(
 15	HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_HUION, PID_INSPIROY_2_M),
 16);
 17
 18/* Filled in by udev-hid-bpf */
 19char UDEV_PROP_HUION_FIRMWARE_ID[64];
 20
 21/* The prefix of the firmware ID we expect for this device. The full firmware
 22 * string has a date suffix, e.g. HUION_T21j_221221
 23 */
 24char EXPECTED_FIRMWARE_ID[] = "HUION_T21k_";
 25
 26/* How this BPF program works: the tablet has two modes, firmware mode and
 27 * tablet mode. In firmware mode (out of the box) the tablet sends button events
 28 * and the dial as keyboard combinations. In tablet mode it uses a vendor specific
 29 * hid report to report everything instead.
 30 * Depending on the mode some hid reports are never sent and the corresponding
 31 * devices are mute.
 32 *
 33 * To switch the tablet use e.g.  https://github.com/whot/huion-switcher
 34 * or one of the tools from the digimend project
 35 *
 36 * This BPF works for both modes. The huion-switcher tool sets the
 37 * HUION_FIRMWARE_ID udev property - if that is set then we disable the firmware
 38 * pad and pen reports (by making them vendor collections that are ignored).
 39 * If that property is not set we fix all hidraw nodes so the tablet works in
 40 * either mode though the drawback is that the device will show up twice if
 41 * you bind it to all event nodes
 42 *
 43 * Default report descriptor for the first exposed hidraw node:
 44 *
 45 * # HUION Huion Tablet_H641P
 46 * # Report descriptor length: 18 bytes
 47 * # 0x06, 0x00, 0xff,              // Usage Page (Vendor Defined Page 0xFF00)   0
 48 * # 0x09, 0x01,                    // Usage (Vendor Usage 0x01)                 3
 49 * # 0xa1, 0x01,                    // Collection (Application)                  5
 50 * # 0x85, 0x08,                    //   Report ID (8)                           7
 51 * # 0x75, 0x58,                    //   Report Size (88)                        9
 52 * # 0x95, 0x01,                    //   Report Count (1)                        11
 53 * # 0x09, 0x01,                    //   Usage (Vendor Usage 0x01)               13
 54 * # 0x81, 0x02,                    //   Input (Data,Var,Abs)                    15
 55 * # 0xc0,                          // End Collection                            17
 56 * R: 18 06 00 ff 09 01 a1 01 85 08 75 58 95 01 09 01 81 02 c0
 57 *
 58 * This rdesc does nothing until the tablet is switched to raw mode, see
 59 * https://github.com/whot/huion-switcher
 60 *
 61 *
 62 * Second hidraw node is the Pen. This one sends events until the tablet is
 63 * switched to raw mode, then it's mute.
 64 *
 65 * # Report descriptor length: 93 bytes
 66 * # 0x05, 0x0d,          // Usage Page (Digitizers)                   0
 67 * # 0x09, 0x02,          // Usage (Pen)                               2
 68 * # 0xa1, 0x01,          // Collection (Application)                  4
 69 * # 0x85, 0x0a,          //   Report ID (10)                          6
 70 * # 0x09, 0x20,          //   Usage (Stylus)                          8
 71 * # 0xa1, 0x01,          //   Collection (Application)                10
 72 * # 0x09, 0x42,          //     Usage (Tip Switch)                    12
 73 * # 0x09, 0x44,          //     Usage (Barrel Switch)                 14
 74 * # 0x09, 0x45,          //     Usage (Eraser)                        16
 75 * # 0x09, 0x3c,          //     Usage (Invert)                        18 <-- has no Invert eraser
 76 * # 0x15, 0x00,          //     Logical Minimum (0)                   20
 77 * # 0x25, 0x01,          //     Logical Maximum (1)                   22
 78 * # 0x75, 0x01,          //     Report Size (1)                       24
 79 * # 0x95, 0x06,          //     Report Count (6)                      26
 80 * # 0x81, 0x02,          //     Input (Data,Var,Abs)                  28
 81 * # 0x09, 0x32,          //     Usage (In Range)                      30
 82 * # 0x75, 0x01,          //     Report Size (1)                       32
 83 * # 0x95, 0x01,          //     Report Count (1)                      34
 84 * # 0x81, 0x02,          //     Input (Data,Var,Abs)                  36
 85 * # 0x81, 0x03,          //     Input (Cnst,Var,Abs)                  38
 86 * # 0x05, 0x01,          //     Usage Page (Generic Desktop)          40
 87 * # 0x09, 0x30,          //     Usage (X)                             42
 88 * # 0x09, 0x31,          //     Usage (Y)                             44
 89 * # 0x55, 0x0d,          //     Unit Exponent (-3)                    46 <-- change to -2
 90 * # 0x65, 0x33,          //     Unit (EnglishLinear: in³)             48 <-- change in³ to in
 91 * # 0x26, 0xff, 0x7f,    //     Logical Maximum (32767)               50
 92 * # 0x35, 0x00,          //     Physical Minimum (0)                  53
 93 * # 0x46, 0x00, 0x08,    //     Physical Maximum (2048)               55 <-- invalid size
 94 * # 0x75, 0x10,          //     Report Size (16)                      58
 95 * # 0x95, 0x02,          //     Report Count (2)                      60
 96 * # 0x81, 0x02,          //     Input (Data,Var,Abs)                  62
 97 * # 0x05, 0x0d,          //     Usage Page (Digitizers)               64
 98 * # 0x09, 0x30,          //     Usage (Tip Pressure)                  66
 99 * # 0x26, 0xff, 0x1f,    //     Logical Maximum (8191)                68
100 * # 0x75, 0x10,          //     Report Size (16)                      71
101 * # 0x95, 0x01,          //     Report Count (1)                      73
102 * # 0x81, 0x02,          //     Input (Data,Var,Abs)                  75
103 * # 0x09, 0x3d,          //     Usage (X Tilt)                        77 <-- No tilt reported
104 * # 0x09, 0x3e,          //     Usage (Y Tilt)                        79
105 * # 0x15, 0x81,          //     Logical Minimum (-127)                81
106 * # 0x25, 0x7f,          //     Logical Maximum (127)                 83
107 * # 0x75, 0x08,          //     Report Size (8)                       85
108 * # 0x95, 0x02,          //     Report Count (2)                      87
109 * # 0x81, 0x02,          //     Input (Data,Var,Abs)                  89
110 * # 0xc0,                //   End Collection                          91
111 * # 0xc0,                // End Collection                            92
112 * R: 93 05 0d 09 02 a1 01 85 0a 09 20 a1 01 09 42 09 44 09 45 09 3c 15 00 25 01 7501 95 06 81 02 09 32 75 01 95 01 81 02 81 03 05 01 09 30 09 31 55 0d 65 33 26 ff7f 35 00 46 00 08 75 10 95 02 81 02 05 0d 09 30 26 ff 1f 75 10 95 01 81 02 09 3d09 3e 15 81 25 7f 75 08 95 02 81 02 c0 c0
113 *
114 * Third hidraw node is the pad which sends a combination of keyboard shortcuts until
115 * the tablet is switched to raw mode, then it's mute:
116 *
117 * # Report descriptor length: 65 bytes
118 * # 0x05, 0x01,          // Usage Page (Generic Desktop)              0
119 * # 0x09, 0x06,          // Usage (Keyboard)                          2
120 * # 0xa1, 0x01,          // Collection (Application)                  4
121 * # 0x85, 0x03,          //   Report ID (3)                           6
122 * # 0x05, 0x07,          //   Usage Page (Keyboard/Keypad)            8
123 * # 0x19, 0xe0,          //   UsageMinimum (224)                      10
124 * # 0x29, 0xe7,          //   UsageMaximum (231)                      12
125 * # 0x15, 0x00,          //   Logical Minimum (0)                     14
126 * # 0x25, 0x01,          //   Logical Maximum (1)                     16
127 * # 0x75, 0x01,          //   Report Size (1)                         18
128 * # 0x95, 0x08,          //   Report Count (8)                        20
129 * # 0x81, 0x02,          //   Input (Data,Var,Abs)                    22
130 * # 0x05, 0x07,          //   Usage Page (Keyboard/Keypad)            24
131 * # 0x19, 0x00,          //   UsageMinimum (0)                        26
132 * # 0x29, 0xff,          //   UsageMaximum (255)                      28
133 * # 0x26, 0xff, 0x00,    //   Logical Maximum (255)                   30
134 * # 0x75, 0x08,          //   Report Size (8)                         33
135 * # 0x95, 0x06,          //   Report Count (6)                        35
136 * # 0x81, 0x00,          //   Input (Data,Arr,Abs)                    37
137 * # 0xc0,                // End Collection                            39
138 * # 0x05, 0x0c,          // Usage Page (Consumer)                     40
139 * # 0x09, 0x01,          // Usage (Consumer Control)                  42
140 * # 0xa1, 0x01,          // Collection (Application)                  44
141 * # 0x85, 0x04,          //   Report ID (4)                           46
142 * # 0x19, 0x00,          //   UsageMinimum (0)                        48
143 * # 0x2a, 0x3c, 0x02,    //   UsageMaximum (572)                      50
144 * # 0x15, 0x00,          //   Logical Minimum (0)                     53
145 * # 0x26, 0x3c, 0x02,    //   Logical Maximum (572)                   55
146 * # 0x95, 0x01,          //   Report Count (1)                        58
147 * # 0x75, 0x10,          //   Report Size (16)                        60
148 * # 0x81, 0x00,          //   Input (Data,Arr,Abs)                    62
149 * # 0xc0,                // End Collection                            64
150 * R: 65 05 01 09 06 a1 01 85 03 05 07 19 e0 29 e7 15 00 25 01 75 01 95 08 81 02 0507 19 00 29 ff 26 ff 00 75 08 95 06 81 00 c0 05 0c 09 01 a1 01 85 04 19 00 2a 3c02 15 00 26 3c 02 95 01 75 10 81 00 c0
151 * N: HUION Huion Tablet_H641P
152 */
153
154#define PAD_REPORT_DESCRIPTOR_LENGTH 133
155#define PEN_REPORT_DESCRIPTOR_LENGTH 93
156#define VENDOR_REPORT_DESCRIPTOR_LENGTH 36
157#define PAD_REPORT_ID 3
158#define PEN_REPORT_ID 10
159#define VENDOR_REPORT_ID 8
160#define PAD_REPORT_LENGTH 8
161#define PEN_REPORT_LENGTH 10
162#define VENDOR_REPORT_LENGTH 12
163
164
165__u16 last_button_state;
166
167static const __u8 fixed_rdesc_pad[] = {
168	UsagePage_GenericDesktop
169	Usage_GD_Keypad
170	CollectionApplication(
171		// -- Byte 0 in report
172		ReportId(PAD_REPORT_ID)
173		LogicalMinimum_i8(0)
174		LogicalMaximum_i8(1)
175		UsagePage_Digitizers
176		Usage_Dig_TabletFunctionKeys
177		CollectionPhysical(
178			// Byte 1 in report - just exists so we get to be a tablet pad
179			Usage_Dig_BarrelSwitch // BTN_STYLUS
180			ReportCount(1)
181			ReportSize(1)
182			Input(Var|Abs)
183			ReportCount(7) // padding
184			Input(Const)
185			// Bytes 2/3 in report - just exists so we get to be a tablet pad
186			UsagePage_GenericDesktop
187			Usage_GD_X
188			Usage_GD_Y
189			ReportCount(2)
190			ReportSize(8)
191			Input(Var|Abs)
192			// Byte 4 in report is the wheel
193			Usage_GD_Wheel
194			LogicalMinimum_i8(-1)
195			LogicalMaximum_i8(1)
196			ReportCount(1)
197			ReportSize(8)
198			Input(Var|Rel)
199			// Byte 5 is the button state
200			UsagePage_Button
201			UsageMinimum_i8(0x1)
202			UsageMaximum_i8(0x8)
203			LogicalMinimum_i8(0x1)
204			LogicalMaximum_i8(0x8)
205			ReportCount(1)
206			ReportSize(8)
207			Input(Arr|Abs)
208		)
209		// Make sure we match our original report length
210		FixedSizeVendorReport(PAD_REPORT_LENGTH)
211	)
212};
213
214static const __u8 fixed_rdesc_pen[] = {
215	UsagePage_Digitizers
216	Usage_Dig_Pen
217	CollectionApplication(
218		// -- Byte 0 in report
219		ReportId(PEN_REPORT_ID)
220		Usage_Dig_Pen
221		CollectionPhysical(
222			// -- Byte 1 in report
223			Usage_Dig_TipSwitch
224			Usage_Dig_BarrelSwitch
225			Usage_Dig_SecondaryBarrelSwitch // maps eraser to BTN_STYLUS2
226			LogicalMinimum_i8(0)
227			LogicalMaximum_i8(1)
228			ReportSize(1)
229			ReportCount(3)
230			Input(Var|Abs)
231			ReportCount(4)  // Padding
232			Input(Const)
233			Usage_Dig_InRange
234			ReportCount(1)
235			Input(Var|Abs)
236			ReportSize(16)
237			ReportCount(1)
238			PushPop(
239				UsagePage_GenericDesktop
240				Unit(cm)
241				UnitExponent(-1)
242				PhysicalMinimum_i16(0)
243				PhysicalMaximum_i16(160)
244				LogicalMinimum_i16(0)
245				LogicalMaximum_i16(32767)
246				Usage_GD_X
247				Input(Var|Abs) // Bytes 2+3
248				PhysicalMinimum_i16(0)
249				PhysicalMaximum_i16(100)
250				LogicalMinimum_i16(0)
251				LogicalMaximum_i16(32767)
252				Usage_GD_Y
253				Input(Var|Abs) // Bytes 4+5
254			)
255			UsagePage_Digitizers
256			Usage_Dig_TipPressure
257			LogicalMinimum_i16(0)
258			LogicalMaximum_i16(8191)
259			Input(Var|Abs) // Byte 6+7
260			// Two bytes padding so we don't need to change the report at all
261			ReportSize(8)
262			ReportCount(2)
263			Input(Const) // Byte 6+7
264		)
265	)
266};
267
268static const __u8 fixed_rdesc_vendor[] = {
269	UsagePage_Digitizers
270	Usage_Dig_Pen
271	CollectionApplication(
272		// Byte 0
273		// We leave the pen on the vendor report ID
274		ReportId(VENDOR_REPORT_ID)
275		Usage_Dig_Pen
276		CollectionPhysical(
277			// Byte 1 are the buttons
278			LogicalMinimum_i8(0)
279			LogicalMaximum_i8(1)
280			ReportSize(1)
281			Usage_Dig_TipSwitch
282			Usage_Dig_BarrelSwitch
283			Usage_Dig_SecondaryBarrelSwitch
284			ReportCount(3)
285			Input(Var|Abs)
286			ReportCount(4) // Padding
287			Input(Const)
288			Usage_Dig_InRange
289			ReportCount(1)
290			Input(Var|Abs)
291			ReportSize(16)
292			ReportCount(1)
293			PushPop(
294				UsagePage_GenericDesktop
295				Unit(cm)
296				UnitExponent(-1)
297				// Note: reported logical range differs
298				// from the pen report ID for x and y
299				LogicalMinimum_i16(0)
300				LogicalMaximum_i16(32000)
301				PhysicalMinimum_i16(0)
302				PhysicalMaximum_i16(160)
303				// Bytes 2/3 in report
304				Usage_GD_X
305				Input(Var|Abs)
306				LogicalMinimum_i16(0)
307				LogicalMaximum_i16(20000)
308				PhysicalMinimum_i16(0)
309				PhysicalMaximum_i16(100)
310				// Bytes 4/5 in report
311				Usage_GD_Y
312				Input(Var|Abs)
313			)
314			// Bytes 6/7 in report
315			LogicalMinimum_i16(0)
316			LogicalMaximum_i16(8192)
317			Usage_Dig_TipPressure
318			Input(Var|Abs)
319		)
320	)
321	UsagePage_GenericDesktop
322	Usage_GD_Keypad
323	CollectionApplication(
324		// Byte 0
325		ReportId(PAD_REPORT_ID)
326		LogicalMinimum_i8(0)
327		LogicalMaximum_i8(1)
328		UsagePage_Digitizers
329		Usage_Dig_TabletFunctionKeys
330		CollectionPhysical(
331			// Byte 1 are the buttons
332			Usage_Dig_BarrelSwitch	 // BTN_STYLUS, needed so we get to be a tablet pad
333			ReportCount(1)
334			ReportSize(1)
335			Input(Var|Abs)
336			ReportCount(7) // Padding
337			Input(Const)
338			// Bytes 2/3 - x/y just exist so we get to be a tablet pad
339			UsagePage_GenericDesktop
340			Usage_GD_X
341			Usage_GD_Y
342			ReportCount(2)
343			ReportSize(8)
344			Input(Var|Abs)
345			// Bytes 4 and 5 are the button state
346			UsagePage_Button
347			UsageMinimum_i8(0x1)
348			UsageMaximum_i8(0xa)
349			LogicalMinimum_i8(0x0)
350			LogicalMaximum_i8(0x1)
351			ReportCount(10)
352			ReportSize(1)
353			Input(Var|Abs)
354			Usage_i8(0x31) // maps to BTN_SOUTH
355			ReportCount(1)
356			Input(Var|Abs)
357			ReportCount(5)
358			Input(Const)
359			// Byte 6 is the wheel
360			UsagePage_GenericDesktop
361			Usage_GD_Wheel
362			LogicalMinimum_i8(-1)
363			LogicalMaximum_i8(1)
364			ReportCount(1)
365			ReportSize(8)
366			Input(Var|Rel)
367		)
368		// Make sure we match our original report length
369		FixedSizeVendorReport(VENDOR_REPORT_LENGTH)
370	)
371};
372
373static const __u8 disabled_rdesc_pen[] = {
374	FixedSizeVendorReport(PEN_REPORT_LENGTH)
375};
376
377static const __u8 disabled_rdesc_pad[] = {
378	FixedSizeVendorReport(PAD_REPORT_LENGTH)
379};
380
381SEC(HID_BPF_RDESC_FIXUP)
382int BPF_PROG(hid_fix_rdesc, struct hid_bpf_ctx *hctx)
383{
384	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */);
385	__s32 rdesc_size = hctx->size;
386	__u8 have_fw_id;
387
388	if (!data)
389		return 0; /* EPERM check */
390
391	/* If we have a firmware ID and it matches our expected prefix, we
392	 * disable the default pad/pen nodes. They won't send events
393	 * but cause duplicate devices.
394	 */
395	have_fw_id = __builtin_memcmp(UDEV_PROP_HUION_FIRMWARE_ID,
396				      EXPECTED_FIRMWARE_ID,
397				      sizeof(EXPECTED_FIRMWARE_ID) - 1) == 0;
398	if (rdesc_size == PAD_REPORT_DESCRIPTOR_LENGTH) {
399		if (have_fw_id) {
400			__builtin_memcpy(data, disabled_rdesc_pad, sizeof(disabled_rdesc_pad));
401			return sizeof(disabled_rdesc_pad);
402		}
403
404		__builtin_memcpy(data, fixed_rdesc_pad, sizeof(fixed_rdesc_pad));
405		return sizeof(fixed_rdesc_pad);
406	}
407	if (rdesc_size == PEN_REPORT_DESCRIPTOR_LENGTH) {
408		if (have_fw_id) {
409			__builtin_memcpy(data, disabled_rdesc_pen, sizeof(disabled_rdesc_pen));
410			return sizeof(disabled_rdesc_pen);
411		}
412
413		__builtin_memcpy(data, fixed_rdesc_pen, sizeof(fixed_rdesc_pen));
414		return sizeof(fixed_rdesc_pen);
415	}
416	/* Always fix the vendor mode so the tablet will work even if nothing sets
417	 * the udev property (e.g. huion-switcher run manually)
418	 */
419	if (rdesc_size == VENDOR_REPORT_DESCRIPTOR_LENGTH) {
420		__builtin_memcpy(data, fixed_rdesc_vendor, sizeof(fixed_rdesc_vendor));
421		return sizeof(fixed_rdesc_vendor);
422	}
423	return 0;
424}
425
426SEC(HID_BPF_DEVICE_EVENT)
427int BPF_PROG(inspiroy_2_fix_events, struct hid_bpf_ctx *hctx)
428{
429	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 10 /* size */);
430
431	if (!data)
432		return 0; /* EPERM check */
433
434	/* Only sent if tablet is in default mode */
435	if (data[0] == PAD_REPORT_ID) {
436		/* Nicely enough, this device only supports one button down at a time so
437		 * the reports are easy to match. Buttons numbered from the top
438		 *   Button released: 03 00 00 00 00 00 00 00
439		 *   Button 1: 03 00 05 00 00 00 00 00 -> b
440		 *   Button 2: 03 07 11 00 00 00 00 00 -> Ctrl Shift N
441		 *   Button 3: 03 00 08 00 00 00 00 00 -> e
442		 *   Button 4: 03 00 0c 00 00 00 00 00 -> i
443		 *   Button 5: 03 00 2c 00 00 00 00 00 -> space
444		 *   Button 6: 03 01 08 00 00 00 00 00 -> Ctrl E
445		 *   Button 7: 03 01 16 00 00 00 00 00 -> Ctrl S
446		 *   Button 8: 03 05 1d 00 00 00 00 00 -> Ctrl Alt Z
447		 *
448		 *   Wheel down: 03 01 2d 00 00 00 00 00 -> Ctrl -
449		 *   Wheel up:   03 01 2e 00 00 00 00 00 -> Ctrl =
450		 */
451		__u8 button = 0;
452		__u8 wheel = 0;
453
454		switch (data[1] << 8 | data[2]) {
455		case 0x0000:
456			break;
457		case 0x0005:
458			button = 1;
459			break;
460		case 0x0711:
461			button = 2;
462			break;
463		case 0x0008:
464			button = 3;
465			break;
466		case 0x000c:
467			button = 4;
468			break;
469		case 0x002c:
470			button = 5;
471			break;
472		case 0x0108:
473			button = 6;
474			break;
475		case 0x0116:
476			button = 7;
477			break;
478		case 0x051d:
479			button = 8;
480			break;
481		case 0x012d:
482			wheel = -1;
483			break;
484		case 0x012e:
485			wheel = 1;
486			break;
487		}
488
489		__u8 report[6] = {PAD_REPORT_ID, 0x0, 0x0, 0x0, wheel, button};
490
491		__builtin_memcpy(data, report, sizeof(report));
492		return sizeof(report);
493	}
494
495	/* Nothing to do for the PEN_REPORT_ID, it's already mapped */
496
497	/* Only sent if tablet is in raw mode */
498	if (data[0] == VENDOR_REPORT_ID) {
499		/* Pad reports */
500		if (data[1] & 0x20) {
501			/* See fixed_rdesc_pad */
502			struct pad_report {
503				__u8 report_id;
504				__u8 btn_stylus;
505				__u8 x;
506				__u8 y;
507				__u16 buttons;
508				__u8 wheel;
509			} __attribute__((packed)) *pad_report;
510			__u8 wheel = 0;
511
512			/* Wheel report */
513			if (data[1] == 0xf1) {
514				if (data[5] == 2)
515					wheel = 0xff;
516				else
517					wheel = data[5];
518			} else {
519				/* data[4] and data[5] are the buttons, mapped correctly */
520				last_button_state = data[4] | (data[5] << 8);
521				wheel = 0; // wheel
522			}
523
524			pad_report = (struct pad_report *)data;
525
526			pad_report->report_id = PAD_REPORT_ID;
527			pad_report->btn_stylus = 0;
528			pad_report->x = 0;
529			pad_report->y = 0;
530			pad_report->buttons = last_button_state;
531			pad_report->wheel = wheel;
532
533			return sizeof(struct pad_report);
534		}
535
536		/* Pen reports need nothing done */
537	}
538
539	return 0;
540}
541
542HID_BPF_OPS(inspiroy_2) = {
543	.hid_device_event = (void *)inspiroy_2_fix_events,
544	.hid_rdesc_fixup = (void *)hid_fix_rdesc,
545};
546
547SEC("syscall")
548int probe(struct hid_bpf_probe_args *ctx)
549{
550	switch (ctx->rdesc_size) {
551	case PAD_REPORT_DESCRIPTOR_LENGTH:
552	case PEN_REPORT_DESCRIPTOR_LENGTH:
553	case VENDOR_REPORT_DESCRIPTOR_LENGTH:
554		ctx->retval = 0;
555		break;
556	default:
557		ctx->retval = -EINVAL;
558	}
559
560	return 0;
561}
562
563char _license[] SEC("license") = "GPL";
~/ Read-only file preview.