Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'for-6.13/bpf' into for-linus

- improvement of the way hid-bpf coexists with specific drivers (others than
hid-generic) that are already bound to devices (Benjamin Tissoires)

+708 -201
+6 -3
drivers/hid/bpf/hid_bpf_dispatch.c
··· 148 148 } 149 149 EXPORT_SYMBOL_GPL(dispatch_hid_bpf_output_report); 150 150 151 - u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, const u8 *rdesc, unsigned int *size) 151 + const u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, const u8 *rdesc, unsigned int *size) 152 152 { 153 153 int ret; 154 154 struct hid_bpf_ctx_kern ctx_kern = { ··· 183 183 184 184 ignore_bpf: 185 185 kfree(ctx_kern.data); 186 - return kmemdup(rdesc, *size, GFP_KERNEL); 186 + return rdesc; 187 187 } 188 188 EXPORT_SYMBOL_GPL(call_hid_bpf_rdesc_fixup); 189 189 ··· 260 260 261 261 int hid_bpf_reconnect(struct hid_device *hdev) 262 262 { 263 - if (!test_and_set_bit(ffs(HID_STAT_REPROBED), &hdev->status)) 263 + if (!test_and_set_bit(ffs(HID_STAT_REPROBED), &hdev->status)) { 264 + /* trigger call to call_hid_bpf_rdesc_fixup() during the next probe */ 265 + hdev->bpf_rsize = 0; 264 266 return device_reprobe(&hdev->dev); 267 + } 265 268 266 269 return 0; 267 270 }
+1
drivers/hid/bpf/hid_bpf_struct_ops.c
··· 79 79 WRITE_RANGE(hid_device, name, true), 80 80 WRITE_RANGE(hid_device, uniq, true), 81 81 WRITE_RANGE(hid_device, phys, true), 82 + WRITE_RANGE(hid_device, quirks, false), 82 83 }; 83 84 #undef WRITE_RANGE 84 85 const struct btf_type *state = NULL;
+44 -22
drivers/hid/bpf/progs/Huion__Dial-2.bpf.c
··· 214 214 CollectionApplication( 215 215 // -- Byte 0 in report 216 216 ReportId(PAD_REPORT_ID) 217 - LogicalRange_i8(0, 1) 217 + LogicalMaximum_i8(0) 218 + LogicalMaximum_i8(1) 218 219 UsagePage_Digitizers 219 220 Usage_Dig_TabletFunctionKeys 220 221 CollectionPhysical( ··· 235 234 Input(Var|Abs) 236 235 // Byte 4 in report is the dial 237 236 Usage_GD_Wheel 238 - LogicalRange_i8(-1, 1) 237 + LogicalMinimum_i8(-1) 238 + LogicalMaximum_i8(1) 239 239 ReportCount(1) 240 240 ReportSize(8) 241 241 Input(Var|Rel) 242 242 // Byte 5 is the button state 243 243 UsagePage_Button 244 - UsageRange_i8(0x01, 0x8) 245 - LogicalRange_i8(0x0, 0x1) 244 + UsageMinimum_i8(0x01) 245 + UsageMaximum_i8(0x08) 246 + LogicalMinimum_i8(0x0) 247 + LogicalMaximum_i8(0x1) 246 248 ReportCount(7) 247 249 ReportSize(1) 248 250 Input(Var|Abs) ··· 269 265 Usage_Dig_TipSwitch 270 266 Usage_Dig_BarrelSwitch 271 267 Usage_Dig_SecondaryBarrelSwitch // maps eraser to BTN_STYLUS2 272 - LogicalRange_i8(0, 1) 268 + LogicalMinimum_i8(0) 269 + LogicalMaximum_i8(1) 273 270 ReportSize(1) 274 271 ReportCount(3) 275 272 Input(Var|Abs) ··· 285 280 UsagePage_GenericDesktop 286 281 Unit(cm) 287 282 UnitExponent(-1) 288 - PhysicalRange_i16(0, 266) 289 - LogicalRange_i16(0, 32767) 283 + PhysicalMinimum_i16(0) 284 + PhysicalMaximum_i16(266) 285 + LogicalMinimum_i16(0) 286 + LogicalMaximum_i16(32767) 290 287 Usage_GD_X 291 288 Input(Var|Abs) // Bytes 2+3 292 - PhysicalRange_i16(0, 166) 293 - LogicalRange_i16(0, 32767) 289 + PhysicalMinimum_i16(0) 290 + PhysicalMaximum_i16(166) 291 + LogicalMinimum_i16(0) 292 + LogicalMaximum_i16(32767) 294 293 Usage_GD_Y 295 294 Input(Var|Abs) // Bytes 4+5 296 295 ) 297 296 UsagePage_Digitizers 298 297 Usage_Dig_TipPressure 299 - LogicalRange_i16(0, 8191) 298 + LogicalMinimum_i16(0) 299 + LogicalMaximum_i16(8191) 300 300 Input(Var|Abs) // Byte 6+7 301 301 ReportSize(8) 302 302 ReportCount(2) 303 - LogicalRange_i8(-60, 60) 303 + LogicalMinimum_i8(-60) 304 + LogicalMaximum_i8(60) 304 305 Usage_Dig_XTilt 305 306 Usage_Dig_YTilt 306 307 Input(Var|Abs) // Byte 8+9 ··· 324 313 Usage_Dig_Pen 325 314 CollectionPhysical( 326 315 // Byte 1 are the buttons 327 - LogicalRange_i8(0, 1) 316 + LogicalMinimum_i8(0) 317 + LogicalMaximum_i8(1) 328 318 ReportSize(1) 329 319 Usage_Dig_TipSwitch 330 320 Usage_Dig_BarrelSwitch ··· 345 333 UnitExponent(-1) 346 334 // Note: reported logical range differs 347 335 // from the pen report ID for x and y 348 - LogicalRange_i16(0, 53340) 349 - PhysicalRange_i16(0, 266) 336 + LogicalMinimum_i16(0) 337 + LogicalMaximum_i16(53340) 338 + PhysicalMinimum_i16(0) 339 + PhysicalMaximum_i16(266) 350 340 // Bytes 2/3 in report 351 341 Usage_GD_X 352 342 Input(Var|Abs) 353 - LogicalRange_i16(0, 33340) 354 - PhysicalRange_i16(0, 166) 343 + LogicalMinimum_i16(0) 344 + LogicalMaximum_i16(33340) 345 + PhysicalMinimum_i16(0) 346 + PhysicalMaximum_i16(166) 355 347 // Bytes 4/5 in report 356 348 Usage_GD_Y 357 349 Input(Var|Abs) 358 350 ) 359 351 // Bytes 6/7 in report 360 - LogicalRange_i16(0, 8191) 352 + LogicalMinimum_i16(0) 353 + LogicalMaximum_i16(8191) 361 354 Usage_Dig_TipPressure 362 355 Input(Var|Abs) 363 356 // Bytes 8/9 in report 364 357 ReportCount(1) // Padding 365 358 Input(Const) 366 - LogicalRange_i8(-60, 60) 359 + LogicalMinimum_i8(-60) 360 + LogicalMaximum_i8(60) 367 361 // Byte 10 in report 368 362 Usage_Dig_XTilt 369 363 // Byte 11 in report ··· 384 366 CollectionApplication( 385 367 // Byte 0 386 368 ReportId(PAD_REPORT_ID) 387 - LogicalRange_i8(0, 1) 369 + LogicalMinimum_i8(0) 370 + LogicalMaximum_i8(1) 388 371 UsagePage_Digitizers 389 372 Usage_Dig_TabletFunctionKeys 390 373 CollectionPhysical( ··· 405 386 Input(Var|Abs) 406 387 // Byte 4 is the button state 407 388 UsagePage_Button 408 - UsageRange_i8(0x01, 0x8) 409 - LogicalRange_i8(0x0, 0x1) 389 + UsageMinimum_i8(0x1) 390 + UsageMaximum_i8(0x8) 391 + LogicalMinimum_i8(0x0) 392 + LogicalMaximum_i8(0x1) 410 393 ReportCount(8) 411 394 ReportSize(1) 412 395 Input(Var|Abs) 413 396 // Byte 5 is the top dial 414 397 UsagePage_GenericDesktop 415 398 Usage_GD_Wheel 416 - LogicalRange_i8(-1, 1) 399 + LogicalMinimum_i8(-1) 400 + LogicalMaximum_i8(1) 417 401 ReportCount(1) 418 402 ReportSize(8) 419 403 Input(Var|Rel)
+40 -20
drivers/hid/bpf/progs/Huion__Inspiroy-2-S.bpf.c
··· 170 170 CollectionApplication( 171 171 // -- Byte 0 in report 172 172 ReportId(PAD_REPORT_ID) 173 - LogicalRange_i8(0, 1) 173 + LogicalMinimum_i8(0) 174 + LogicalMaximum_i8(1) 174 175 UsagePage_Digitizers 175 176 Usage_Dig_TabletFunctionKeys 176 177 CollectionPhysical( ··· 191 190 Input(Var|Abs) 192 191 // Byte 4 in report is the wheel 193 192 Usage_GD_Wheel 194 - LogicalRange_i8(-1, 1) 193 + LogicalMinimum_i8(-1) 194 + LogicalMaximum_i8(1) 195 195 ReportCount(1) 196 196 ReportSize(8) 197 197 Input(Var|Rel) 198 198 // Byte 5 is the button state 199 199 UsagePage_Button 200 - UsageRange_i8(0x01, 0x6) 201 - LogicalRange_i8(0x01, 0x6) 200 + UsageMinimum_i8(0x1) 201 + UsageMaximum_i8(0x6) 202 + LogicalMinimum_i8(0x1) 203 + LogicalMaximum_i8(0x6) 202 204 ReportCount(1) 203 205 ReportSize(8) 204 206 Input(Arr|Abs) ··· 223 219 Usage_Dig_TipSwitch 224 220 Usage_Dig_BarrelSwitch 225 221 Usage_Dig_SecondaryBarrelSwitch // maps eraser to BTN_STYLUS2 226 - LogicalRange_i8(0, 1) 222 + LogicalMinimum_i8(0) 223 + LogicalMaximum_i8(1) 227 224 ReportSize(1) 228 225 ReportCount(3) 229 226 Input(Var|Abs) ··· 239 234 UsagePage_GenericDesktop 240 235 Unit(cm) 241 236 UnitExponent(-1) 242 - PhysicalRange_i16(0, 160) 243 - LogicalRange_i16(0, 32767) 237 + PhysicalMinimum_i16(0) 238 + PhysicalMaximum_i16(160) 239 + LogicalMinimum_i16(0) 240 + LogicalMaximum_i16(32767) 244 241 Usage_GD_X 245 242 Input(Var|Abs) // Bytes 2+3 246 - PhysicalRange_i16(0, 100) 247 - LogicalRange_i16(0, 32767) 243 + PhysicalMinimum_i16(0) 244 + PhysicalMaximum_i16(100) 245 + LogicalMinimum_i16(0) 246 + LogicalMaximum_i16(32767) 248 247 Usage_GD_Y 249 248 Input(Var|Abs) // Bytes 4+5 250 249 ) 251 250 UsagePage_Digitizers 252 251 Usage_Dig_TipPressure 253 - LogicalRange_i16(0, 8191) 252 + LogicalMinimum_i16(0) 253 + LogicalMaximum_i16(8191) 254 254 Input(Var|Abs) // Byte 6+7 255 255 // Two bytes padding so we don't need to change the report at all 256 256 ReportSize(8) ··· 275 265 Usage_Dig_Pen 276 266 CollectionPhysical( 277 267 // Byte 1 are the buttons 278 - LogicalRange_i8(0, 1) 268 + LogicalMinimum_i8(0) 269 + LogicalMaximum_i8(1) 279 270 ReportSize(1) 280 271 Usage_Dig_TipSwitch 281 272 Usage_Dig_BarrelSwitch ··· 296 285 UnitExponent(-1) 297 286 // Note: reported logical range differs 298 287 // from the pen report ID for x and y 299 - LogicalRange_i16(0, 32000) 300 - PhysicalRange_i16(0, 160) 288 + LogicalMinimum_i16(0) 289 + LogicalMaximum_i16(32000) 290 + PhysicalMinimum_i16(0) 291 + PhysicalMaximum_i16(160) 301 292 // Bytes 2/3 in report 302 293 Usage_GD_X 303 294 Input(Var|Abs) 304 - LogicalRange_i16(0, 20000) 305 - PhysicalRange_i16(0, 100) 295 + LogicalMinimum_i16(0) 296 + LogicalMaximum_i16(20000) 297 + PhysicalMinimum_i16(0) 298 + PhysicalMaximum_i16(100) 306 299 // Bytes 4/5 in report 307 300 Usage_GD_Y 308 301 Input(Var|Abs) 309 302 ) 310 303 // Bytes 6/7 in report 311 - LogicalRange_i16(0, 8192) 304 + LogicalMinimum_i16(0) 305 + LogicalMaximum_i16(8192) 312 306 Usage_Dig_TipPressure 313 307 Input(Var|Abs) 314 308 ) ··· 323 307 CollectionApplication( 324 308 // Byte 0 325 309 ReportId(PAD_REPORT_ID) 326 - LogicalRange_i8(0, 1) 310 + LogicalMinimum_i8(0) 311 + LogicalMaximum_i8(1) 327 312 UsagePage_Digitizers 328 313 Usage_Dig_TabletFunctionKeys 329 314 CollectionPhysical( ··· 344 327 Input(Var|Abs) 345 328 // Byte 4 is the button state 346 329 UsagePage_Button 347 - UsageRange_i8(0x01, 0x6) 348 - LogicalRange_i8(0x0, 0x1) 330 + UsageMinimum_i8(0x1) 331 + UsageMaximum_i8(0x6) 332 + LogicalMinimum_i8(0x0) 333 + LogicalMaximum_i8(0x1) 349 334 ReportCount(6) 350 335 ReportSize(1) 351 336 Input(Var|Abs) ··· 356 337 // Byte 5 is the wheel 357 338 UsagePage_GenericDesktop 358 339 Usage_GD_Wheel 359 - LogicalRange_i8(-1, 1) 340 + LogicalMinimum_i8(-1) 341 + LogicalMaximum_i8(1) 360 342 ReportCount(1) 361 343 ReportSize(8) 362 344 Input(Var|Rel)
+154
drivers/hid/bpf/progs/Mistel__MD770.bpf.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + /* Copyright (c) 2024 Tatsuyuki Ishi 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_HOLTEK 0x04D9 11 + #define PID_MD770 0x0339 12 + #define RDESC_SIZE 203 13 + 14 + HID_BPF_CONFIG( 15 + HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_HOLTEK, PID_MD770) 16 + ); 17 + 18 + /* 19 + * The Mistel MD770 keyboard reports the first 6 simultaneous key presses 20 + * through the first interface, and anything beyond that through a second 21 + * interface. Unfortunately, the second interface's report descriptor has an 22 + * error, causing events to be malformed and ignored. This HID-BPF driver 23 + * fixes the descriptor to allow NKRO to work again. 24 + * 25 + * For reference, this is the original report descriptor: 26 + * 27 + * 0x05, 0x01, // Usage Page (Generic Desktop) 0 28 + * 0x09, 0x80, // Usage (System Control) 2 29 + * 0xa1, 0x01, // Collection (Application) 4 30 + * 0x85, 0x01, // Report ID (1) 6 31 + * 0x19, 0x81, // Usage Minimum (129) 8 32 + * 0x29, 0x83, // Usage Maximum (131) 10 33 + * 0x15, 0x00, // Logical Minimum (0) 12 34 + * 0x25, 0x01, // Logical Maximum (1) 14 35 + * 0x95, 0x03, // Report Count (3) 16 36 + * 0x75, 0x01, // Report Size (1) 18 37 + * 0x81, 0x02, // Input (Data,Var,Abs) 20 38 + * 0x95, 0x01, // Report Count (1) 22 39 + * 0x75, 0x05, // Report Size (5) 24 40 + * 0x81, 0x01, // Input (Cnst,Arr,Abs) 26 41 + * 0xc0, // End Collection 28 42 + * 0x05, 0x0c, // Usage Page (Consumer Devices) 29 43 + * 0x09, 0x01, // Usage (Consumer Control) 31 44 + * 0xa1, 0x01, // Collection (Application) 33 45 + * 0x85, 0x02, // Report ID (2) 35 46 + * 0x15, 0x00, // Logical Minimum (0) 37 47 + * 0x25, 0x01, // Logical Maximum (1) 39 48 + * 0x95, 0x12, // Report Count (18) 41 49 + * 0x75, 0x01, // Report Size (1) 43 50 + * 0x0a, 0x83, 0x01, // Usage (AL Consumer Control Config) 45 51 + * 0x0a, 0x8a, 0x01, // Usage (AL Email Reader) 48 52 + * 0x0a, 0x92, 0x01, // Usage (AL Calculator) 51 53 + * 0x0a, 0x94, 0x01, // Usage (AL Local Machine Browser) 54 54 + * 0x09, 0xcd, // Usage (Play/Pause) 57 55 + * 0x09, 0xb7, // Usage (Stop) 59 56 + * 0x09, 0xb6, // Usage (Scan Previous Track) 61 57 + * 0x09, 0xb5, // Usage (Scan Next Track) 63 58 + * 0x09, 0xe2, // Usage (Mute) 65 59 + * 0x09, 0xea, // Usage (Volume Down) 67 60 + * 0x09, 0xe9, // Usage (Volume Up) 69 61 + * 0x0a, 0x21, 0x02, // Usage (AC Search) 71 62 + * 0x0a, 0x23, 0x02, // Usage (AC Home) 74 63 + * 0x0a, 0x24, 0x02, // Usage (AC Back) 77 64 + * 0x0a, 0x25, 0x02, // Usage (AC Forward) 80 65 + * 0x0a, 0x26, 0x02, // Usage (AC Stop) 83 66 + * 0x0a, 0x27, 0x02, // Usage (AC Refresh) 86 67 + * 0x0a, 0x2a, 0x02, // Usage (AC Bookmarks) 89 68 + * 0x81, 0x02, // Input (Data,Var,Abs) 92 69 + * 0x95, 0x01, // Report Count (1) 94 70 + * 0x75, 0x0e, // Report Size (14) 96 71 + * 0x81, 0x01, // Input (Cnst,Arr,Abs) 98 72 + * 0xc0, // End Collection 100 73 + * 0x05, 0x01, // Usage Page (Generic Desktop) 101 74 + * 0x09, 0x02, // Usage (Mouse) 103 75 + * 0xa1, 0x01, // Collection (Application) 105 76 + * 0x09, 0x01, // Usage (Pointer) 107 77 + * 0xa1, 0x00, // Collection (Physical) 109 78 + * 0x85, 0x03, // Report ID (3) 111 79 + * 0x05, 0x09, // Usage Page (Button) 113 80 + * 0x19, 0x01, // Usage Minimum (1) 115 81 + * 0x29, 0x08, // Usage Maximum (8) 117 82 + * 0x15, 0x00, // Logical Minimum (0) 119 83 + * 0x25, 0x01, // Logical Maximum (1) 121 84 + * 0x75, 0x01, // Report Size (1) 123 85 + * 0x95, 0x08, // Report Count (8) 125 86 + * 0x81, 0x02, // Input (Data,Var,Abs) 127 87 + * 0x05, 0x01, // Usage Page (Generic Desktop) 129 88 + * 0x09, 0x30, // Usage (X) 131 89 + * 0x09, 0x31, // Usage (Y) 133 90 + * 0x16, 0x01, 0x80, // Logical Minimum (-32767) 135 91 + * 0x26, 0xff, 0x7f, // Logical Maximum (32767) 138 92 + * 0x75, 0x10, // Report Size (16) 141 93 + * 0x95, 0x02, // Report Count (2) 143 94 + * 0x81, 0x06, // Input (Data,Var,Rel) 145 95 + * 0x09, 0x38, // Usage (Wheel) 147 96 + * 0x15, 0x81, // Logical Minimum (-127) 149 97 + * 0x25, 0x7f, // Logical Maximum (127) 151 98 + * 0x75, 0x08, // Report Size (8) 153 99 + * 0x95, 0x01, // Report Count (1) 155 100 + * 0x81, 0x06, // Input (Data,Var,Rel) 157 101 + * 0x05, 0x0c, // Usage Page (Consumer Devices) 159 102 + * 0x0a, 0x38, 0x02, // Usage (AC Pan) 161 103 + * 0x95, 0x01, // Report Count (1) 164 104 + * 0x81, 0x06, // Input (Data,Var,Rel) 166 105 + * 0xc0, // End Collection 168 106 + * 0xc0, // End Collection 169 107 + * 0x05, 0x01, // Usage Page (Generic Desktop) 170 108 + * 0x09, 0x06, // Usage (Keyboard) 172 109 + * 0xa1, 0x01, // Collection (Application) 174 110 + * 0x85, 0x04, // Report ID (4) 176 111 + * 0x05, 0x07, // Usage Page (Keyboard) 178 112 + * 0x95, 0x01, // Report Count (1) 180 113 + * 0x75, 0x08, // Report Size (8) 182 114 + * 0x81, 0x03, // Input (Cnst,Var,Abs) 184 115 + * 0x95, 0xe8, // Report Count (232) 186 116 + * 0x75, 0x01, // Report Size (1) 188 117 + * 0x15, 0x00, // Logical Minimum (0) 190 118 + * 0x25, 0x01, // Logical Maximum (1) 192 119 + * 0x05, 0x07, // Usage Page (Keyboard) 194 120 + * 0x19, 0x00, // Usage Minimum (0) 196 121 + * 0x29, 0xe7, // Usage Maximum (231) 198 122 + * 0x81, 0x00, // Input (Data,Arr,Abs) 200 <- change to 0x81, 0x02 (Data,Var,Abs) 123 + * 0xc0, // End Collection 202 124 + */ 125 + 126 + SEC(HID_BPF_RDESC_FIXUP) 127 + int BPF_PROG(hid_rdesc_fixup_mistel_md770, struct hid_bpf_ctx *hctx) 128 + { 129 + __u8 *data = hid_bpf_get_data(hctx, 0, HID_MAX_DESCRIPTOR_SIZE); 130 + 131 + if (!data) 132 + return 0; /* EPERM check */ 133 + 134 + if (data[201] == 0x00) 135 + data[201] = 0x02; 136 + 137 + return 0; 138 + } 139 + 140 + HID_BPF_OPS(mistel_md770) = { 141 + .hid_rdesc_fixup = (void *)hid_rdesc_fixup_mistel_md770, 142 + }; 143 + 144 + SEC("syscall") 145 + int probe(struct hid_bpf_probe_args *ctx) 146 + { 147 + ctx->retval = ctx->rdesc_size != RDESC_SIZE; 148 + if (ctx->retval) 149 + ctx->retval = -EINVAL; 150 + 151 + return 0; 152 + } 153 + 154 + char _license[] SEC("license") = "GPL";
+148
drivers/hid/bpf/progs/Rapoo__M50-Plus-Silent.bpf.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Copyright (c) 2024 José Expósito 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_RAPOO 0x24AE 11 + #define PID_M50 0x2015 12 + #define RDESC_SIZE 186 13 + 14 + HID_BPF_CONFIG( 15 + HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, VID_RAPOO, PID_M50) 16 + ); 17 + 18 + /* 19 + * The Rapoo M50 Plus Silent mouse has 2 side buttons in addition to the left, 20 + * right and middle buttons. However, its original HID descriptor has a Usage 21 + * Maximum of 3, preventing the side buttons to work. This HID-BPF driver 22 + * changes that usage to 5. 23 + * 24 + * For reference, this is the original report descriptor: 25 + * 26 + * 0x05, 0x01, // Usage Page (Generic Desktop) 0 27 + * 0x09, 0x02, // Usage (Mouse) 2 28 + * 0xa1, 0x01, // Collection (Application) 4 29 + * 0x85, 0x01, // Report ID (1) 6 30 + * 0x09, 0x01, // Usage (Pointer) 8 31 + * 0xa1, 0x00, // Collection (Physical) 10 32 + * 0x05, 0x09, // Usage Page (Button) 12 33 + * 0x19, 0x01, // Usage Minimum (1) 14 34 + * 0x29, 0x03, // Usage Maximum (3) 16 <- change to 0x05 35 + * 0x15, 0x00, // Logical Minimum (0) 18 36 + * 0x25, 0x01, // Logical Maximum (1) 20 37 + * 0x75, 0x01, // Report Size (1) 22 38 + * 0x95, 0x05, // Report Count (5) 24 39 + * 0x81, 0x02, // Input (Data,Var,Abs) 26 40 + * 0x75, 0x03, // Report Size (3) 28 41 + * 0x95, 0x01, // Report Count (1) 30 42 + * 0x81, 0x01, // Input (Cnst,Arr,Abs) 32 43 + * 0x05, 0x01, // Usage Page (Generic Desktop) 34 44 + * 0x09, 0x30, // Usage (X) 36 45 + * 0x09, 0x31, // Usage (Y) 38 46 + * 0x16, 0x01, 0x80, // Logical Minimum (-32767) 40 47 + * 0x26, 0xff, 0x7f, // Logical Maximum (32767) 43 48 + * 0x75, 0x10, // Report Size (16) 46 49 + * 0x95, 0x02, // Report Count (2) 48 50 + * 0x81, 0x06, // Input (Data,Var,Rel) 50 51 + * 0x09, 0x38, // Usage (Wheel) 52 52 + * 0x15, 0x81, // Logical Minimum (-127) 54 53 + * 0x25, 0x7f, // Logical Maximum (127) 56 54 + * 0x75, 0x08, // Report Size (8) 58 55 + * 0x95, 0x01, // Report Count (1) 60 56 + * 0x81, 0x06, // Input (Data,Var,Rel) 62 57 + * 0xc0, // End Collection 64 58 + * 0xc0, // End Collection 65 59 + * 0x05, 0x0c, // Usage Page (Consumer Devices) 66 60 + * 0x09, 0x01, // Usage (Consumer Control) 68 61 + * 0xa1, 0x01, // Collection (Application) 70 62 + * 0x85, 0x02, // Report ID (2) 72 63 + * 0x75, 0x10, // Report Size (16) 74 64 + * 0x95, 0x01, // Report Count (1) 76 65 + * 0x15, 0x01, // Logical Minimum (1) 78 66 + * 0x26, 0x8c, 0x02, // Logical Maximum (652) 80 67 + * 0x19, 0x01, // Usage Minimum (1) 83 68 + * 0x2a, 0x8c, 0x02, // Usage Maximum (652) 85 69 + * 0x81, 0x00, // Input (Data,Arr,Abs) 88 70 + * 0xc0, // End Collection 90 71 + * 0x05, 0x01, // Usage Page (Generic Desktop) 91 72 + * 0x09, 0x80, // Usage (System Control) 93 73 + * 0xa1, 0x01, // Collection (Application) 95 74 + * 0x85, 0x03, // Report ID (3) 97 75 + * 0x09, 0x82, // Usage (System Sleep) 99 76 + * 0x09, 0x81, // Usage (System Power Down) 101 77 + * 0x09, 0x83, // Usage (System Wake Up) 103 78 + * 0x15, 0x00, // Logical Minimum (0) 105 79 + * 0x25, 0x01, // Logical Maximum (1) 107 80 + * 0x19, 0x01, // Usage Minimum (1) 109 81 + * 0x29, 0x03, // Usage Maximum (3) 111 82 + * 0x75, 0x01, // Report Size (1) 113 83 + * 0x95, 0x03, // Report Count (3) 115 84 + * 0x81, 0x02, // Input (Data,Var,Abs) 117 85 + * 0x95, 0x05, // Report Count (5) 119 86 + * 0x81, 0x01, // Input (Cnst,Arr,Abs) 121 87 + * 0xc0, // End Collection 123 88 + * 0x05, 0x01, // Usage Page (Generic Desktop) 124 89 + * 0x09, 0x00, // Usage (Undefined) 126 90 + * 0xa1, 0x01, // Collection (Application) 128 91 + * 0x85, 0x05, // Report ID (5) 130 92 + * 0x06, 0x00, 0xff, // Usage Page (Vendor Defined Page 1) 132 93 + * 0x09, 0x01, // Usage (Vendor Usage 1) 135 94 + * 0x15, 0x81, // Logical Minimum (-127) 137 95 + * 0x25, 0x7f, // Logical Maximum (127) 139 96 + * 0x75, 0x08, // Report Size (8) 141 97 + * 0x95, 0x07, // Report Count (7) 143 98 + * 0xb1, 0x02, // Feature (Data,Var,Abs) 145 99 + * 0xc0, // End Collection 147 100 + * 0x06, 0x00, 0xff, // Usage Page (Vendor Defined Page 1) 148 101 + * 0x09, 0x0e, // Usage (Vendor Usage 0x0e) 151 102 + * 0xa1, 0x01, // Collection (Application) 153 103 + * 0x85, 0xba, // Report ID (186) 155 104 + * 0x95, 0x1f, // Report Count (31) 157 105 + * 0x75, 0x08, // Report Size (8) 159 106 + * 0x26, 0xff, 0x00, // Logical Maximum (255) 161 107 + * 0x15, 0x00, // Logical Minimum (0) 164 108 + * 0x09, 0x01, // Usage (Vendor Usage 1) 166 109 + * 0x91, 0x02, // Output (Data,Var,Abs) 168 110 + * 0x85, 0xba, // Report ID (186) 170 111 + * 0x95, 0x1f, // Report Count (31) 172 112 + * 0x75, 0x08, // Report Size (8) 174 113 + * 0x26, 0xff, 0x00, // Logical Maximum (255) 176 114 + * 0x15, 0x00, // Logical Minimum (0) 179 115 + * 0x09, 0x01, // Usage (Vendor Usage 1) 181 116 + * 0x81, 0x02, // Input (Data,Var,Abs) 183 117 + * 0xc0, // End Collection 185 118 + */ 119 + 120 + SEC(HID_BPF_RDESC_FIXUP) 121 + int BPF_PROG(hid_rdesc_fixup_rapoo_m50, struct hid_bpf_ctx *hctx) 122 + { 123 + __u8 *data = hid_bpf_get_data(hctx, 0, HID_MAX_DESCRIPTOR_SIZE); 124 + 125 + if (!data) 126 + return 0; /* EPERM check */ 127 + 128 + if (data[17] == 0x03) 129 + data[17] = 0x05; 130 + 131 + return 0; 132 + } 133 + 134 + HID_BPF_OPS(rapoo_m50) = { 135 + .hid_rdesc_fixup = (void *)hid_rdesc_fixup_rapoo_m50, 136 + }; 137 + 138 + SEC("syscall") 139 + int probe(struct hid_bpf_probe_args *ctx) 140 + { 141 + ctx->retval = ctx->rdesc_size != RDESC_SIZE; 142 + if (ctx->retval) 143 + ctx->retval = -EINVAL; 144 + 145 + return 0; 146 + } 147 + 148 + char _license[] SEC("license") = "GPL";
+27 -9
drivers/hid/bpf/progs/hid_report_helpers.h
··· 52 52 * Usage_GD_Keyboard 53 53 * CollectionApplication( ← Open the collection 54 54 * ReportId(3) 55 - * LogicalRange_i8(0, 1) 55 + * LogicalMinimum_i8(0) 56 + * LogicalMaximum_i8(1) 56 57 * // other fields 57 58 * ) ← End EndCollection 58 59 * ··· 75 74 #define Arr 0x0 76 75 #define Abs 0x0 77 76 #define Rel 0x4 77 + #define Null 0x40 78 + #define Buff 0x0100 78 79 79 80 /* Use like this: Input(Var|Abs) */ 80 81 #define Input(i_) 0x081, i8(i_), 81 82 #define Output(i_) 0x091, i8(i_), 82 83 #define Feature(i_) 0x0b1, i8(i_), 83 84 85 + #define Input_i16(i_) 0x082, LE16(i_), 86 + #define Output_i16(i_) 0x092, LE16(i_), 87 + #define Feature_i16(i_) 0x0b2, LE16(i_), 88 + 84 89 #define ReportId(id_) 0x85, i8(id_), 85 90 #define ReportSize(sz_) 0x75, i8(sz_), 86 91 #define ReportCount(cnt_) 0x95, i8(cnt_), 87 92 88 - #define LogicalRange_i8(min_, max_) 0x15, i8(min_), 0x25, i8(max_), 89 - #define LogicalRange_i16(min_, max_) 0x16, LE16(min_), 0x26, LE16(max_), 90 - #define LogicalRange_i32(min_, max_) 0x17, LE32(min_), 0x27, LE32(max_), 93 + #define LogicalMinimum_i8(min_) 0x15, i8(min_), 94 + #define LogicalMinimum_i16(min_) 0x16, LE16(min_), 95 + #define LogicalMinimum_i32(min_) 0x17, LE32(min_), 91 96 92 - #define PhysicalRange_i8(min_, max_) 0x35, i8(min_), 0x45, i8(max_), 93 - #define PhysicalRange_i16(min_, max_) 0x36, LE16(min_), 0x46, LE16(max_), 94 - #define PhysicalRange_i32(min_, max_) 0x37, LE32(min_), 0x47, LE32(max_), 97 + #define LogicalMaximum_i8(max_) 0x25, i8(max_), 98 + #define LogicalMaximum_i16(max_) 0x26, LE16(max_), 99 + #define LogicalMaximum_i32(max_) 0x27, LE32(max_), 95 100 96 - #define UsageRange_i8(min_, max_) 0x19, i8(min_), 0x29, i8(max_), 97 - #define UsageRange_i16(min_, max_) 0x1a, LE16(min_), 0x2a, LE16(max_), 101 + #define PhysicalMinimum_i8(min_) 0x35, i8(min_), 102 + #define PhysicalMinimum_i16(min_) 0x36, LE16(min_), 103 + #define PhysicalMinimum_i32(min_) 0x37, LE32(min_), 104 + 105 + #define PhysicalMaximum_i8(max_) 0x45, i8(max_), 106 + #define PhysicalMaximum_i16(max_) 0x46, LE16(max_), 107 + #define PhysicalMaximum_i32(max_) 0x47, LE32(max_), 108 + 109 + #define UsageMinimum_i8(min_) 0x19, i8(min_), 110 + #define UsageMinimum_i16(min_) 0x1a, LE16(min_), 111 + 112 + #define UsageMaximum_i8(max_) 0x29, i8(max_), 113 + #define UsageMaximum_i16(max_) 0x2a, LE16(max_), 98 114 99 115 #define UsagePage_i8(p_) 0x05, i8(p_), 100 116 #define UsagePage_i16(p_) 0x06, LE16(p_),
+65 -19
drivers/hid/hid-core.c
··· 713 713 INIT_LIST_HEAD(&report_enum->report_list); 714 714 } 715 715 716 - kfree(device->rdesc); 716 + /* 717 + * If the HID driver had a rdesc_fixup() callback, dev->rdesc 718 + * will be allocated by hid-core and needs to be freed. 719 + * Otherwise, it is either equal to dev_rdesc or bpf_rdesc, in 720 + * which cases it'll be freed later on device removal or destroy. 721 + */ 722 + if (device->rdesc != device->dev_rdesc && device->rdesc != device->bpf_rdesc) 723 + kfree(device->rdesc); 717 724 device->rdesc = NULL; 718 725 device->rsize = 0; 719 726 ··· 733 726 device->status &= ~HID_STAT_PARSED; 734 727 } 735 728 729 + static inline void hid_free_bpf_rdesc(struct hid_device *hdev) 730 + { 731 + /* bpf_rdesc is either equal to dev_rdesc or allocated by call_hid_bpf_rdesc_fixup() */ 732 + if (hdev->bpf_rdesc != hdev->dev_rdesc) 733 + kfree(hdev->bpf_rdesc); 734 + hdev->bpf_rdesc = NULL; 735 + } 736 + 736 737 /* 737 738 * Free a device structure, all reports, and all fields. 738 739 */ ··· 750 735 struct hid_device *hid = container_of(ref, struct hid_device, ref); 751 736 752 737 hid_close_report(hid); 738 + hid_free_bpf_rdesc(hid); 753 739 kfree(hid->dev_rdesc); 754 740 kfree(hid); 755 741 } ··· 1243 1227 struct hid_item item; 1244 1228 unsigned int size; 1245 1229 const __u8 *start; 1246 - __u8 *buf; 1247 1230 const __u8 *end; 1248 1231 const __u8 *next; 1249 1232 int ret; ··· 1258 1243 if (WARN_ON(device->status & HID_STAT_PARSED)) 1259 1244 return -EBUSY; 1260 1245 1261 - start = device->dev_rdesc; 1246 + start = device->bpf_rdesc; 1262 1247 if (WARN_ON(!start)) 1263 1248 return -ENODEV; 1264 - size = device->dev_rsize; 1249 + size = device->bpf_rsize; 1265 1250 1266 - /* call_hid_bpf_rdesc_fixup() ensures we work on a copy of rdesc */ 1267 - buf = call_hid_bpf_rdesc_fixup(device, start, &size); 1268 - if (buf == NULL) 1269 - return -ENOMEM; 1251 + if (device->driver->report_fixup) { 1252 + /* 1253 + * device->driver->report_fixup() needs to work 1254 + * on a copy of our report descriptor so it can 1255 + * change it. 1256 + */ 1257 + __u8 *buf = kmemdup(start, size, GFP_KERNEL); 1270 1258 1271 - if (device->driver->report_fixup) 1259 + if (buf == NULL) 1260 + return -ENOMEM; 1261 + 1272 1262 start = device->driver->report_fixup(device, buf, &size); 1273 - else 1274 - start = buf; 1275 1263 1276 - start = kmemdup(start, size, GFP_KERNEL); 1277 - kfree(buf); 1278 - if (start == NULL) 1279 - return -ENOMEM; 1264 + /* 1265 + * The second kmemdup is required in case report_fixup() returns 1266 + * a static read-only memory, but we have no idea if that memory 1267 + * needs to be cleaned up or not at the end. 1268 + */ 1269 + start = kmemdup(start, size, GFP_KERNEL); 1270 + kfree(buf); 1271 + if (start == NULL) 1272 + return -ENOMEM; 1273 + } 1280 1274 1281 1275 device->rdesc = start; 1282 1276 device->rsize = size; ··· 2680 2656 /* 2681 2657 * hid-generic implements .match(), so we must be dealing with a 2682 2658 * different HID driver here, and can simply check if 2683 - * hid_ignore_special_drivers is set or not. 2659 + * hid_ignore_special_drivers or HID_QUIRK_IGNORE_SPECIAL_DRIVER 2660 + * are set or not. 2684 2661 */ 2685 - return !hid_ignore_special_drivers; 2662 + return !hid_ignore_special_drivers && !(hdev->quirks & HID_QUIRK_IGNORE_SPECIAL_DRIVER); 2686 2663 } 2687 2664 2688 2665 static int __hid_device_probe(struct hid_device *hdev, struct hid_driver *hdrv) 2689 2666 { 2690 2667 const struct hid_device_id *id; 2691 2668 int ret; 2669 + 2670 + if (!hdev->bpf_rsize) { 2671 + unsigned int quirks; 2672 + 2673 + /* reset the quirks that has been previously set */ 2674 + quirks = hid_lookup_quirk(hdev); 2675 + hdev->quirks = quirks; 2676 + 2677 + /* in case a bpf program gets detached, we need to free the old one */ 2678 + hid_free_bpf_rdesc(hdev); 2679 + 2680 + /* keep this around so we know we called it once */ 2681 + hdev->bpf_rsize = hdev->dev_rsize; 2682 + 2683 + /* call_hid_bpf_rdesc_fixup will always return a valid pointer */ 2684 + hdev->bpf_rdesc = call_hid_bpf_rdesc_fixup(hdev, hdev->dev_rdesc, 2685 + &hdev->bpf_rsize); 2686 + if (quirks ^ hdev->quirks) 2687 + hid_info(hdev, "HID-BPF toggled quirks on the device: %04x", 2688 + quirks ^ hdev->quirks); 2689 + } 2692 2690 2693 2691 if (!hid_check_device_match(hdev, hdrv, &id)) 2694 2692 return -ENODEV; ··· 2719 2673 if (!hdev->devres_group_id) 2720 2674 return -ENOMEM; 2721 2675 2722 - /* reset the quirks that has been previously set */ 2723 - hdev->quirks = hid_lookup_quirk(hdev); 2724 2676 hdev->driver = hdrv; 2725 2677 2726 2678 if (hdrv->probe) { ··· 2966 2922 hid_debug_unregister(hdev); 2967 2923 hdev->status &= ~HID_STAT_ADDED; 2968 2924 } 2925 + hid_free_bpf_rdesc(hdev); 2969 2926 kfree(hdev->dev_rdesc); 2970 2927 hdev->dev_rdesc = NULL; 2971 2928 hdev->dev_rsize = 0; 2929 + hdev->bpf_rsize = 0; 2972 2930 } 2973 2931 2974 2932 /**
+3
drivers/hid/hid-generic.c
··· 40 40 if (ignore_special_driver) 41 41 return true; 42 42 43 + if (hdev->quirks & HID_QUIRK_IGNORE_SPECIAL_DRIVER) 44 + return true; 45 + 43 46 if (hdev->quirks & HID_QUIRK_HAVE_SPECIAL_DRIVER) 44 47 return false; 45 48
+12 -8
include/linux/hid.h
··· 359 359 * | @HID_QUIRK_NO_OUTPUT_REPORTS_ON_INTR_EP: 360 360 * | @HID_QUIRK_HAVE_SPECIAL_DRIVER: 361 361 * | @HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE: 362 + * | @HID_QUIRK_IGNORE_SPECIAL_DRIVER 362 363 * | @HID_QUIRK_FULLSPEED_INTERVAL: 363 364 * | @HID_QUIRK_NO_INIT_REPORTS: 364 365 * | @HID_QUIRK_NO_IGNORE: ··· 385 384 #define HID_QUIRK_HAVE_SPECIAL_DRIVER BIT(19) 386 385 #define HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE BIT(20) 387 386 #define HID_QUIRK_NOINVERT BIT(21) 387 + #define HID_QUIRK_IGNORE_SPECIAL_DRIVER BIT(22) 388 388 #define HID_QUIRK_FULLSPEED_INTERVAL BIT(28) 389 389 #define HID_QUIRK_NO_INIT_REPORTS BIT(29) 390 390 #define HID_QUIRK_NO_IGNORE BIT(30) ··· 601 599 struct hid_driver; 602 600 struct hid_ll_driver; 603 601 604 - struct hid_device { /* device report descriptor */ 605 - const __u8 *dev_rdesc; 606 - unsigned dev_rsize; 607 - const __u8 *rdesc; 608 - unsigned rsize; 602 + struct hid_device { 603 + const __u8 *dev_rdesc; /* device report descriptor */ 604 + const __u8 *bpf_rdesc; /* bpf modified report descriptor, if any */ 605 + const __u8 *rdesc; /* currently used report descriptor */ 606 + unsigned int dev_rsize; 607 + unsigned int bpf_rsize; 608 + unsigned int rsize; 609 + unsigned int collection_size; /* Number of allocated hid_collections */ 609 610 struct hid_collection *collection; /* List of HID collections */ 610 - unsigned collection_size; /* Number of allocated hid_collections */ 611 - unsigned maxcollection; /* Number of parsed collections */ 612 - unsigned maxapplication; /* Number of applications */ 611 + unsigned int maxcollection; /* Number of parsed collections */ 612 + unsigned int maxapplication; /* Number of applications */ 613 613 __u16 bus; /* BUS ID */ 614 614 __u16 group; /* Report group */ 615 615 __u32 vendor; /* Vendor ID */
+3 -8
include/linux/hid_bpf.h
··· 212 212 void hid_bpf_disconnect_device(struct hid_device *hdev); 213 213 void hid_bpf_destroy_device(struct hid_device *hid); 214 214 int hid_bpf_device_init(struct hid_device *hid); 215 - u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, const u8 *rdesc, unsigned int *size); 215 + const u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, const u8 *rdesc, unsigned int *size); 216 216 #else /* CONFIG_HID_BPF */ 217 217 static inline u8 *dispatch_hid_bpf_device_event(struct hid_device *hid, enum hid_report_type type, 218 218 u8 *data, u32 *size, int interrupt, ··· 228 228 static inline void hid_bpf_disconnect_device(struct hid_device *hdev) {} 229 229 static inline void hid_bpf_destroy_device(struct hid_device *hid) {} 230 230 static inline int hid_bpf_device_init(struct hid_device *hid) { return 0; } 231 - /* 232 - * This specialized allocator has to be a macro for its allocations to be 233 - * accounted separately (to have a separate alloc_tag). The typecast is 234 - * intentional to enforce typesafety. 235 - */ 236 - #define call_hid_bpf_rdesc_fixup(_hdev, _rdesc, _size) \ 237 - ((u8 *)kmemdup(_rdesc, *(_size), GFP_KERNEL)) 231 + static inline const u8 *call_hid_bpf_rdesc_fixup(struct hid_device *hdev, const u8 *rdesc, 232 + unsigned int *size) { return rdesc; } 238 233 239 234 #endif /* CONFIG_HID_BPF */ 240 235
+1 -1
tools/testing/selftests/hid/Makefile
··· 232 232 $(Q)$(BPFTOOL) gen object $(<:.o=.linked1.o) $< 233 233 $(Q)$(BPFTOOL) gen skeleton $(<:.o=.linked1.o) name $(notdir $(<:.bpf.o=)) > $@ 234 234 235 - $(OUTPUT)/%.o: %.c $(BPF_SKELS) 235 + $(OUTPUT)/%.o: %.c $(BPF_SKELS) hid_common.h 236 236 $(call msg,CC,,$@) 237 237 $(Q)$(CC) $(CFLAGS) -c $(filter %.c,$^) $(LDLIBS) -o $@ 238 238
+102 -47
tools/testing/selftests/hid/hid_bpf.c
··· 4 4 #include "hid_common.h" 5 5 #include <bpf/bpf.h> 6 6 7 - struct attach_prog_args { 8 - int prog_fd; 9 - unsigned int hid; 10 - int retval; 11 - int insert_head; 12 - }; 13 - 14 7 struct hid_hw_request_syscall_args { 15 8 __u8 data[10]; 16 9 unsigned int hid; ··· 14 21 }; 15 22 16 23 FIXTURE(hid_bpf) { 17 - int dev_id; 18 - int uhid_fd; 24 + struct uhid_device hid; 19 25 int hidraw_fd; 20 - int hid_id; 21 - pthread_t tid; 22 26 struct hid *skel; 23 27 struct bpf_link *hid_links[3]; /* max number of programs loaded in a single test */ 24 28 }; ··· 44 54 FIXTURE_TEARDOWN(hid_bpf) { 45 55 void *uhid_err; 46 56 47 - uhid_destroy(_metadata, self->uhid_fd); 57 + uhid_destroy(_metadata, &self->hid); 48 58 49 59 detach_bpf(self); 50 - pthread_join(self->tid, &uhid_err); 60 + pthread_join(self->hid.tid, &uhid_err); 51 61 } 52 62 #define TEARDOWN_LOG(fmt, ...) do { \ 53 63 TH_LOG(fmt, ##__VA_ARGS__); \ 54 64 hid_bpf_teardown(_metadata, self, variant); \ 55 65 } while (0) 56 66 67 + struct specific_device { 68 + const char test_name[64]; 69 + __u16 bus; 70 + __u32 vid; 71 + __u32 pid; 72 + }; 73 + 57 74 FIXTURE_SETUP(hid_bpf) 58 75 { 59 - time_t t; 76 + const struct specific_device *match = NULL; 60 77 int err; 61 78 62 - /* initialize random number generator */ 63 - srand((unsigned int)time(&t)); 79 + const struct specific_device devices[] = { 80 + { 81 + .test_name = "test_hid_driver_probe", 82 + .bus = BUS_BLUETOOTH, 83 + .vid = 0x05ac, /* USB_VENDOR_ID_APPLE */ 84 + .pid = 0x022c, /* USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI */ 85 + }, { 86 + .test_name = "*", 87 + .bus = BUS_USB, 88 + .vid = 0x0001, 89 + .pid = 0x0a36, 90 + }}; 64 91 65 - self->dev_id = rand() % 1024; 92 + for (int i = 0; i < ARRAY_SIZE(devices); i++) { 93 + match = &devices[i]; 94 + if (!strncmp(_metadata->name, devices[i].test_name, sizeof(devices[i].test_name))) 95 + break; 96 + } 66 97 67 - self->uhid_fd = setup_uhid(_metadata, self->dev_id); 98 + ASSERT_OK_PTR(match); 68 99 69 - /* locate the uev, self, variant);ent file of the created device */ 70 - self->hid_id = get_hid_id(self->dev_id); 71 - ASSERT_GT(self->hid_id, 0) 72 - TEARDOWN_LOG("Could not locate uhid device id: %d", self->hid_id); 73 - 74 - err = uhid_start_listener(_metadata, &self->tid, self->uhid_fd); 75 - ASSERT_EQ(0, err) TEARDOWN_LOG("could not start udev listener: %d", err); 100 + err = setup_uhid(_metadata, &self->hid, match->bus, match->vid, match->pid, 101 + rdesc, sizeof(rdesc)); 102 + ASSERT_OK(err); 76 103 } 77 104 78 105 struct test_program { ··· 136 129 ops_hid_id = bpf_map__initial_value(map, NULL); 137 130 ASSERT_OK_PTR(ops_hid_id) TH_LOG("unable to retrieve struct_ops data"); 138 131 139 - *ops_hid_id = self->hid_id; 132 + *ops_hid_id = self->hid.hid_id; 140 133 } 141 134 142 135 /* we disable the auto-attach feature of all maps because we ··· 164 157 165 158 hid__attach(self->skel); 166 159 167 - self->hidraw_fd = open_hidraw(self->dev_id); 160 + self->hidraw_fd = open_hidraw(&self->hid); 168 161 ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw"); 169 162 } 170 163 ··· 199 192 /* inject one event */ 200 193 buf[0] = 1; 201 194 buf[1] = 42; 202 - uhid_send_event(_metadata, self->uhid_fd, buf, 6); 195 + uhid_send_event(_metadata, &self->hid, buf, 6); 203 196 204 197 /* check that hid_first_event() was executed */ 205 198 ASSERT_EQ(self->skel->data->callback_check, 42) TH_LOG("callback_check1"); ··· 215 208 memset(buf, 0, sizeof(buf)); 216 209 buf[0] = 1; 217 210 buf[1] = 47; 218 - uhid_send_event(_metadata, self->uhid_fd, buf, 6); 211 + uhid_send_event(_metadata, &self->hid, buf, 6); 219 212 220 213 /* check that hid_first_event() was executed */ 221 214 ASSERT_EQ(self->skel->data->callback_check, 47) TH_LOG("callback_check1"); ··· 246 239 /* inject one event */ 247 240 buf[0] = 1; 248 241 buf[1] = 42; 249 - uhid_send_event(_metadata, self->uhid_fd, buf, 6); 242 + uhid_send_event(_metadata, &self->hid, buf, 6); 250 243 251 244 /* read the data from hidraw */ 252 245 memset(buf, 0, sizeof(buf)); ··· 259 252 memset(buf, 0, sizeof(buf)); 260 253 buf[0] = 1; 261 254 buf[1] = 47; 262 - uhid_send_event(_metadata, self->uhid_fd, buf, 6); 255 + uhid_send_event(_metadata, &self->hid, buf, 6); 263 256 264 257 /* read the data from hidraw */ 265 258 memset(buf, 0, sizeof(buf)); ··· 310 303 /* inject one event */ 311 304 buf[0] = 1; 312 305 buf[1] = 42; 313 - uhid_send_event(_metadata, self->uhid_fd, buf, 6); 306 + uhid_send_event(_metadata, &self->hid, buf, 6); 314 307 315 308 /* read the data from hidraw */ 316 309 memset(buf, 0, sizeof(buf)); ··· 333 326 /* detach the program */ 334 327 detach_bpf(self); 335 328 336 - self->hidraw_fd = open_hidraw(self->dev_id); 329 + self->hidraw_fd = open_hidraw(&self->hid); 337 330 ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw"); 338 331 339 332 /* inject another event */ 340 333 memset(buf, 0, sizeof(buf)); 341 334 buf[0] = 1; 342 335 buf[1] = 47; 343 - uhid_send_event(_metadata, self->uhid_fd, buf, 6); 336 + uhid_send_event(_metadata, &self->hid, buf, 6); 344 337 345 338 /* read the data from hidraw */ 346 339 memset(buf, 0, sizeof(buf)); ··· 359 352 memset(buf, 0, sizeof(buf)); 360 353 buf[0] = 1; 361 354 buf[1] = 42; 362 - uhid_send_event(_metadata, self->uhid_fd, buf, 6); 355 + uhid_send_event(_metadata, &self->hid, buf, 6); 363 356 364 357 /* read the data from hidraw */ 365 358 memset(buf, 0, sizeof(buf)); ··· 389 382 /* inject one event */ 390 383 buf[0] = 1; 391 384 buf[1] = 42; 392 - uhid_send_event(_metadata, self->uhid_fd, buf, 6); 385 + uhid_send_event(_metadata, &self->hid, buf, 6); 393 386 394 387 /* read the data from hidraw */ 395 388 memset(buf, 0, sizeof(buf)); ··· 419 412 420 413 LOAD_BPF; 421 414 422 - args.hid = self->hid_id; 415 + args.hid = self->hid.hid_id; 423 416 args.data[0] = 1; /* report ID */ 424 417 args.data[1] = 2; /* report ID */ 425 418 args.data[2] = 42; /* report ID */ ··· 465 458 466 459 LOAD_BPF; 467 460 468 - args.hid = self->hid_id; 461 + args.hid = self->hid.hid_id; 469 462 args.data[0] = 1; /* report ID */ 470 463 args.data[1] = 2; /* report ID */ 471 464 args.data[2] = 42; /* report ID */ ··· 513 506 514 507 LOAD_BPF; 515 508 516 - args.hid = self->hid_id; 509 + args.hid = self->hid.hid_id; 517 510 args.data[0] = 1; /* report ID */ 518 511 519 512 prog_fd = bpf_program__fd(self->skel->progs.hid_user_raw_request); ··· 546 539 /* inject one event */ 547 540 buf[0] = 1; 548 541 buf[1] = 42; 549 - uhid_send_event(_metadata, self->uhid_fd, buf, 6); 542 + uhid_send_event(_metadata, &self->hid, buf, 6); 550 543 551 544 /* read the data from hidraw */ 552 545 memset(buf, 0, sizeof(buf)); ··· 572 565 /* detach the program */ 573 566 detach_bpf(self); 574 567 575 - self->hidraw_fd = open_hidraw(self->dev_id); 568 + self->hidraw_fd = open_hidraw(&self->hid); 576 569 ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw"); 577 570 578 571 err = ioctl(self->hidraw_fd, HIDIOCGFEATURE(sizeof(buf)), buf); ··· 648 641 /* inject one event */ 649 642 buf[0] = 1; 650 643 buf[1] = 42; 651 - uhid_send_event(_metadata, self->uhid_fd, buf, 6); 644 + uhid_send_event(_metadata, &self->hid, buf, 6); 652 645 653 646 /* read the data from hidraw */ 654 647 memset(buf, 0, sizeof(buf)); ··· 674 667 /* detach the program */ 675 668 detach_bpf(self); 676 669 677 - self->hidraw_fd = open_hidraw(self->dev_id); 670 + self->hidraw_fd = open_hidraw(&self->hid); 678 671 ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw"); 679 672 680 673 err = write(self->hidraw_fd, buf, 3); ··· 749 742 /* inject one event */ 750 743 buf[0] = 1; 751 744 buf[1] = 42; 752 - uhid_send_event(_metadata, self->uhid_fd, buf, 6); 745 + uhid_send_event(_metadata, &self->hid, buf, 6); 753 746 754 747 /* read the data from hidraw */ 755 748 memset(buf, 0, sizeof(buf)); ··· 787 780 /* inject one event */ 788 781 buf[0] = 1; 789 782 buf[1] = 42; 790 - uhid_send_event(_metadata, self->uhid_fd, buf, 6); 783 + uhid_send_event(_metadata, &self->hid, buf, 6); 791 784 792 785 /* read the data from hidraw */ 793 786 memset(buf, 0, sizeof(buf)); ··· 823 816 buf[1] = 2; 824 817 buf[2] = 42; 825 818 826 - uhid_send_event(_metadata, self->uhid_fd, buf, 6); 819 + uhid_send_event(_metadata, &self->hid, buf, 6); 827 820 828 821 /* read the data from hidraw */ 829 822 memset(buf, 0, sizeof(buf)); ··· 874 867 875 868 /* inject one event */ 876 869 buf[0] = 1; 877 - uhid_send_event(_metadata, self->uhid_fd, buf, 6); 870 + uhid_send_event(_metadata, &self->hid, buf, 6); 878 871 879 872 /* read the data from hidraw */ 880 873 memset(buf, 0, sizeof(buf)); ··· 883 876 ASSERT_EQ(buf[1], 1); 884 877 ASSERT_EQ(buf[2], 2); 885 878 ASSERT_EQ(buf[3], 3); 879 + } 880 + 881 + static bool is_using_driver(struct __test_metadata *_metadata, struct uhid_device *hid, 882 + const char *driver) 883 + { 884 + char driver_line[512]; 885 + char uevent[1024]; 886 + char temp[512]; 887 + int fd, nread; 888 + bool found = false; 889 + 890 + sprintf(uevent, "/sys/bus/hid/devices/%04X:%04X:%04X.%04X/uevent", 891 + hid->bus, hid->vid, hid->pid, hid->hid_id); 892 + 893 + fd = open(uevent, O_RDONLY | O_NONBLOCK); 894 + if (fd < 0) { 895 + TH_LOG("couldn't open '%s': %d, %d", uevent, fd, errno); 896 + return false; 897 + } 898 + 899 + sprintf(driver_line, "DRIVER=%s", driver); 900 + 901 + nread = read(fd, temp, ARRAY_SIZE(temp)); 902 + if (nread > 0 && (strstr(temp, driver_line)) != NULL) 903 + found = true; 904 + 905 + close(fd); 906 + 907 + return found; 908 + } 909 + 910 + /* 911 + * Attach hid_driver_probe to the given uhid device, 912 + * check that the device is now using hid-generic. 913 + */ 914 + TEST_F(hid_bpf, test_hid_driver_probe) 915 + { 916 + const struct test_program progs[] = { 917 + { 918 + .name = "hid_test_driver_probe", 919 + }, 920 + }; 921 + 922 + ASSERT_TRUE(is_using_driver(_metadata, &self->hid, "apple")); 923 + 924 + LOAD_PROGRAMS(progs); 925 + 926 + ASSERT_TRUE(is_using_driver(_metadata, &self->hid, "hid-generic")); 886 927 } 887 928 888 929 /*
+75 -37
tools/testing/selftests/hid/hid_common.h
··· 19 19 __typeof__(b) _b = (b); \ 20 20 _a < _b ? _a : _b; }) 21 21 22 + struct uhid_device { 23 + int dev_id; /* uniq (random) number to identify the device */ 24 + int uhid_fd; 25 + int hid_id; /* HID device id in the system */ 26 + __u16 bus; 27 + __u32 vid; 28 + __u32 pid; 29 + pthread_t tid; /* thread for reading uhid events */ 30 + }; 31 + 22 32 static unsigned char rdesc[] = { 23 33 0x06, 0x00, 0xff, /* Usage Page (Vendor Defined Page 1) */ 24 34 0x09, 0x21, /* Usage (Vendor Usage 0x21) */ ··· 132 122 } 133 123 } 134 124 135 - static int uhid_create(struct __test_metadata *_metadata, int fd, int rand_nb) 125 + static int uhid_create(struct __test_metadata *_metadata, int fd, int rand_nb, 126 + __u16 bus, __u32 vid, __u32 pid, __u8 *rdesc, 127 + size_t rdesc_size) 136 128 { 137 129 struct uhid_event ev; 138 130 char buf[25]; ··· 145 133 ev.type = UHID_CREATE; 146 134 strcpy((char *)ev.u.create.name, buf); 147 135 ev.u.create.rd_data = rdesc; 148 - ev.u.create.rd_size = sizeof(rdesc); 149 - ev.u.create.bus = BUS_USB; 150 - ev.u.create.vendor = 0x0001; 151 - ev.u.create.product = 0x0a37; 136 + ev.u.create.rd_size = rdesc_size; 137 + ev.u.create.bus = bus; 138 + ev.u.create.vendor = vid; 139 + ev.u.create.product = pid; 152 140 ev.u.create.version = 0; 153 141 ev.u.create.country = 0; 154 142 ··· 158 146 return uhid_write(_metadata, fd, &ev); 159 147 } 160 148 161 - static void uhid_destroy(struct __test_metadata *_metadata, int fd) 149 + static void uhid_destroy(struct __test_metadata *_metadata, struct uhid_device *hid) 162 150 { 163 151 struct uhid_event ev; 164 152 165 153 memset(&ev, 0, sizeof(ev)); 166 154 ev.type = UHID_DESTROY; 167 155 168 - uhid_write(_metadata, fd, &ev); 156 + uhid_write(_metadata, hid->uhid_fd, &ev); 169 157 } 170 158 171 159 static int uhid_event(struct __test_metadata *_metadata, int fd) ··· 293 281 return 0; 294 282 } 295 283 296 - static int uhid_send_event(struct __test_metadata *_metadata, int fd, __u8 *buf, size_t size) 284 + static int uhid_send_event(struct __test_metadata *_metadata, struct uhid_device *hid, 285 + __u8 *buf, size_t size) 297 286 { 298 287 struct uhid_event ev; 299 288 ··· 307 294 308 295 memcpy(ev.u.input2.data, buf, size); 309 296 310 - return uhid_write(_metadata, fd, &ev); 297 + return uhid_write(_metadata, hid->uhid_fd, &ev); 311 298 } 312 299 313 - static int setup_uhid(struct __test_metadata *_metadata, int rand_nb) 300 + static bool match_sysfs_device(struct uhid_device *hid, const char *workdir, struct dirent *dir) 314 301 { 315 - int fd; 316 - const char *path = "/dev/uhid"; 317 - int ret; 318 - 319 - fd = open(path, O_RDWR | O_CLOEXEC); 320 - ASSERT_GE(fd, 0) TH_LOG("open uhid-cdev failed; %d", fd); 321 - 322 - ret = uhid_create(_metadata, fd, rand_nb); 323 - ASSERT_EQ(0, ret) { 324 - TH_LOG("create uhid device failed: %d", ret); 325 - close(fd); 326 - } 327 - 328 - return fd; 329 - } 330 - 331 - static bool match_sysfs_device(int dev_id, const char *workdir, struct dirent *dir) 332 - { 333 - const char *target = "0003:0001:0A37.*"; 302 + char target[20] = ""; 334 303 char phys[512]; 335 304 char uevent[1024]; 336 305 char temp[512]; 337 306 int fd, nread; 338 307 bool found = false; 308 + 309 + snprintf(target, sizeof(target), "%04X:%04X:%04X.*", hid->bus, hid->vid, hid->pid); 339 310 340 311 if (fnmatch(target, dir->d_name, 0)) 341 312 return false; ··· 331 334 if (fd < 0) 332 335 return false; 333 336 334 - sprintf(phys, "PHYS=%d", dev_id); 337 + sprintf(phys, "PHYS=%d", hid->dev_id); 335 338 336 339 nread = read(fd, temp, ARRAY_SIZE(temp)); 337 340 if (nread > 0 && (strstr(temp, phys)) != NULL) ··· 342 345 return found; 343 346 } 344 347 345 - static int get_hid_id(int dev_id) 348 + static int get_hid_id(struct uhid_device *hid) 346 349 { 347 350 const char *workdir = "/sys/devices/virtual/misc/uhid"; 348 351 const char *str_id; ··· 357 360 d = opendir(workdir); 358 361 if (d) { 359 362 while ((dir = readdir(d)) != NULL) { 360 - if (!match_sysfs_device(dev_id, workdir, dir)) 363 + if (!match_sysfs_device(hid, workdir, dir)) 361 364 continue; 362 365 363 - str_id = dir->d_name + sizeof("0003:0001:0A37."); 366 + str_id = dir->d_name + sizeof("0000:0000:0000."); 364 367 found = (int)strtol(str_id, NULL, 16); 365 368 366 369 break; ··· 374 377 return found; 375 378 } 376 379 377 - static int get_hidraw(int dev_id) 380 + static int get_hidraw(struct uhid_device *hid) 378 381 { 379 382 const char *workdir = "/sys/devices/virtual/misc/uhid"; 380 383 char sysfs[1024]; ··· 391 394 continue; 392 395 393 396 while ((dir = readdir(d)) != NULL) { 394 - if (!match_sysfs_device(dev_id, workdir, dir)) 397 + if (!match_sysfs_device(hid, workdir, dir)) 395 398 continue; 396 399 397 400 sprintf(sysfs, "%s/%s/hidraw", workdir, dir->d_name); ··· 418 421 return found; 419 422 } 420 423 421 - static int open_hidraw(int dev_id) 424 + static int open_hidraw(struct uhid_device *hid) 422 425 { 423 426 int hidraw_number; 424 427 char hidraw_path[64] = { 0 }; 425 428 426 - hidraw_number = get_hidraw(dev_id); 429 + hidraw_number = get_hidraw(hid); 427 430 if (hidraw_number < 0) 428 431 return hidraw_number; 429 432 430 433 /* open hidraw node to check the other side of the pipe */ 431 434 sprintf(hidraw_path, "/dev/hidraw%d", hidraw_number); 432 435 return open(hidraw_path, O_RDWR | O_NONBLOCK); 436 + } 437 + 438 + static int setup_uhid(struct __test_metadata *_metadata, struct uhid_device *hid, 439 + __u16 bus, __u32 vid, __u32 pid, const __u8 *rdesc, size_t rdesc_size) 440 + { 441 + const char *path = "/dev/uhid"; 442 + time_t t; 443 + int ret; 444 + 445 + /* initialize random number generator */ 446 + srand((unsigned int)time(&t)); 447 + 448 + hid->dev_id = rand() % 1024; 449 + hid->bus = bus; 450 + hid->vid = vid; 451 + hid->pid = pid; 452 + 453 + hid->uhid_fd = open(path, O_RDWR | O_CLOEXEC); 454 + ASSERT_GE(hid->uhid_fd, 0) TH_LOG("open uhid-cdev failed; %d", hid->uhid_fd); 455 + 456 + ret = uhid_create(_metadata, hid->uhid_fd, hid->dev_id, bus, vid, pid, 457 + (__u8 *)rdesc, rdesc_size); 458 + ASSERT_EQ(0, ret) { 459 + TH_LOG("create uhid device failed: %d", ret); 460 + close(hid->uhid_fd); 461 + return ret; 462 + } 463 + 464 + /* locate the uevent file of the created device */ 465 + hid->hid_id = get_hid_id(hid); 466 + ASSERT_GT(hid->hid_id, 0) 467 + TH_LOG("Could not locate uhid device id: %d", hid->hid_id); 468 + 469 + ret = uhid_start_listener(_metadata, &hid->tid, hid->uhid_fd); 470 + ASSERT_EQ(0, ret) { 471 + TH_LOG("could not start udev listener: %d", ret); 472 + close(hid->uhid_fd); 473 + return ret; 474 + } 475 + 476 + return 0; 433 477 }
+10 -26
tools/testing/selftests/hid/hidraw.c
··· 9 9 #endif /* HIDIOCREVOKE */ 10 10 11 11 FIXTURE(hidraw) { 12 - int dev_id; 13 - int uhid_fd; 12 + struct uhid_device hid; 14 13 int hidraw_fd; 15 - int hid_id; 16 - pthread_t tid; 17 14 }; 18 15 static void close_hidraw(FIXTURE_DATA(hidraw) * self) 19 16 { ··· 22 25 FIXTURE_TEARDOWN(hidraw) { 23 26 void *uhid_err; 24 27 25 - uhid_destroy(_metadata, self->uhid_fd); 28 + uhid_destroy(_metadata, &self->hid); 26 29 27 30 close_hidraw(self); 28 - pthread_join(self->tid, &uhid_err); 31 + pthread_join(self->hid.tid, &uhid_err); 29 32 } 30 33 #define TEARDOWN_LOG(fmt, ...) do { \ 31 34 TH_LOG(fmt, ##__VA_ARGS__); \ ··· 34 37 35 38 FIXTURE_SETUP(hidraw) 36 39 { 37 - time_t t; 38 40 int err; 39 41 40 - /* initialize random number generator */ 41 - srand((unsigned int)time(&t)); 42 + err = setup_uhid(_metadata, &self->hid, BUS_USB, 0x0001, 0x0a37, rdesc, sizeof(rdesc)); 43 + ASSERT_OK(err); 42 44 43 - self->dev_id = rand() % 1024; 44 - 45 - self->uhid_fd = setup_uhid(_metadata, self->dev_id); 46 - 47 - /* locate the uev, self, variant);ent file of the created device */ 48 - self->hid_id = get_hid_id(self->dev_id); 49 - ASSERT_GT(self->hid_id, 0) 50 - TEARDOWN_LOG("Could not locate uhid device id: %d", self->hid_id); 51 - 52 - err = uhid_start_listener(_metadata, &self->tid, self->uhid_fd); 53 - ASSERT_EQ(0, err) TEARDOWN_LOG("could not start udev listener: %d", err); 54 - 55 - self->hidraw_fd = open_hidraw(self->dev_id); 45 + self->hidraw_fd = open_hidraw(&self->hid); 56 46 ASSERT_GE(self->hidraw_fd, 0) TH_LOG("open_hidraw"); 57 47 } 58 48 ··· 63 79 /* inject one event */ 64 80 buf[0] = 1; 65 81 buf[1] = 42; 66 - uhid_send_event(_metadata, self->uhid_fd, buf, 6); 82 + uhid_send_event(_metadata, &self->hid, buf, 6); 67 83 68 84 /* read the data from hidraw */ 69 85 memset(buf, 0, sizeof(buf)); ··· 85 101 /* inject one event */ 86 102 buf[0] = 1; 87 103 buf[1] = 42; 88 - uhid_send_event(_metadata, self->uhid_fd, buf, 6); 104 + uhid_send_event(_metadata, &self->hid, buf, 6); 89 105 90 106 /* read the data from hidraw */ 91 107 memset(buf, 0, sizeof(buf)); ··· 101 117 /* inject one other event */ 102 118 buf[0] = 1; 103 119 buf[1] = 43; 104 - uhid_send_event(_metadata, self->uhid_fd, buf, 6); 120 + uhid_send_event(_metadata, &self->hid, buf, 6); 105 121 106 122 /* read the data from hidraw */ 107 123 memset(buf, 0, sizeof(buf)); ··· 145 161 /* inject one event */ 146 162 buf[0] = 1; 147 163 buf[1] = 42; 148 - uhid_send_event(_metadata, self->uhid_fd, buf, 6); 164 + uhid_send_event(_metadata, &self->hid, buf, 6); 149 165 150 166 while (true) { 151 167 ready = poll(pfds, 1, 5000);
+12
tools/testing/selftests/hid/progs/hid.c
··· 598 598 struct hid_bpf_ops test_infinite_loop_input_report = { 599 599 .hid_device_event = (void *)hid_test_infinite_loop_input_report, 600 600 }; 601 + 602 + SEC("?struct_ops.s/hid_rdesc_fixup") 603 + int BPF_PROG(hid_test_driver_probe, struct hid_bpf_ctx *hid_ctx) 604 + { 605 + hid_ctx->hid->quirks |= HID_QUIRK_IGNORE_SPECIAL_DRIVER; 606 + return 0; 607 + } 608 + 609 + SEC(".struct_ops.link") 610 + struct hid_bpf_ops test_driver_probe = { 611 + .hid_rdesc_fixup = (void *)hid_test_driver_probe, 612 + };
+5 -1
tools/testing/selftests/hid/progs/hid_bpf_helpers.h
··· 84 84 struct hid_device *hdev; 85 85 }; 86 86 87 + #define BIT(n) (1U << n) 88 + 87 89 #ifndef BPF_F_BEFORE 88 - #define BPF_F_BEFORE (1U << 3) 90 + #define BPF_F_BEFORE BIT(3) 89 91 #endif 92 + 93 + #define HID_QUIRK_IGNORE_SPECIAL_DRIVER BIT(22) 90 94 91 95 /* following are kfuncs exported by HID for HID-BPF */ 92 96 extern __u8 *hid_bpf_get_data(struct hid_bpf_ctx *ctx,