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