1*a56a2569SBenjamin Tissoires // SPDX-License-Identifier: GPL-2.0-only
2*a56a2569SBenjamin Tissoires /* Copyright (c) 2022 Benjamin Tissoires
3*a56a2569SBenjamin Tissoires  */
4*a56a2569SBenjamin Tissoires 
5*a56a2569SBenjamin Tissoires #include "vmlinux.h"
6*a56a2569SBenjamin Tissoires #include <bpf/bpf_helpers.h>
7*a56a2569SBenjamin Tissoires #include <bpf/bpf_tracing.h>
8*a56a2569SBenjamin Tissoires #include "hid_bpf_helpers.h"
9*a56a2569SBenjamin Tissoires 
10*a56a2569SBenjamin Tissoires #define HID_UP_BUTTON		0x0009
11*a56a2569SBenjamin Tissoires #define HID_GD_WHEEL		0x0038
12*a56a2569SBenjamin Tissoires 
13*a56a2569SBenjamin Tissoires SEC("fmod_ret/hid_bpf_device_event")
BPF_PROG(hid_event,struct hid_bpf_ctx * hctx)14*a56a2569SBenjamin Tissoires int BPF_PROG(hid_event, struct hid_bpf_ctx *hctx)
15*a56a2569SBenjamin Tissoires {
16*a56a2569SBenjamin Tissoires 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 9 /* size */);
17*a56a2569SBenjamin Tissoires 
18*a56a2569SBenjamin Tissoires 	if (!data)
19*a56a2569SBenjamin Tissoires 		return 0; /* EPERM check */
20*a56a2569SBenjamin Tissoires 
21*a56a2569SBenjamin Tissoires 	/* Touch */
22*a56a2569SBenjamin Tissoires 	data[1] &= 0xfd;
23*a56a2569SBenjamin Tissoires 
24*a56a2569SBenjamin Tissoires 	/* X */
25*a56a2569SBenjamin Tissoires 	data[4] = 0;
26*a56a2569SBenjamin Tissoires 	data[5] = 0;
27*a56a2569SBenjamin Tissoires 
28*a56a2569SBenjamin Tissoires 	/* Y */
29*a56a2569SBenjamin Tissoires 	data[6] = 0;
30*a56a2569SBenjamin Tissoires 	data[7] = 0;
31*a56a2569SBenjamin Tissoires 
32*a56a2569SBenjamin Tissoires 	return 0;
33*a56a2569SBenjamin Tissoires }
34*a56a2569SBenjamin Tissoires 
35*a56a2569SBenjamin Tissoires /* 72 == 360 / 5 -> 1 report every 5 degrees */
36*a56a2569SBenjamin Tissoires int resolution = 72;
37*a56a2569SBenjamin Tissoires int physical = 5;
38*a56a2569SBenjamin Tissoires 
39*a56a2569SBenjamin Tissoires struct haptic_syscall_args {
40*a56a2569SBenjamin Tissoires 	unsigned int hid;
41*a56a2569SBenjamin Tissoires 	int retval;
42*a56a2569SBenjamin Tissoires };
43*a56a2569SBenjamin Tissoires 
44*a56a2569SBenjamin Tissoires static __u8 haptic_data[8];
45*a56a2569SBenjamin Tissoires 
46*a56a2569SBenjamin Tissoires SEC("syscall")
set_haptic(struct haptic_syscall_args * args)47*a56a2569SBenjamin Tissoires int set_haptic(struct haptic_syscall_args *args)
48*a56a2569SBenjamin Tissoires {
49*a56a2569SBenjamin Tissoires 	struct hid_bpf_ctx *ctx;
50*a56a2569SBenjamin Tissoires 	const size_t size = sizeof(haptic_data);
51*a56a2569SBenjamin Tissoires 	u16 *res;
52*a56a2569SBenjamin Tissoires 	int ret;
53*a56a2569SBenjamin Tissoires 
54*a56a2569SBenjamin Tissoires 	if (size > sizeof(haptic_data))
55*a56a2569SBenjamin Tissoires 		return -7; /* -E2BIG */
56*a56a2569SBenjamin Tissoires 
57*a56a2569SBenjamin Tissoires 	ctx = hid_bpf_allocate_context(args->hid);
58*a56a2569SBenjamin Tissoires 	if (!ctx)
59*a56a2569SBenjamin Tissoires 		return -1; /* EPERM check */
60*a56a2569SBenjamin Tissoires 
61*a56a2569SBenjamin Tissoires 	haptic_data[0] = 1;  /* report ID */
62*a56a2569SBenjamin Tissoires 
63*a56a2569SBenjamin Tissoires 	ret = hid_bpf_hw_request(ctx, haptic_data, size, HID_FEATURE_REPORT, HID_REQ_GET_REPORT);
64*a56a2569SBenjamin Tissoires 
65*a56a2569SBenjamin Tissoires 	bpf_printk("probed/remove event ret value: %d", ret);
66*a56a2569SBenjamin Tissoires 	bpf_printk("buf: %02x %02x %02x",
67*a56a2569SBenjamin Tissoires 		   haptic_data[0],
68*a56a2569SBenjamin Tissoires 		   haptic_data[1],
69*a56a2569SBenjamin Tissoires 		   haptic_data[2]);
70*a56a2569SBenjamin Tissoires 	bpf_printk("     %02x %02x %02x",
71*a56a2569SBenjamin Tissoires 		   haptic_data[3],
72*a56a2569SBenjamin Tissoires 		   haptic_data[4],
73*a56a2569SBenjamin Tissoires 		   haptic_data[5]);
74*a56a2569SBenjamin Tissoires 	bpf_printk("     %02x %02x",
75*a56a2569SBenjamin Tissoires 		   haptic_data[6],
76*a56a2569SBenjamin Tissoires 		   haptic_data[7]);
77*a56a2569SBenjamin Tissoires 
78*a56a2569SBenjamin Tissoires 	/* whenever resolution multiplier is not 3600, we have the fixed report descriptor */
79*a56a2569SBenjamin Tissoires 	res = (u16 *)&haptic_data[1];
80*a56a2569SBenjamin Tissoires 	if (*res != 3600) {
81*a56a2569SBenjamin Tissoires //		haptic_data[1] = 72; /* resolution multiplier */
82*a56a2569SBenjamin Tissoires //		haptic_data[2] = 0;  /* resolution multiplier */
83*a56a2569SBenjamin Tissoires //		haptic_data[3] = 0;  /* Repeat Count */
84*a56a2569SBenjamin Tissoires 		haptic_data[4] = 3;  /* haptic Auto Trigger */
85*a56a2569SBenjamin Tissoires //		haptic_data[5] = 5;  /* Waveform Cutoff Time */
86*a56a2569SBenjamin Tissoires //		haptic_data[6] = 80; /* Retrigger Period */
87*a56a2569SBenjamin Tissoires //		haptic_data[7] = 0;  /* Retrigger Period */
88*a56a2569SBenjamin Tissoires 	} else {
89*a56a2569SBenjamin Tissoires 		haptic_data[4] = 0;
90*a56a2569SBenjamin Tissoires 	}
91*a56a2569SBenjamin Tissoires 
92*a56a2569SBenjamin Tissoires 	ret = hid_bpf_hw_request(ctx, haptic_data, size, HID_FEATURE_REPORT, HID_REQ_SET_REPORT);
93*a56a2569SBenjamin Tissoires 
94*a56a2569SBenjamin Tissoires 	bpf_printk("set haptic ret value: %d -> %d", ret, haptic_data[4]);
95*a56a2569SBenjamin Tissoires 
96*a56a2569SBenjamin Tissoires 	args->retval = ret;
97*a56a2569SBenjamin Tissoires 
98*a56a2569SBenjamin Tissoires 	hid_bpf_release_context(ctx);
99*a56a2569SBenjamin Tissoires 
100*a56a2569SBenjamin Tissoires 	return 0;
101*a56a2569SBenjamin Tissoires }
102*a56a2569SBenjamin Tissoires 
103*a56a2569SBenjamin Tissoires /* Convert REL_DIAL into REL_WHEEL */
104*a56a2569SBenjamin Tissoires SEC("fmod_ret/hid_bpf_rdesc_fixup")
BPF_PROG(hid_rdesc_fixup,struct hid_bpf_ctx * hctx)105*a56a2569SBenjamin Tissoires int BPF_PROG(hid_rdesc_fixup, struct hid_bpf_ctx *hctx)
106*a56a2569SBenjamin Tissoires {
107*a56a2569SBenjamin Tissoires 	__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 4096 /* size */);
108*a56a2569SBenjamin Tissoires 	__u16 *res, *phys;
109*a56a2569SBenjamin Tissoires 
110*a56a2569SBenjamin Tissoires 	if (!data)
111*a56a2569SBenjamin Tissoires 		return 0; /* EPERM check */
112*a56a2569SBenjamin Tissoires 
113*a56a2569SBenjamin Tissoires 	/* Convert TOUCH into a button */
114*a56a2569SBenjamin Tissoires 	data[31] = HID_UP_BUTTON;
115*a56a2569SBenjamin Tissoires 	data[33] = 2;
116*a56a2569SBenjamin Tissoires 
117*a56a2569SBenjamin Tissoires 	/* Convert REL_DIAL into REL_WHEEL */
118*a56a2569SBenjamin Tissoires 	data[45] = HID_GD_WHEEL;
119*a56a2569SBenjamin Tissoires 
120*a56a2569SBenjamin Tissoires 	/* Change Resolution Multiplier */
121*a56a2569SBenjamin Tissoires 	phys = (__u16 *)&data[61];
122*a56a2569SBenjamin Tissoires 	*phys = physical;
123*a56a2569SBenjamin Tissoires 	res = (__u16 *)&data[66];
124*a56a2569SBenjamin Tissoires 	*res = resolution;
125*a56a2569SBenjamin Tissoires 
126*a56a2569SBenjamin Tissoires 	/* Convert X,Y from Abs to Rel */
127*a56a2569SBenjamin Tissoires 	data[88] = 0x06;
128*a56a2569SBenjamin Tissoires 	data[98] = 0x06;
129*a56a2569SBenjamin Tissoires 
130*a56a2569SBenjamin Tissoires 	return 0;
131*a56a2569SBenjamin Tissoires }
132*a56a2569SBenjamin Tissoires 
133*a56a2569SBenjamin Tissoires char _license[] SEC("license") = "GPL";
134*a56a2569SBenjamin Tissoires u32 _version SEC("version") = 1;
135