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