]> git.ipfire.org Git - thirdparty/kernel/stable.git/blob - drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
HID: i2c-hid: override HID descriptors for certain devices
[thirdparty/kernel/stable.git] / drivers / hid / i2c-hid / i2c-hid-dmi-quirks.c
1 // SPDX-License-Identifier: GPL-2.0+
2
3 /*
4 * Quirks for I2C-HID devices that do not supply proper descriptors
5 *
6 * Copyright (c) 2018 Julian Sax <jsbc@gmx.de>
7 *
8 */
9
10 #include <linux/types.h>
11 #include <linux/dmi.h>
12 #include <linux/mod_devicetable.h>
13
14 #include "i2c-hid.h"
15
16
17 struct i2c_hid_desc_override {
18 union {
19 struct i2c_hid_desc *i2c_hid_desc;
20 uint8_t *i2c_hid_desc_buffer;
21 };
22 uint8_t *hid_report_desc;
23 unsigned int hid_report_desc_size;
24 uint8_t *i2c_name;
25 };
26
27
28 /*
29 * descriptors for the SIPODEV SP1064 touchpad
30 *
31 * This device does not supply any descriptors and on windows a filter
32 * driver operates between the i2c-hid layer and the device and injects
33 * these descriptors when the device is prompted. The descriptors were
34 * extracted by listening to the i2c-hid traffic that occurs between the
35 * windows filter driver and the windows i2c-hid driver.
36 */
37
38 static const struct i2c_hid_desc_override sipodev_desc = {
39 .i2c_hid_desc_buffer = (uint8_t [])
40 {0x1e, 0x00, /* Length of descriptor */
41 0x00, 0x01, /* Version of descriptor */
42 0xdb, 0x01, /* Length of report descriptor */
43 0x21, 0x00, /* Location of report descriptor */
44 0x24, 0x00, /* Location of input report */
45 0x1b, 0x00, /* Max input report length */
46 0x25, 0x00, /* Location of output report */
47 0x11, 0x00, /* Max output report length */
48 0x22, 0x00, /* Location of command register */
49 0x23, 0x00, /* Location of data register */
50 0x11, 0x09, /* Vendor ID */
51 0x88, 0x52, /* Product ID */
52 0x06, 0x00, /* Version ID */
53 0x00, 0x00, 0x00, 0x00 /* Reserved */
54 },
55
56 .hid_report_desc = (uint8_t [])
57 {0x05, 0x01, /* Usage Page (Desktop), */
58 0x09, 0x02, /* Usage (Mouse), */
59 0xA1, 0x01, /* Collection (Application), */
60 0x85, 0x01, /* Report ID (1), */
61 0x09, 0x01, /* Usage (Pointer), */
62 0xA1, 0x00, /* Collection (Physical), */
63 0x05, 0x09, /* Usage Page (Button), */
64 0x19, 0x01, /* Usage Minimum (01h), */
65 0x29, 0x02, /* Usage Maximum (02h), */
66 0x25, 0x01, /* Logical Maximum (1), */
67 0x75, 0x01, /* Report Size (1), */
68 0x95, 0x02, /* Report Count (2), */
69 0x81, 0x02, /* Input (Variable), */
70 0x95, 0x06, /* Report Count (6), */
71 0x81, 0x01, /* Input (Constant), */
72 0x05, 0x01, /* Usage Page (Desktop), */
73 0x09, 0x30, /* Usage (X), */
74 0x09, 0x31, /* Usage (Y), */
75 0x15, 0x81, /* Logical Minimum (-127), */
76 0x25, 0x7F, /* Logical Maximum (127), */
77 0x75, 0x08, /* Report Size (8), */
78 0x95, 0x02, /* Report Count (2), */
79 0x81, 0x06, /* Input (Variable, Relative), */
80 0xC0, /* End Collection, */
81 0xC0, /* End Collection, */
82 0x05, 0x0D, /* Usage Page (Digitizer), */
83 0x09, 0x05, /* Usage (Touchpad), */
84 0xA1, 0x01, /* Collection (Application), */
85 0x85, 0x04, /* Report ID (4), */
86 0x05, 0x0D, /* Usage Page (Digitizer), */
87 0x09, 0x22, /* Usage (Finger), */
88 0xA1, 0x02, /* Collection (Logical), */
89 0x15, 0x00, /* Logical Minimum (0), */
90 0x25, 0x01, /* Logical Maximum (1), */
91 0x09, 0x47, /* Usage (Touch Valid), */
92 0x09, 0x42, /* Usage (Tip Switch), */
93 0x95, 0x02, /* Report Count (2), */
94 0x75, 0x01, /* Report Size (1), */
95 0x81, 0x02, /* Input (Variable), */
96 0x95, 0x01, /* Report Count (1), */
97 0x75, 0x03, /* Report Size (3), */
98 0x25, 0x05, /* Logical Maximum (5), */
99 0x09, 0x51, /* Usage (Contact Identifier), */
100 0x81, 0x02, /* Input (Variable), */
101 0x75, 0x01, /* Report Size (1), */
102 0x95, 0x03, /* Report Count (3), */
103 0x81, 0x03, /* Input (Constant, Variable), */
104 0x05, 0x01, /* Usage Page (Desktop), */
105 0x26, 0x44, 0x0A, /* Logical Maximum (2628), */
106 0x75, 0x10, /* Report Size (16), */
107 0x55, 0x0E, /* Unit Exponent (14), */
108 0x65, 0x11, /* Unit (Centimeter), */
109 0x09, 0x30, /* Usage (X), */
110 0x46, 0x1A, 0x04, /* Physical Maximum (1050), */
111 0x95, 0x01, /* Report Count (1), */
112 0x81, 0x02, /* Input (Variable), */
113 0x46, 0xBC, 0x02, /* Physical Maximum (700), */
114 0x26, 0x34, 0x05, /* Logical Maximum (1332), */
115 0x09, 0x31, /* Usage (Y), */
116 0x81, 0x02, /* Input (Variable), */
117 0xC0, /* End Collection, */
118 0x05, 0x0D, /* Usage Page (Digitizer), */
119 0x09, 0x22, /* Usage (Finger), */
120 0xA1, 0x02, /* Collection (Logical), */
121 0x25, 0x01, /* Logical Maximum (1), */
122 0x09, 0x47, /* Usage (Touch Valid), */
123 0x09, 0x42, /* Usage (Tip Switch), */
124 0x95, 0x02, /* Report Count (2), */
125 0x75, 0x01, /* Report Size (1), */
126 0x81, 0x02, /* Input (Variable), */
127 0x95, 0x01, /* Report Count (1), */
128 0x75, 0x03, /* Report Size (3), */
129 0x25, 0x05, /* Logical Maximum (5), */
130 0x09, 0x51, /* Usage (Contact Identifier), */
131 0x81, 0x02, /* Input (Variable), */
132 0x75, 0x01, /* Report Size (1), */
133 0x95, 0x03, /* Report Count (3), */
134 0x81, 0x03, /* Input (Constant, Variable), */
135 0x05, 0x01, /* Usage Page (Desktop), */
136 0x26, 0x44, 0x0A, /* Logical Maximum (2628), */
137 0x75, 0x10, /* Report Size (16), */
138 0x09, 0x30, /* Usage (X), */
139 0x46, 0x1A, 0x04, /* Physical Maximum (1050), */
140 0x95, 0x01, /* Report Count (1), */
141 0x81, 0x02, /* Input (Variable), */
142 0x46, 0xBC, 0x02, /* Physical Maximum (700), */
143 0x26, 0x34, 0x05, /* Logical Maximum (1332), */
144 0x09, 0x31, /* Usage (Y), */
145 0x81, 0x02, /* Input (Variable), */
146 0xC0, /* End Collection, */
147 0x05, 0x0D, /* Usage Page (Digitizer), */
148 0x09, 0x22, /* Usage (Finger), */
149 0xA1, 0x02, /* Collection (Logical), */
150 0x25, 0x01, /* Logical Maximum (1), */
151 0x09, 0x47, /* Usage (Touch Valid), */
152 0x09, 0x42, /* Usage (Tip Switch), */
153 0x95, 0x02, /* Report Count (2), */
154 0x75, 0x01, /* Report Size (1), */
155 0x81, 0x02, /* Input (Variable), */
156 0x95, 0x01, /* Report Count (1), */
157 0x75, 0x03, /* Report Size (3), */
158 0x25, 0x05, /* Logical Maximum (5), */
159 0x09, 0x51, /* Usage (Contact Identifier), */
160 0x81, 0x02, /* Input (Variable), */
161 0x75, 0x01, /* Report Size (1), */
162 0x95, 0x03, /* Report Count (3), */
163 0x81, 0x03, /* Input (Constant, Variable), */
164 0x05, 0x01, /* Usage Page (Desktop), */
165 0x26, 0x44, 0x0A, /* Logical Maximum (2628), */
166 0x75, 0x10, /* Report Size (16), */
167 0x09, 0x30, /* Usage (X), */
168 0x46, 0x1A, 0x04, /* Physical Maximum (1050), */
169 0x95, 0x01, /* Report Count (1), */
170 0x81, 0x02, /* Input (Variable), */
171 0x46, 0xBC, 0x02, /* Physical Maximum (700), */
172 0x26, 0x34, 0x05, /* Logical Maximum (1332), */
173 0x09, 0x31, /* Usage (Y), */
174 0x81, 0x02, /* Input (Variable), */
175 0xC0, /* End Collection, */
176 0x05, 0x0D, /* Usage Page (Digitizer), */
177 0x09, 0x22, /* Usage (Finger), */
178 0xA1, 0x02, /* Collection (Logical), */
179 0x25, 0x01, /* Logical Maximum (1), */
180 0x09, 0x47, /* Usage (Touch Valid), */
181 0x09, 0x42, /* Usage (Tip Switch), */
182 0x95, 0x02, /* Report Count (2), */
183 0x75, 0x01, /* Report Size (1), */
184 0x81, 0x02, /* Input (Variable), */
185 0x95, 0x01, /* Report Count (1), */
186 0x75, 0x03, /* Report Size (3), */
187 0x25, 0x05, /* Logical Maximum (5), */
188 0x09, 0x51, /* Usage (Contact Identifier), */
189 0x81, 0x02, /* Input (Variable), */
190 0x75, 0x01, /* Report Size (1), */
191 0x95, 0x03, /* Report Count (3), */
192 0x81, 0x03, /* Input (Constant, Variable), */
193 0x05, 0x01, /* Usage Page (Desktop), */
194 0x26, 0x44, 0x0A, /* Logical Maximum (2628), */
195 0x75, 0x10, /* Report Size (16), */
196 0x09, 0x30, /* Usage (X), */
197 0x46, 0x1A, 0x04, /* Physical Maximum (1050), */
198 0x95, 0x01, /* Report Count (1), */
199 0x81, 0x02, /* Input (Variable), */
200 0x46, 0xBC, 0x02, /* Physical Maximum (700), */
201 0x26, 0x34, 0x05, /* Logical Maximum (1332), */
202 0x09, 0x31, /* Usage (Y), */
203 0x81, 0x02, /* Input (Variable), */
204 0xC0, /* End Collection, */
205 0x05, 0x0D, /* Usage Page (Digitizer), */
206 0x55, 0x0C, /* Unit Exponent (12), */
207 0x66, 0x01, 0x10, /* Unit (Seconds), */
208 0x47, 0xFF, 0xFF, 0x00, 0x00,/* Physical Maximum (65535), */
209 0x27, 0xFF, 0xFF, 0x00, 0x00,/* Logical Maximum (65535), */
210 0x75, 0x10, /* Report Size (16), */
211 0x95, 0x01, /* Report Count (1), */
212 0x09, 0x56, /* Usage (Scan Time), */
213 0x81, 0x02, /* Input (Variable), */
214 0x09, 0x54, /* Usage (Contact Count), */
215 0x25, 0x7F, /* Logical Maximum (127), */
216 0x75, 0x08, /* Report Size (8), */
217 0x81, 0x02, /* Input (Variable), */
218 0x05, 0x09, /* Usage Page (Button), */
219 0x09, 0x01, /* Usage (01h), */
220 0x25, 0x01, /* Logical Maximum (1), */
221 0x75, 0x01, /* Report Size (1), */
222 0x95, 0x01, /* Report Count (1), */
223 0x81, 0x02, /* Input (Variable), */
224 0x95, 0x07, /* Report Count (7), */
225 0x81, 0x03, /* Input (Constant, Variable), */
226 0x05, 0x0D, /* Usage Page (Digitizer), */
227 0x85, 0x02, /* Report ID (2), */
228 0x09, 0x55, /* Usage (Contact Count Maximum), */
229 0x09, 0x59, /* Usage (59h), */
230 0x75, 0x04, /* Report Size (4), */
231 0x95, 0x02, /* Report Count (2), */
232 0x25, 0x0F, /* Logical Maximum (15), */
233 0xB1, 0x02, /* Feature (Variable), */
234 0x05, 0x0D, /* Usage Page (Digitizer), */
235 0x85, 0x07, /* Report ID (7), */
236 0x09, 0x60, /* Usage (60h), */
237 0x75, 0x01, /* Report Size (1), */
238 0x95, 0x01, /* Report Count (1), */
239 0x25, 0x01, /* Logical Maximum (1), */
240 0xB1, 0x02, /* Feature (Variable), */
241 0x95, 0x07, /* Report Count (7), */
242 0xB1, 0x03, /* Feature (Constant, Variable), */
243 0x85, 0x06, /* Report ID (6), */
244 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
245 0x09, 0xC5, /* Usage (C5h), */
246 0x26, 0xFF, 0x00, /* Logical Maximum (255), */
247 0x75, 0x08, /* Report Size (8), */
248 0x96, 0x00, 0x01, /* Report Count (256), */
249 0xB1, 0x02, /* Feature (Variable), */
250 0xC0, /* End Collection, */
251 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
252 0x09, 0x01, /* Usage (01h), */
253 0xA1, 0x01, /* Collection (Application), */
254 0x85, 0x0D, /* Report ID (13), */
255 0x26, 0xFF, 0x00, /* Logical Maximum (255), */
256 0x19, 0x01, /* Usage Minimum (01h), */
257 0x29, 0x02, /* Usage Maximum (02h), */
258 0x75, 0x08, /* Report Size (8), */
259 0x95, 0x02, /* Report Count (2), */
260 0xB1, 0x02, /* Feature (Variable), */
261 0xC0, /* End Collection, */
262 0x05, 0x0D, /* Usage Page (Digitizer), */
263 0x09, 0x0E, /* Usage (Configuration), */
264 0xA1, 0x01, /* Collection (Application), */
265 0x85, 0x03, /* Report ID (3), */
266 0x09, 0x22, /* Usage (Finger), */
267 0xA1, 0x02, /* Collection (Logical), */
268 0x09, 0x52, /* Usage (Device Mode), */
269 0x25, 0x0A, /* Logical Maximum (10), */
270 0x95, 0x01, /* Report Count (1), */
271 0xB1, 0x02, /* Feature (Variable), */
272 0xC0, /* End Collection, */
273 0x09, 0x22, /* Usage (Finger), */
274 0xA1, 0x00, /* Collection (Physical), */
275 0x85, 0x05, /* Report ID (5), */
276 0x09, 0x57, /* Usage (57h), */
277 0x09, 0x58, /* Usage (58h), */
278 0x75, 0x01, /* Report Size (1), */
279 0x95, 0x02, /* Report Count (2), */
280 0x25, 0x01, /* Logical Maximum (1), */
281 0xB1, 0x02, /* Feature (Variable), */
282 0x95, 0x06, /* Report Count (6), */
283 0xB1, 0x03, /* Feature (Constant, Variable),*/
284 0xC0, /* End Collection, */
285 0xC0 /* End Collection */
286 },
287 .hid_report_desc_size = 475,
288 .i2c_name = "SYNA3602:00"
289 };
290
291
292 static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = {
293 {
294 .ident = "Teclast F6 Pro",
295 .matches = {
296 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TECLAST"),
297 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "F6 Pro"),
298 },
299 .driver_data = (void *)&sipodev_desc
300 },
301 {
302 .ident = "Teclast F7",
303 .matches = {
304 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TECLAST"),
305 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "F7"),
306 },
307 .driver_data = (void *)&sipodev_desc
308 },
309 {
310 .ident = "Trekstor Primebook C13",
311 .matches = {
312 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
313 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Primebook C13"),
314 },
315 .driver_data = (void *)&sipodev_desc
316 },
317 {
318 .ident = "Trekstor Primebook C11",
319 .matches = {
320 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
321 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Primebook C11"),
322 },
323 .driver_data = (void *)&sipodev_desc
324 },
325 {
326 .ident = "Direkt-Tek DTLAPY116-2",
327 .matches = {
328 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Direkt-Tek"),
329 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "DTLAPY116-2"),
330 },
331 .driver_data = (void *)&sipodev_desc
332 },
333 {
334 .ident = "Mediacom Flexbook Edge 11",
335 .matches = {
336 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MEDIACOM"),
337 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "FlexBook edge11 - M-FBE11"),
338 },
339 .driver_data = (void *)&sipodev_desc
340 }
341 };
342
343
344 struct i2c_hid_desc *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name)
345 {
346 struct i2c_hid_desc_override *override;
347 const struct dmi_system_id *system_id;
348
349 system_id = dmi_first_match(i2c_hid_dmi_desc_override_table);
350 if (!system_id)
351 return NULL;
352
353 override = system_id->driver_data;
354 if (strcmp(override->i2c_name, i2c_name))
355 return NULL;
356
357 return override->i2c_hid_desc;
358 }
359
360 char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name,
361 unsigned int *size)
362 {
363 struct i2c_hid_desc_override *override;
364 const struct dmi_system_id *system_id;
365
366 system_id = dmi_first_match(i2c_hid_dmi_desc_override_table);
367 if (!system_id)
368 return NULL;
369
370 override = system_id->driver_data;
371 if (strcmp(override->i2c_name, i2c_name))
372 return NULL;
373
374 *size = override->hid_report_desc_size;
375 return override->hid_report_desc;
376 }