]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blob - queue-4.14/hid-i2c-hid-override-hid-descriptors-for-certain-dev.patch
autosel patches for 4.14
[thirdparty/kernel/stable-queue.git] / queue-4.14 / hid-i2c-hid-override-hid-descriptors-for-certain-dev.patch
1 From 43bdcb2c62ee2195fd4054909d4ccddfc4cbe1b3 Mon Sep 17 00:00:00 2001
2 From: Julian Sax <jsbc@gmx.de>
3 Date: Wed, 19 Sep 2018 11:46:23 +0200
4 Subject: HID: i2c-hid: override HID descriptors for certain devices
5
6 [ Upstream commit 9ee3e06610fdb8a601cde59c92089fb6c1deb4aa ]
7
8 A particular touchpad (SIPODEV SP1064) refuses to supply the HID
9 descriptors. This patch provides the framework for overriding these
10 descriptors based on DMI data. It also includes the descriptors for
11 said touchpad, which were extracted by listening to the traffic of the
12 windows filter driver, as well as the DMI data for the laptops known
13 to use this device.
14
15 Relevant Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1526312
16
17 Cc: Hans de Goede <hdegoede@redhat.com>
18 Reported-and-tested-by: ahormann@gmx.net
19 Reported-and-tested-by: Bruno Jesus <bruno.fl.jesus@gmail.com>
20 Reported-and-tested-by: Dietrich <enaut.w@googlemail.com>
21 Reported-and-tested-by: kloxdami@yahoo.com
22 Signed-off-by: Julian Sax <jsbc@gmx.de>
23 Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
24 Signed-off-by: Jiri Kosina <jkosina@suse.cz>
25 Signed-off-by: Sasha Levin <sashal@kernel.org>
26 ---
27 drivers/hid/i2c-hid/Makefile | 3 +
28 .../hid/i2c-hid/{i2c-hid.c => i2c-hid-core.c} | 56 ++-
29 drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c | 376 ++++++++++++++++++
30 drivers/hid/i2c-hid/i2c-hid.h | 20 +
31 4 files changed, 437 insertions(+), 18 deletions(-)
32 rename drivers/hid/i2c-hid/{i2c-hid.c => i2c-hid-core.c} (96%)
33 create mode 100644 drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
34 create mode 100644 drivers/hid/i2c-hid/i2c-hid.h
35
36 diff --git a/drivers/hid/i2c-hid/Makefile b/drivers/hid/i2c-hid/Makefile
37 index 832d8f9aaba2..099e1ce2f234 100644
38 --- a/drivers/hid/i2c-hid/Makefile
39 +++ b/drivers/hid/i2c-hid/Makefile
40 @@ -3,3 +3,6 @@
41 #
42
43 obj-$(CONFIG_I2C_HID) += i2c-hid.o
44 +
45 +i2c-hid-objs = i2c-hid-core.o
46 +i2c-hid-$(CONFIG_DMI) += i2c-hid-dmi-quirks.o
47 diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid-core.c
48 similarity index 96%
49 rename from drivers/hid/i2c-hid/i2c-hid.c
50 rename to drivers/hid/i2c-hid/i2c-hid-core.c
51 index 136a34dc31b8..7842d76aa813 100644
52 --- a/drivers/hid/i2c-hid/i2c-hid.c
53 +++ b/drivers/hid/i2c-hid/i2c-hid-core.c
54 @@ -43,6 +43,7 @@
55 #include <linux/platform_data/i2c-hid.h>
56
57 #include "../hid-ids.h"
58 +#include "i2c-hid.h"
59
60 /* quirks to control the device */
61 #define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV BIT(0)
62 @@ -663,6 +664,7 @@ static int i2c_hid_parse(struct hid_device *hid)
63 char *rdesc;
64 int ret;
65 int tries = 3;
66 + char *use_override;
67
68 i2c_hid_dbg(ihid, "entering %s\n", __func__);
69
70 @@ -681,26 +683,37 @@ static int i2c_hid_parse(struct hid_device *hid)
71 if (ret)
72 return ret;
73
74 - rdesc = kzalloc(rsize, GFP_KERNEL);
75 + use_override = i2c_hid_get_dmi_hid_report_desc_override(client->name,
76 + &rsize);
77
78 - if (!rdesc) {
79 - dbg_hid("couldn't allocate rdesc memory\n");
80 - return -ENOMEM;
81 - }
82 + if (use_override) {
83 + rdesc = use_override;
84 + i2c_hid_dbg(ihid, "Using a HID report descriptor override\n");
85 + } else {
86 + rdesc = kzalloc(rsize, GFP_KERNEL);
87
88 - i2c_hid_dbg(ihid, "asking HID report descriptor\n");
89 + if (!rdesc) {
90 + dbg_hid("couldn't allocate rdesc memory\n");
91 + return -ENOMEM;
92 + }
93
94 - ret = i2c_hid_command(client, &hid_report_descr_cmd, rdesc, rsize);
95 - if (ret) {
96 - hid_err(hid, "reading report descriptor failed\n");
97 - kfree(rdesc);
98 - return -EIO;
99 + i2c_hid_dbg(ihid, "asking HID report descriptor\n");
100 +
101 + ret = i2c_hid_command(client, &hid_report_descr_cmd,
102 + rdesc, rsize);
103 + if (ret) {
104 + hid_err(hid, "reading report descriptor failed\n");
105 + kfree(rdesc);
106 + return -EIO;
107 + }
108 }
109
110 i2c_hid_dbg(ihid, "Report Descriptor: %*ph\n", rsize, rdesc);
111
112 ret = hid_parse_report(hid, rdesc, rsize);
113 - kfree(rdesc);
114 + if (!use_override)
115 + kfree(rdesc);
116 +
117 if (ret) {
118 dbg_hid("parsing report descriptor failed\n");
119 return ret;
120 @@ -827,12 +840,19 @@ static int i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid)
121 int ret;
122
123 /* i2c hid fetch using a fixed descriptor size (30 bytes) */
124 - i2c_hid_dbg(ihid, "Fetching the HID descriptor\n");
125 - ret = i2c_hid_command(client, &hid_descr_cmd, ihid->hdesc_buffer,
126 - sizeof(struct i2c_hid_desc));
127 - if (ret) {
128 - dev_err(&client->dev, "hid_descr_cmd failed\n");
129 - return -ENODEV;
130 + if (i2c_hid_get_dmi_i2c_hid_desc_override(client->name)) {
131 + i2c_hid_dbg(ihid, "Using a HID descriptor override\n");
132 + ihid->hdesc =
133 + *i2c_hid_get_dmi_i2c_hid_desc_override(client->name);
134 + } else {
135 + i2c_hid_dbg(ihid, "Fetching the HID descriptor\n");
136 + ret = i2c_hid_command(client, &hid_descr_cmd,
137 + ihid->hdesc_buffer,
138 + sizeof(struct i2c_hid_desc));
139 + if (ret) {
140 + dev_err(&client->dev, "hid_descr_cmd failed\n");
141 + return -ENODEV;
142 + }
143 }
144
145 /* Validate the length of HID descriptor, the 4 first bytes:
146 diff --git a/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c b/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
147 new file mode 100644
148 index 000000000000..1d645c9ab417
149 --- /dev/null
150 +++ b/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
151 @@ -0,0 +1,376 @@
152 +// SPDX-License-Identifier: GPL-2.0+
153 +
154 +/*
155 + * Quirks for I2C-HID devices that do not supply proper descriptors
156 + *
157 + * Copyright (c) 2018 Julian Sax <jsbc@gmx.de>
158 + *
159 + */
160 +
161 +#include <linux/types.h>
162 +#include <linux/dmi.h>
163 +#include <linux/mod_devicetable.h>
164 +
165 +#include "i2c-hid.h"
166 +
167 +
168 +struct i2c_hid_desc_override {
169 + union {
170 + struct i2c_hid_desc *i2c_hid_desc;
171 + uint8_t *i2c_hid_desc_buffer;
172 + };
173 + uint8_t *hid_report_desc;
174 + unsigned int hid_report_desc_size;
175 + uint8_t *i2c_name;
176 +};
177 +
178 +
179 +/*
180 + * descriptors for the SIPODEV SP1064 touchpad
181 + *
182 + * This device does not supply any descriptors and on windows a filter
183 + * driver operates between the i2c-hid layer and the device and injects
184 + * these descriptors when the device is prompted. The descriptors were
185 + * extracted by listening to the i2c-hid traffic that occurs between the
186 + * windows filter driver and the windows i2c-hid driver.
187 + */
188 +
189 +static const struct i2c_hid_desc_override sipodev_desc = {
190 + .i2c_hid_desc_buffer = (uint8_t [])
191 + {0x1e, 0x00, /* Length of descriptor */
192 + 0x00, 0x01, /* Version of descriptor */
193 + 0xdb, 0x01, /* Length of report descriptor */
194 + 0x21, 0x00, /* Location of report descriptor */
195 + 0x24, 0x00, /* Location of input report */
196 + 0x1b, 0x00, /* Max input report length */
197 + 0x25, 0x00, /* Location of output report */
198 + 0x11, 0x00, /* Max output report length */
199 + 0x22, 0x00, /* Location of command register */
200 + 0x23, 0x00, /* Location of data register */
201 + 0x11, 0x09, /* Vendor ID */
202 + 0x88, 0x52, /* Product ID */
203 + 0x06, 0x00, /* Version ID */
204 + 0x00, 0x00, 0x00, 0x00 /* Reserved */
205 + },
206 +
207 + .hid_report_desc = (uint8_t [])
208 + {0x05, 0x01, /* Usage Page (Desktop), */
209 + 0x09, 0x02, /* Usage (Mouse), */
210 + 0xA1, 0x01, /* Collection (Application), */
211 + 0x85, 0x01, /* Report ID (1), */
212 + 0x09, 0x01, /* Usage (Pointer), */
213 + 0xA1, 0x00, /* Collection (Physical), */
214 + 0x05, 0x09, /* Usage Page (Button), */
215 + 0x19, 0x01, /* Usage Minimum (01h), */
216 + 0x29, 0x02, /* Usage Maximum (02h), */
217 + 0x25, 0x01, /* Logical Maximum (1), */
218 + 0x75, 0x01, /* Report Size (1), */
219 + 0x95, 0x02, /* Report Count (2), */
220 + 0x81, 0x02, /* Input (Variable), */
221 + 0x95, 0x06, /* Report Count (6), */
222 + 0x81, 0x01, /* Input (Constant), */
223 + 0x05, 0x01, /* Usage Page (Desktop), */
224 + 0x09, 0x30, /* Usage (X), */
225 + 0x09, 0x31, /* Usage (Y), */
226 + 0x15, 0x81, /* Logical Minimum (-127), */
227 + 0x25, 0x7F, /* Logical Maximum (127), */
228 + 0x75, 0x08, /* Report Size (8), */
229 + 0x95, 0x02, /* Report Count (2), */
230 + 0x81, 0x06, /* Input (Variable, Relative), */
231 + 0xC0, /* End Collection, */
232 + 0xC0, /* End Collection, */
233 + 0x05, 0x0D, /* Usage Page (Digitizer), */
234 + 0x09, 0x05, /* Usage (Touchpad), */
235 + 0xA1, 0x01, /* Collection (Application), */
236 + 0x85, 0x04, /* Report ID (4), */
237 + 0x05, 0x0D, /* Usage Page (Digitizer), */
238 + 0x09, 0x22, /* Usage (Finger), */
239 + 0xA1, 0x02, /* Collection (Logical), */
240 + 0x15, 0x00, /* Logical Minimum (0), */
241 + 0x25, 0x01, /* Logical Maximum (1), */
242 + 0x09, 0x47, /* Usage (Touch Valid), */
243 + 0x09, 0x42, /* Usage (Tip Switch), */
244 + 0x95, 0x02, /* Report Count (2), */
245 + 0x75, 0x01, /* Report Size (1), */
246 + 0x81, 0x02, /* Input (Variable), */
247 + 0x95, 0x01, /* Report Count (1), */
248 + 0x75, 0x03, /* Report Size (3), */
249 + 0x25, 0x05, /* Logical Maximum (5), */
250 + 0x09, 0x51, /* Usage (Contact Identifier), */
251 + 0x81, 0x02, /* Input (Variable), */
252 + 0x75, 0x01, /* Report Size (1), */
253 + 0x95, 0x03, /* Report Count (3), */
254 + 0x81, 0x03, /* Input (Constant, Variable), */
255 + 0x05, 0x01, /* Usage Page (Desktop), */
256 + 0x26, 0x44, 0x0A, /* Logical Maximum (2628), */
257 + 0x75, 0x10, /* Report Size (16), */
258 + 0x55, 0x0E, /* Unit Exponent (14), */
259 + 0x65, 0x11, /* Unit (Centimeter), */
260 + 0x09, 0x30, /* Usage (X), */
261 + 0x46, 0x1A, 0x04, /* Physical Maximum (1050), */
262 + 0x95, 0x01, /* Report Count (1), */
263 + 0x81, 0x02, /* Input (Variable), */
264 + 0x46, 0xBC, 0x02, /* Physical Maximum (700), */
265 + 0x26, 0x34, 0x05, /* Logical Maximum (1332), */
266 + 0x09, 0x31, /* Usage (Y), */
267 + 0x81, 0x02, /* Input (Variable), */
268 + 0xC0, /* End Collection, */
269 + 0x05, 0x0D, /* Usage Page (Digitizer), */
270 + 0x09, 0x22, /* Usage (Finger), */
271 + 0xA1, 0x02, /* Collection (Logical), */
272 + 0x25, 0x01, /* Logical Maximum (1), */
273 + 0x09, 0x47, /* Usage (Touch Valid), */
274 + 0x09, 0x42, /* Usage (Tip Switch), */
275 + 0x95, 0x02, /* Report Count (2), */
276 + 0x75, 0x01, /* Report Size (1), */
277 + 0x81, 0x02, /* Input (Variable), */
278 + 0x95, 0x01, /* Report Count (1), */
279 + 0x75, 0x03, /* Report Size (3), */
280 + 0x25, 0x05, /* Logical Maximum (5), */
281 + 0x09, 0x51, /* Usage (Contact Identifier), */
282 + 0x81, 0x02, /* Input (Variable), */
283 + 0x75, 0x01, /* Report Size (1), */
284 + 0x95, 0x03, /* Report Count (3), */
285 + 0x81, 0x03, /* Input (Constant, Variable), */
286 + 0x05, 0x01, /* Usage Page (Desktop), */
287 + 0x26, 0x44, 0x0A, /* Logical Maximum (2628), */
288 + 0x75, 0x10, /* Report Size (16), */
289 + 0x09, 0x30, /* Usage (X), */
290 + 0x46, 0x1A, 0x04, /* Physical Maximum (1050), */
291 + 0x95, 0x01, /* Report Count (1), */
292 + 0x81, 0x02, /* Input (Variable), */
293 + 0x46, 0xBC, 0x02, /* Physical Maximum (700), */
294 + 0x26, 0x34, 0x05, /* Logical Maximum (1332), */
295 + 0x09, 0x31, /* Usage (Y), */
296 + 0x81, 0x02, /* Input (Variable), */
297 + 0xC0, /* End Collection, */
298 + 0x05, 0x0D, /* Usage Page (Digitizer), */
299 + 0x09, 0x22, /* Usage (Finger), */
300 + 0xA1, 0x02, /* Collection (Logical), */
301 + 0x25, 0x01, /* Logical Maximum (1), */
302 + 0x09, 0x47, /* Usage (Touch Valid), */
303 + 0x09, 0x42, /* Usage (Tip Switch), */
304 + 0x95, 0x02, /* Report Count (2), */
305 + 0x75, 0x01, /* Report Size (1), */
306 + 0x81, 0x02, /* Input (Variable), */
307 + 0x95, 0x01, /* Report Count (1), */
308 + 0x75, 0x03, /* Report Size (3), */
309 + 0x25, 0x05, /* Logical Maximum (5), */
310 + 0x09, 0x51, /* Usage (Contact Identifier), */
311 + 0x81, 0x02, /* Input (Variable), */
312 + 0x75, 0x01, /* Report Size (1), */
313 + 0x95, 0x03, /* Report Count (3), */
314 + 0x81, 0x03, /* Input (Constant, Variable), */
315 + 0x05, 0x01, /* Usage Page (Desktop), */
316 + 0x26, 0x44, 0x0A, /* Logical Maximum (2628), */
317 + 0x75, 0x10, /* Report Size (16), */
318 + 0x09, 0x30, /* Usage (X), */
319 + 0x46, 0x1A, 0x04, /* Physical Maximum (1050), */
320 + 0x95, 0x01, /* Report Count (1), */
321 + 0x81, 0x02, /* Input (Variable), */
322 + 0x46, 0xBC, 0x02, /* Physical Maximum (700), */
323 + 0x26, 0x34, 0x05, /* Logical Maximum (1332), */
324 + 0x09, 0x31, /* Usage (Y), */
325 + 0x81, 0x02, /* Input (Variable), */
326 + 0xC0, /* End Collection, */
327 + 0x05, 0x0D, /* Usage Page (Digitizer), */
328 + 0x09, 0x22, /* Usage (Finger), */
329 + 0xA1, 0x02, /* Collection (Logical), */
330 + 0x25, 0x01, /* Logical Maximum (1), */
331 + 0x09, 0x47, /* Usage (Touch Valid), */
332 + 0x09, 0x42, /* Usage (Tip Switch), */
333 + 0x95, 0x02, /* Report Count (2), */
334 + 0x75, 0x01, /* Report Size (1), */
335 + 0x81, 0x02, /* Input (Variable), */
336 + 0x95, 0x01, /* Report Count (1), */
337 + 0x75, 0x03, /* Report Size (3), */
338 + 0x25, 0x05, /* Logical Maximum (5), */
339 + 0x09, 0x51, /* Usage (Contact Identifier), */
340 + 0x81, 0x02, /* Input (Variable), */
341 + 0x75, 0x01, /* Report Size (1), */
342 + 0x95, 0x03, /* Report Count (3), */
343 + 0x81, 0x03, /* Input (Constant, Variable), */
344 + 0x05, 0x01, /* Usage Page (Desktop), */
345 + 0x26, 0x44, 0x0A, /* Logical Maximum (2628), */
346 + 0x75, 0x10, /* Report Size (16), */
347 + 0x09, 0x30, /* Usage (X), */
348 + 0x46, 0x1A, 0x04, /* Physical Maximum (1050), */
349 + 0x95, 0x01, /* Report Count (1), */
350 + 0x81, 0x02, /* Input (Variable), */
351 + 0x46, 0xBC, 0x02, /* Physical Maximum (700), */
352 + 0x26, 0x34, 0x05, /* Logical Maximum (1332), */
353 + 0x09, 0x31, /* Usage (Y), */
354 + 0x81, 0x02, /* Input (Variable), */
355 + 0xC0, /* End Collection, */
356 + 0x05, 0x0D, /* Usage Page (Digitizer), */
357 + 0x55, 0x0C, /* Unit Exponent (12), */
358 + 0x66, 0x01, 0x10, /* Unit (Seconds), */
359 + 0x47, 0xFF, 0xFF, 0x00, 0x00,/* Physical Maximum (65535), */
360 + 0x27, 0xFF, 0xFF, 0x00, 0x00,/* Logical Maximum (65535), */
361 + 0x75, 0x10, /* Report Size (16), */
362 + 0x95, 0x01, /* Report Count (1), */
363 + 0x09, 0x56, /* Usage (Scan Time), */
364 + 0x81, 0x02, /* Input (Variable), */
365 + 0x09, 0x54, /* Usage (Contact Count), */
366 + 0x25, 0x7F, /* Logical Maximum (127), */
367 + 0x75, 0x08, /* Report Size (8), */
368 + 0x81, 0x02, /* Input (Variable), */
369 + 0x05, 0x09, /* Usage Page (Button), */
370 + 0x09, 0x01, /* Usage (01h), */
371 + 0x25, 0x01, /* Logical Maximum (1), */
372 + 0x75, 0x01, /* Report Size (1), */
373 + 0x95, 0x01, /* Report Count (1), */
374 + 0x81, 0x02, /* Input (Variable), */
375 + 0x95, 0x07, /* Report Count (7), */
376 + 0x81, 0x03, /* Input (Constant, Variable), */
377 + 0x05, 0x0D, /* Usage Page (Digitizer), */
378 + 0x85, 0x02, /* Report ID (2), */
379 + 0x09, 0x55, /* Usage (Contact Count Maximum), */
380 + 0x09, 0x59, /* Usage (59h), */
381 + 0x75, 0x04, /* Report Size (4), */
382 + 0x95, 0x02, /* Report Count (2), */
383 + 0x25, 0x0F, /* Logical Maximum (15), */
384 + 0xB1, 0x02, /* Feature (Variable), */
385 + 0x05, 0x0D, /* Usage Page (Digitizer), */
386 + 0x85, 0x07, /* Report ID (7), */
387 + 0x09, 0x60, /* Usage (60h), */
388 + 0x75, 0x01, /* Report Size (1), */
389 + 0x95, 0x01, /* Report Count (1), */
390 + 0x25, 0x01, /* Logical Maximum (1), */
391 + 0xB1, 0x02, /* Feature (Variable), */
392 + 0x95, 0x07, /* Report Count (7), */
393 + 0xB1, 0x03, /* Feature (Constant, Variable), */
394 + 0x85, 0x06, /* Report ID (6), */
395 + 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
396 + 0x09, 0xC5, /* Usage (C5h), */
397 + 0x26, 0xFF, 0x00, /* Logical Maximum (255), */
398 + 0x75, 0x08, /* Report Size (8), */
399 + 0x96, 0x00, 0x01, /* Report Count (256), */
400 + 0xB1, 0x02, /* Feature (Variable), */
401 + 0xC0, /* End Collection, */
402 + 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */
403 + 0x09, 0x01, /* Usage (01h), */
404 + 0xA1, 0x01, /* Collection (Application), */
405 + 0x85, 0x0D, /* Report ID (13), */
406 + 0x26, 0xFF, 0x00, /* Logical Maximum (255), */
407 + 0x19, 0x01, /* Usage Minimum (01h), */
408 + 0x29, 0x02, /* Usage Maximum (02h), */
409 + 0x75, 0x08, /* Report Size (8), */
410 + 0x95, 0x02, /* Report Count (2), */
411 + 0xB1, 0x02, /* Feature (Variable), */
412 + 0xC0, /* End Collection, */
413 + 0x05, 0x0D, /* Usage Page (Digitizer), */
414 + 0x09, 0x0E, /* Usage (Configuration), */
415 + 0xA1, 0x01, /* Collection (Application), */
416 + 0x85, 0x03, /* Report ID (3), */
417 + 0x09, 0x22, /* Usage (Finger), */
418 + 0xA1, 0x02, /* Collection (Logical), */
419 + 0x09, 0x52, /* Usage (Device Mode), */
420 + 0x25, 0x0A, /* Logical Maximum (10), */
421 + 0x95, 0x01, /* Report Count (1), */
422 + 0xB1, 0x02, /* Feature (Variable), */
423 + 0xC0, /* End Collection, */
424 + 0x09, 0x22, /* Usage (Finger), */
425 + 0xA1, 0x00, /* Collection (Physical), */
426 + 0x85, 0x05, /* Report ID (5), */
427 + 0x09, 0x57, /* Usage (57h), */
428 + 0x09, 0x58, /* Usage (58h), */
429 + 0x75, 0x01, /* Report Size (1), */
430 + 0x95, 0x02, /* Report Count (2), */
431 + 0x25, 0x01, /* Logical Maximum (1), */
432 + 0xB1, 0x02, /* Feature (Variable), */
433 + 0x95, 0x06, /* Report Count (6), */
434 + 0xB1, 0x03, /* Feature (Constant, Variable),*/
435 + 0xC0, /* End Collection, */
436 + 0xC0 /* End Collection */
437 + },
438 + .hid_report_desc_size = 475,
439 + .i2c_name = "SYNA3602:00"
440 +};
441 +
442 +
443 +static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = {
444 + {
445 + .ident = "Teclast F6 Pro",
446 + .matches = {
447 + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TECLAST"),
448 + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "F6 Pro"),
449 + },
450 + .driver_data = (void *)&sipodev_desc
451 + },
452 + {
453 + .ident = "Teclast F7",
454 + .matches = {
455 + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TECLAST"),
456 + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "F7"),
457 + },
458 + .driver_data = (void *)&sipodev_desc
459 + },
460 + {
461 + .ident = "Trekstor Primebook C13",
462 + .matches = {
463 + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
464 + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Primebook C13"),
465 + },
466 + .driver_data = (void *)&sipodev_desc
467 + },
468 + {
469 + .ident = "Trekstor Primebook C11",
470 + .matches = {
471 + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
472 + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Primebook C11"),
473 + },
474 + .driver_data = (void *)&sipodev_desc
475 + },
476 + {
477 + .ident = "Direkt-Tek DTLAPY116-2",
478 + .matches = {
479 + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Direkt-Tek"),
480 + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "DTLAPY116-2"),
481 + },
482 + .driver_data = (void *)&sipodev_desc
483 + },
484 + {
485 + .ident = "Mediacom Flexbook Edge 11",
486 + .matches = {
487 + DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MEDIACOM"),
488 + DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "FlexBook edge11 - M-FBE11"),
489 + },
490 + .driver_data = (void *)&sipodev_desc
491 + }
492 +};
493 +
494 +
495 +struct i2c_hid_desc *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name)
496 +{
497 + struct i2c_hid_desc_override *override;
498 + const struct dmi_system_id *system_id;
499 +
500 + system_id = dmi_first_match(i2c_hid_dmi_desc_override_table);
501 + if (!system_id)
502 + return NULL;
503 +
504 + override = system_id->driver_data;
505 + if (strcmp(override->i2c_name, i2c_name))
506 + return NULL;
507 +
508 + return override->i2c_hid_desc;
509 +}
510 +
511 +char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name,
512 + unsigned int *size)
513 +{
514 + struct i2c_hid_desc_override *override;
515 + const struct dmi_system_id *system_id;
516 +
517 + system_id = dmi_first_match(i2c_hid_dmi_desc_override_table);
518 + if (!system_id)
519 + return NULL;
520 +
521 + override = system_id->driver_data;
522 + if (strcmp(override->i2c_name, i2c_name))
523 + return NULL;
524 +
525 + *size = override->hid_report_desc_size;
526 + return override->hid_report_desc;
527 +}
528 diff --git a/drivers/hid/i2c-hid/i2c-hid.h b/drivers/hid/i2c-hid/i2c-hid.h
529 new file mode 100644
530 index 000000000000..a8c19aef5824
531 --- /dev/null
532 +++ b/drivers/hid/i2c-hid/i2c-hid.h
533 @@ -0,0 +1,20 @@
534 +/* SPDX-License-Identifier: GPL-2.0+ */
535 +
536 +#ifndef I2C_HID_H
537 +#define I2C_HID_H
538 +
539 +
540 +#ifdef CONFIG_DMI
541 +struct i2c_hid_desc *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name);
542 +char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name,
543 + unsigned int *size);
544 +#else
545 +static inline struct i2c_hid_desc
546 + *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name)
547 +{ return NULL; }
548 +static inline char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name,
549 + unsigned int *size)
550 +{ return NULL; }
551 +#endif
552 +
553 +#endif
554 --
555 2.19.1
556