16008105bSBenjamin Tissoires // SPDX-License-Identifier: GPL-2.0 26008105bSBenjamin Tissoires 36008105bSBenjamin Tissoires #include "vmlinux.h" 46008105bSBenjamin Tissoires #include <bpf/bpf_helpers.h> 56008105bSBenjamin Tissoires #include <bpf/bpf_tracing.h> 66008105bSBenjamin Tissoires #include "hid_bpf_helpers.h" 76008105bSBenjamin Tissoires 8*e342d6f6SBenjamin Tissoires static int hid_y_event(struct hid_bpf_ctx *hctx) 96008105bSBenjamin Tissoires { 106008105bSBenjamin Tissoires s16 y; 116008105bSBenjamin Tissoires __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */); 126008105bSBenjamin Tissoires 136008105bSBenjamin Tissoires if (!data) 146008105bSBenjamin Tissoires return 0; /* EPERM check */ 156008105bSBenjamin Tissoires 166008105bSBenjamin Tissoires bpf_printk("event: size: %d", hctx->size); 176008105bSBenjamin Tissoires bpf_printk("incoming event: %02x %02x %02x", 186008105bSBenjamin Tissoires data[0], 196008105bSBenjamin Tissoires data[1], 206008105bSBenjamin Tissoires data[2]); 216008105bSBenjamin Tissoires bpf_printk(" %02x %02x %02x", 226008105bSBenjamin Tissoires data[3], 236008105bSBenjamin Tissoires data[4], 246008105bSBenjamin Tissoires data[5]); 256008105bSBenjamin Tissoires bpf_printk(" %02x %02x %02x", 266008105bSBenjamin Tissoires data[6], 276008105bSBenjamin Tissoires data[7], 286008105bSBenjamin Tissoires data[8]); 296008105bSBenjamin Tissoires 306008105bSBenjamin Tissoires y = data[3] | (data[4] << 8); 316008105bSBenjamin Tissoires 326008105bSBenjamin Tissoires y = -y; 336008105bSBenjamin Tissoires 346008105bSBenjamin Tissoires data[3] = y & 0xFF; 356008105bSBenjamin Tissoires data[4] = (y >> 8) & 0xFF; 366008105bSBenjamin Tissoires 376008105bSBenjamin Tissoires bpf_printk("modified event: %02x %02x %02x", 386008105bSBenjamin Tissoires data[0], 396008105bSBenjamin Tissoires data[1], 406008105bSBenjamin Tissoires data[2]); 416008105bSBenjamin Tissoires bpf_printk(" %02x %02x %02x", 426008105bSBenjamin Tissoires data[3], 436008105bSBenjamin Tissoires data[4], 446008105bSBenjamin Tissoires data[5]); 456008105bSBenjamin Tissoires bpf_printk(" %02x %02x %02x", 466008105bSBenjamin Tissoires data[6], 476008105bSBenjamin Tissoires data[7], 486008105bSBenjamin Tissoires data[8]); 496008105bSBenjamin Tissoires 506008105bSBenjamin Tissoires return 0; 516008105bSBenjamin Tissoires } 526008105bSBenjamin Tissoires 53*e342d6f6SBenjamin Tissoires static int hid_x_event(struct hid_bpf_ctx *hctx) 546008105bSBenjamin Tissoires { 556008105bSBenjamin Tissoires s16 x; 566008105bSBenjamin Tissoires __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */); 576008105bSBenjamin Tissoires 586008105bSBenjamin Tissoires if (!data) 596008105bSBenjamin Tissoires return 0; /* EPERM check */ 606008105bSBenjamin Tissoires 616008105bSBenjamin Tissoires x = data[1] | (data[2] << 8); 626008105bSBenjamin Tissoires 636008105bSBenjamin Tissoires x = -x; 646008105bSBenjamin Tissoires 656008105bSBenjamin Tissoires data[1] = x & 0xFF; 666008105bSBenjamin Tissoires data[2] = (x >> 8) & 0xFF; 676008105bSBenjamin Tissoires return 0; 686008105bSBenjamin Tissoires } 696008105bSBenjamin Tissoires 70*e342d6f6SBenjamin Tissoires SEC("struct_ops/device_event") 71*e342d6f6SBenjamin Tissoires int BPF_PROG(hid_event, struct hid_bpf_ctx *hctx, enum hid_report_type type) 72*e342d6f6SBenjamin Tissoires { 73*e342d6f6SBenjamin Tissoires int ret = hid_y_event(hctx); 74*e342d6f6SBenjamin Tissoires 75*e342d6f6SBenjamin Tissoires if (ret) 76*e342d6f6SBenjamin Tissoires return ret; 77*e342d6f6SBenjamin Tissoires 78*e342d6f6SBenjamin Tissoires return hid_x_event(hctx); 79*e342d6f6SBenjamin Tissoires } 80*e342d6f6SBenjamin Tissoires 81*e342d6f6SBenjamin Tissoires 82*e342d6f6SBenjamin Tissoires SEC("struct_ops/rdesc_fixup") 836008105bSBenjamin Tissoires int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx) 846008105bSBenjamin Tissoires { 856008105bSBenjamin Tissoires __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */); 866008105bSBenjamin Tissoires 876008105bSBenjamin Tissoires if (!data) 886008105bSBenjamin Tissoires return 0; /* EPERM check */ 896008105bSBenjamin Tissoires 906008105bSBenjamin Tissoires bpf_printk("rdesc: %02x %02x %02x", 916008105bSBenjamin Tissoires data[0], 926008105bSBenjamin Tissoires data[1], 936008105bSBenjamin Tissoires data[2]); 946008105bSBenjamin Tissoires bpf_printk(" %02x %02x %02x", 956008105bSBenjamin Tissoires data[3], 966008105bSBenjamin Tissoires data[4], 976008105bSBenjamin Tissoires data[5]); 986008105bSBenjamin Tissoires bpf_printk(" %02x %02x %02x ...", 996008105bSBenjamin Tissoires data[6], 1006008105bSBenjamin Tissoires data[7], 1016008105bSBenjamin Tissoires data[8]); 1026008105bSBenjamin Tissoires 1036008105bSBenjamin Tissoires /* 1046008105bSBenjamin Tissoires * The original report descriptor contains: 1056008105bSBenjamin Tissoires * 1066008105bSBenjamin Tissoires * 0x05, 0x01, // Usage Page (Generic Desktop) 30 1076008105bSBenjamin Tissoires * 0x16, 0x01, 0x80, // Logical Minimum (-32767) 32 1086008105bSBenjamin Tissoires * 0x26, 0xff, 0x7f, // Logical Maximum (32767) 35 1096008105bSBenjamin Tissoires * 0x09, 0x30, // Usage (X) 38 1106008105bSBenjamin Tissoires * 0x09, 0x31, // Usage (Y) 40 1116008105bSBenjamin Tissoires * 1126008105bSBenjamin Tissoires * So byte 39 contains Usage X and byte 41 Usage Y. 1136008105bSBenjamin Tissoires * 1146008105bSBenjamin Tissoires * We simply swap the axes here. 1156008105bSBenjamin Tissoires */ 1166008105bSBenjamin Tissoires data[39] = 0x31; 1176008105bSBenjamin Tissoires data[41] = 0x30; 1186008105bSBenjamin Tissoires 1196008105bSBenjamin Tissoires return 0; 1206008105bSBenjamin Tissoires } 1216008105bSBenjamin Tissoires 122*e342d6f6SBenjamin Tissoires SEC(".struct_ops.link") 123*e342d6f6SBenjamin Tissoires struct hid_bpf_ops mouse_invert = { 124*e342d6f6SBenjamin Tissoires .rdesc_fixup = (void *)hid_rdesc_fixup, 125*e342d6f6SBenjamin Tissoires .device_event = (void *)hid_event, 126*e342d6f6SBenjamin Tissoires }; 127*e342d6f6SBenjamin Tissoires 1286008105bSBenjamin Tissoires char _license[] SEC("license") = "GPL"; 129