summaryrefslogtreecommitdiffstats
path: root/samples/hid/hid_mouse.bpf.c
blob: f7f722dcf56dbd92d49e38b9f772e6b7d970bfd9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// 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";