GNU Linux-libre 6.7.9-gnu
[releases.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 #include <linux/hid.h>
14
15 #include "i2c-hid.h"
16 #include "../hid-ids.h"
17
18
19 struct i2c_hid_desc_override {
20         union {
21                 struct i2c_hid_desc *i2c_hid_desc;
22                 uint8_t             *i2c_hid_desc_buffer;
23         };
24         uint8_t              *hid_report_desc;
25         unsigned int          hid_report_desc_size;
26         uint8_t              *i2c_name;
27 };
28
29
30 /*
31  * descriptors for the SIPODEV SP1064 touchpad
32  *
33  * This device does not supply any descriptors and on windows a filter
34  * driver operates between the i2c-hid layer and the device and injects
35  * these descriptors when the device is prompted. The descriptors were
36  * extracted by listening to the i2c-hid traffic that occurs between the
37  * windows filter driver and the windows i2c-hid driver.
38  */
39
40 static const struct i2c_hid_desc_override sipodev_desc = {
41         .i2c_hid_desc_buffer = (uint8_t [])
42         {0x1e, 0x00,                  /* Length of descriptor                 */
43          0x00, 0x01,                  /* Version of descriptor                */
44          0xdb, 0x01,                  /* Length of report descriptor          */
45          0x21, 0x00,                  /* Location of report descriptor        */
46          0x24, 0x00,                  /* Location of input report             */
47          0x1b, 0x00,                  /* Max input report length              */
48          0x25, 0x00,                  /* Location of output report            */
49          0x11, 0x00,                  /* Max output report length             */
50          0x22, 0x00,                  /* Location of command register         */
51          0x23, 0x00,                  /* Location of data register            */
52          0x11, 0x09,                  /* Vendor ID                            */
53          0x88, 0x52,                  /* Product ID                           */
54          0x06, 0x00,                  /* Version ID                           */
55          0x00, 0x00, 0x00, 0x00       /* Reserved                             */
56         },
57
58         .hid_report_desc = (uint8_t [])
59         {0x05, 0x01,                  /* Usage Page (Desktop),                */
60          0x09, 0x02,                  /* Usage (Mouse),                       */
61          0xA1, 0x01,                  /* Collection (Application),            */
62          0x85, 0x01,                  /*     Report ID (1),                   */
63          0x09, 0x01,                  /*     Usage (Pointer),                 */
64          0xA1, 0x00,                  /*     Collection (Physical),           */
65          0x05, 0x09,                  /*         Usage Page (Button),         */
66          0x19, 0x01,                  /*         Usage Minimum (01h),         */
67          0x29, 0x02,                  /*         Usage Maximum (02h),         */
68          0x25, 0x01,                  /*         Logical Maximum (1),         */
69          0x75, 0x01,                  /*         Report Size (1),             */
70          0x95, 0x02,                  /*         Report Count (2),            */
71          0x81, 0x02,                  /*         Input (Variable),            */
72          0x95, 0x06,                  /*         Report Count (6),            */
73          0x81, 0x01,                  /*         Input (Constant),            */
74          0x05, 0x01,                  /*         Usage Page (Desktop),        */
75          0x09, 0x30,                  /*         Usage (X),                   */
76          0x09, 0x31,                  /*         Usage (Y),                   */
77          0x15, 0x81,                  /*         Logical Minimum (-127),      */
78          0x25, 0x7F,                  /*         Logical Maximum (127),       */
79          0x75, 0x08,                  /*         Report Size (8),             */
80          0x95, 0x02,                  /*         Report Count (2),            */
81          0x81, 0x06,                  /*         Input (Variable, Relative),  */
82          0xC0,                        /*     End Collection,                  */
83          0xC0,                        /* End Collection,                      */
84          0x05, 0x0D,                  /* Usage Page (Digitizer),              */
85          0x09, 0x05,                  /* Usage (Touchpad),                    */
86          0xA1, 0x01,                  /* Collection (Application),            */
87          0x85, 0x04,                  /*     Report ID (4),                   */
88          0x05, 0x0D,                  /*     Usage Page (Digitizer),          */
89          0x09, 0x22,                  /*     Usage (Finger),                  */
90          0xA1, 0x02,                  /*     Collection (Logical),            */
91          0x15, 0x00,                  /*         Logical Minimum (0),         */
92          0x25, 0x01,                  /*         Logical Maximum (1),         */
93          0x09, 0x47,                  /*         Usage (Touch Valid),         */
94          0x09, 0x42,                  /*         Usage (Tip Switch),          */
95          0x95, 0x02,                  /*         Report Count (2),            */
96          0x75, 0x01,                  /*         Report Size (1),             */
97          0x81, 0x02,                  /*         Input (Variable),            */
98          0x95, 0x01,                  /*         Report Count (1),            */
99          0x75, 0x03,                  /*         Report Size (3),             */
100          0x25, 0x05,                  /*         Logical Maximum (5),         */
101          0x09, 0x51,                  /*         Usage (Contact Identifier),  */
102          0x81, 0x02,                  /*         Input (Variable),            */
103          0x75, 0x01,                  /*         Report Size (1),             */
104          0x95, 0x03,                  /*         Report Count (3),            */
105          0x81, 0x03,                  /*         Input (Constant, Variable),  */
106          0x05, 0x01,                  /*         Usage Page (Desktop),        */
107          0x26, 0x44, 0x0A,            /*         Logical Maximum (2628),      */
108          0x75, 0x10,                  /*         Report Size (16),            */
109          0x55, 0x0E,                  /*         Unit Exponent (14),          */
110          0x65, 0x11,                  /*         Unit (Centimeter),           */
111          0x09, 0x30,                  /*         Usage (X),                   */
112          0x46, 0x1A, 0x04,            /*         Physical Maximum (1050),     */
113          0x95, 0x01,                  /*         Report Count (1),            */
114          0x81, 0x02,                  /*         Input (Variable),            */
115          0x46, 0xBC, 0x02,            /*         Physical Maximum (700),      */
116          0x26, 0x34, 0x05,            /*         Logical Maximum (1332),      */
117          0x09, 0x31,                  /*         Usage (Y),                   */
118          0x81, 0x02,                  /*         Input (Variable),            */
119          0xC0,                        /*     End Collection,                  */
120          0x05, 0x0D,                  /*     Usage Page (Digitizer),          */
121          0x09, 0x22,                  /*     Usage (Finger),                  */
122          0xA1, 0x02,                  /*     Collection (Logical),            */
123          0x25, 0x01,                  /*         Logical Maximum (1),         */
124          0x09, 0x47,                  /*         Usage (Touch Valid),         */
125          0x09, 0x42,                  /*         Usage (Tip Switch),          */
126          0x95, 0x02,                  /*         Report Count (2),            */
127          0x75, 0x01,                  /*         Report Size (1),             */
128          0x81, 0x02,                  /*         Input (Variable),            */
129          0x95, 0x01,                  /*         Report Count (1),            */
130          0x75, 0x03,                  /*         Report Size (3),             */
131          0x25, 0x05,                  /*         Logical Maximum (5),         */
132          0x09, 0x51,                  /*         Usage (Contact Identifier),  */
133          0x81, 0x02,                  /*         Input (Variable),            */
134          0x75, 0x01,                  /*         Report Size (1),             */
135          0x95, 0x03,                  /*         Report Count (3),            */
136          0x81, 0x03,                  /*         Input (Constant, Variable),  */
137          0x05, 0x01,                  /*         Usage Page (Desktop),        */
138          0x26, 0x44, 0x0A,            /*         Logical Maximum (2628),      */
139          0x75, 0x10,                  /*         Report Size (16),            */
140          0x09, 0x30,                  /*         Usage (X),                   */
141          0x46, 0x1A, 0x04,            /*         Physical Maximum (1050),     */
142          0x95, 0x01,                  /*         Report Count (1),            */
143          0x81, 0x02,                  /*         Input (Variable),            */
144          0x46, 0xBC, 0x02,            /*         Physical Maximum (700),      */
145          0x26, 0x34, 0x05,            /*         Logical Maximum (1332),      */
146          0x09, 0x31,                  /*         Usage (Y),                   */
147          0x81, 0x02,                  /*         Input (Variable),            */
148          0xC0,                        /*     End Collection,                  */
149          0x05, 0x0D,                  /*     Usage Page (Digitizer),          */
150          0x09, 0x22,                  /*     Usage (Finger),                  */
151          0xA1, 0x02,                  /*     Collection (Logical),            */
152          0x25, 0x01,                  /*         Logical Maximum (1),         */
153          0x09, 0x47,                  /*         Usage (Touch Valid),         */
154          0x09, 0x42,                  /*         Usage (Tip Switch),          */
155          0x95, 0x02,                  /*         Report Count (2),            */
156          0x75, 0x01,                  /*         Report Size (1),             */
157          0x81, 0x02,                  /*         Input (Variable),            */
158          0x95, 0x01,                  /*         Report Count (1),            */
159          0x75, 0x03,                  /*         Report Size (3),             */
160          0x25, 0x05,                  /*         Logical Maximum (5),         */
161          0x09, 0x51,                  /*         Usage (Contact Identifier),  */
162          0x81, 0x02,                  /*         Input (Variable),            */
163          0x75, 0x01,                  /*         Report Size (1),             */
164          0x95, 0x03,                  /*         Report Count (3),            */
165          0x81, 0x03,                  /*         Input (Constant, Variable),  */
166          0x05, 0x01,                  /*         Usage Page (Desktop),        */
167          0x26, 0x44, 0x0A,            /*         Logical Maximum (2628),      */
168          0x75, 0x10,                  /*         Report Size (16),            */
169          0x09, 0x30,                  /*         Usage (X),                   */
170          0x46, 0x1A, 0x04,            /*         Physical Maximum (1050),     */
171          0x95, 0x01,                  /*         Report Count (1),            */
172          0x81, 0x02,                  /*         Input (Variable),            */
173          0x46, 0xBC, 0x02,            /*         Physical Maximum (700),      */
174          0x26, 0x34, 0x05,            /*         Logical Maximum (1332),      */
175          0x09, 0x31,                  /*         Usage (Y),                   */
176          0x81, 0x02,                  /*         Input (Variable),            */
177          0xC0,                        /*     End Collection,                  */
178          0x05, 0x0D,                  /*     Usage Page (Digitizer),          */
179          0x09, 0x22,                  /*     Usage (Finger),                  */
180          0xA1, 0x02,                  /*     Collection (Logical),            */
181          0x25, 0x01,                  /*         Logical Maximum (1),         */
182          0x09, 0x47,                  /*         Usage (Touch Valid),         */
183          0x09, 0x42,                  /*         Usage (Tip Switch),          */
184          0x95, 0x02,                  /*         Report Count (2),            */
185          0x75, 0x01,                  /*         Report Size (1),             */
186          0x81, 0x02,                  /*         Input (Variable),            */
187          0x95, 0x01,                  /*         Report Count (1),            */
188          0x75, 0x03,                  /*         Report Size (3),             */
189          0x25, 0x05,                  /*         Logical Maximum (5),         */
190          0x09, 0x51,                  /*         Usage (Contact Identifier),  */
191          0x81, 0x02,                  /*         Input (Variable),            */
192          0x75, 0x01,                  /*         Report Size (1),             */
193          0x95, 0x03,                  /*         Report Count (3),            */
194          0x81, 0x03,                  /*         Input (Constant, Variable),  */
195          0x05, 0x01,                  /*         Usage Page (Desktop),        */
196          0x26, 0x44, 0x0A,            /*         Logical Maximum (2628),      */
197          0x75, 0x10,                  /*         Report Size (16),            */
198          0x09, 0x30,                  /*         Usage (X),                   */
199          0x46, 0x1A, 0x04,            /*         Physical Maximum (1050),     */
200          0x95, 0x01,                  /*         Report Count (1),            */
201          0x81, 0x02,                  /*         Input (Variable),            */
202          0x46, 0xBC, 0x02,            /*         Physical Maximum (700),      */
203          0x26, 0x34, 0x05,            /*         Logical Maximum (1332),      */
204          0x09, 0x31,                  /*         Usage (Y),                   */
205          0x81, 0x02,                  /*         Input (Variable),            */
206          0xC0,                        /*     End Collection,                  */
207          0x05, 0x0D,                  /*     Usage Page (Digitizer),          */
208          0x55, 0x0C,                  /*     Unit Exponent (12),              */
209          0x66, 0x01, 0x10,            /*     Unit (Seconds),                  */
210          0x47, 0xFF, 0xFF, 0x00, 0x00,/*     Physical Maximum (65535),        */
211          0x27, 0xFF, 0xFF, 0x00, 0x00,/*     Logical Maximum (65535),         */
212          0x75, 0x10,                  /*     Report Size (16),                */
213          0x95, 0x01,                  /*     Report Count (1),                */
214          0x09, 0x56,                  /*     Usage (Scan Time),               */
215          0x81, 0x02,                  /*     Input (Variable),                */
216          0x09, 0x54,                  /*     Usage (Contact Count),           */
217          0x25, 0x7F,                  /*     Logical Maximum (127),           */
218          0x75, 0x08,                  /*     Report Size (8),                 */
219          0x81, 0x02,                  /*     Input (Variable),                */
220          0x05, 0x09,                  /*     Usage Page (Button),             */
221          0x09, 0x01,                  /*     Usage (01h),                     */
222          0x25, 0x01,                  /*     Logical Maximum (1),             */
223          0x75, 0x01,                  /*     Report Size (1),                 */
224          0x95, 0x01,                  /*     Report Count (1),                */
225          0x81, 0x02,                  /*     Input (Variable),                */
226          0x95, 0x07,                  /*     Report Count (7),                */
227          0x81, 0x03,                  /*     Input (Constant, Variable),      */
228          0x05, 0x0D,                  /*     Usage Page (Digitizer),          */
229          0x85, 0x02,                  /*     Report ID (2),                   */
230          0x09, 0x55,                  /*     Usage (Contact Count Maximum),   */
231          0x09, 0x59,                  /*     Usage (59h),                     */
232          0x75, 0x04,                  /*     Report Size (4),                 */
233          0x95, 0x02,                  /*     Report Count (2),                */
234          0x25, 0x0F,                  /*     Logical Maximum (15),            */
235          0xB1, 0x02,                  /*     Feature (Variable),              */
236          0x05, 0x0D,                  /*     Usage Page (Digitizer),          */
237          0x85, 0x07,                  /*     Report ID (7),                   */
238          0x09, 0x60,                  /*     Usage (60h),                     */
239          0x75, 0x01,                  /*     Report Size (1),                 */
240          0x95, 0x01,                  /*     Report Count (1),                */
241          0x25, 0x01,                  /*     Logical Maximum (1),             */
242          0xB1, 0x02,                  /*     Feature (Variable),              */
243          0x95, 0x07,                  /*     Report Count (7),                */
244          0xB1, 0x03,                  /*     Feature (Constant, Variable),    */
245          0x85, 0x06,                  /*     Report ID (6),                   */
246          0x06, 0x00, 0xFF,            /*     Usage Page (FF00h),              */
247          0x09, 0xC5,                  /*     Usage (C5h),                     */
248          0x26, 0xFF, 0x00,            /*     Logical Maximum (255),           */
249          0x75, 0x08,                  /*     Report Size (8),                 */
250          0x96, 0x00, 0x01,            /*     Report Count (256),              */
251          0xB1, 0x02,                  /*     Feature (Variable),              */
252          0xC0,                        /* End Collection,                      */
253          0x06, 0x00, 0xFF,            /* Usage Page (FF00h),                  */
254          0x09, 0x01,                  /* Usage (01h),                         */
255          0xA1, 0x01,                  /* Collection (Application),            */
256          0x85, 0x0D,                  /*     Report ID (13),                  */
257          0x26, 0xFF, 0x00,            /*     Logical Maximum (255),           */
258          0x19, 0x01,                  /*     Usage Minimum (01h),             */
259          0x29, 0x02,                  /*     Usage Maximum (02h),             */
260          0x75, 0x08,                  /*     Report Size (8),                 */
261          0x95, 0x02,                  /*     Report Count (2),                */
262          0xB1, 0x02,                  /*     Feature (Variable),              */
263          0xC0,                        /* End Collection,                      */
264          0x05, 0x0D,                  /* Usage Page (Digitizer),              */
265          0x09, 0x0E,                  /* Usage (Configuration),               */
266          0xA1, 0x01,                  /* Collection (Application),            */
267          0x85, 0x03,                  /*     Report ID (3),                   */
268          0x09, 0x22,                  /*     Usage (Finger),                  */
269          0xA1, 0x02,                  /*     Collection (Logical),            */
270          0x09, 0x52,                  /*         Usage (Device Mode),         */
271          0x25, 0x0A,                  /*         Logical Maximum (10),        */
272          0x95, 0x01,                  /*         Report Count (1),            */
273          0xB1, 0x02,                  /*         Feature (Variable),          */
274          0xC0,                        /*     End Collection,                  */
275          0x09, 0x22,                  /*     Usage (Finger),                  */
276          0xA1, 0x00,                  /*     Collection (Physical),           */
277          0x85, 0x05,                  /*         Report ID (5),               */
278          0x09, 0x57,                  /*         Usage (57h),                 */
279          0x09, 0x58,                  /*         Usage (58h),                 */
280          0x75, 0x01,                  /*         Report Size (1),             */
281          0x95, 0x02,                  /*         Report Count (2),            */
282          0x25, 0x01,                  /*         Logical Maximum (1),         */
283          0xB1, 0x02,                  /*         Feature (Variable),          */
284          0x95, 0x06,                  /*         Report Count (6),            */
285          0xB1, 0x03,                  /*         Feature (Constant, Variable),*/
286          0xC0,                        /*     End Collection,                  */
287          0xC0                         /* End Collection                       */
288         },
289         .hid_report_desc_size = 475,
290         .i2c_name = "SYNA3602:00"
291 };
292
293
294 static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = {
295         {
296                 .ident = "Teclast F6 Pro",
297                 .matches = {
298                         DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TECLAST"),
299                         DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "F6 Pro"),
300                 },
301                 .driver_data = (void *)&sipodev_desc
302         },
303         {
304                 .ident = "Teclast F7",
305                 .matches = {
306                         DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TECLAST"),
307                         DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "F7"),
308                 },
309                 .driver_data = (void *)&sipodev_desc
310         },
311         {
312                 .ident = "Trekstor Primebook C13",
313                 .matches = {
314                         DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
315                         DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Primebook C13"),
316                 },
317                 .driver_data = (void *)&sipodev_desc
318         },
319         {
320                 .ident = "Trekstor Primebook C11",
321                 .matches = {
322                         DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
323                         DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Primebook C11"),
324                 },
325                 .driver_data = (void *)&sipodev_desc
326         },
327         {
328                 /*
329                  * There are at least 2 Primebook C11B versions, the older
330                  * version has a product-name of "Primebook C11B", and a
331                  * bios version / release / firmware revision of:
332                  * V2.1.2 / 05/03/2018 / 18.2
333                  * The new version has "PRIMEBOOK C11B" as product-name and a
334                  * bios version / release / firmware revision of:
335                  * CFALKSW05_BIOS_V1.1.2 / 11/19/2018 / 19.2
336                  * Only the older version needs this quirk, note the newer
337                  * version will not match as it has a different product-name.
338                  */
339                 .ident = "Trekstor Primebook C11B",
340                 .matches = {
341                         DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
342                         DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Primebook C11B"),
343                 },
344                 .driver_data = (void *)&sipodev_desc
345         },
346         {
347                 .ident = "Trekstor SURFBOOK E11B",
348                 .matches = {
349                         DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
350                         DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SURFBOOK E11B"),
351                 },
352                 .driver_data = (void *)&sipodev_desc
353         },
354         {
355                 .ident = "Direkt-Tek DTLAPY116-2",
356                 .matches = {
357                         DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Direkt-Tek"),
358                         DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "DTLAPY116-2"),
359                 },
360                 .driver_data = (void *)&sipodev_desc
361         },
362         {
363                 .ident = "Direkt-Tek DTLAPY133-1",
364                 .matches = {
365                         DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Direkt-Tek"),
366                         DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "DTLAPY133-1"),
367                 },
368                 .driver_data = (void *)&sipodev_desc
369         },
370         {
371                 .ident = "Mediacom Flexbook Edge 11",
372                 .matches = {
373                         DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MEDIACOM"),
374                         DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "FlexBook edge11 - M-FBE11"),
375                 },
376                 .driver_data = (void *)&sipodev_desc
377         },
378         {
379                 .ident = "Mediacom FlexBook edge 13",
380                 .matches = {
381                         DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MEDIACOM"),
382                         DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "FlexBook_edge13-M-FBE13"),
383                 },
384                 .driver_data = (void *)&sipodev_desc
385         },
386         {
387                 .ident = "Odys Winbook 13",
388                 .matches = {
389                         DMI_EXACT_MATCH(DMI_SYS_VENDOR, "AXDIA International GmbH"),
390                         DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "WINBOOK 13"),
391                 },
392                 .driver_data = (void *)&sipodev_desc
393         },
394         {
395                 .ident = "iBall Aer3",
396                 .matches = {
397                         DMI_EXACT_MATCH(DMI_SYS_VENDOR, "iBall"),
398                         DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Aer3"),
399                 },
400                 .driver_data = (void *)&sipodev_desc
401         },
402         {
403                 .ident = "Schneider SCL142ALM",
404                 .matches = {
405                         DMI_EXACT_MATCH(DMI_SYS_VENDOR, "SCHNEIDER"),
406                         DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "SCL142ALM"),
407                 },
408                 .driver_data = (void *)&sipodev_desc
409         },
410         {
411                 .ident = "Vero K147",
412                 .matches = {
413                         DMI_EXACT_MATCH(DMI_SYS_VENDOR, "VERO"),
414                         DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "K147"),
415                 },
416                 .driver_data = (void *)&sipodev_desc
417         },
418         { }     /* Terminate list */
419 };
420
421 static const struct hid_device_id i2c_hid_elan_flipped_quirks = {
422         HID_DEVICE(BUS_I2C, HID_GROUP_MULTITOUCH_WIN_8, USB_VENDOR_ID_ELAN, 0x2dcd),
423                 HID_QUIRK_X_INVERT | HID_QUIRK_Y_INVERT
424 };
425
426 /*
427  * This list contains devices which have specific issues based on the system
428  * they're on and not just the device itself. The driver_data will have a
429  * specific hid device to match against.
430  */
431 static const struct dmi_system_id i2c_hid_dmi_quirk_table[] = {
432         {
433                 .ident = "DynaBook K50/FR",
434                 .matches = {
435                         DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Dynabook Inc."),
436                         DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "dynabook K50/FR"),
437                 },
438                 .driver_data = (void *)&i2c_hid_elan_flipped_quirks,
439         },
440         { }     /* Terminate list */
441 };
442
443
444 struct i2c_hid_desc *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name)
445 {
446         struct i2c_hid_desc_override *override;
447         const struct dmi_system_id *system_id;
448
449         system_id = dmi_first_match(i2c_hid_dmi_desc_override_table);
450         if (!system_id)
451                 return NULL;
452
453         override = system_id->driver_data;
454         if (strcmp(override->i2c_name, i2c_name))
455                 return NULL;
456
457         return override->i2c_hid_desc;
458 }
459
460 char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name,
461                                                unsigned int *size)
462 {
463         struct i2c_hid_desc_override *override;
464         const struct dmi_system_id *system_id;
465
466         system_id = dmi_first_match(i2c_hid_dmi_desc_override_table);
467         if (!system_id)
468                 return NULL;
469
470         override = system_id->driver_data;
471         if (strcmp(override->i2c_name, i2c_name))
472                 return NULL;
473
474         *size = override->hid_report_desc_size;
475         return override->hid_report_desc;
476 }
477
478 u32 i2c_hid_get_dmi_quirks(const u16 vendor, const u16 product)
479 {
480         u32 quirks = 0;
481         const struct dmi_system_id *system_id =
482                         dmi_first_match(i2c_hid_dmi_quirk_table);
483
484         if (system_id) {
485                 const struct hid_device_id *device_id =
486                                 (struct hid_device_id *)(system_id->driver_data);
487
488                 if (device_id && device_id->vendor == vendor &&
489                     device_id->product == product)
490                         quirks = device_id->driver_data;
491         }
492
493         return quirks;
494 }