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
8SEC("fmod_ret/hid_bpf_device_event")
9int 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
54SEC("fmod_ret/hid_bpf_device_event")
55int 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
72SEC("fmod_ret/hid_bpf_rdesc_fixup")
73int 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
112char _license[] SEC("license") = "GPL";
113