| // 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"; |