// SPDX-License-Identifier: GPL-2.0 #include "vmlinux.h" #include #include #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/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/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 = { .rdesc_fixup = (void *)hid_rdesc_fixup, .device_event = (void *)hid_event, }; char _license[] SEC("license") = "GPL";