1*88b5468fSBenjamin Tissoires // SPDX-License-Identifier: GPL-2.0-only 2*88b5468fSBenjamin Tissoires 3*88b5468fSBenjamin Tissoires #include "vmlinux.h" 4*88b5468fSBenjamin Tissoires #include "hid_bpf.h" 5*88b5468fSBenjamin Tissoires #include "hid_bpf_helpers.h" 6*88b5468fSBenjamin Tissoires #include "hid_report_helpers.h" 7*88b5468fSBenjamin Tissoires #include <bpf/bpf_tracing.h> 8*88b5468fSBenjamin Tissoires 9*88b5468fSBenjamin Tissoires #define VID_UGEE 0x28BD 10*88b5468fSBenjamin Tissoires #define PID_DECO_02 0x0803 11*88b5468fSBenjamin Tissoires 12*88b5468fSBenjamin Tissoires HID_BPF_CONFIG( 13*88b5468fSBenjamin Tissoires HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_UGEE, PID_DECO_02), 14*88b5468fSBenjamin Tissoires ); 15*88b5468fSBenjamin Tissoires 16*88b5468fSBenjamin Tissoires /* 17*88b5468fSBenjamin Tissoires * Devices are: 18*88b5468fSBenjamin Tissoires * - Pad input, including pen (This is the only one we are interested in) 19*88b5468fSBenjamin Tissoires * - Pen input as mouse 20*88b5468fSBenjamin Tissoires * - Vendor 21*88b5468fSBenjamin Tissoires * 22*88b5468fSBenjamin Tissoires * Descriptors on main device are: 23*88b5468fSBenjamin Tissoires * - 7: Pen 24*88b5468fSBenjamin Tissoires * - 6: Vendor settings? Unclear 25*88b5468fSBenjamin Tissoires * - 3: Keyboard (This is what we want to modify) 26*88b5468fSBenjamin Tissoires * - 5: Feature report 27*88b5468fSBenjamin Tissoires * 28*88b5468fSBenjamin Tissoires * This creates three event nodes: 29*88b5468fSBenjamin Tissoires * - XP-PEN DECO 02 Stylus 30*88b5468fSBenjamin Tissoires * - XP-PEN DECO 02 31*88b5468fSBenjamin Tissoires * - XP-PEN DECO 02 Keyboard (Again, what we want to modify) 32*88b5468fSBenjamin Tissoires * 33*88b5468fSBenjamin Tissoires * # Report descriptor length: 188 bytes 34*88b5468fSBenjamin Tissoires * # 0x05, 0x0d, // Usage Page (Digitizers) 0 35*88b5468fSBenjamin Tissoires * # 0x09, 0x02, // Usage (Pen) 2 36*88b5468fSBenjamin Tissoires * # 0xa1, 0x01, // Collection (Application) 4 37*88b5468fSBenjamin Tissoires * # 0x85, 0x07, // Report ID (7) 6 38*88b5468fSBenjamin Tissoires * # 0x09, 0x20, // Usage (Stylus) 8 39*88b5468fSBenjamin Tissoires * # 0xa1, 0x00, // Collection (Physical) 10 40*88b5468fSBenjamin Tissoires * # 0x09, 0x42, // Usage (Tip Switch) 12 41*88b5468fSBenjamin Tissoires * # 0x09, 0x44, // Usage (Barrel Switch) 14 42*88b5468fSBenjamin Tissoires * # 0x09, 0x45, // Usage (Eraser) 16 43*88b5468fSBenjamin Tissoires * # 0x09, 0x3c, // Usage (Invert) 18 44*88b5468fSBenjamin Tissoires * # 0x09, 0x32, // Usage (In Range) 20 45*88b5468fSBenjamin Tissoires * # 0x15, 0x00, // Logical Minimum (0) 22 46*88b5468fSBenjamin Tissoires * # 0x25, 0x01, // Logical Maximum (1) 24 47*88b5468fSBenjamin Tissoires * # 0x75, 0x01, // Report Size (1) 26 48*88b5468fSBenjamin Tissoires * # 0x95, 0x05, // Report Count (5) 28 49*88b5468fSBenjamin Tissoires * # 0x81, 0x02, // Input (Data,Var,Abs) 30 50*88b5468fSBenjamin Tissoires * # 0x95, 0x03, // Report Count (3) 32 51*88b5468fSBenjamin Tissoires * # 0x81, 0x03, // Input (Cnst,Var,Abs) 34 52*88b5468fSBenjamin Tissoires * # 0x05, 0x01, // Usage Page (Generic Desktop) 36 53*88b5468fSBenjamin Tissoires * # 0x09, 0x30, // Usage (X) 38 54*88b5468fSBenjamin Tissoires * # 0x15, 0x00, // Logical Minimum (0) 40 55*88b5468fSBenjamin Tissoires * # 0x26, 0x50, 0x57, // Logical Maximum (22352) 42 56*88b5468fSBenjamin Tissoires * # 0x55, 0x0d, // Unit Exponent (-3) 45 57*88b5468fSBenjamin Tissoires * # 0x65, 0x13, // Unit (EnglishLinear: in) 47 58*88b5468fSBenjamin Tissoires * # 0x35, 0x00, // Physical Minimum (0) 49 59*88b5468fSBenjamin Tissoires * # 0x46, 0x50, 0x57, // Physical Maximum (22352) 51 60*88b5468fSBenjamin Tissoires * # 0x75, 0x10, // Report Size (16) 54 61*88b5468fSBenjamin Tissoires * # 0x95, 0x01, // Report Count (1) 56 62*88b5468fSBenjamin Tissoires * # 0x81, 0x02, // Input (Data,Var,Abs) 58 63*88b5468fSBenjamin Tissoires * # 0x09, 0x31, // Usage (Y) 60 64*88b5468fSBenjamin Tissoires * # 0x15, 0x00, // Logical Minimum (0) 62 65*88b5468fSBenjamin Tissoires * # 0x26, 0x92, 0x36, // Logical Maximum (13970) 64 66*88b5468fSBenjamin Tissoires * # 0x55, 0x0d, // Unit Exponent (-3) 67 67*88b5468fSBenjamin Tissoires * # 0x65, 0x13, // Unit (EnglishLinear: in) 69 68*88b5468fSBenjamin Tissoires * # 0x35, 0x00, // Physical Minimum (0) 71 69*88b5468fSBenjamin Tissoires * # 0x46, 0x92, 0x36, // Physical Maximum (13970) 73 70*88b5468fSBenjamin Tissoires * # 0x75, 0x10, // Report Size (16) 76 71*88b5468fSBenjamin Tissoires * # 0x95, 0x01, // Report Count (1) 78 72*88b5468fSBenjamin Tissoires * # 0x81, 0x02, // Input (Data,Var,Abs) 80 73*88b5468fSBenjamin Tissoires * # 0x05, 0x0d, // Usage Page (Digitizers) 82 74*88b5468fSBenjamin Tissoires * # 0x09, 0x30, // Usage (Tip Pressure) 84 75*88b5468fSBenjamin Tissoires * # 0x15, 0x00, // Logical Minimum (0) 86 76*88b5468fSBenjamin Tissoires * # 0x26, 0xff, 0x1f, // Logical Maximum (8191) 88 77*88b5468fSBenjamin Tissoires * # 0x75, 0x10, // Report Size (16) 91 78*88b5468fSBenjamin Tissoires * # 0x95, 0x01, // Report Count (1) 93 79*88b5468fSBenjamin Tissoires * # 0x81, 0x02, // Input (Data,Var,Abs) 95 80*88b5468fSBenjamin Tissoires * # 0xc0, // End Collection 97 81*88b5468fSBenjamin Tissoires * # 0xc0, // End Collection 98 82*88b5468fSBenjamin Tissoires * # 0x09, 0x0e, // Usage (Device Configuration) 99 83*88b5468fSBenjamin Tissoires * # 0xa1, 0x01, // Collection (Application) 101 84*88b5468fSBenjamin Tissoires * # 0x85, 0x05, // Report ID (5) 103 85*88b5468fSBenjamin Tissoires * # 0x09, 0x23, // Usage (Device Settings) 105 86*88b5468fSBenjamin Tissoires * # 0xa1, 0x02, // Collection (Logical) 107 87*88b5468fSBenjamin Tissoires * # 0x09, 0x52, // Usage (Inputmode) 109 88*88b5468fSBenjamin Tissoires * # 0x09, 0x53, // Usage (Device Index) 111 89*88b5468fSBenjamin Tissoires * # 0x25, 0x0a, // Logical Maximum (10) 113 90*88b5468fSBenjamin Tissoires * # 0x75, 0x08, // Report Size (8) 115 91*88b5468fSBenjamin Tissoires * # 0x95, 0x02, // Report Count (2) 117 92*88b5468fSBenjamin Tissoires * # 0xb1, 0x02, // Feature (Data,Var,Abs) 119 93*88b5468fSBenjamin Tissoires * # 0xc0, // End Collection 121 94*88b5468fSBenjamin Tissoires * # 0xc0, // End Collection 122 95*88b5468fSBenjamin Tissoires * # 0x05, 0x0c, // Usage Page (Consumer Devices) 123 96*88b5468fSBenjamin Tissoires * # 0x09, 0x36, // Usage (Function Buttons) 125 97*88b5468fSBenjamin Tissoires * # 0xa1, 0x00, // Collection (Physical) 127 98*88b5468fSBenjamin Tissoires * # 0x85, 0x06, // Report ID (6) 129 99*88b5468fSBenjamin Tissoires * # 0x05, 0x09, // Usage Page (Button) 131 100*88b5468fSBenjamin Tissoires * # 0x19, 0x01, // Usage Minimum (1) 133 101*88b5468fSBenjamin Tissoires * # 0x29, 0x20, // Usage Maximum (32) 135 102*88b5468fSBenjamin Tissoires * # 0x15, 0x00, // Logical Minimum (0) 137 103*88b5468fSBenjamin Tissoires * # 0x25, 0x01, // Logical Maximum (1) 139 104*88b5468fSBenjamin Tissoires * # 0x95, 0x20, // Report Count (32) 141 105*88b5468fSBenjamin Tissoires * # 0x75, 0x01, // Report Size (1) 143 106*88b5468fSBenjamin Tissoires * # 0x81, 0x02, // Input (Data,Var,Abs) 145 107*88b5468fSBenjamin Tissoires * # 0xc0, // End Collection 147 108*88b5468fSBenjamin Tissoires * # 0x05, 0x01, // Usage Page (Generic Desktop) 148 109*88b5468fSBenjamin Tissoires * # 0x09, 0x06, // Usage (Keyboard) 150 110*88b5468fSBenjamin Tissoires * # 0xa1, 0x01, // Collection (Application) 152 111*88b5468fSBenjamin Tissoires * # 0x85, 0x03, // Report ID (3) 154 112*88b5468fSBenjamin Tissoires * # 0x05, 0x07, // Usage Page (Keyboard) 156 113*88b5468fSBenjamin Tissoires * # 0x19, 0xe0, // Usage Minimum (224) 158 114*88b5468fSBenjamin Tissoires * # 0x29, 0xe7, // Usage Maximum (231) 160 115*88b5468fSBenjamin Tissoires * # 0x15, 0x00, // Logical Minimum (0) 162 116*88b5468fSBenjamin Tissoires * # 0x25, 0x01, // Logical Maximum (1) 164 117*88b5468fSBenjamin Tissoires * # 0x75, 0x01, // Report Size (1) 166 118*88b5468fSBenjamin Tissoires * # 0x95, 0x08, // Report Count (8) 168 119*88b5468fSBenjamin Tissoires * # 0x81, 0x02, // Input (Data,Var,Abs) 170 120*88b5468fSBenjamin Tissoires * # 0x05, 0x07, // Usage Page (Keyboard) 172 121*88b5468fSBenjamin Tissoires * # 0x19, 0x00, // Usage Minimum (0) 174 122*88b5468fSBenjamin Tissoires * # 0x29, 0xff, // Usage Maximum (255) 176 123*88b5468fSBenjamin Tissoires * # 0x26, 0xff, 0x00, // Logical Maximum (255) 178 124*88b5468fSBenjamin Tissoires * # 0x75, 0x08, // Report Size (8) 181 125*88b5468fSBenjamin Tissoires * # 0x95, 0x06, // Report Count (6) 183 126*88b5468fSBenjamin Tissoires * # 0x81, 0x00, // Input (Data,Arr,Abs) 185 127*88b5468fSBenjamin Tissoires * # 0xc0, // End Collection 187 128*88b5468fSBenjamin Tissoires * 129*88b5468fSBenjamin Tissoires * Key events; top to bottom: 130*88b5468fSBenjamin Tissoires * Buttons released: 03 00 00 00 00 00 00 00 131*88b5468fSBenjamin Tissoires * Button1: 03 00 05 00 00 00 00 00 -> 'b and B' 132*88b5468fSBenjamin Tissoires * Button2: 03 00 2c 00 00 00 00 00 -> 'Spacebar' 133*88b5468fSBenjamin Tissoires * Button3: 03 00 08 00 00 00 00 00 -> 'e and E' 134*88b5468fSBenjamin Tissoires * Button4: 03 00 0c 00 00 00 00 00 -> 'i and I' 135*88b5468fSBenjamin Tissoires * Button5: 03 05 1d 00 00 00 00 00 -> LeftControl + LeftAlt + 'z and Z' 136*88b5468fSBenjamin Tissoires * Button6: 03 01 16 00 00 00 00 00 -> LeftControl + 's and S' 137*88b5468fSBenjamin Tissoires * 138*88b5468fSBenjamin Tissoires * Dial Events: 139*88b5468fSBenjamin Tissoires * Clockwise: 03 01 2e 00 00 00 00 00 -> LeftControl + '= and +' 140*88b5468fSBenjamin Tissoires * Anticlockwise: 03 01 2d 00 00 00 00 00 -> LeftControl + '- and (underscore)' 141*88b5468fSBenjamin Tissoires * 142*88b5468fSBenjamin Tissoires * NOTE: Input event descriptions begin at byte 2, and progressively build 143*88b5468fSBenjamin Tissoires * towards byte 7 as each new key is pressed maintaining the press order. 144*88b5468fSBenjamin Tissoires * For example: 145*88b5468fSBenjamin Tissoires * BTN1 followed by BTN2 is 03 00 05 2c 00 00 00 00 146*88b5468fSBenjamin Tissoires * BTN2 followed by BTN1 is 03 00 2c 05 00 00 00 00 147*88b5468fSBenjamin Tissoires * 148*88b5468fSBenjamin Tissoires * Releasing a button causes its byte to be freed, and the next item in the list 149*88b5468fSBenjamin Tissoires * is pushed forwards. Dial events are released immediately after an event is 150*88b5468fSBenjamin Tissoires * registered (i.e. after each "click"), so will continually appear pushed 151*88b5468fSBenjamin Tissoires * backwards in the report. 152*88b5468fSBenjamin Tissoires * 153*88b5468fSBenjamin Tissoires * When a button with a modifier key is pressed, the button identifier stacks in 154*88b5468fSBenjamin Tissoires * an abnormal way, where the highest modifier byte always supersedes others. 155*88b5468fSBenjamin Tissoires * In these cases, the button with the higher modifier is always last. 156*88b5468fSBenjamin Tissoires * For example: 157*88b5468fSBenjamin Tissoires * BTN6 followed by BTN5 is 03 05 1d 16 00 00 00 00 158*88b5468fSBenjamin Tissoires * BTN5 followed by BTN6 is 03 05 1d 16 00 00 00 00 159*88b5468fSBenjamin Tissoires * BTN5 followed by BTN1 is 03 05 05 1d 00 00 00 00 160*88b5468fSBenjamin Tissoires * 161*88b5468fSBenjamin Tissoires * For three button presses in order, demonstrating strictly above rules: 162*88b5468fSBenjamin Tissoires * BTN6, BTN1, BTN5 is 03 05 05 1d 16 00 00 00 163*88b5468fSBenjamin Tissoires * BTN5, BTN1, BTN6 is 03 05 05 1d 16 00 00 00 164*88b5468fSBenjamin Tissoires * 165*88b5468fSBenjamin Tissoires * In short, when BTN5/6 are pressed, the order of operations is lost, as they 166*88b5468fSBenjamin Tissoires * will always float to the end when pressed in combination with others. 167*88b5468fSBenjamin Tissoires * 168*88b5468fSBenjamin Tissoires * Fortunately, all states are recorded in the same way, with no overlaps. 169*88b5468fSBenjamin Tissoires * Byte 1 can be used as a spare for the wheel, since this is for mod keys. 170*88b5468fSBenjamin Tissoires */ 171*88b5468fSBenjamin Tissoires 172*88b5468fSBenjamin Tissoires #define RDESC_SIZE_PAD 188 173*88b5468fSBenjamin Tissoires #define REPORT_SIZE_PAD 8 174*88b5468fSBenjamin Tissoires #define REPORT_ID_BUTTONS 3 175*88b5468fSBenjamin Tissoires #define PAD_BUTTON_COUNT 6 176*88b5468fSBenjamin Tissoires #define RDESC_KEYBOARD_OFFSET 148 177*88b5468fSBenjamin Tissoires 178*88b5468fSBenjamin Tissoires static const __u8 fixed_rdesc_pad[] = { 179*88b5468fSBenjamin Tissoires /* Copy of pen descriptor to avoid losing functionality */ 180*88b5468fSBenjamin Tissoires UsagePage_Digitizers 181*88b5468fSBenjamin Tissoires Usage_Dig_Pen 182*88b5468fSBenjamin Tissoires CollectionApplication( 183*88b5468fSBenjamin Tissoires ReportId(7) 184*88b5468fSBenjamin Tissoires Usage_Dig_Stylus 185*88b5468fSBenjamin Tissoires CollectionPhysical( 186*88b5468fSBenjamin Tissoires Usage_Dig_TipSwitch 187*88b5468fSBenjamin Tissoires Usage_Dig_BarrelSwitch 188*88b5468fSBenjamin Tissoires Usage_Dig_Eraser 189*88b5468fSBenjamin Tissoires Usage_Dig_Invert 190*88b5468fSBenjamin Tissoires Usage_Dig_InRange 191*88b5468fSBenjamin Tissoires LogicalMinimum_i8(0) 192*88b5468fSBenjamin Tissoires LogicalMaximum_i8(1) 193*88b5468fSBenjamin Tissoires ReportSize(1) 194*88b5468fSBenjamin Tissoires ReportCount(5) 195*88b5468fSBenjamin Tissoires Input(Var|Abs) 196*88b5468fSBenjamin Tissoires ReportCount(3) 197*88b5468fSBenjamin Tissoires Input(Const) /* Input (Const, Var, Abs) */ 198*88b5468fSBenjamin Tissoires UsagePage_GenericDesktop 199*88b5468fSBenjamin Tissoires Usage_GD_X 200*88b5468fSBenjamin Tissoires LogicalMinimum_i16(0) 201*88b5468fSBenjamin Tissoires LogicalMaximum_i16(22352) 202*88b5468fSBenjamin Tissoires UnitExponent(-3) 203*88b5468fSBenjamin Tissoires Unit(in) /* (EnglishLinear: in) */ 204*88b5468fSBenjamin Tissoires PhysicalMinimum_i16(0) 205*88b5468fSBenjamin Tissoires PhysicalMaximum_i16(22352) 206*88b5468fSBenjamin Tissoires ReportSize(16) 207*88b5468fSBenjamin Tissoires ReportCount(1) 208*88b5468fSBenjamin Tissoires Input(Var|Abs) 209*88b5468fSBenjamin Tissoires Usage_GD_Y 210*88b5468fSBenjamin Tissoires LogicalMinimum_i16(0) 211*88b5468fSBenjamin Tissoires LogicalMaximum_i16(13970) 212*88b5468fSBenjamin Tissoires UnitExponent(-3) 213*88b5468fSBenjamin Tissoires Unit(in) /* (EnglishLinear: in) */ 214*88b5468fSBenjamin Tissoires PhysicalMinimum_i16(0) 215*88b5468fSBenjamin Tissoires PhysicalMaximum_i16(13970) 216*88b5468fSBenjamin Tissoires ReportSize(16) 217*88b5468fSBenjamin Tissoires ReportCount(1) 218*88b5468fSBenjamin Tissoires Input(Var|Abs) 219*88b5468fSBenjamin Tissoires UsagePage_Digitizers 220*88b5468fSBenjamin Tissoires Usage_Dig_TipPressure 221*88b5468fSBenjamin Tissoires LogicalMinimum_i16(0) 222*88b5468fSBenjamin Tissoires LogicalMaximum_i16(8191) 223*88b5468fSBenjamin Tissoires ReportSize(16) 224*88b5468fSBenjamin Tissoires ReportCount(1) 225*88b5468fSBenjamin Tissoires Input(Var|Abs) 226*88b5468fSBenjamin Tissoires ) 227*88b5468fSBenjamin Tissoires ) 228*88b5468fSBenjamin Tissoires 229*88b5468fSBenjamin Tissoires /* FIXES BEGIN */ 230*88b5468fSBenjamin Tissoires UsagePage_GenericDesktop 231*88b5468fSBenjamin Tissoires Usage_GD_Keypad 232*88b5468fSBenjamin Tissoires CollectionApplication( 233*88b5468fSBenjamin Tissoires ReportId(REPORT_ID_BUTTONS) /* Retain original ID on byte 0 */ 234*88b5468fSBenjamin Tissoires ReportCount(1) 235*88b5468fSBenjamin Tissoires ReportSize(REPORT_SIZE_PAD) 236*88b5468fSBenjamin Tissoires UsagePage_Digitizers 237*88b5468fSBenjamin Tissoires Usage_Dig_TabletFunctionKeys 238*88b5468fSBenjamin Tissoires CollectionPhysical( 239*88b5468fSBenjamin Tissoires /* Byte 1: Dial state */ 240*88b5468fSBenjamin Tissoires UsagePage_GenericDesktop 241*88b5468fSBenjamin Tissoires Usage_GD_Dial 242*88b5468fSBenjamin Tissoires LogicalMinimum_i8(-1) 243*88b5468fSBenjamin Tissoires LogicalMaximum_i8(1) 244*88b5468fSBenjamin Tissoires ReportCount(1) 245*88b5468fSBenjamin Tissoires ReportSize(REPORT_SIZE_PAD) 246*88b5468fSBenjamin Tissoires Input(Var|Rel) 247*88b5468fSBenjamin Tissoires /* Byte 2: Button state */ 248*88b5468fSBenjamin Tissoires UsagePage_Button 249*88b5468fSBenjamin Tissoires ReportSize(1) 250*88b5468fSBenjamin Tissoires ReportCount(PAD_BUTTON_COUNT) 251*88b5468fSBenjamin Tissoires UsageMinimum_i8(0x01) 252*88b5468fSBenjamin Tissoires UsageMaximum_i8(PAD_BUTTON_COUNT) /* Number of buttons */ 253*88b5468fSBenjamin Tissoires LogicalMinimum_i8(0x0) 254*88b5468fSBenjamin Tissoires LogicalMaximum_i8(0x1) 255*88b5468fSBenjamin Tissoires Input(Var|Abs) 256*88b5468fSBenjamin Tissoires /* Byte 3: Exists to be tablet pad */ 257*88b5468fSBenjamin Tissoires UsagePage_Digitizers 258*88b5468fSBenjamin Tissoires Usage_Dig_BarrelSwitch 259*88b5468fSBenjamin Tissoires ReportCount(1) 260*88b5468fSBenjamin Tissoires ReportSize(1) 261*88b5468fSBenjamin Tissoires Input(Var|Abs) 262*88b5468fSBenjamin Tissoires ReportCount(7) /* Padding, to fill full report space */ 263*88b5468fSBenjamin Tissoires Input(Const) 264*88b5468fSBenjamin Tissoires /* Byte 4/5: Exists to be a tablet pad */ 265*88b5468fSBenjamin Tissoires UsagePage_GenericDesktop 266*88b5468fSBenjamin Tissoires Usage_GD_X 267*88b5468fSBenjamin Tissoires Usage_GD_Y 268*88b5468fSBenjamin Tissoires ReportCount(2) 269*88b5468fSBenjamin Tissoires ReportSize(8) 270*88b5468fSBenjamin Tissoires Input(Var|Abs) 271*88b5468fSBenjamin Tissoires /* Bytes 6/7: Padding, to match original length */ 272*88b5468fSBenjamin Tissoires ReportCount(2) 273*88b5468fSBenjamin Tissoires ReportSize(8) 274*88b5468fSBenjamin Tissoires Input(Const) 275*88b5468fSBenjamin Tissoires ) 276*88b5468fSBenjamin Tissoires FixedSizeVendorReport(RDESC_SIZE_PAD) 277*88b5468fSBenjamin Tissoires ) 278*88b5468fSBenjamin Tissoires }; 279*88b5468fSBenjamin Tissoires 280*88b5468fSBenjamin Tissoires SEC(HID_BPF_RDESC_FIXUP) 281*88b5468fSBenjamin Tissoires int BPF_PROG(xppen_deco02_rdesc_fixup, struct hid_bpf_ctx *hctx) 282*88b5468fSBenjamin Tissoires { 283*88b5468fSBenjamin Tissoires __u8 *data = hid_bpf_get_data(hctx, 0, HID_MAX_DESCRIPTOR_SIZE); 284*88b5468fSBenjamin Tissoires 285*88b5468fSBenjamin Tissoires if (!data) 286*88b5468fSBenjamin Tissoires return 0; /* EPERM Check */ 287*88b5468fSBenjamin Tissoires 288*88b5468fSBenjamin Tissoires if (hctx->size == RDESC_SIZE_PAD) { 289*88b5468fSBenjamin Tissoires __builtin_memcpy(data, fixed_rdesc_pad, sizeof(fixed_rdesc_pad)); 290*88b5468fSBenjamin Tissoires return sizeof(fixed_rdesc_pad); 291*88b5468fSBenjamin Tissoires } 292*88b5468fSBenjamin Tissoires 293*88b5468fSBenjamin Tissoires return 0; 294*88b5468fSBenjamin Tissoires } 295*88b5468fSBenjamin Tissoires 296*88b5468fSBenjamin Tissoires SEC(HID_BPF_DEVICE_EVENT) 297*88b5468fSBenjamin Tissoires int BPF_PROG(xppen_deco02_device_event, struct hid_bpf_ctx *hctx) 298*88b5468fSBenjamin Tissoires { 299*88b5468fSBenjamin Tissoires __u8 *data = hid_bpf_get_data(hctx, 0, REPORT_SIZE_PAD); 300*88b5468fSBenjamin Tissoires 301*88b5468fSBenjamin Tissoires if (!data || data[0] != REPORT_ID_BUTTONS) 302*88b5468fSBenjamin Tissoires return 0; /* EPERM or wrong report */ 303*88b5468fSBenjamin Tissoires 304*88b5468fSBenjamin Tissoires __u8 dial_code = 0; 305*88b5468fSBenjamin Tissoires __u8 button_mask = 0; 306*88b5468fSBenjamin Tissoires size_t d; 307*88b5468fSBenjamin Tissoires 308*88b5468fSBenjamin Tissoires /* Start from 2; 0 is report ID, 1 is modifier keys, replaced by dial */ 309*88b5468fSBenjamin Tissoires for (d = 2; d < 8; d++) { 310*88b5468fSBenjamin Tissoires switch (data[d]) { 311*88b5468fSBenjamin Tissoires case 0x2e: 312*88b5468fSBenjamin Tissoires dial_code = 1; 313*88b5468fSBenjamin Tissoires break; 314*88b5468fSBenjamin Tissoires case 0x2d: 315*88b5468fSBenjamin Tissoires dial_code = -1; 316*88b5468fSBenjamin Tissoires break; 317*88b5468fSBenjamin Tissoires /* below are buttons, top to bottom */ 318*88b5468fSBenjamin Tissoires case 0x05: 319*88b5468fSBenjamin Tissoires button_mask |= BIT(0); 320*88b5468fSBenjamin Tissoires break; 321*88b5468fSBenjamin Tissoires case 0x2c: 322*88b5468fSBenjamin Tissoires button_mask |= BIT(1); 323*88b5468fSBenjamin Tissoires break; 324*88b5468fSBenjamin Tissoires case 0x08: 325*88b5468fSBenjamin Tissoires button_mask |= BIT(2); 326*88b5468fSBenjamin Tissoires break; 327*88b5468fSBenjamin Tissoires case 0x0c: 328*88b5468fSBenjamin Tissoires button_mask |= BIT(3); 329*88b5468fSBenjamin Tissoires break; 330*88b5468fSBenjamin Tissoires case 0x1d: 331*88b5468fSBenjamin Tissoires button_mask |= BIT(4); 332*88b5468fSBenjamin Tissoires break; 333*88b5468fSBenjamin Tissoires case 0x16: 334*88b5468fSBenjamin Tissoires button_mask |= BIT(05); 335*88b5468fSBenjamin Tissoires break; 336*88b5468fSBenjamin Tissoires default: 337*88b5468fSBenjamin Tissoires break; 338*88b5468fSBenjamin Tissoires } 339*88b5468fSBenjamin Tissoires } 340*88b5468fSBenjamin Tissoires 341*88b5468fSBenjamin Tissoires __u8 report[8] = { REPORT_ID_BUTTONS, dial_code, button_mask, 0x00 }; 342*88b5468fSBenjamin Tissoires 343*88b5468fSBenjamin Tissoires __builtin_memcpy(data, report, sizeof(report)); 344*88b5468fSBenjamin Tissoires return 0; 345*88b5468fSBenjamin Tissoires } 346*88b5468fSBenjamin Tissoires 347*88b5468fSBenjamin Tissoires HID_BPF_OPS(xppen_deco02) = { 348*88b5468fSBenjamin Tissoires .hid_rdesc_fixup = (void *)xppen_deco02_rdesc_fixup, 349*88b5468fSBenjamin Tissoires .hid_device_event = (void *)xppen_deco02_device_event, 350*88b5468fSBenjamin Tissoires }; 351*88b5468fSBenjamin Tissoires 352*88b5468fSBenjamin Tissoires SEC("syscall") 353*88b5468fSBenjamin Tissoires int probe(struct hid_bpf_probe_args *ctx) 354*88b5468fSBenjamin Tissoires { 355*88b5468fSBenjamin Tissoires ctx->retval = ctx->rdesc_size != RDESC_SIZE_PAD ? -EINVAL : 0; 356*88b5468fSBenjamin Tissoires return 0; 357*88b5468fSBenjamin Tissoires } 358*88b5468fSBenjamin Tissoires 359*88b5468fSBenjamin Tissoires char _license[] SEC("license") = "GPL"; 360