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