aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJulian Sax <jsbc@gmx.de>2018-09-19 05:46:23 -0400
committerJiri Kosina <jkosina@suse.cz>2018-09-29 15:25:59 -0400
commit9ee3e06610fdb8a601cde59c92089fb6c1deb4aa (patch)
tree90689de6f079e313896cadd3282c29fad0b70601
parentdc4e05d079591c6f69bb28a07bcc13d4f1c9993b (diff)
HID: i2c-hid: override HID descriptors for certain devices
A particular touchpad (SIPODEV SP1064) refuses to supply the HID descriptors. This patch provides the framework for overriding these descriptors based on DMI data. It also includes the descriptors for said touchpad, which were extracted by listening to the traffic of the windows filter driver, as well as the DMI data for the laptops known to use this device. Relevant Bug: https://bugzilla.redhat.com/show_bug.cgi?id=1526312 Cc: Hans de Goede <hdegoede@redhat.com> Reported-and-tested-by: ahormann@gmx.net Reported-and-tested-by: Bruno Jesus <bruno.fl.jesus@gmail.com> Reported-and-tested-by: Dietrich <enaut.w@googlemail.com> Reported-and-tested-by: kloxdami@yahoo.com Signed-off-by: Julian Sax <jsbc@gmx.de> Reviewed-by: Benjamin Tissoires <benjamin.tissoires@redhat.com> Signed-off-by: Jiri Kosina <jkosina@suse.cz>
-rw-r--r--drivers/hid/i2c-hid/Makefile3
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-core.c (renamed from drivers/hid/i2c-hid/i2c-hid.c)60
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c376
-rw-r--r--drivers/hid/i2c-hid/i2c-hid.h20
4 files changed, 439 insertions, 20 deletions
diff --git a/drivers/hid/i2c-hid/Makefile b/drivers/hid/i2c-hid/Makefile
index 832d8f9aaba2..099e1ce2f234 100644
--- a/drivers/hid/i2c-hid/Makefile
+++ b/drivers/hid/i2c-hid/Makefile
@@ -3,3 +3,6 @@
3# 3#
4 4
5obj-$(CONFIG_I2C_HID) += i2c-hid.o 5obj-$(CONFIG_I2C_HID) += i2c-hid.o
6
7i2c-hid-objs = i2c-hid-core.o
8i2c-hid-$(CONFIG_DMI) += i2c-hid-dmi-quirks.o
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid-core.c
index f3076659361a..823c63ad08b1 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid-core.c
@@ -43,6 +43,7 @@
43#include <linux/platform_data/i2c-hid.h> 43#include <linux/platform_data/i2c-hid.h>
44 44
45#include "../hid-ids.h" 45#include "../hid-ids.h"
46#include "i2c-hid.h"
46 47
47/* quirks to control the device */ 48/* quirks to control the device */
48#define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV BIT(0) 49#define I2C_HID_QUIRK_SET_PWR_WAKEUP_DEV BIT(0)
@@ -669,6 +670,7 @@ static int i2c_hid_parse(struct hid_device *hid)
669 char *rdesc; 670 char *rdesc;
670 int ret; 671 int ret;
671 int tries = 3; 672 int tries = 3;
673 char *use_override;
672 674
673 i2c_hid_dbg(ihid, "entering %s\n", __func__); 675 i2c_hid_dbg(ihid, "entering %s\n", __func__);
674 676
@@ -687,26 +689,37 @@ static int i2c_hid_parse(struct hid_device *hid)
687 if (ret) 689 if (ret)
688 return ret; 690 return ret;
689 691
690 rdesc = kzalloc(rsize, GFP_KERNEL); 692 use_override = i2c_hid_get_dmi_hid_report_desc_override(client->name,
693 &rsize);
691 694
692 if (!rdesc) { 695 if (use_override) {
693 dbg_hid("couldn't allocate rdesc memory\n"); 696 rdesc = use_override;
694 return -ENOMEM; 697 i2c_hid_dbg(ihid, "Using a HID report descriptor override\n");
695 } 698 } else {
696 699 rdesc = kzalloc(rsize, GFP_KERNEL);
697 i2c_hid_dbg(ihid, "asking HID report descriptor\n"); 700
698 701 if (!rdesc) {
699 ret = i2c_hid_command(client, &hid_report_descr_cmd, rdesc, rsize); 702 dbg_hid("couldn't allocate rdesc memory\n");
700 if (ret) { 703 return -ENOMEM;
701 hid_err(hid, "reading report descriptor failed\n"); 704 }
702 kfree(rdesc); 705
703 return -EIO; 706 i2c_hid_dbg(ihid, "asking HID report descriptor\n");
707
708 ret = i2c_hid_command(client, &hid_report_descr_cmd,
709 rdesc, rsize);
710 if (ret) {
711 hid_err(hid, "reading report descriptor failed\n");
712 kfree(rdesc);
713 return -EIO;
714 }
704 } 715 }
705 716
706 i2c_hid_dbg(ihid, "Report Descriptor: %*ph\n", rsize, rdesc); 717 i2c_hid_dbg(ihid, "Report Descriptor: %*ph\n", rsize, rdesc);
707 718
708 ret = hid_parse_report(hid, rdesc, rsize); 719 ret = hid_parse_report(hid, rdesc, rsize);
709 kfree(rdesc); 720 if (!use_override)
721 kfree(rdesc);
722
710 if (ret) { 723 if (ret) {
711 dbg_hid("parsing report descriptor failed\n"); 724 dbg_hid("parsing report descriptor failed\n");
712 return ret; 725 return ret;
@@ -833,12 +846,19 @@ static int i2c_hid_fetch_hid_descriptor(struct i2c_hid *ihid)
833 int ret; 846 int ret;
834 847
835 /* i2c hid fetch using a fixed descriptor size (30 bytes) */ 848 /* i2c hid fetch using a fixed descriptor size (30 bytes) */
836 i2c_hid_dbg(ihid, "Fetching the HID descriptor\n"); 849 if (i2c_hid_get_dmi_i2c_hid_desc_override(client->name)) {
837 ret = i2c_hid_command(client, &hid_descr_cmd, ihid->hdesc_buffer, 850 i2c_hid_dbg(ihid, "Using a HID descriptor override\n");
838 sizeof(struct i2c_hid_desc)); 851 ihid->hdesc =
839 if (ret) { 852 *i2c_hid_get_dmi_i2c_hid_desc_override(client->name);
840 dev_err(&client->dev, "hid_descr_cmd failed\n"); 853 } else {
841 return -ENODEV; 854 i2c_hid_dbg(ihid, "Fetching the HID descriptor\n");
855 ret = i2c_hid_command(client, &hid_descr_cmd,
856 ihid->hdesc_buffer,
857 sizeof(struct i2c_hid_desc));
858 if (ret) {
859 dev_err(&client->dev, "hid_descr_cmd failed\n");
860 return -ENODEV;
861 }
842 } 862 }
843 863
844 /* Validate the length of HID descriptor, the 4 first bytes: 864 /* Validate the length of HID descriptor, the 4 first bytes:
diff --git a/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c b/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
new file mode 100644
index 000000000000..1d645c9ab417
--- /dev/null
+++ b/drivers/hid/i2c-hid/i2c-hid-dmi-quirks.c
@@ -0,0 +1,376 @@
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
17struct 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
38static 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
292static const struct dmi_system_id i2c_hid_dmi_desc_override_table[] = {
293 {
294 .ident = "Teclast F6 Pro",
295 .matches = {
296 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TECLAST"),
297 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "F6 Pro"),
298 },
299 .driver_data = (void *)&sipodev_desc
300 },
301 {
302 .ident = "Teclast F7",
303 .matches = {
304 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TECLAST"),
305 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "F7"),
306 },
307 .driver_data = (void *)&sipodev_desc
308 },
309 {
310 .ident = "Trekstor Primebook C13",
311 .matches = {
312 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
313 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Primebook C13"),
314 },
315 .driver_data = (void *)&sipodev_desc
316 },
317 {
318 .ident = "Trekstor Primebook C11",
319 .matches = {
320 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "TREKSTOR"),
321 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Primebook C11"),
322 },
323 .driver_data = (void *)&sipodev_desc
324 },
325 {
326 .ident = "Direkt-Tek DTLAPY116-2",
327 .matches = {
328 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Direkt-Tek"),
329 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "DTLAPY116-2"),
330 },
331 .driver_data = (void *)&sipodev_desc
332 },
333 {
334 .ident = "Mediacom Flexbook Edge 11",
335 .matches = {
336 DMI_EXACT_MATCH(DMI_SYS_VENDOR, "MEDIACOM"),
337 DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "FlexBook edge11 - M-FBE11"),
338 },
339 .driver_data = (void *)&sipodev_desc
340 }
341};
342
343
344struct i2c_hid_desc *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name)
345{
346 struct i2c_hid_desc_override *override;
347 const struct dmi_system_id *system_id;
348
349 system_id = dmi_first_match(i2c_hid_dmi_desc_override_table);
350 if (!system_id)
351 return NULL;
352
353 override = system_id->driver_data;
354 if (strcmp(override->i2c_name, i2c_name))
355 return NULL;
356
357 return override->i2c_hid_desc;
358}
359
360char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name,
361 unsigned int *size)
362{
363 struct i2c_hid_desc_override *override;
364 const struct dmi_system_id *system_id;
365
366 system_id = dmi_first_match(i2c_hid_dmi_desc_override_table);
367 if (!system_id)
368 return NULL;
369
370 override = system_id->driver_data;
371 if (strcmp(override->i2c_name, i2c_name))
372 return NULL;
373
374 *size = override->hid_report_desc_size;
375 return override->hid_report_desc;
376}
diff --git a/drivers/hid/i2c-hid/i2c-hid.h b/drivers/hid/i2c-hid/i2c-hid.h
new file mode 100644
index 000000000000..a8c19aef5824
--- /dev/null
+++ b/drivers/hid/i2c-hid/i2c-hid.h
@@ -0,0 +1,20 @@
1/* SPDX-License-Identifier: GPL-2.0+ */
2
3#ifndef I2C_HID_H
4#define I2C_HID_H
5
6
7#ifdef CONFIG_DMI
8struct i2c_hid_desc *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name);
9char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name,
10 unsigned int *size);
11#else
12static inline struct i2c_hid_desc
13 *i2c_hid_get_dmi_i2c_hid_desc_override(uint8_t *i2c_name)
14{ return NULL; }
15static inline char *i2c_hid_get_dmi_hid_report_desc_override(uint8_t *i2c_name,
16 unsigned int *size)
17{ return NULL; }
18#endif
19
20#endif