xref: /freebsd/sys/dev/usb/quirk/usb_quirk.c (revision b3aaa0cc21c63d388230c7ef2a80abd631ff20d5)
1 /* $FreeBSD$ */
2 /*-
3  * Copyright (c) 1998 The NetBSD Foundation, Inc. All rights reserved.
4  * Copyright (c) 1998 Lennart Augustsson. All rights reserved.
5  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <dev/usb/usb.h>
30 #include <dev/usb/usb_ioctl.h>
31 #include <dev/usb/usb_mfunc.h>
32 #include "usbdevs.h"
33 
34 #define	USB_DEBUG_VAR usb2_debug
35 
36 #include <dev/usb/usb_core.h>
37 #include <dev/usb/usb_lookup.h>
38 #include <dev/usb/usb_debug.h>
39 #include <dev/usb/usb_dynamic.h>
40 
41 #include <dev/usb/quirk/usb_quirk.h>
42 
43 MODULE_DEPEND(usb_quirk, usb, 1, 1, 1);
44 MODULE_VERSION(usb_quirk, 1);
45 
46 /*
47  * The following macro adds one or more quirks for a USB device:
48  */
49 #define	USB_QUIRK_ENTRY(v,p,l,h,...) \
50   .vid = (v), .pid = (p), .lo_rev = (l), .hi_rev = (h), .quirks = { __VA_ARGS__ }
51 
52 #define	USB_DEV_QUIRKS_MAX 128
53 #define	USB_SUB_QUIRKS_MAX 8
54 
55 struct usb2_quirk_entry {
56 	uint16_t vid;
57 	uint16_t pid;
58 	uint16_t lo_rev;
59 	uint16_t hi_rev;
60 	uint16_t quirks[USB_SUB_QUIRKS_MAX];
61 };
62 
63 static struct mtx usb2_quirk_mtx;
64 
65 static struct usb2_quirk_entry usb2_quirks[USB_DEV_QUIRKS_MAX] = {
66 	{USB_QUIRK_ENTRY(USB_VENDOR_ASUS, USB_PRODUCT_ASUS_LCM, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
67 	{USB_QUIRK_ENTRY(USB_VENDOR_INSIDEOUT, USB_PRODUCT_INSIDEOUT_EDGEPORT4, 0x094, 0x094, UQ_SWAP_UNICODE, UQ_NONE)},
68 	{USB_QUIRK_ENTRY(USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2, 0x0a2, UQ_BAD_ADC, UQ_NONE)},
69 	{USB_QUIRK_ENTRY(USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2, 0x0a2, UQ_AU_NO_XU, UQ_NONE)},
70 	{USB_QUIRK_ENTRY(USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ADA70, 0x103, 0x103, UQ_BAD_ADC, UQ_NONE)},
71 	{USB_QUIRK_ENTRY(USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ASC495, 0x000, 0x000, UQ_BAD_AUDIO, UQ_NONE)},
72 	{USB_QUIRK_ENTRY(USB_VENDOR_QTRONIX, USB_PRODUCT_QTRONIX_980N, 0x110, 0x110, UQ_SPUR_BUT_UP, UQ_NONE)},
73 	{USB_QUIRK_ENTRY(USB_VENDOR_ALCOR2, USB_PRODUCT_ALCOR2_KBD_HUB, 0x001, 0x001, UQ_SPUR_BUT_UP, UQ_NONE)},
74 	{USB_QUIRK_ENTRY(USB_VENDOR_MCT, USB_PRODUCT_MCT_HUB0100, 0x102, 0x102, UQ_BUS_POWERED, UQ_NONE)},
75 	{USB_QUIRK_ENTRY(USB_VENDOR_MCT, USB_PRODUCT_MCT_USB232, 0x102, 0x102, UQ_BUS_POWERED, UQ_NONE)},
76 	{USB_QUIRK_ENTRY(USB_VENDOR_TI, USB_PRODUCT_TI_UTUSB41, 0x110, 0x110, UQ_POWER_CLAIM, UQ_NONE)},
77 	{USB_QUIRK_ENTRY(USB_VENDOR_TELEX, USB_PRODUCT_TELEX_MIC1, 0x009, 0x009, UQ_AU_NO_FRAC, UQ_NONE)},
78 	{USB_QUIRK_ENTRY(USB_VENDOR_SILICONPORTALS, USB_PRODUCT_SILICONPORTALS_YAPPHONE, 0x100, 0x100, UQ_AU_INP_ASYNC, UQ_NONE)},
79 	{USB_QUIRK_ENTRY(USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_UN53B, 0x0000, 0xFFFF, UQ_NO_STRINGS, UQ_NONE)},
80 
81 	/*
82 	 * XXX The following quirks should have a more specific revision
83 	 * number:
84 	 */
85 	{USB_QUIRK_ENTRY(USB_VENDOR_HP, USB_PRODUCT_HP_895C, 0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
86 	{USB_QUIRK_ENTRY(USB_VENDOR_HP, USB_PRODUCT_HP_880C, 0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
87 	{USB_QUIRK_ENTRY(USB_VENDOR_HP, USB_PRODUCT_HP_815C, 0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
88 	{USB_QUIRK_ENTRY(USB_VENDOR_HP, USB_PRODUCT_HP_810C, 0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
89 	{USB_QUIRK_ENTRY(USB_VENDOR_HP, USB_PRODUCT_HP_830C, 0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
90 	{USB_QUIRK_ENTRY(USB_VENDOR_HP, USB_PRODUCT_HP_1220C, 0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
91 	{USB_QUIRK_ENTRY(USB_VENDOR_XEROX, USB_PRODUCT_XEROX_WCM15, 0x0000, 0xFFFF, UQ_BROKEN_BIDIR, UQ_NONE)},
92 	/* Devices which should be ignored by uhid */
93 	{USB_QUIRK_ENTRY(USB_VENDOR_APC, USB_PRODUCT_APC_UPS, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
94 	{USB_QUIRK_ENTRY(USB_VENDOR_BELKIN, USB_PRODUCT_BELKIN_F6C550AVR, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
95 	{USB_QUIRK_ENTRY(USB_VENDOR_CYBERPOWER, USB_PRODUCT_CYBERPOWER_1500CAVRLCD, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
96 	{USB_QUIRK_ENTRY(USB_VENDOR_DELORME, USB_PRODUCT_DELORME_EARTHMATE, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
97 	{USB_QUIRK_ENTRY(USB_VENDOR_ITUNERNET, USB_PRODUCT_ITUNERNET_USBLCD2X20, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
98 	{USB_QUIRK_ENTRY(USB_VENDOR_ITUNERNET, USB_PRODUCT_ITUNERNET_USBLCD4X20, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
99 	{USB_QUIRK_ENTRY(USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS1, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
100 	{USB_QUIRK_ENTRY(USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS2, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
101 	{USB_QUIRK_ENTRY(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
102 	{USB_QUIRK_ENTRY(USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3G, 0x0000, 0xFFFF, UQ_HID_IGNORE, UQ_NONE)},
103 	/* Devices which should be ignored by both ukbd and uhid */
104 	{USB_QUIRK_ENTRY(USB_VENDOR_CYPRESS, USB_PRODUCT_CYPRESS_WISPY1A, 0x0000, 0xFFFF, UQ_KBD_IGNORE, UQ_HID_IGNORE, UQ_NONE)},
105 	{USB_QUIRK_ENTRY(USB_VENDOR_METAGEEK, USB_PRODUCT_METAGEEK_WISPY1B, 0x0000, 0xFFFF, UQ_KBD_IGNORE, UQ_HID_IGNORE, UQ_NONE)},
106 	{USB_QUIRK_ENTRY(USB_VENDOR_TENX, USB_PRODUCT_TENX_UAUDIO0, 0x0101, 0x0101, UQ_AUDIO_SWAP_LR, UQ_NONE)},
107 	/* MS keyboards do weird things */
108 	{USB_QUIRK_ENTRY(USB_VENDOR_MICROSOFT, USB_PRODUCT_MICROSOFT_WLINTELLIMOUSE, 0x0000, 0xFFFF, UQ_MS_LEADING_BYTE, UQ_NONE)},
109 	{USB_QUIRK_ENTRY(USB_VENDOR_METAGEEK, USB_PRODUCT_METAGEEK_WISPY24X, 0x0000, 0xFFFF, UQ_KBD_IGNORE, UQ_HID_IGNORE, UQ_NONE)},
110 };
111 
112 static const char *usb_quirk_str[USB_QUIRK_MAX] = {
113 	[UQ_NONE]		= "UQ_NONE",
114 	[UQ_AUDIO_SWAP_LR]	= "UQ_AUDIO_SWAP_LR",
115 	[UQ_AU_INP_ASYNC]	= "UQ_AU_INP_ASYNC",
116 	[UQ_AU_NO_FRAC]		= "UQ_AU_NO_FRAC",
117 	[UQ_AU_NO_XU]		= "UQ_AU_NO_XU",
118 	[UQ_BAD_ADC]		= "UQ_BAD_ADC",
119 	[UQ_BAD_AUDIO]		= "UQ_BAD_AUDIO",
120 	[UQ_BROKEN_BIDIR]	= "UQ_BROKEN_BIDIR",
121 	[UQ_BUS_POWERED]	= "UQ_BUS_POWERED",
122 	[UQ_HID_IGNORE]		= "UQ_HID_IGNORE",
123 	[UQ_KBD_IGNORE]		= "UQ_KBD_IGNORE",
124 	[UQ_MS_BAD_CLASS]	= "UQ_MS_BAD_CLASS",
125 	[UQ_MS_LEADING_BYTE]	= "UQ_MS_LEADING_BYTE",
126 	[UQ_MS_REVZ]		= "UQ_MS_REVZ",
127 	[UQ_NO_STRINGS]		= "UQ_NO_STRINGS",
128 	[UQ_OPEN_CLEARSTALL]	= "UQ_OPEN_CLEARSTALL",
129 	[UQ_POWER_CLAIM]	= "UQ_POWER_CLAIM",
130 	[UQ_SPUR_BUT_UP]	= "UQ_SPUR_BUT_UP",
131 	[UQ_SWAP_UNICODE]	= "UQ_SWAP_UNICODE",
132 	[UQ_CFG_INDEX_1]	= "UQ_CFG_INDEX_1",
133 	[UQ_CFG_INDEX_2]	= "UQ_CFG_INDEX_2",
134 	[UQ_CFG_INDEX_3]	= "UQ_CFG_INDEX_3",
135 	[UQ_CFG_INDEX_4]	= "UQ_CFG_INDEX_4",
136 	[UQ_CFG_INDEX_0]	= "UQ_CFG_INDEX_0",
137 };
138 
139 /*------------------------------------------------------------------------*
140  *	usb2_quirkstr
141  *
142  * This function converts an USB quirk code into a string.
143  *------------------------------------------------------------------------*/
144 static const char *
145 usb2_quirkstr(uint16_t quirk)
146 {
147 	return ((quirk < USB_QUIRK_MAX) ?
148 	    usb_quirk_str[quirk] : "USB_QUIRK_UNKNOWN");
149 }
150 
151 /*------------------------------------------------------------------------*
152  *	usb2_test_quirk_by_info
153  *
154  * Returns:
155  * 0: Quirk not found
156  * Else: Quirk found
157  *------------------------------------------------------------------------*/
158 static uint8_t
159 usb2_test_quirk_by_info(const struct usb2_lookup_info *info, uint16_t quirk)
160 {
161 	uint16_t x;
162 	uint16_t y;
163 
164 	if (quirk == UQ_NONE) {
165 		return (0);
166 	}
167 	mtx_lock(&usb2_quirk_mtx);
168 
169 	for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
170 		/* see if quirk information does not match */
171 		if ((usb2_quirks[x].vid != info->idVendor) ||
172 		    (usb2_quirks[x].pid != info->idProduct) ||
173 		    (usb2_quirks[x].lo_rev > info->bcdDevice) ||
174 		    (usb2_quirks[x].hi_rev < info->bcdDevice)) {
175 			continue;
176 		}
177 		/* lookup quirk */
178 		for (y = 0; y != USB_SUB_QUIRKS_MAX; y++) {
179 			if (usb2_quirks[x].quirks[y] == quirk) {
180 				mtx_unlock(&usb2_quirk_mtx);
181 				DPRINTF("Found quirk '%s'.\n", usb2_quirkstr(quirk));
182 				return (1);
183 			}
184 		}
185 		/* no quirk found */
186 		break;
187 	}
188 	mtx_unlock(&usb2_quirk_mtx);
189 	return (0);
190 }
191 
192 static struct usb2_quirk_entry *
193 usb2_quirk_get_entry(uint16_t vid, uint16_t pid,
194     uint16_t lo_rev, uint16_t hi_rev, uint8_t do_alloc)
195 {
196 	uint16_t x;
197 
198 	mtx_assert(&usb2_quirk_mtx, MA_OWNED);
199 
200 	if ((vid | pid | lo_rev | hi_rev) == 0) {
201 		/* all zero - special case */
202 		return (usb2_quirks + USB_DEV_QUIRKS_MAX - 1);
203 	}
204 	/* search for an existing entry */
205 	for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
206 		/* see if quirk information does not match */
207 		if ((usb2_quirks[x].vid != vid) ||
208 		    (usb2_quirks[x].pid != pid) ||
209 		    (usb2_quirks[x].lo_rev != lo_rev) ||
210 		    (usb2_quirks[x].hi_rev != hi_rev)) {
211 			continue;
212 		}
213 		return (usb2_quirks + x);
214 	}
215 
216 	if (do_alloc == 0) {
217 		/* no match */
218 		return (NULL);
219 	}
220 	/* search for a free entry */
221 	for (x = 0; x != USB_DEV_QUIRKS_MAX; x++) {
222 		/* see if quirk information does not match */
223 		if ((usb2_quirks[x].vid |
224 		    usb2_quirks[x].pid |
225 		    usb2_quirks[x].lo_rev |
226 		    usb2_quirks[x].hi_rev) != 0) {
227 			continue;
228 		}
229 		usb2_quirks[x].vid = vid;
230 		usb2_quirks[x].pid = pid;
231 		usb2_quirks[x].lo_rev = lo_rev;
232 		usb2_quirks[x].hi_rev = hi_rev;
233 
234 		return (usb2_quirks + x);
235 	}
236 
237 	/* no entry found */
238 	return (NULL);
239 }
240 
241 /*------------------------------------------------------------------------*
242  *	usb2_quirk_ioctl - handle quirk IOCTLs
243  *
244  * Returns:
245  * 0: Success
246  * Else: Failure
247  *------------------------------------------------------------------------*/
248 static int
249 usb2_quirk_ioctl(unsigned long cmd, caddr_t data,
250     int fflag, struct thread *td)
251 {
252 	struct usb2_gen_quirk *pgq;
253 	struct usb2_quirk_entry *pqe;
254 	uint32_t x;
255 	uint32_t y;
256 	int err;
257 
258 	switch (cmd) {
259 	case USB_DEV_QUIRK_GET:
260 		pgq = (void *)data;
261 		x = pgq->index % USB_SUB_QUIRKS_MAX;
262 		y = pgq->index / USB_SUB_QUIRKS_MAX;
263 		if (y >= USB_DEV_QUIRKS_MAX) {
264 			return (EINVAL);
265 		}
266 		mtx_lock(&usb2_quirk_mtx);
267 		/* copy out data */
268 		pgq->vid = usb2_quirks[y].vid;
269 		pgq->pid = usb2_quirks[y].pid;
270 		pgq->bcdDeviceLow = usb2_quirks[y].lo_rev;
271 		pgq->bcdDeviceHigh = usb2_quirks[y].hi_rev;
272 		strlcpy(pgq->quirkname,
273 		    usb2_quirkstr(usb2_quirks[y].quirks[x]),
274 		    sizeof(pgq->quirkname));
275 		mtx_unlock(&usb2_quirk_mtx);
276 		return (0);		/* success */
277 
278 	case USB_QUIRK_NAME_GET:
279 		pgq = (void *)data;
280 		x = pgq->index;
281 		if (x >= USB_QUIRK_MAX) {
282 			return (EINVAL);
283 		}
284 		strlcpy(pgq->quirkname,
285 		    usb2_quirkstr(x), sizeof(pgq->quirkname));
286 		return (0);		/* success */
287 
288 	case USB_DEV_QUIRK_ADD:
289 		pgq = (void *)data;
290 
291 		/* check privileges */
292 		err = priv_check(curthread, PRIV_DRIVER);
293 		if (err) {
294 			return (err);
295 		}
296 		/* convert quirk string into numerical */
297 		for (y = 0; y != USB_DEV_QUIRKS_MAX; y++) {
298 			if (strcmp(pgq->quirkname, usb2_quirkstr(y)) == 0) {
299 				break;
300 			}
301 		}
302 		if (y == USB_DEV_QUIRKS_MAX) {
303 			return (EINVAL);
304 		}
305 		if (y == UQ_NONE) {
306 			return (EINVAL);
307 		}
308 		mtx_lock(&usb2_quirk_mtx);
309 		pqe = usb2_quirk_get_entry(pgq->vid, pgq->pid,
310 		    pgq->bcdDeviceLow, pgq->bcdDeviceHigh, 1);
311 		for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
312 			if (pqe->quirks[x] == UQ_NONE) {
313 				pqe->quirks[x] = y;
314 				break;
315 			}
316 		}
317 		mtx_unlock(&usb2_quirk_mtx);
318 		if (x == USB_SUB_QUIRKS_MAX) {
319 			return (ENOMEM);
320 		}
321 		return (0);		/* success */
322 
323 	case USB_DEV_QUIRK_REMOVE:
324 		pgq = (void *)data;
325 		/* check privileges */
326 		err = priv_check(curthread, PRIV_DRIVER);
327 		if (err) {
328 			return (err);
329 		}
330 		/* convert quirk string into numerical */
331 		for (y = 0; y != USB_DEV_QUIRKS_MAX; y++) {
332 			if (strcmp(pgq->quirkname, usb2_quirkstr(y)) == 0) {
333 				break;
334 			}
335 		}
336 		if (y == USB_DEV_QUIRKS_MAX) {
337 			return (EINVAL);
338 		}
339 		if (y == UQ_NONE) {
340 			return (EINVAL);
341 		}
342 		mtx_lock(&usb2_quirk_mtx);
343 		pqe = usb2_quirk_get_entry(pgq->vid, pgq->pid,
344 		    pgq->bcdDeviceLow, pgq->bcdDeviceHigh, 0);
345 		for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
346 			if (pqe->quirks[x] == y) {
347 				pqe->quirks[x] = UQ_NONE;
348 				break;
349 			}
350 		}
351 		if (x == USB_SUB_QUIRKS_MAX) {
352 			mtx_unlock(&usb2_quirk_mtx);
353 			return (ENOMEM);
354 		}
355 		for (x = 0; x != USB_SUB_QUIRKS_MAX; x++) {
356 			if (pqe->quirks[x] != UQ_NONE) {
357 				break;
358 			}
359 		}
360 		if (x == USB_SUB_QUIRKS_MAX) {
361 			/* all quirk entries are unused - release */
362 			memset(pqe, 0, sizeof(pqe));
363 		}
364 		mtx_unlock(&usb2_quirk_mtx);
365 		return (0);		/* success */
366 
367 	default:
368 		break;
369 	}
370 	return (ENOIOCTL);
371 }
372 
373 static void
374 usb2_quirk_init(void *arg)
375 {
376 	/* initialize mutex */
377 	mtx_init(&usb2_quirk_mtx, "USB quirk", NULL, MTX_DEF);
378 
379 	/* register our function */
380 	usb2_test_quirk_p = &usb2_test_quirk_by_info;
381 	usb2_quirk_ioctl_p = &usb2_quirk_ioctl;
382 }
383 
384 static void
385 usb2_quirk_uninit(void *arg)
386 {
387 	usb2_quirk_unload(arg);
388 
389 	/* destroy mutex */
390 	mtx_destroy(&usb2_quirk_mtx);
391 }
392 
393 SYSINIT(usb2_quirk_init, SI_SUB_LOCK, SI_ORDER_FIRST, usb2_quirk_init, NULL);
394 SYSUNINIT(usb2_quirk_uninit, SI_SUB_LOCK, SI_ORDER_ANY, usb2_quirk_uninit, NULL);
395