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
19struct 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
40static 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
294static 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
421static 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 */
431static 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
444struct 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
460char *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
478u32 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}
495