| // SPDX-License-Identifier: GPL-2.0 | |
| #include "vmlinux.h" | |
| #include <bpf/bpf_helpers.h> | |
| #include <bpf/bpf_tracing.h> | |
| #include "hid_bpf_helpers.h" | |
| static int hid_y_event(struct hid_bpf_ctx *hctx) | |
| { | |
| s16 y; | |
| __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */); | |
| if (!data) | |
| return 0; /* EPERM check */ | |
| bpf_printk("event: size: %d", hctx->size); | |
| bpf_printk("incoming event: %02x %02x %02x", | |
| data[0], | |
| data[1], | |
| data[2]); | |
| bpf_printk(" %02x %02x %02x", | |
| data[3], | |
| data[4], | |
| data[5]); | |
| bpf_printk(" %02x %02x %02x", | |
| data[6], | |
| data[7], | |
| data[8]); | |
| y = data[3] | (data[4] << 8); | |
| y = -y; | |
| data[3] = y & 0xFF; | |
| data[4] = (y >> 8) & 0xFF; | |
| bpf_printk("modified event: %02x %02x %02x", | |
| data[0], | |
| data[1], | |
| data[2]); | |
| bpf_printk(" %02x %02x %02x", | |
| data[3], | |
| data[4], | |
| data[5]); | |
| bpf_printk(" %02x %02x %02x", | |
| data[6], | |
| data[7], | |
| data[8]); | |
| return 0; | |
| } | |
| static int hid_x_event(struct hid_bpf_ctx *hctx) | |
| { | |
| s16 x; | |
| __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */); | |
| if (!data) | |
| return 0; /* EPERM check */ | |
| x = data[1] | (data[2] << 8); | |
| x = -x; | |
| data[1] = x & 0xFF; | |
| data[2] = (x >> 8) & 0xFF; | |
| return 0; | |
| } | |
| SEC("struct_ops/hid_device_event") | |
| int BPF_PROG(hid_event, struct hid_bpf_ctx *hctx, enum hid_report_type type) | |
| { | |
| int ret = hid_y_event(hctx); | |
| if (ret) | |
| return ret; | |
| return hid_x_event(hctx); | |
| } | |
| SEC("struct_ops/hid_rdesc_fixup") | |
| int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx) | |
| { | |
| __u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */); | |
| if (!data) | |
| return 0; /* EPERM check */ | |
| bpf_printk("rdesc: %02x %02x %02x", | |
| data[0], | |
| data[1], | |
| data[2]); | |
| bpf_printk(" %02x %02x %02x", | |
| data[3], | |
| data[4], | |
| data[5]); | |
| bpf_printk(" %02x %02x %02x ...", | |
| data[6], | |
| data[7], | |
| data[8]); | |
| /* | |
| * The original report descriptor contains: | |
| * | |
| * 0x05, 0x01, // Usage Page (Generic Desktop) 30 | |
| * 0x16, 0x01, 0x80, // Logical Minimum (-32767) 32 | |
| * 0x26, 0xff, 0x7f, // Logical Maximum (32767) 35 | |
| * 0x09, 0x30, // Usage (X) 38 | |
| * 0x09, 0x31, // Usage (Y) 40 | |
| * | |
| * So byte 39 contains Usage X and byte 41 Usage Y. | |
| * | |
| * We simply swap the axes here. | |
| */ | |
| data[39] = 0x31; | |
| data[41] = 0x30; | |
| return 0; | |
| } | |
| SEC(".struct_ops.link") | |
| struct hid_bpf_ops mouse_invert = { | |
| .hid_rdesc_fixup = (void *)hid_rdesc_fixup, | |
| .hid_device_event = (void *)hid_event, | |
| }; | |
| char _license[] SEC("license") = "GPL"; |