1 // SPDX-License-Identifier: GPL-2.0 2 3 #include "vmlinux.h" 4 #include <bpf/bpf_helpers.h> 5 #include <bpf/bpf_tracing.h> 6 #include "hid_bpf_helpers.h" 7 8 SEC("fmod_ret/hid_bpf_device_event") 9 int BPF_PROG(hid_y_event, struct hid_bpf_ctx *hctx) 10 { 11 s16 y; 12 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */); 13 14 if (!data) 15 return 0; /* EPERM check */ 16 17 bpf_printk("event: size: %d", hctx->size); 18 bpf_printk("incoming event: %02x %02x %02x", 19 data[0], 20 data[1], 21 data[2]); 22 bpf_printk(" %02x %02x %02x", 23 data[3], 24 data[4], 25 data[5]); 26 bpf_printk(" %02x %02x %02x", 27 data[6], 28 data[7], 29 data[8]); 30 31 y = data[3] | (data[4] << 8); 32 33 y = -y; 34 35 data[3] = y & 0xFF; 36 data[4] = (y >> 8) & 0xFF; 37 38 bpf_printk("modified event: %02x %02x %02x", 39 data[0], 40 data[1], 41 data[2]); 42 bpf_printk(" %02x %02x %02x", 43 data[3], 44 data[4], 45 data[5]); 46 bpf_printk(" %02x %02x %02x", 47 data[6], 48 data[7], 49 data[8]); 50 51 return 0; 52 } 53 54 SEC("fmod_ret/hid_bpf_device_event") 55 int BPF_PROG(hid_x_event, struct hid_bpf_ctx *hctx) 56 { 57 s16 x; 58 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */); 59 60 if (!data) 61 return 0; /* EPERM check */ 62 63 x = data[1] | (data[2] << 8); 64 65 x = -x; 66 67 data[1] = x & 0xFF; 68 data[2] = (x >> 8) & 0xFF; 69 return 0; 70 } 71 72 SEC("fmod_ret/hid_bpf_rdesc_fixup") 73 int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx) 74 { 75 __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */); 76 77 if (!data) 78 return 0; /* EPERM check */ 79 80 bpf_printk("rdesc: %02x %02x %02x", 81 data[0], 82 data[1], 83 data[2]); 84 bpf_printk(" %02x %02x %02x", 85 data[3], 86 data[4], 87 data[5]); 88 bpf_printk(" %02x %02x %02x ...", 89 data[6], 90 data[7], 91 data[8]); 92 93 /* 94 * The original report descriptor contains: 95 * 96 * 0x05, 0x01, // Usage Page (Generic Desktop) 30 97 * 0x16, 0x01, 0x80, // Logical Minimum (-32767) 32 98 * 0x26, 0xff, 0x7f, // Logical Maximum (32767) 35 99 * 0x09, 0x30, // Usage (X) 38 100 * 0x09, 0x31, // Usage (Y) 40 101 * 102 * So byte 39 contains Usage X and byte 41 Usage Y. 103 * 104 * We simply swap the axes here. 105 */ 106 data[39] = 0x31; 107 data[41] = 0x30; 108 109 return 0; 110 } 111 112 char _license[] SEC("license") = "GPL"; 113