1*e91196a2Sdholland /* $NetBSD: usb_quirks.c,v 1.108 2024/02/28 21:52:40 dholland Exp $ */
2906987bbSimp /* $FreeBSD: src/sys/dev/usb/usb_quirks.c,v 1.30 2003/01/02 04:15:55 imp Exp $ */
3deb00272Saugustss
4deb00272Saugustss /*
52d562a01Smycroft * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
6deb00272Saugustss * All rights reserved.
7deb00272Saugustss *
8ca707fcdSaugustss * This code is derived from software contributed to The NetBSD Foundation
930c20f93Saugustss * by Lennart Augustsson (lennart@augustsson.net) at
10ca707fcdSaugustss * Carlstedt Research & Technology.
11deb00272Saugustss *
12deb00272Saugustss * Redistribution and use in source and binary forms, with or without
13deb00272Saugustss * modification, are permitted provided that the following conditions
14deb00272Saugustss * are met:
15deb00272Saugustss * 1. Redistributions of source code must retain the above copyright
16deb00272Saugustss * notice, this list of conditions and the following disclaimer.
17deb00272Saugustss * 2. Redistributions in binary form must reproduce the above copyright
18deb00272Saugustss * notice, this list of conditions and the following disclaimer in the
19deb00272Saugustss * documentation and/or other materials provided with the distribution.
20deb00272Saugustss *
21deb00272Saugustss * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22deb00272Saugustss * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23deb00272Saugustss * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24deb00272Saugustss * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25deb00272Saugustss * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26deb00272Saugustss * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27deb00272Saugustss * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28deb00272Saugustss * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29deb00272Saugustss * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30deb00272Saugustss * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31deb00272Saugustss * POSSIBILITY OF SUCH DAMAGE.
32deb00272Saugustss */
33deb00272Saugustss
34667807e4Slukem #include <sys/cdefs.h>
35*e91196a2Sdholland __KERNEL_RCSID(0, "$NetBSD: usb_quirks.c,v 1.108 2024/02/28 21:52:40 dholland Exp $");
367c2a9a09Sskrll
377c2a9a09Sskrll #ifdef _KERNEL_OPT
387c2a9a09Sskrll #include "opt_usb.h"
397c2a9a09Sskrll #endif
40667807e4Slukem
41deb00272Saugustss #include <sys/param.h>
42deb00272Saugustss #include <sys/systm.h>
43deb00272Saugustss
44deb00272Saugustss #include <dev/usb/usb.h>
45deb00272Saugustss #include <dev/usb/usbdevs.h>
46077b167aSmanu #include <dev/usb/usbdi.h>
47077b167aSmanu #include <dev/usb/usbdivar.h>
48077b167aSmanu #include <dev/usb/usbhist.h>
49deb00272Saugustss #include <dev/usb/usb_quirks.h>
50deb00272Saugustss
51077b167aSmanu #define DPRINTF(FMT,A,B,C,D) USBHIST_LOG(usbdebug,FMT,A,B,C,D)
52077b167aSmanu
53b86cb140Saugustss #define ANY 0xffff
54077b167aSmanu #define _USETW(w) { (w) & 0x00ff, ((w) & 0xff00) >> 8 }
55077b167aSmanu
56077b167aSmanu /*
57077b167aSmanu * NXP PN533 NFC chip descriptors
58077b167aSmanu */
59077b167aSmanu static const usb_endpoint_descriptor_t desc_ep_pn533_in = {
60077b167aSmanu /* bLength */ sizeof(desc_ep_pn533_in),
61077b167aSmanu /* bDescriptorType */ UDESC_ENDPOINT,
62077b167aSmanu /* bEndpointAddress */ UE_DIR_IN | 0x04,
63077b167aSmanu /* bmAttributes */ UE_BULK,
64077b167aSmanu /* wMaxPacketSize */ _USETW(0x0040),
65077b167aSmanu /* bInterval */ 0x04, /* 255ms */
66077b167aSmanu };
67077b167aSmanu
68077b167aSmanu static const usb_endpoint_descriptor_t desc_ep_pn533_out = {
69077b167aSmanu /* bLength */ sizeof(desc_ep_pn533_in),
70077b167aSmanu /* bDescriptorType */ UDESC_ENDPOINT,
71077b167aSmanu /* bEndpointAddress */ UE_DIR_OUT | 0x04,
72077b167aSmanu /* bmAttributes */ UE_BULK,
73077b167aSmanu /* wMaxPacketSize */ _USETW(0x0040),
74077b167aSmanu /* bInterval */ 0x04, /* 255ms */
75077b167aSmanu };
76077b167aSmanu
77077b167aSmanu static const usb_interface_descriptor_t desc_iface_pn533 = {
78077b167aSmanu /* bLength */ sizeof(desc_iface_pn533),
79077b167aSmanu /* bDescriptorType */ UDESC_INTERFACE,
80077b167aSmanu /* bInterfaceNumber */ 0,
81077b167aSmanu /* bAlternateSetting */ 0,
82077b167aSmanu /* bNumEndpoints */ 2,
83077b167aSmanu /* bInterfaceClass */ 0xff,
84077b167aSmanu /* bInterfaceSubClass */ 0xff,
85077b167aSmanu /* bInterfaceProtocol */ 0xff,
86077b167aSmanu /* iInterface */ 0,
87077b167aSmanu };
88077b167aSmanu
89077b167aSmanu static const usb_config_descriptor_t desc_conf_pn533 = {
90077b167aSmanu /* bLength */ sizeof(desc_conf_pn533),
91077b167aSmanu /* bDescriptorType */ UDESC_CONFIG,
92077b167aSmanu /* wTotalLength */ _USETW(sizeof(desc_conf_pn533) +
93077b167aSmanu sizeof(desc_iface_pn533) +
94077b167aSmanu sizeof(desc_ep_pn533_in) +
95077b167aSmanu sizeof(desc_ep_pn533_out)
96077b167aSmanu ),
972e0bf311Sandvar /* bNumInterface */ 1,
98077b167aSmanu /* bConfigurationValue */1,
99077b167aSmanu /* iConfiguration */ 0,
100077b167aSmanu /* bmAttributes */ UC_ATTR_MBO,
101077b167aSmanu /* bMaxPower */ 0x32, /* 100mA */
102077b167aSmanu };
103077b167aSmanu
104077b167aSmanu static const usb_descriptor_t *desc_pn533[] = {
105077b167aSmanu (const usb_descriptor_t *)&desc_conf_pn533,
106077b167aSmanu (const usb_descriptor_t *)&desc_iface_pn533,
107077b167aSmanu (const usb_descriptor_t *)&desc_ep_pn533_out,
108077b167aSmanu (const usb_descriptor_t *)&desc_ep_pn533_in,
109077b167aSmanu NULL
110077b167aSmanu };
111077b167aSmanu
112077b167aSmanu
113077b167aSmanu usbd_status
usbd_get_desc_fake(struct usbd_device * dev,int type,int index,int len,void * desc)114077b167aSmanu usbd_get_desc_fake(struct usbd_device *dev, int type, int index,
115077b167aSmanu int len, void *desc)
116077b167aSmanu {
117077b167aSmanu USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
118077b167aSmanu #ifdef USB_DEBUG
119077b167aSmanu const usb_device_descriptor_t *dd = usbd_get_device_descriptor(dev);
120077b167aSmanu #endif
121077b167aSmanu const usb_descriptor_t *ub;
122077b167aSmanu int i = 0;
123077b167aSmanu int j = 0;
124077b167aSmanu usbd_status err = USBD_INVAL;
125077b167aSmanu
126077b167aSmanu if (dev->ud_quirks == NULL || dev->ud_quirks->desc == NULL) {
12713fbb093Schristos DPRINTF("%04jx/%04j: no fake descriptors",
128077b167aSmanu UGETW(dd->idVendor), UGETW(dd->idProduct), 0, 0);
129077b167aSmanu goto out;
130077b167aSmanu }
131077b167aSmanu
132077b167aSmanu for (j = 0; dev->ud_quirks->desc[j]; j++) {
133077b167aSmanu ub = dev->ud_quirks->desc[j];
134077b167aSmanu if (ub->bDescriptorType == type && i++ == index)
135077b167aSmanu break;
136077b167aSmanu }
137077b167aSmanu
138077b167aSmanu if (dev->ud_quirks->desc[j] == NULL) {
13913fbb093Schristos DPRINTF("%04jx/%04jx: no fake descriptor type = %jd, len = %jd",
140077b167aSmanu UGETW(dd->idVendor), UGETW(dd->idProduct), type, len);
141077b167aSmanu goto out;
142077b167aSmanu }
143077b167aSmanu
144077b167aSmanu do {
145077b167aSmanu ub = dev->ud_quirks->desc[j];
146077b167aSmanu
147077b167aSmanu if (ub->bLength > len) {
14813fbb093Schristos DPRINTF("%04jx/%04jx: short buf len = %jd, bLength = %jd",
149077b167aSmanu UGETW(dd->idVendor), UGETW(dd->idProduct),
150077b167aSmanu type, ub->bLength);
151077b167aSmanu goto out;
152077b167aSmanu }
153077b167aSmanu
154077b167aSmanu memcpy(desc, ub, ub->bLength);
15513fbb093Schristos DPRINTF("%04jx/%04jx: Use fake descriptor type %jd",
156077b167aSmanu UGETW(dd->idVendor), UGETW(dd->idProduct),
157077b167aSmanu type, 0);
158077b167aSmanu
159077b167aSmanu desc = (char *)desc + ub->bLength;
160077b167aSmanu len -= ub->bLength;
161077b167aSmanu j++;
162077b167aSmanu } while (len && dev->ud_quirks->desc[j] &&
163077b167aSmanu dev->ud_quirks->desc[j]->bDescriptorType != type);
164077b167aSmanu
165077b167aSmanu err = USBD_NORMAL_COMPLETION;
166077b167aSmanu
16713fbb093Schristos DPRINTF("%04jx/%04jx: Using fake USB descriptors\n",
168077b167aSmanu UGETW(dd->idVendor), UGETW(dd->idProduct), 0, 0);
169077b167aSmanu out:
17013fbb093Schristos DPRINTF("return err = %jd", err, 0, 0, 0);
171077b167aSmanu return err;
172077b167aSmanu }
173595f18daSaugustss
17434c8ae80Sjdolecek Static const struct usbd_quirk_entry {
1754e8e6643Sskrll uint16_t idVendor;
1764e8e6643Sskrll uint16_t idProduct;
1774e8e6643Sskrll uint16_t bcdDevice;
178deb00272Saugustss struct usbd_quirks quirks;
1790d2fabdfSaugustss } usb_quirks[] = {
180d7415fbdSveego /* Devices which should be ignored by uhid */
181077b167aSmanu { USB_VENDOR_APC, USB_PRODUCT_APC_UPS, ANY,
182077b167aSmanu { UQ_HID_IGNORE, NULL }},
183550203a6Smartin { USB_VENDOR_APC, USB_PRODUCT_APC_UPS3, ANY,
184550203a6Smartin { UQ_HID_IGNORE, NULL }},
1852fbfb43fSmrg { USB_VENDOR_CYBERPOWER, USB_PRODUCT_CYBERPOWER_UPS0, ANY,
1862fbfb43fSmrg { UQ_HID_IGNORE, NULL }},
187077b167aSmanu { USB_VENDOR_CYBERPOWER, USB_PRODUCT_CYBERPOWER_UPS, ANY,
188077b167aSmanu { UQ_HID_IGNORE, NULL }},
1892fbfb43fSmrg { USB_VENDOR_CYBERPOWER, USB_PRODUCT_CYBERPOWER_UPS2, ANY,
1902fbfb43fSmrg { UQ_HID_IGNORE, NULL }},
1912ed68a82Sjakllsch { USB_VENDOR_GRETAGMACBETH, ANY, ANY,
1922ed68a82Sjakllsch { UQ_HID_IGNORE, NULL }},
193077b167aSmanu { USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS1, ANY,
194077b167aSmanu { UQ_HID_IGNORE, NULL }},
195077b167aSmanu { USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS2, ANY,
196077b167aSmanu { UQ_HID_IGNORE, NULL }},
197077b167aSmanu { USB_VENDOR_MICROCHIP, USB_PRODUCT_MICROCHIP_PICKIT1, ANY,
198077b167aSmanu { UQ_HID_IGNORE, NULL }},
199bbc532e0Sbouyer { USB_VENDOR_MICROCHIP, USB_PRODUCT_MICROCHIP_PICKIT2, ANY,
200bbc532e0Sbouyer { UQ_HID_IGNORE, NULL }},
201bbc532e0Sbouyer { USB_VENDOR_MICROCHIP, USB_PRODUCT_MICROCHIP_PICKIT3, ANY,
202bbc532e0Sbouyer { UQ_HID_IGNORE, NULL }},
203077b167aSmanu { USB_VENDOR_TRIPPLITE2, ANY, ANY,
204077b167aSmanu { UQ_HID_IGNORE, NULL }},
205077b167aSmanu { USB_VENDOR_MISC, USB_PRODUCT_MISC_WISPY_24X, ANY,
206077b167aSmanu { UQ_HID_IGNORE, NULL }},
207077b167aSmanu { USB_VENDOR_WELTREND, USB_PRODUCT_WELTREND_HID, ANY,
208077b167aSmanu { UQ_HID_IGNORE, NULL }},
209077b167aSmanu { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_EC3, ANY,
210077b167aSmanu { UQ_HID_IGNORE, NULL }},
211077b167aSmanu { USB_VENDOR_TI, USB_PRODUCT_TI_MSP430, ANY,
212077b167aSmanu { UQ_HID_IGNORE, NULL }},
2132ed68a82Sjakllsch { USB_VENDOR_XRITE, ANY, ANY,
2142ed68a82Sjakllsch { UQ_HID_IGNORE, NULL }},
215a99a2d70Sjym { USB_VENDOR_WAYTECH, USB_PRODUCT_WAYTECH_USB2SERIAL, ANY,
216a99a2d70Sjym { UQ_HID_IGNORE, NULL }},
217077b167aSmanu { USB_VENDOR_KYE, USB_PRODUCT_KYE_NICHE, 0x100,
218077b167aSmanu { UQ_NO_SET_PROTO, NULL }},
219077b167aSmanu { USB_VENDOR_INSIDEOUT, USB_PRODUCT_INSIDEOUT_EDGEPORT4, 0x094,
220077b167aSmanu { UQ_SWAP_UNICODE, NULL }},
221077b167aSmanu { USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2,
222077b167aSmanu { UQ_BAD_ADC, NULL }},
223077b167aSmanu { USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502, 0x0a2,
224077b167aSmanu { UQ_AU_NO_XU, NULL }},
225077b167aSmanu { USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ADA70, 0x103,
226077b167aSmanu { UQ_BAD_ADC, NULL }},
227077b167aSmanu { USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ASC495, 0x000,
228077b167aSmanu { UQ_BAD_AUDIO, NULL }},
229077b167aSmanu { USB_VENDOR_SONY, USB_PRODUCT_SONY_PS2EYETOY4, 0x000,
230077b167aSmanu { UQ_BAD_AUDIO, NULL }},
231077b167aSmanu { USB_VENDOR_SONY, USB_PRODUCT_SONY_PS2EYETOY5, 0x000,
232077b167aSmanu { UQ_BAD_AUDIO, NULL }},
233077b167aSmanu { USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_PCVC740K, ANY,
234077b167aSmanu { UQ_BAD_AUDIO, NULL }},
235077b167aSmanu { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMPRONB, 0x000,
236077b167aSmanu { UQ_BAD_AUDIO, NULL }},
237077b167aSmanu { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMPRO4K, 0x000,
238077b167aSmanu { UQ_BAD_AUDIO, NULL }},
239077b167aSmanu { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMMESS, 0x100,
240077b167aSmanu { UQ_BAD_ADC, NULL }},
241077b167aSmanu { USB_VENDOR_QTRONIX, USB_PRODUCT_QTRONIX_980N, 0x110,
242077b167aSmanu { UQ_SPUR_BUT_UP, NULL }},
243077b167aSmanu { USB_VENDOR_ALCOR2, USB_PRODUCT_ALCOR2_KBD_HUB, 0x001,
244077b167aSmanu { UQ_SPUR_BUT_UP, NULL }},
245077b167aSmanu { USB_VENDOR_METRICOM, USB_PRODUCT_METRICOM_RICOCHET_GS, 0x100,
246077b167aSmanu { UQ_ASSUME_CM_OVER_DATA, NULL }},
247077b167aSmanu { USB_VENDOR_SANYO, USB_PRODUCT_SANYO_SCP4900, 0x000,
248077b167aSmanu { UQ_ASSUME_CM_OVER_DATA, NULL }},
249077b167aSmanu { USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_T720C, 0x001,
250077b167aSmanu { UQ_ASSUME_CM_OVER_DATA, NULL }},
251077b167aSmanu { USB_VENDOR_EICON, USB_PRODUCT_EICON_DIVA852, 0x100,
252077b167aSmanu { UQ_ASSUME_CM_OVER_DATA, NULL }},
253077b167aSmanu { USB_VENDOR_SIEMENS2, USB_PRODUCT_SIEMENS2_MC75, 0x000,
254077b167aSmanu { UQ_ASSUME_CM_OVER_DATA, NULL }},
255077b167aSmanu { USB_VENDOR_TELEX, USB_PRODUCT_TELEX_MIC1, 0x009,
256077b167aSmanu { UQ_AU_NO_FRAC, NULL }},
257077b167aSmanu { USB_VENDOR_SILICONPORTALS, USB_PRODUCT_SILICONPORTALS_YAPPHONE, 0x100,
258077b167aSmanu { UQ_AU_INP_ASYNC, NULL }},
259077b167aSmanu { USB_VENDOR_AVANCELOGIC, USB_PRODUCT_AVANCELOGIC_USBAUDIO, 0x101,
260077b167aSmanu { UQ_AU_INP_ASYNC, NULL }},
261077b167aSmanu { USB_VENDOR_PLANTRONICS, USB_PRODUCT_PLANTRONICS_HEADSET, 0x004,
262077b167aSmanu { UQ_AU_INP_ASYNC, NULL }},
263077b167aSmanu { USB_VENDOR_CMEDIA, USB_PRODUCT_CMEDIA_USBAUDIO, ANY,
264077b167aSmanu { UQ_AU_INP_ASYNC, NULL }},
2655c8acba5Srmind
266595f18daSaugustss /* XXX These should have a revision number, but I don't know what they are. */
267077b167aSmanu { USB_VENDOR_HP, USB_PRODUCT_HP_895C, ANY,
268077b167aSmanu { UQ_BROKEN_BIDIR, NULL }},
269077b167aSmanu { USB_VENDOR_HP, USB_PRODUCT_HP_880C, ANY,
270077b167aSmanu { UQ_BROKEN_BIDIR, NULL }},
271077b167aSmanu { USB_VENDOR_HP, USB_PRODUCT_HP_815C, ANY,
272077b167aSmanu { UQ_BROKEN_BIDIR, NULL }},
273077b167aSmanu { USB_VENDOR_HP, USB_PRODUCT_HP_810C, ANY,
274077b167aSmanu { UQ_BROKEN_BIDIR, NULL }},
275077b167aSmanu { USB_VENDOR_HP, USB_PRODUCT_HP_830C, ANY,
276077b167aSmanu { UQ_BROKEN_BIDIR, NULL }},
277077b167aSmanu { USB_VENDOR_HP, USB_PRODUCT_HP_885C, ANY,
278077b167aSmanu { UQ_BROKEN_BIDIR, NULL }},
279077b167aSmanu { USB_VENDOR_HP, USB_PRODUCT_HP_840C, ANY,
280077b167aSmanu { UQ_BROKEN_BIDIR, NULL }},
281077b167aSmanu { USB_VENDOR_HP, USB_PRODUCT_HP_816C, ANY,
282077b167aSmanu { UQ_BROKEN_BIDIR, NULL }},
283077b167aSmanu { USB_VENDOR_HP, USB_PRODUCT_HP_959C, ANY,
284077b167aSmanu { UQ_BROKEN_BIDIR, NULL }},
285077b167aSmanu { USB_VENDOR_MTK, USB_PRODUCT_MTK_GPS_RECEIVER, ANY,
286077b167aSmanu { UQ_NO_UNION_NRM, NULL }},
287077b167aSmanu { USB_VENDOR_NEC, USB_PRODUCT_NEC_PICTY900, ANY,
288077b167aSmanu { UQ_BROKEN_BIDIR, NULL }},
289077b167aSmanu { USB_VENDOR_NEC, USB_PRODUCT_NEC_PICTY760, ANY,
290077b167aSmanu { UQ_BROKEN_BIDIR, NULL }},
291077b167aSmanu { USB_VENDOR_NEC, USB_PRODUCT_NEC_PICTY920, ANY,
292077b167aSmanu { UQ_BROKEN_BIDIR, NULL }},
293077b167aSmanu { USB_VENDOR_NEC, USB_PRODUCT_NEC_PICTY800, ANY,
294077b167aSmanu { UQ_BROKEN_BIDIR, NULL }},
295077b167aSmanu { USB_VENDOR_HP, USB_PRODUCT_HP_1220C, ANY,
296077b167aSmanu { UQ_BROKEN_BIDIR, NULL }},
2979cc3a93fSsalo
298d5068131Sphx /* Apple internal notebook ISO keyboards have swapped keys */
299077b167aSmanu { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_FOUNTAIN_ISO, ANY,
300077b167aSmanu { UQ_APPLE_ISO, NULL }},
301077b167aSmanu { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_GEYSER_ISO, ANY,
302077b167aSmanu { UQ_APPLE_ISO, NULL }},
303d5068131Sphx
304fc513621Sjmcneill /* HID and audio are both invalid on iPhone/iPod Touch */
305077b167aSmanu { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE, ANY,
306077b167aSmanu { UQ_HID_IGNORE | UQ_BAD_AUDIO, NULL }},
307077b167aSmanu { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPOD_TOUCH, ANY,
308077b167aSmanu { UQ_HID_IGNORE | UQ_BAD_AUDIO, NULL }},
309077b167aSmanu { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPOD_TOUCH_4G, ANY,
310077b167aSmanu { UQ_HID_IGNORE | UQ_BAD_AUDIO, NULL }},
311077b167aSmanu { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3G, ANY,
312077b167aSmanu { UQ_HID_IGNORE | UQ_BAD_AUDIO, NULL }},
313077b167aSmanu { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3GS, ANY,
314077b167aSmanu { UQ_HID_IGNORE | UQ_BAD_AUDIO, NULL }},
315fc513621Sjmcneill
3167676dfd5Smartin /*
3177676dfd5Smartin * Various devices using serial boot loader protocol, as supported
3187676dfd5Smartin * by pkgsrc/sysutils/imx_usb_loader
3197676dfd5Smartin */
3207676dfd5Smartin { 0x066f, 0x3780, /* mx23 */ ANY,
3217676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3227676dfd5Smartin { 0x15a2, 0x004f, /* mx28 */ ANY,
3237676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3247676dfd5Smartin { 0x15a2, 0x0052, /* mx50 */ ANY,
3257676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3267676dfd5Smartin { 0x15a2, 0x0054, /* mx6 */ ANY,
3277676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3287676dfd5Smartin { 0x15a2, 0x0061, /* mx6 */ ANY,
3297676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3307676dfd5Smartin { 0x15a2, 0x0063, /* mx6 */ ANY,
3317676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3327676dfd5Smartin { 0x15a2, 0x0071, /* mx6 */ ANY,
3337676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3347676dfd5Smartin { 0x15a2, 0x007d, /* mx6 */ ANY,
3357676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3367676dfd5Smartin { 0x15a2, 0x0080, /* mx6ull */ ANY,
3377676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3387676dfd5Smartin { 0x1fc9, 0x0128, /* mx6 */ ANY,
3397676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3407676dfd5Smartin { 0x15a2, 0x0076, /* mx7 */ ANY,
3417676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3427676dfd5Smartin { 0x1fc9, 0x0126, /* mx7ulp */ ANY,
3437676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3447676dfd5Smartin { 0x15a2, 0x0041, /* mx51 */ ANY,
3457676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3467676dfd5Smartin { 0x15a2, 0x004e, /* mx53 */ ANY,
3477676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3487676dfd5Smartin { 0x15a2, 0x006a, /* vybrid */ ANY,
3497676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3507676dfd5Smartin { 0x066f, 0x37ff, /* linux_gadget */ ANY,
3517676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3527676dfd5Smartin { 0x1b67, 0x4fff, /* mx6 */ ANY,
3537676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3547676dfd5Smartin { 0x0525, 0xb4a4, /* mx6 */ ANY,
3557676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3567676dfd5Smartin { 0x1fc9, 0x012b, /* mx8mq */ ANY,
3577676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3587676dfd5Smartin { 0x1fc9, 0x0134, /* mx8mm */ ANY,
3597676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3607676dfd5Smartin { 0x1fc9, 0x013e, /* mx8mn */ ANY,
3617676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3627676dfd5Smartin { 0x3016, 0x1001, /* mx8mn */ ANY,
3637676dfd5Smartin { UQ_HID_IGNORE, NULL }},
3647676dfd5Smartin
365077b167aSmanu { USB_VENDOR_LG, USB_PRODUCT_LG_CDMA_MSM, ANY,
366077b167aSmanu { UQ_ASSUME_CM_OVER_DATA, NULL }},
367077b167aSmanu { USB_VENDOR_QUALCOMM2, USB_PRODUCT_QUALCOMM2_CDMA_MSM, ANY,
368077b167aSmanu { UQ_ASSUME_CM_OVER_DATA, NULL }},
369077b167aSmanu { USB_VENDOR_HYUNDAI, USB_PRODUCT_HYUNDAI_UM175, ANY,
370077b167aSmanu { UQ_ASSUME_CM_OVER_DATA, NULL }},
371077b167aSmanu { USB_VENDOR_ZOOM, USB_PRODUCT_ZOOM_3095, ANY,
372077b167aSmanu { UQ_LOST_CS_DESC, NULL }},
373077b167aSmanu
3741818bfe1Smanu /*
3751818bfe1Smanu * NXP PN533 bugs
3761818bfe1Smanu *
3771818bfe1Smanu * 1. It corrupts its USB descriptors. The quirk is to provide hardcoded
3781818bfe1Smanu * descriptors instead of getting them from the device.
3791818bfe1Smanu * 2. It mishandles the USB toggle bit. This causes some replies to be
38052cba97cSandvar * filtered out by the USB host controller and be reported as timed out.
3811818bfe1Smanu * NFC tool's libnfc workaround this bug by sending a dummy frame to
3821818bfe1Smanu * resync the toggle bit, but in order to succeed, that operation must
3831818bfe1Smanu * not be reported as failed. The quirk is therefore to pretend to
3841818bfe1Smanu * userland that output timeouts are successes.
3851818bfe1Smanu */
386529c99a3Smartin { USB_VENDOR_PHILIPSSEMI, USB_PRODUCT_PHILIPSSEMI_PN533, ANY,
3871818bfe1Smanu { UQ_DESC_CORRUPT | UQ_MISS_OUT_ACK, desc_pn533 }},
388077b167aSmanu { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_SCL3711, ANY,
3891818bfe1Smanu { UQ_DESC_CORRUPT | UQ_MISS_OUT_ACK, desc_pn533 }},
390077b167aSmanu { USB_VENDOR_SHUTTLE, USB_PRODUCT_SHUTTLE_SCL3712, ANY,
3911818bfe1Smanu { UQ_DESC_CORRUPT | UQ_MISS_OUT_ACK, desc_pn533 }},
39298194e60Smacallan
39398194e60Smacallan /*
39498194e60Smacallan * These cheap mice will disconnect after 60 seconds,
39598194e60Smacallan * reconnect, and then disconnect again (ad nauseum)
39698194e60Smacallan * unless it's kept open.
39798194e60Smacallan */
39898194e60Smacallan { USB_VENDOR_CHICONY, USB_PRODUCT_CHICONY_OPTMOUSE0939, ANY,
39998194e60Smacallan { UQ_ALWAYS_ON, NULL }},
40098194e60Smacallan { USB_VENDOR_PIXART, USB_PRODUCT_PIXART_RPIMOUSE, ANY,
40198194e60Smacallan { UQ_ALWAYS_ON, NULL }},
402*e91196a2Sdholland { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_B100_1, ANY,
403*e91196a2Sdholland { UQ_ALWAYS_ON, NULL }},
404*e91196a2Sdholland { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_B100_2, ANY,
405d6dbababSmrg { UQ_ALWAYS_ON, NULL }},
406ffe203d7Spgoyette { USB_VENDOR_LENOVO, USB_PRODUCT_LENOVO_OPTUSBMOUSE, ANY, { UQ_ALWAYS_ON, NULL }},
40798194e60Smacallan /*
40898194e60Smacallan * The HAILUCK USB Keyboard has a built-in touchpad, which
40998194e60Smacallan * needs to be active for the keyboard to function properly.
41098194e60Smacallan */
41198194e60Smacallan { USB_VENDOR_HAILUCK, USB_PRODUCT_HAILUCK_KEYBOARD, ANY,
41298194e60Smacallan { UQ_ALWAYS_ON, NULL }},
41398194e60Smacallan
414077b167aSmanu { 0, 0, 0, { 0, NULL } }
415deb00272Saugustss };
416deb00272Saugustss
41734c8ae80Sjdolecek const struct usbd_quirks usbd_no_quirk = { 0 };
418deb00272Saugustss
41934c8ae80Sjdolecek const struct usbd_quirks *
usbd_find_quirk(usb_device_descriptor_t * d)420ed9486e1Saugustss usbd_find_quirk(usb_device_descriptor_t *d)
421deb00272Saugustss {
42234c8ae80Sjdolecek const struct usbd_quirk_entry *t;
4234e8e6643Sskrll uint16_t vendor = UGETW(d->idVendor);
4244e8e6643Sskrll uint16_t product = UGETW(d->idProduct);
4254e8e6643Sskrll uint16_t revision = UGETW(d->bcdDevice);
426deb00272Saugustss
4270d2fabdfSaugustss for (t = usb_quirks; t->idVendor != 0; t++) {
428595f18daSaugustss if (t->idVendor == vendor &&
42956873b1eSgarbled (t->idProduct == ANY || t->idProduct == product) &&
430b86cb140Saugustss (t->bcdDevice == ANY || t->bcdDevice == revision))
431deb00272Saugustss break;
432deb00272Saugustss }
433deb00272Saugustss #ifdef USB_DEBUG
434deb00272Saugustss if (usbdebug && t->quirks.uq_flags)
435aa3d6ec1Schristos printf("usbd_find_quirk 0x%04x/0x%04x/%x: %d\n",
436deb00272Saugustss UGETW(d->idVendor), UGETW(d->idProduct),
437deb00272Saugustss UGETW(d->bcdDevice), t->quirks.uq_flags);
438deb00272Saugustss #endif
4394e8e6643Sskrll return &t->quirks;
440deb00272Saugustss }
441