i2c-hid: properly terminate i2c_hid_dmi_desc_override_table[] array
[muen/linux.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         { }     /* Terminate list */
342 };
343
344
345 struct i2c_hid_desc *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name)
346 {
347         struct i2c_hid_desc_override *override;
348         const struct dmi_system_id *system_id;
349
350         system_id = dmi_first_match(i2c_hid_dmi_desc_override_table);
351         if (!system_id)
352                 return NULL;
353
354         override = system_id->driver_data;
355         if (strcmp(override->i2c_name, i2c_name))
356                 return NULL;
357
358         return override->i2c_hid_desc;
359 }
360
361 char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name,
362                                                unsigned int *size)
363 {
364         struct i2c_hid_desc_override *override;
365         const struct dmi_system_id *system_id;
366
367         system_id = dmi_first_match(i2c_hid_dmi_desc_override_table);
368         if (!system_id)
369                 return NULL;
370
371         override = system_id->driver_data;
372         if (strcmp(override->i2c_name, i2c_name))
373                 return NULL;
374
375         *size = override->hid_report_desc_size;
376         return override->hid_report_desc;
377 }