1/* $FreeBSD$ */
2/*-
3 * SPDX-License-Identifier: BSD-2-Clause-NetBSD
4 *
5 * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
6 * Copyright (c) 1998 Lennart Augustsson. All rights reserved.
7 * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
8 * Copyright (c) 2020 Vladimir Kondratyev <wulf@FreeBSD.org>
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31
32#include <sys/stdint.h>
33#include <sys/stddef.h>
34#include <sys/param.h>
35#include <sys/queue.h>
36#include <sys/types.h>
37#include <sys/systm.h>
38#include <sys/kernel.h>
39#include <sys/bus.h>
40#include <sys/module.h>
41#include <sys/lock.h>
42#include <sys/mutex.h>
43#include <sys/condvar.h>
44#include <sys/sysctl.h>
45#include <sys/sx.h>
46#include <sys/unistd.h>
47#include <sys/callout.h>
48#include <sys/malloc.h>
49#include <sys/priv.h>
50
51#include <dev/evdev/input.h>
52
53#define	HID_DEBUG_VAR hid_debug
54#include <dev/hid/hid.h>
55#include <dev/hid/hidquirk.h>
56#include "usbdevs.h"
57
58
59MODULE_DEPEND(hidquirk, hid, 1, 1, 1);
60MODULE_VERSION(hidquirk, 1);
61
62#define	HID_DEV_QUIRKS_MAX 384
63#define	HID_SUB_QUIRKS_MAX 8
64#define	HID_QUIRK_ENVROOT "hw.hid.quirk."
65
66struct hidquirk_entry {
67	uint16_t bus;
68	uint16_t vid;
69	uint16_t pid;
70	uint16_t lo_rev;
71	uint16_t hi_rev;
72	uint16_t quirks[HID_SUB_QUIRKS_MAX];
73};
74
75static struct mtx hidquirk_mtx;
76
77#define	HID_QUIRK_VP(b,v,p,l,h,...) \
78  { .bus = (b), .vid = (v), .pid = (p), .lo_rev = (l), .hi_rev = (h), \
79    .quirks = { __VA_ARGS__ } }
80#define	USB_QUIRK(v,p,l,h,...) \
81  HID_QUIRK_VP(BUS_USB, USB_VENDOR_##v, USB_PRODUCT_##v##_##p, l, h, __VA_ARGS__)
82
83static struct hidquirk_entry hidquirks[HID_DEV_QUIRKS_MAX] = {
84	USB_QUIRK(ASUS, LCM, 0x0000, 0xffff, HQ_HID_IGNORE),
85	USB_QUIRK(QTRONIX, 980N, 0x110, 0x110, HQ_SPUR_BUT_UP),
86	USB_QUIRK(ALCOR2, KBD_HUB, 0x001, 0x001, HQ_SPUR_BUT_UP),
87	USB_QUIRK(LOGITECH, G510S, 0x0000, 0xFFFF, HQ_KBD_BOOTPROTO),
88	/* Devices which should be ignored by usbhid */
89	USB_QUIRK(APC, UPS, 0x0000, 0xffff, HQ_HID_IGNORE),
90	USB_QUIRK(BELKIN, F6H375USB, 0x0000, 0xffff, HQ_HID_IGNORE),
91	USB_QUIRK(BELKIN, F6C550AVR, 0x0000, 0xffff, HQ_HID_IGNORE),
92	USB_QUIRK(BELKIN, F6C1250TWRK, 0x0000, 0xffff, HQ_HID_IGNORE),
93	USB_QUIRK(BELKIN, F6C1500TWRK, 0x0000, 0xffff, HQ_HID_IGNORE),
94	USB_QUIRK(BELKIN, F6C900UNV, 0x0000, 0xffff, HQ_HID_IGNORE),
95	USB_QUIRK(BELKIN, F6C100UNV, 0x0000, 0xffff, HQ_HID_IGNORE),
96	USB_QUIRK(BELKIN, F6C120UNV, 0x0000, 0xffff, HQ_HID_IGNORE),
97	USB_QUIRK(BELKIN, F6C800UNV, 0x0000, 0xffff, HQ_HID_IGNORE),
98	USB_QUIRK(BELKIN, F6C1100UNV, 0x0000, 0xffff, HQ_HID_IGNORE),
99	USB_QUIRK(CYBERPOWER, BC900D, 0x0000, 0xffff, HQ_HID_IGNORE),
100	USB_QUIRK(CYBERPOWER, 1500CAVRLCD, 0x0000, 0xffff, HQ_HID_IGNORE),
101	USB_QUIRK(CYBERPOWER, OR2200LCDRM2U, 0x0000, 0xffff, HQ_HID_IGNORE),
102	USB_QUIRK(DELL2, VARIOUS_UPS, 0x0000, 0xffff, HQ_HID_IGNORE),
103	USB_QUIRK(CYPRESS, SILVERSHIELD, 0x0000, 0xffff, HQ_HID_IGNORE),
104	USB_QUIRK(DELORME, EARTHMATE, 0x0000, 0xffff, HQ_HID_IGNORE),
105	USB_QUIRK(DREAMLINK, DL100B, 0x0000, 0xffff, HQ_HID_IGNORE),
106	USB_QUIRK(MICROCHIP, PICOLCD20X2, 0x0000, 0xffff, HQ_HID_IGNORE),
107	USB_QUIRK(MICROCHIP, PICOLCD4X20, 0x0000, 0xffff, HQ_HID_IGNORE),
108	USB_QUIRK(LIEBERT, POWERSURE_PXT, 0x0000, 0xffff, HQ_HID_IGNORE),
109	USB_QUIRK(LIEBERT2, PSI1000, 0x0000, 0xffff, HQ_HID_IGNORE),
110	USB_QUIRK(LIEBERT2, POWERSURE_PSA, 0x0000, 0xffff, HQ_HID_IGNORE),
111	USB_QUIRK(MGE, UPS1, 0x0000, 0xffff, HQ_HID_IGNORE),
112	USB_QUIRK(MGE, UPS2, 0x0000, 0xffff, HQ_HID_IGNORE),
113	USB_QUIRK(POWERCOM, IMPERIAL_SERIES, 0x0000, 0xffff, HQ_HID_IGNORE),
114	USB_QUIRK(POWERCOM, SMART_KING_PRO, 0x0000, 0xffff, HQ_HID_IGNORE),
115	USB_QUIRK(POWERCOM, WOW, 0x0000, 0xffff, HQ_HID_IGNORE),
116	USB_QUIRK(POWERCOM, VANGUARD, 0x0000, 0xffff, HQ_HID_IGNORE),
117	USB_QUIRK(POWERCOM, BLACK_KNIGHT_PRO, 0x0000, 0xffff, HQ_HID_IGNORE),
118	USB_QUIRK(TRIPPLITE2, AVR550U, 0x0000, 0xffff, HQ_HID_IGNORE),
119	USB_QUIRK(TRIPPLITE2, AVR750U, 0x0000, 0xffff, HQ_HID_IGNORE),
120	USB_QUIRK(TRIPPLITE2, ECO550UPS, 0x0000, 0xffff, HQ_HID_IGNORE),
121	USB_QUIRK(TRIPPLITE2, T750_INTL, 0x0000, 0xffff, HQ_HID_IGNORE),
122	USB_QUIRK(TRIPPLITE2, RT_2200_INTL, 0x0000, 0xffff, HQ_HID_IGNORE),
123	USB_QUIRK(TRIPPLITE2, OMNI1000LCD, 0x0000, 0xffff, HQ_HID_IGNORE),
124	USB_QUIRK(TRIPPLITE2, OMNI900LCD, 0x0000, 0xffff, HQ_HID_IGNORE),
125	USB_QUIRK(TRIPPLITE2, SMART_2200RMXL2U, 0x0000, 0xffff, HQ_HID_IGNORE),
126	USB_QUIRK(TRIPPLITE2, UPS_3014, 0x0000, 0xffff, HQ_HID_IGNORE),
127	USB_QUIRK(TRIPPLITE2, SU1500RTXL2UA, 0x0000, 0xffff, HQ_HID_IGNORE),
128	USB_QUIRK(TRIPPLITE2, SU6000RT4U, 0x0000, 0xffff, HQ_HID_IGNORE),
129	USB_QUIRK(TRIPPLITE2, SU1500RTXL2UA_2, 0x0000, 0xffff, HQ_HID_IGNORE),
130	USB_QUIRK(APPLE, IPHONE, 0x0000, 0xffff, HQ_HID_IGNORE),
131	USB_QUIRK(APPLE, IPHONE_3G, 0x0000, 0xffff, HQ_HID_IGNORE),
132	USB_QUIRK(MEGATEC, UPS, 0x0000, 0xffff, HQ_HID_IGNORE),
133	/* Devices which should be ignored by both ukbd and uhid */
134	USB_QUIRK(CYPRESS, WISPY1A, 0x0000, 0xffff, HQ_HID_IGNORE),
135	USB_QUIRK(METAGEEK, WISPY1B, 0x0000, 0xffff, HQ_HID_IGNORE),
136	USB_QUIRK(METAGEEK, WISPY24X, 0x0000, 0xffff, HQ_HID_IGNORE),
137	USB_QUIRK(METAGEEK2, WISPYDBX, 0x0000, 0xffff, HQ_HID_IGNORE),
138	/* MS keyboards do weird things */
139	USB_QUIRK(MICROSOFT, NATURAL4000, 0x0000, 0xFFFF, HQ_KBD_BOOTPROTO),
140	USB_QUIRK(MICROSOFT, WLINTELLIMOUSE, 0x0000, 0xffff, HQ_MS_LEADING_BYTE),
141	/* Quirk for Corsair Vengeance K60 keyboard */
142	USB_QUIRK(CORSAIR, K60, 0x0000, 0xffff, HQ_KBD_BOOTPROTO),
143	/* Quirk for Corsair Gaming K68 keyboard */
144	USB_QUIRK(CORSAIR, K68, 0x0000, 0xffff, HQ_KBD_BOOTPROTO),
145	/* Quirk for Corsair Vengeance K70 keyboard */
146	USB_QUIRK(CORSAIR, K70, 0x0000, 0xffff, HQ_KBD_BOOTPROTO),
147	/* Quirk for Corsair K70 RGB keyboard */
148	USB_QUIRK(CORSAIR, K70_RGB, 0x0000, 0xffff, HQ_KBD_BOOTPROTO),
149	/* Quirk for Corsair STRAFE Gaming keyboard */
150	USB_QUIRK(CORSAIR, STRAFE, 0x0000, 0xffff, HQ_KBD_BOOTPROTO),
151	USB_QUIRK(CORSAIR, STRAFE2, 0x0000, 0xffff, HQ_KBD_BOOTPROTO),
152	/* Holtek USB gaming keyboard */
153	USB_QUIRK(HOLTEK, F85, 0x0000, 0xffff, HQ_KBD_BOOTPROTO),
154};
155#undef HID_QUIRK_VP
156#undef USB_QUIRK
157
158/* hidquirk.h exposes only HID_QUIRK_LIST macro when HQ() is defined */
159#define	HQ(x)	[HQ_##x] = "HQ_"#x
160#include "hidquirk.h"
161static const char *hidquirk_str[HID_QUIRK_MAX] = { HID_QUIRK_LIST() };
162#undef HQ
163
164static hid_test_quirk_t hid_test_quirk_by_info;
165
166/*------------------------------------------------------------------------*
167 *	hidquirkstr
168 *
169 * This function converts an USB quirk code into a string.
170 *------------------------------------------------------------------------*/
171static const char *
172hidquirkstr(uint16_t quirk)
173{
174	return ((quirk < HID_QUIRK_MAX && hidquirk_str[quirk] != NULL) ?
175	    hidquirk_str[quirk] : "HQ_UNKNOWN");
176}
177
178/*------------------------------------------------------------------------*
179 *	hid_strquirk
180 *
181 * This function converts a string into a HID quirk code.
182 *
183 * Returns:
184 * Less than HID_QUIRK_MAX: Quirk code
185 * Else: Quirk code not found
186 *------------------------------------------------------------------------*/
187static uint16_t
188hid_strquirk(const char *str, size_t len)
189{
190	const char *quirk;
191	uint16_t x;
192
193	for (x = 0; x != HID_QUIRK_MAX; x++) {
194		quirk = hidquirkstr(x);
195		if (strncmp(str, quirk, len) == 0 &&
196		    quirk[len] == 0)
197			break;
198	}
199	return (x);
200}
201
202/*------------------------------------------------------------------------*
203 *	hid_test_quirk_by_info
204 *
205 * Returns:
206 * false: Quirk not found
207 * true: Quirk found
208 *------------------------------------------------------------------------*/
209bool
210hid_test_quirk_by_info(const struct hid_device_info *info, uint16_t quirk)
211{
212	uint16_t x;
213	uint16_t y;
214
215	if (quirk == HQ_NONE)
216		goto done;
217
218	mtx_lock(&hidquirk_mtx);
219
220	for (x = 0; x != HID_DEV_QUIRKS_MAX; x++) {
221		/* see if quirk information does not match */
222		if ((hidquirks[x].bus != info->idBus) ||
223		    (hidquirks[x].vid != info->idVendor) ||
224		    (hidquirks[x].lo_rev > info->idVersion) ||
225		    (hidquirks[x].hi_rev < info->idVersion)) {
226			continue;
227		}
228		/* see if quirk only should match vendor ID */
229		if (hidquirks[x].pid != info->idProduct) {
230			if (hidquirks[x].pid != 0)
231				continue;
232
233			for (y = 0; y != HID_SUB_QUIRKS_MAX; y++) {
234				if (hidquirks[x].quirks[y] == HQ_MATCH_VENDOR_ONLY)
235					break;
236			}
237			if (y == HID_SUB_QUIRKS_MAX)
238				continue;
239		}
240		/* lookup quirk */
241		for (y = 0; y != HID_SUB_QUIRKS_MAX; y++) {
242			if (hidquirks[x].quirks[y] == quirk) {
243				mtx_unlock(&hidquirk_mtx);
244				DPRINTF("Found quirk '%s'.\n", hidquirkstr(quirk));
245				return (true);
246			}
247		}
248	}
249	mtx_unlock(&hidquirk_mtx);
250done:
251	return (false);			/* no quirk match */
252}
253
254static struct hidquirk_entry *
255hidquirk_get_entry(uint16_t bus, uint16_t vid, uint16_t pid,
256    uint16_t lo_rev, uint16_t hi_rev, uint8_t do_alloc)
257{
258	uint16_t x;
259
260	mtx_assert(&hidquirk_mtx, MA_OWNED);
261
262	if ((bus | vid | pid | lo_rev | hi_rev) == 0) {
263		/* all zero - special case */
264		return (hidquirks + HID_DEV_QUIRKS_MAX - 1);
265	}
266	/* search for an existing entry */
267	for (x = 0; x != HID_DEV_QUIRKS_MAX; x++) {
268		/* see if quirk information does not match */
269		if ((hidquirks[x].bus != bus) ||
270		    (hidquirks[x].vid != vid) ||
271		    (hidquirks[x].pid != pid) ||
272		    (hidquirks[x].lo_rev != lo_rev) ||
273		    (hidquirks[x].hi_rev != hi_rev)) {
274			continue;
275		}
276		return (hidquirks + x);
277	}
278
279	if (do_alloc == 0) {
280		/* no match */
281		return (NULL);
282	}
283	/* search for a free entry */
284	for (x = 0; x != HID_DEV_QUIRKS_MAX; x++) {
285		/* see if quirk information does not match */
286		if ((hidquirks[x].bus |
287		    hidquirks[x].vid |
288		    hidquirks[x].pid |
289		    hidquirks[x].lo_rev |
290		    hidquirks[x].hi_rev) != 0) {
291			continue;
292		}
293		hidquirks[x].bus = bus;
294		hidquirks[x].vid = vid;
295		hidquirks[x].pid = pid;
296		hidquirks[x].lo_rev = lo_rev;
297		hidquirks[x].hi_rev = hi_rev;
298
299		return (hidquirks + x);
300	}
301
302	/* no entry found */
303	return (NULL);
304}
305
306/*------------------------------------------------------------------------*
307 *	usb_quirk_strtou16
308 *
309 * Helper function to scan a 16-bit integer.
310 *------------------------------------------------------------------------*/
311static uint16_t
312hidquirk_strtou16(const char **pptr, const char *name, const char *what)
313{
314	unsigned long value;
315	char *end;
316
317	value = strtoul(*pptr, &end, 0);
318	if (value > 65535 || *pptr == end || (*end != ' ' && *end != '\t')) {
319		printf("%s: %s 16-bit %s value set to zero\n",
320		    name, what, *end == 0 ? "incomplete" : "invalid");
321		return (0);
322	}
323	*pptr = end + 1;
324	return ((uint16_t)value);
325}
326
327/*------------------------------------------------------------------------*
328 *	usb_quirk_add_entry_from_str
329 *
330 * Add a USB quirk entry from string.
331 *     "VENDOR PRODUCT LO_REV HI_REV QUIRK[,QUIRK[,...]]"
332 *------------------------------------------------------------------------*/
333static void
334hidquirk_add_entry_from_str(const char *name, const char *env)
335{
336	struct hidquirk_entry entry = { };
337	struct hidquirk_entry *new;
338	uint16_t quirk_idx;
339	uint16_t quirk;
340	const char *end;
341
342	/* check for invalid environment variable */
343	if (name == NULL || env == NULL)
344		return;
345
346	if (bootverbose)
347		printf("Adding HID QUIRK '%s' = '%s'\n", name, env);
348
349	/* parse device information */
350	entry.bus = hidquirk_strtou16(&env, name, "Bus ID");
351	entry.vid = hidquirk_strtou16(&env, name, "Vendor ID");
352	entry.pid = hidquirk_strtou16(&env, name, "Product ID");
353	entry.lo_rev = hidquirk_strtou16(&env, name, "Low revision");
354	entry.hi_rev = hidquirk_strtou16(&env, name, "High revision");
355
356	/* parse quirk information */
357	quirk_idx = 0;
358	while (*env != 0 && quirk_idx != HID_SUB_QUIRKS_MAX) {
359		/* skip whitespace before quirks */
360		while (*env == ' ' || *env == '\t')
361			env++;
362
363		/* look for quirk separation character */
364		end = strchr(env, ',');
365		if (end == NULL)
366			end = env + strlen(env);
367
368		/* lookup quirk in string table */
369		quirk = hid_strquirk(env, end - env);
370		if (quirk < HID_QUIRK_MAX) {
371			entry.quirks[quirk_idx++] = quirk;
372		} else {
373			printf("%s: unknown HID quirk '%.*s' (skipped)\n",
374			    name, (int)(end - env), env);
375		}
376		env = end;
377
378		/* skip quirk delimiter, if any */
379		if (*env != 0)
380			env++;
381	}
382
383	/* register quirk */
384	if (quirk_idx != 0) {
385		if (*env != 0) {
386			printf("%s: Too many HID quirks, only %d allowed!\n",
387			    name, HID_SUB_QUIRKS_MAX);
388		}
389		mtx_lock(&hidquirk_mtx);
390		new = hidquirk_get_entry(entry.bus, entry.vid, entry.pid,
391		    entry.lo_rev, entry.hi_rev, 1);
392		if (new == NULL)
393			printf("%s: HID quirks table is full!\n", name);
394		else
395			memcpy(new->quirks, entry.quirks, sizeof(entry.quirks));
396		mtx_unlock(&hidquirk_mtx);
397	} else {
398		printf("%s: No USB quirks found!\n", name);
399	}
400}
401
402static void
403hidquirk_init(void *arg)
404{
405	char envkey[sizeof(HID_QUIRK_ENVROOT) + 2];	/* 2 digits max, 0 to 99 */
406	int i;
407
408	/* initialize mutex */
409	mtx_init(&hidquirk_mtx, "HID quirk", NULL, MTX_DEF);
410
411	/* look for quirks defined by the environment variable */
412	for (i = 0; i != 100; i++) {
413		snprintf(envkey, sizeof(envkey), HID_QUIRK_ENVROOT "%d", i);
414
415		/* Stop at first undefined var */
416		if (!testenv(envkey))
417			break;
418
419		/* parse environment variable */
420		hidquirk_add_entry_from_str(envkey, kern_getenv(envkey));
421	}
422
423	/* register our function */
424	hid_test_quirk_p = &hid_test_quirk_by_info;
425}
426
427static void
428hidquirk_uninit(void *arg)
429{
430	hid_quirk_unload(arg);
431
432	/* destroy mutex */
433	mtx_destroy(&hidquirk_mtx);
434}
435
436SYSINIT(hidquirk_init, SI_SUB_LOCK, SI_ORDER_FIRST, hidquirk_init, NULL);
437SYSUNINIT(hidquirk_uninit, SI_SUB_LOCK, SI_ORDER_ANY, hidquirk_uninit, NULL);
438