xref: /linux/samples/hid/hid_mouse.bpf.c (revision 4436e6da008fee87d54c038e983e5be9a6baf8fb)
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 
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 
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")
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")
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