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