Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/hid/bpf/progs/Huion__KeydialK20-Bluetooth.bpf.c
170956 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/* Copyright (c) 2024 Red Hat, Inc
3
*/
4
5
#include "vmlinux.h"
6
#include "hid_bpf.h"
7
#include "hid_bpf_helpers.h"
8
#include "hid_report_helpers.h"
9
#include <bpf/bpf_tracing.h>
10
11
#define VID_HUION 0x256C
12
#define PID_KEYDIAL_K20_BLUETOOTH 0x8251
13
14
HID_BPF_CONFIG(
15
HID_DEVICE(BUS_BLUETOOTH, HID_GROUP_GENERIC, VID_HUION, PID_KEYDIAL_K20_BLUETOOTH),
16
);
17
18
/* This is the same device as in 0010-Huion__KeydialK20 but connected via Bluetooth.
19
* It does not need (to support?) switching to a vendor mode so we just modify the
20
* existing mode.
21
*
22
* By default it exports two hidraw nodes, only the second one sends events.
23
*
24
* This is the first hidraw node which we disable:
25
*
26
* # Keydial mini-050
27
* # Report descriptor length: 114 bytes
28
* # Bytes // Field Name Offset
29
* # ----------------------------------------------------------------------------------
30
* # 🮥 0x05, 0x01, // Usage Page (Generic Desktop) 0
31
* # 🭬 0x09, 0x0e, // Usage (System Multi-Axis Controller) 2
32
* # 0xa1, 0x01, // Collection (Application) 4
33
* # â”… 0x85, 0x03, // Report ID (3) 6
34
* # 🮥 0x05, 0x0d, // Usage Page (Digitizers) 8
35
* # 0x75, 0x08, // Report Size (8) 10
36
* # 0x95, 0x01, // Report Count (1) 12
37
* # ┇ 0x81, 0x01, // Input (Cnst,Arr,Abs) 14
38
* # 🭬 0x09, 0x21, // Usage (Puck) 16
39
* # 0xa1, 0x02, // Collection (Logical) 18
40
* # 0x15, 0x00, // Logical Minimum (0) 20
41
* # 0x25, 0x01, // Logical Maximum (1) 22
42
* # 0x75, 0x01, // Report Size (1) 24
43
* # 0x95, 0x01, // Report Count (1) 26
44
* # 0xa1, 0x00, // Collection (Physical) 28
45
* # 🮥 0x05, 0x09, // Usage Page (Button) 30
46
* # 🭬 0x09, 0x01, // Usage (Button 1) 32
47
* # ┇ 0x81, 0x02, // Input (Data,Var,Abs) 34
48
* # 🮥 0x05, 0x0d, // Usage Page (Digitizers) 36
49
* # 🭬 0x09, 0x33, // Usage (Touch) 38
50
* # ┇ 0x81, 0x02, // Input (Data,Var,Abs) 40
51
* # 0x95, 0x06, // Report Count (6) 42
52
* # ┇ 0x81, 0x03, // Input (Cnst,Var,Abs) 44
53
* # 0xa1, 0x02, // Collection (Logical) 46
54
* # 🮥 0x05, 0x01, // Usage Page (Generic Desktop) 48
55
* # 🭬 0x09, 0x37, // Usage (Dial) 50
56
* # 0x16, 0x00, 0x80, // Logical Minimum (32768) 52
57
* # 0x26, 0xff, 0x7f, // Logical Maximum (32767) 55
58
* # 0x75, 0x10, // Report Size (16) 58
59
* # 0x95, 0x01, // Report Count (1) 60
60
* # ┇ 0x81, 0x06, // Input (Data,Var,Rel) 62
61
* # 0x35, 0x00, // Physical Minimum (0) 64
62
* # 0x46, 0x10, 0x0e, // Physical Maximum (3600) 66
63
* # 0x15, 0x00, // Logical Minimum (0) 69
64
* # 0x26, 0x10, 0x0e, // Logical Maximum (3600) 71
65
* # 🭬 0x09, 0x48, // Usage (Resolution Multiplier) 74
66
* # â•‘ 0xb1, 0x02, // Feature (Data,Var,Abs) 76
67
* # 0x45, 0x00, // Physical Maximum (0) 78
68
* # 0xc0, // End Collection 80
69
* # 0x75, 0x08, // Report Size (8) 81
70
* # 0x95, 0x01, // Report Count (1) 83
71
* # ┇ 0x81, 0x01, // Input (Cnst,Arr,Abs) 85
72
* # 0x75, 0x08, // Report Size (8) 87
73
* # 0x95, 0x01, // Report Count (1) 89
74
* # ┇ 0x81, 0x01, // Input (Cnst,Arr,Abs) 91
75
* # 0x75, 0x08, // Report Size (8) 93
76
* # 0x95, 0x01, // Report Count (1) 95
77
* # ┇ 0x81, 0x01, // Input (Cnst,Arr,Abs) 97
78
* # 0x75, 0x08, // Report Size (8) 99
79
* # 0x95, 0x01, // Report Count (1) 101
80
* # ┇ 0x81, 0x01, // Input (Cnst,Arr,Abs) 103
81
* # 0x75, 0x08, // Report Size (8) 105
82
* # 0x95, 0x01, // Report Count (1) 107
83
* # ┇ 0x81, 0x01, // Input (Cnst,Arr,Abs) 109
84
* # 0xc0, // End Collection 111
85
* # 0xc0, // End Collection 112
86
* # 0xc0, // End Collection 113
87
* R: 114 05 01 09 0e a1 01 85 03 05 0d 75 08 95 01 81 01 09 21 a1 02 15 00 25 01 75 01 95 01 a1 00 05 09 09 01 81 02 05 0d 09 33 81 02 95 06 81 03 a1 02 05 01 09 37 16 00 80 26 ff 7f 75 10 95 01 81 06 35 00 46 10 0e 15 00 26 10 0e 09 48 b1 02 45 00 c0 75 08 95 01 81 01 75 08 95 01 81 01 75 08 95 01 81 01 75 08 95 01 81 01 75 08 95 01 81 01 c0 c0 c0
88
* N: Keydial mini-050
89
* I: 5 256c 8251
90
*
91
* The second hidraw node is what sends events:
92
*
93
* # Keydial mini-050
94
* # Report descriptor length: 160 bytes
95
* # Bytes // Field Name Offset
96
* # ----------------------------------------------------------------------------------
97
* # 🮥 0x05, 0x01, // Usage Page (Generic Desktop) 0
98
* # 🭬 0x09, 0x06, // Usage (Keyboard) 2
99
* # 0xa1, 0x01, // Collection (Application) 4
100
* # â”… 0x85, 0x01, // Report ID (1) 6
101
* # 🮥 0x05, 0x07, // Usage Page (Keyboard/Keypad) 8
102
* # 🭬 0x19, 0xe0, // Usage Minimum (224) 10
103
* # 🭬 0x29, 0xe7, // Usage Maximum (231) 12
104
* # 0x15, 0x00, // Logical Minimum (0) 14
105
* # 0x25, 0x01, // Logical Maximum (1) 16
106
* # 0x75, 0x01, // Report Size (1) 18
107
* # 0x95, 0x08, // Report Count (8) 20
108
* # ┇ 0x81, 0x02, // Input (Data,Var,Abs) 22
109
* # 0x95, 0x01, // Report Count (1) 24
110
* # 0x75, 0x08, // Report Size (8) 26
111
* # ┇ 0x81, 0x01, // Input (Cnst,Arr,Abs) 28
112
* # 0x95, 0x05, // Report Count (5) 30
113
* # 0x75, 0x01, // Report Size (1) 32
114
* # 🮥 0x05, 0x08, // Usage Page (LED) 34
115
* # 🭬 0x19, 0x01, // Usage Minimum (1) 36
116
* # 🭬 0x29, 0x05, // Usage Maximum (5) 38
117
* # ┊ 0x91, 0x02, // Output (Data,Var,Abs) 40
118
* # 0x95, 0x01, // Report Count (1) 42
119
* # 0x75, 0x03, // Report Size (3) 44
120
* # ┊ 0x91, 0x01, // Output (Cnst,Arr,Abs) 46
121
* # 0x95, 0x06, // Report Count (6) 48
122
* # 0x75, 0x08, // Report Size (8) 50
123
* # 0x15, 0x00, // Logical Minimum (0) 52
124
* # 0x25, 0xf1, // Logical Maximum (241) 54
125
* # 🮥 0x05, 0x07, // Usage Page (Keyboard/Keypad) 56
126
* # 🭬 0x19, 0x00, // Usage Minimum (0) 58
127
* # 🭬 0x29, 0xf1, // Usage Maximum (241) 60
128
* # ┇ 0x81, 0x00, // Input (Data,Arr,Abs) 62
129
* # 0xc0, // End Collection 64
130
* # 🮥 0x05, 0x0c, // Usage Page (Consumer) 65
131
* # 🭬 0x09, 0x01, // Usage (Consumer Control) 67
132
* # 0xa1, 0x01, // Collection (Application) 69
133
* # â”… 0x85, 0x02, // Report ID (2) 71
134
* # 🮥 0x05, 0x0c, // Usage Page (Consumer) 73
135
* # 🭬 0x19, 0x00, // Usage Minimum (0) 75
136
* # 🭬 0x2a, 0x80, 0x03, // Usage Maximum (896) 77
137
* # 0x15, 0x00, // Logical Minimum (0) 80
138
* # 0x26, 0x80, 0x03, // Logical Maximum (896) 82
139
* # 0x75, 0x10, // Report Size (16) 85
140
* # 0x95, 0x01, // Report Count (1) 87
141
* # ┇ 0x81, 0x00, // Input (Data,Arr,Abs) 89
142
* # 0xc0, // End Collection 91
143
* # 🮥 0x05, 0x01, // Usage Page (Generic Desktop) 92
144
* # 🭬 0x09, 0x02, // Usage (Mouse) 94
145
* # 0xa1, 0x01, // Collection (Application) 96
146
* # 🭬 0x09, 0x01, // Usage (Pointer) 98
147
* # â”… 0x85, 0x05, // Report ID (5) 100
148
* # 0xa1, 0x00, // Collection (Physical) 102
149
* # 🮥 0x05, 0x09, // Usage Page (Button) 104
150
* # 🭬 0x19, 0x01, // Usage Minimum (1) 106
151
* # 🭬 0x29, 0x05, // Usage Maximum (5) 108
152
* # 0x15, 0x00, // Logical Minimum (0) 110
153
* # 0x25, 0x01, // Logical Maximum (1) 112
154
* # 0x95, 0x05, // Report Count (5) 114
155
* # 0x75, 0x01, // Report Size (1) 116
156
* # ┇ 0x81, 0x02, // Input (Data,Var,Abs) 118
157
* # 0x95, 0x01, // Report Count (1) 120
158
* # 0x75, 0x03, // Report Size (3) 122
159
* # ┇ 0x81, 0x01, // Input (Cnst,Arr,Abs) 124
160
* # 🮥 0x05, 0x01, // Usage Page (Generic Desktop) 126
161
* # 🭬 0x09, 0x30, // Usage (X) 128
162
* # 🭬 0x09, 0x31, // Usage (Y) 130
163
* # 0x16, 0x01, 0x80, // Logical Minimum (32769) 132
164
* # 0x26, 0xff, 0x7f, // Logical Maximum (32767) 135
165
* # 0x75, 0x10, // Report Size (16) 138
166
* # 0x95, 0x02, // Report Count (2) 140
167
* # ┇ 0x81, 0x06, // Input (Data,Var,Rel) 142
168
* # 🮥 0x05, 0x01, // Usage Page (Generic Desktop) 144
169
* # 🭬 0x09, 0x38, // Usage (Wheel) 146
170
* # 0x15, 0x81, // Logical Minimum (129) 148
171
* # 0x25, 0x7f, // Logical Maximum (127) 150
172
* # 0x95, 0x01, // Report Count (1) 152
173
* # 0x75, 0x08, // Report Size (8) 154
174
* # ┇ 0x81, 0x06, // Input (Data,Var,Rel) 156
175
* # 0xc0, // End Collection 158
176
* # 0xc0, // End Collection 159
177
* R: 160 05 01 09 06 a1 01 85 01 05 07 19 e0 29 e7 15 00 25 01 75 01 95 08 81 02 95 01 75 08 81 01 95 05 75 01 05 08 19 01 29 05 91 02 95 01 75 03 91 01 95 06 75 08 15 00 25 f1 05 07 19 00 29 f1 81 00 c0 05 0c 09 01 a1 01 85 02 05 0c 19 00 2a 80 03 15 00 26 80 03 75 10 95 01 81 00 c0 05 01 09 02 a1 01 09 01 85 05 a1 00 05 09 19 01 29 05 15 00 25 01 95 05 75 01 81 02 95 01 75 03 81 01 05 01 09 30 09 31 16 01 80 26 ff 7f 75 10 95 02 81 06 05 01 09 38 15 81 25 7f 95 01 75 08 81 06 c0 c0
178
* N: Keydial mini-050
179
* I: 5 256c 8251
180
* # Report descriptor:
181
* # ------- Input Report -------
182
* # â–‘ Report ID: 1
183
* # â–‘ | Report size: 72 bits
184
* # â–‘ Bit: 8 Usage: 0007/00e0: Keyboard/Keypad / Keyboard LeftControl Logical Range: 0..=1
185
* # â–‘ Bit: 9 Usage: 0007/00e1: Keyboard/Keypad / Keyboard LeftShift Logical Range: 0..=1
186
* # â–‘ Bit: 10 Usage: 0007/00e2: Keyboard/Keypad / Keyboard LeftAlt Logical Range: 0..=1
187
* # â–‘ Bit: 11 Usage: 0007/00e3: Keyboard/Keypad / Keyboard Left GUI Logical Range: 0..=1
188
* # â–‘ Bit: 12 Usage: 0007/00e4: Keyboard/Keypad / Keyboard RightControl Logical Range: 0..=1
189
* # â–‘ Bit: 13 Usage: 0007/00e5: Keyboard/Keypad / Keyboard RightShift Logical Range: 0..=1
190
* # â–‘ Bit: 14 Usage: 0007/00e6: Keyboard/Keypad / Keyboard RightAlt Logical Range: 0..=1
191
* # â–‘ Bit: 15 Usage: 0007/00e7: Keyboard/Keypad / Keyboard Right GUI Logical Range: 0..=1
192
* # â–‘ Bits: 16..=23 ######### Padding
193
* # â–‘ Bits: 24..=71 Usages: Logical Range: 0..=241
194
* # â–‘ 0007/0000: <unknown>
195
* # â–‘ 0007/0001: Keyboard/Keypad / ErrorRollOver
196
* # â–‘ 0007/0002: Keyboard/Keypad / POSTFail
197
* # â–‘ 0007/0003: Keyboard/Keypad / ErrorUndefined
198
* # â–‘ 0007/0004: Keyboard/Keypad / Keyboard A
199
* # â–‘ ... use --full to see all usages
200
* # ------- Input Report -------
201
* # â–’ Report ID: 2
202
* # â–’ | Report size: 24 bits
203
* # â–’ Bits: 8..=23 Usages: Logical Range: 0..=896
204
* # â–’ 000c/0000: <unknown>
205
* # â–’ 000c/0001: Consumer / Consumer Control
206
* # â–’ 000c/0002: Consumer / Numeric Key Pad
207
* # â–’ 000c/0003: Consumer / Programmable Buttons
208
* # â–’ 000c/0004: Consumer / Microphone
209
* # â–’ ... use --full to see all usages
210
* # ------- Input Report -------
211
* # â–ž Report ID: 5
212
* # â–ž | Report size: 56 bits
213
* # â–ž Bit: 8 Usage: 0009/0001: Button / Button 1 Logical Range: 0..=1
214
* # â–ž Bit: 9 Usage: 0009/0002: Button / Button 2 Logical Range: 0..=1
215
* # â–ž Bit: 10 Usage: 0009/0003: Button / Button 3 Logical Range: 0..=1
216
* # â–ž Bit: 11 Usage: 0009/0004: Button / Button 4 Logical Range: 0..=1
217
* # â–ž Bit: 12 Usage: 0009/0005: Button / Button 5 Logical Range: 0..=1
218
* # â–ž Bits: 13..=15 ######### Padding
219
* # â–ž Bits: 16..=31 Usage: 0001/0030: Generic Desktop / X Logical Range: 32769..=32767
220
* # â–ž Bits: 32..=47 Usage: 0001/0031: Generic Desktop / Y Logical Range: 32769..=32767
221
* # â–ž Bits: 48..=55 Usage: 0001/0038: Generic Desktop / Wheel Logical Range: 129..=127
222
* # ------- Output Report -------
223
* # â–‘ Report ID: 1
224
* # â–‘ | Report size: 16 bits
225
* # â–‘ Bit: 8 Usage: 0008/0001: LED / Num Lock Logical Range: 0..=1
226
* # â–‘ Bit: 9 Usage: 0008/0002: LED / Caps Lock Logical Range: 0..=1
227
* # â–‘ Bit: 10 Usage: 0008/0003: LED / Scroll Lock Logical Range: 0..=1
228
* # â–‘ Bit: 11 Usage: 0008/0004: LED / Compose Logical Range: 0..=1
229
* # â–‘ Bit: 12 Usage: 0008/0005: LED / Kana Logical Range: 0..=1
230
* # â–‘ Bits: 13..=15 ######### Padding
231
* ##############################################################################
232
* # Event nodes:
233
* # - /dev/input/event12: "Keydial mini-050 Keyboard"
234
* # - /dev/input/event14: "Keydial mini-050 Mouse"
235
* ##############################################################################
236
* # Recorded events below in format:
237
* # E: <seconds>.<microseconds> <length-in-bytes> [bytes ...]
238
* #
239
*
240
* - Report ID 1 sends keyboard shortcuts when pressing the buttons, e.g.
241
*
242
* # â–‘ Report ID: 1 /
243
* # â–‘ Keyboard LeftControl: 0 |Keyboard LeftShift: 0 |Keyboard LeftAlt: 0 |Keyboard Left GUI: 0 |Keyboard RightControl: 0 |Keyboard RightShift: 0 |Keyboard RightAlt: 0 |Keyboard Right GUI: 0 |<8 bits padding> |0007/0000: 0| Keyboard K: 14| 0007/0000: 0| 0007/0000: 0| 0007/0000: 0| 0007/0000: 0
244
* E: 000000.000292 9 01 00 00 00 0e 00 00 00 00
245
*
246
* - Report ID 2 sends the button inside the wheel/dial thing
247
* # â–’ Report ID: 2 /
248
* # â–’ Play/Pause: 205
249
* E: 000134.347845 3 02 cd 00
250
* # â–’ Report ID: 2 /
251
* # â–’ 000c/0000: 0
252
* E: 000134.444965 3 02 00 00
253
*
254
* - Report ID 5 sends the wheel relative events (always a double-event with the second as zero)
255
* # â–ž Report ID: 5 /
256
* # â–ž Button 1: 0 |Button 2: 0 |Button 3: 0 |Button 4: 0 |Button 5: 0 |<3 bits padding> |X: 0 |Y: 0 |Wheel: 255
257
* E: 000064.859915 7 05 00 00 00 00 00 ff
258
* # â–ž Report ID: 5 /
259
* # â–ž Button 1: 0 |Button 2: 0 |Button 3: 0 |Button 4: 0 |Button 5: 0 |<3 bits padding> |X: 0 |Y: 0 |Wheel: 0
260
* E: 000064.882009 7 05 00 00 00 00 00 00
261
*/
262
263
#define BT_PAD_REPORT_DESCRIPTOR_LENGTH 160
264
#define BT_PUCK_REPORT_DESCRIPTOR_LENGTH 114 // This one doesn't send events
265
#define BT_PAD_KBD_REPORT_ID 1
266
#define BT_PAD_CC_REPORT_ID 2
267
#define BT_PAD_MOUSE_REPORT_ID 5
268
#define BT_PAD_KBD_REPORT_LENGTH 9
269
#define BT_PAD_CC_REPORT_LENGTH 3
270
#define BT_PAD_MOUSE_REPORT_LENGTH 7
271
#define OUR_REPORT_ID 11 /* "randomly" picked report ID for our reports */
272
273
__u32 last_button_state = 0;
274
275
static const __u8 disabled_rdesc_puck[] = {
276
FixedSizeVendorReport(BT_PUCK_REPORT_DESCRIPTOR_LENGTH)
277
};
278
279
static const __u8 fixed_rdesc_pad[] = {
280
UsagePage_GenericDesktop
281
Usage_GD_Keypad
282
CollectionApplication(
283
// Byte 0
284
ReportId(OUR_REPORT_ID)
285
UsagePage_Digitizers
286
Usage_Dig_TabletFunctionKeys
287
CollectionPhysical(
288
// Byte 1 is a button so we look like a tablet
289
Usage_Dig_BarrelSwitch // BTN_STYLUS, needed so we get to be a tablet pad
290
ReportCount(1)
291
ReportSize(1)
292
Input(Var|Abs)
293
ReportCount(7) // Padding
294
Input(Const)
295
// Bytes 2/3 - x/y just exist so we get to be a tablet pad
296
UsagePage_GenericDesktop
297
Usage_GD_X
298
Usage_GD_Y
299
LogicalMinimum_i8(0x0)
300
LogicalMaximum_i8(0x1)
301
ReportCount(2)
302
ReportSize(8)
303
Input(Var|Abs)
304
// Bytes 4-7 are the button state for 19 buttons + pad out to u32
305
// We send the first 10 buttons as buttons 1-10 which is BTN_0 -> BTN_9
306
UsagePage_Button
307
UsageMinimum_i8(1)
308
UsageMaximum_i8(10)
309
LogicalMinimum_i8(0x0)
310
LogicalMaximum_i8(0x1)
311
ReportCount(10)
312
ReportSize(1)
313
Input(Var|Abs)
314
// We send the other 9 buttons as buttons 0x31 and above -> BTN_A - BTN_TL2
315
UsageMinimum_i8(0x31)
316
UsageMaximum_i8(0x3a)
317
ReportCount(9)
318
ReportSize(1)
319
Input(Var|Abs)
320
ReportCount(13)
321
ReportSize(1)
322
Input(Const) // padding
323
// Byte 8 is the wheel
324
UsagePage_GenericDesktop
325
Usage_GD_Wheel
326
LogicalMinimum_i8(-1)
327
LogicalMaximum_i8(1)
328
ReportCount(1)
329
ReportSize(8)
330
Input(Var|Rel)
331
)
332
// Make sure we match our original report length
333
FixedSizeVendorReport(BT_PAD_KBD_REPORT_LENGTH)
334
)
335
};
336
337
SEC(HID_BPF_RDESC_FIXUP)
338
int BPF_PROG(k20_bt_fix_rdesc, struct hid_bpf_ctx *hctx)
339
{
340
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, HID_MAX_DESCRIPTOR_SIZE /* size */);
341
__s32 rdesc_size = hctx->size;
342
343
if (!data)
344
return 0; /* EPERM check */
345
346
if (rdesc_size == BT_PAD_REPORT_DESCRIPTOR_LENGTH) {
347
__builtin_memcpy(data, fixed_rdesc_pad, sizeof(fixed_rdesc_pad));
348
return sizeof(fixed_rdesc_pad);
349
}
350
if (rdesc_size == BT_PUCK_REPORT_DESCRIPTOR_LENGTH) {
351
// This hidraw node doesn't send anything and can be ignored
352
__builtin_memcpy(data, disabled_rdesc_puck, sizeof(disabled_rdesc_puck));
353
return sizeof(disabled_rdesc_puck);
354
}
355
356
return 0;
357
}
358
359
SEC(HID_BPF_DEVICE_EVENT)
360
int BPF_PROG(k20_bt_fix_events, struct hid_bpf_ctx *hctx)
361
{
362
__u8 *data = hid_bpf_get_data(hctx, 0 /* offset */, 12 /* size */);
363
struct pad_report {
364
__u8 report_id;
365
__u8 btn_stylus:1;
366
__u8 pad:7;
367
__u8 x;
368
__u8 y;
369
__u32 buttons;
370
__u8 wheel;
371
} __packed * pad_report = (struct pad_report *)data;
372
373
if (!data)
374
return 0; /* EPERM check */
375
376
/* Report ID 1 - Keyboard events (button presses) */
377
if (data[0] == BT_PAD_KBD_REPORT_ID) {
378
const __u8 button_mapping[] = {
379
0x0e, /* Button 1: K */
380
0x0a, /* Button 2: G */
381
0x0f, /* Button 3: L */
382
0x4c, /* Button 4: Delete */
383
0x0c, /* Button 5: I */
384
0x07, /* Button 6: D */
385
0x05, /* Button 7: B */
386
0x08, /* Button 8: E */
387
0x16, /* Button 9: S */
388
0x1d, /* Button 10: Z */
389
0x06, /* Button 11: C */
390
0x19, /* Button 12: V */
391
0xff, /* Button 13: LeftControl */
392
0xff, /* Button 14: LeftAlt */
393
0xff, /* Button 15: LeftShift */
394
0x28, /* Button 16: Return Enter */
395
0x2c, /* Button 17: Spacebar */
396
0x11, /* Button 18: N */
397
};
398
399
__u8 modifiers = data[1];
400
__u32 buttons = 0;
401
402
if (modifiers & 0x01) { /* Control */
403
buttons |= BIT(12);
404
}
405
if (modifiers & 0x02) { /* Shift */
406
buttons |= BIT(14);
407
}
408
if (modifiers & 0x04) { /* Alt */
409
buttons |= BIT(13);
410
}
411
412
for (int i = 4; i < BT_PAD_KBD_REPORT_LENGTH; i++) {
413
if (!data[i])
414
break;
415
416
for (size_t b = 0; b < ARRAY_SIZE(button_mapping); b++) {
417
if (data[i] != 0xff && data[i] == button_mapping[b]) {
418
buttons |= BIT(b);
419
break;
420
}
421
}
422
}
423
424
last_button_state = buttons;
425
426
pad_report->report_id = OUR_REPORT_ID;
427
pad_report->btn_stylus = 0;
428
pad_report->x = 0;
429
pad_report->y = 0;
430
pad_report->buttons = buttons;
431
pad_report->wheel = 0;
432
433
return sizeof(struct pad_report);
434
}
435
436
/* Report ID 2 - Consumer control events (the button inside the wheel) */
437
if (data[0] == BT_PAD_CC_REPORT_ID) {
438
const __u8 PlayPause = 0xcd;
439
440
if (data[1] == PlayPause)
441
last_button_state |= BIT(18);
442
else
443
last_button_state &= ~BIT(18);
444
445
pad_report->report_id = OUR_REPORT_ID;
446
pad_report->btn_stylus = 0;
447
pad_report->x = 0;
448
pad_report->y = 0;
449
pad_report->buttons = last_button_state;
450
pad_report->wheel = 0;
451
452
return sizeof(struct pad_report);
453
}
454
455
/* Report ID 5 - Mouse events (wheel rotation) */
456
if (data[0] == BT_PAD_MOUSE_REPORT_ID) {
457
__u8 wheel_delta = data[6];
458
459
pad_report->report_id = OUR_REPORT_ID;
460
pad_report->btn_stylus = 0;
461
pad_report->x = 0;
462
pad_report->y = 0;
463
pad_report->buttons = last_button_state;
464
pad_report->wheel = wheel_delta;
465
466
return sizeof(struct pad_report);
467
}
468
469
return 0;
470
}
471
472
HID_BPF_OPS(keydial_k20_bluetooth) = {
473
.hid_device_event = (void *)k20_bt_fix_events,
474
.hid_rdesc_fixup = (void *)k20_bt_fix_rdesc,
475
};
476
477
SEC("syscall")
478
int probe(struct hid_bpf_probe_args *ctx)
479
{
480
switch (ctx->rdesc_size) {
481
case BT_PAD_REPORT_DESCRIPTOR_LENGTH:
482
case BT_PUCK_REPORT_DESCRIPTOR_LENGTH:
483
ctx->retval = 0;
484
break;
485
default:
486
ctx->retval = -EINVAL;
487
}
488
489
return 0;
490
}
491
492
char _license[] SEC("license") = "GPL";
493
494