Home | History | Annotate | Line # | Download | only in usb
      1  1.108  dholland /*	$NetBSD: usb_quirks.c,v 1.108 2024/02/28 21:52:40 dholland Exp $	*/
      2   1.42       imp /*	$FreeBSD: src/sys/dev/usb/usb_quirks.c,v 1.30 2003/01/02 04:15:55 imp Exp $	*/
      3    1.1  augustss 
      4    1.1  augustss /*
      5   1.52   mycroft  * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
      6    1.1  augustss  * All rights reserved.
      7    1.1  augustss  *
      8    1.2  augustss  * This code is derived from software contributed to The NetBSD Foundation
      9   1.26  augustss  * by Lennart Augustsson (lennart (at) augustsson.net) at
     10    1.2  augustss  * Carlstedt Research & Technology.
     11    1.1  augustss  *
     12    1.1  augustss  * Redistribution and use in source and binary forms, with or without
     13    1.1  augustss  * modification, are permitted provided that the following conditions
     14    1.1  augustss  * are met:
     15    1.1  augustss  * 1. Redistributions of source code must retain the above copyright
     16    1.1  augustss  *    notice, this list of conditions and the following disclaimer.
     17    1.1  augustss  * 2. Redistributions in binary form must reproduce the above copyright
     18    1.1  augustss  *    notice, this list of conditions and the following disclaimer in the
     19    1.1  augustss  *    documentation and/or other materials provided with the distribution.
     20    1.1  augustss  *
     21    1.1  augustss  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     22    1.1  augustss  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     23    1.1  augustss  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     24    1.1  augustss  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     25    1.1  augustss  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     26    1.1  augustss  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     27    1.1  augustss  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     28    1.1  augustss  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     29    1.1  augustss  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     30    1.1  augustss  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     31    1.1  augustss  * POSSIBILITY OF SUCH DAMAGE.
     32    1.1  augustss  */
     33   1.39     lukem 
     34   1.39     lukem #include <sys/cdefs.h>
     35  1.108  dholland __KERNEL_RCSID(0, "$NetBSD: usb_quirks.c,v 1.108 2024/02/28 21:52:40 dholland Exp $");
     36   1.81     skrll 
     37   1.81     skrll #ifdef _KERNEL_OPT
     38   1.81     skrll #include "opt_usb.h"
     39   1.81     skrll #endif
     40    1.1  augustss 
     41    1.1  augustss #include <sys/param.h>
     42    1.1  augustss #include <sys/systm.h>
     43   1.40  augustss 
     44    1.1  augustss #include <dev/usb/usb.h>
     45    1.1  augustss #include <dev/usb/usbdevs.h>
     46   1.88      manu #include <dev/usb/usbdi.h>
     47   1.88      manu #include <dev/usb/usbdivar.h>
     48   1.88      manu #include <dev/usb/usbhist.h>
     49    1.1  augustss #include <dev/usb/usb_quirks.h>
     50    1.1  augustss 
     51   1.88      manu #define DPRINTF(FMT,A,B,C,D)    USBHIST_LOG(usbdebug,FMT,A,B,C,D)
     52   1.88      manu 
     53   1.38  augustss #define ANY 0xffff
     54   1.88      manu #define _USETW(w) { (w) & 0x00ff, ((w) & 0xff00) >> 8 }
     55   1.88      manu 
     56   1.88      manu /*
     57   1.88      manu  * NXP PN533 NFC chip descriptors
     58   1.88      manu  */
     59   1.88      manu static const usb_endpoint_descriptor_t desc_ep_pn533_in = {
     60   1.88      manu 	/* bLength */		sizeof(desc_ep_pn533_in),
     61   1.88      manu 	/* bDescriptorType */	UDESC_ENDPOINT,
     62   1.88      manu 	/* bEndpointAddress */	UE_DIR_IN | 0x04,
     63   1.88      manu 	/* bmAttributes */	UE_BULK,
     64   1.88      manu 	/* wMaxPacketSize */	_USETW(0x0040),
     65   1.88      manu 	/* bInterval */		0x04, /* 255ms */
     66   1.88      manu };
     67   1.88      manu 
     68   1.88      manu static const usb_endpoint_descriptor_t desc_ep_pn533_out = {
     69   1.88      manu 	/* bLength */		sizeof(desc_ep_pn533_in),
     70   1.88      manu 	/* bDescriptorType */	UDESC_ENDPOINT,
     71   1.88      manu 	/* bEndpointAddress */	UE_DIR_OUT | 0x04,
     72   1.88      manu 	/* bmAttributes */	UE_BULK,
     73   1.88      manu 	/* wMaxPacketSize */	_USETW(0x0040),
     74   1.88      manu 	/* bInterval */		0x04, /* 255ms */
     75   1.88      manu };
     76   1.88      manu 
     77   1.88      manu static const usb_interface_descriptor_t desc_iface_pn533 = {
     78   1.88      manu 	/* bLength */		sizeof(desc_iface_pn533),
     79   1.88      manu 	/* bDescriptorType */	 UDESC_INTERFACE,
     80   1.88      manu 	/* bInterfaceNumber */	 0,
     81   1.88      manu 	/* bAlternateSetting */	 0,
     82   1.88      manu 	/* bNumEndpoints */	 2,
     83   1.88      manu 	/* bInterfaceClass */	 0xff,
     84   1.88      manu 	/* bInterfaceSubClass */ 0xff,
     85   1.88      manu 	/* bInterfaceProtocol */ 0xff,
     86   1.88      manu 	/* iInterface */	 0,
     87   1.88      manu };
     88   1.88      manu 
     89   1.88      manu static const usb_config_descriptor_t desc_conf_pn533 = {
     90   1.88      manu 	/* bLength */		 sizeof(desc_conf_pn533),
     91   1.88      manu 	/* bDescriptorType */	 UDESC_CONFIG,
     92   1.88      manu 	/* wTotalLength	 */	 _USETW(sizeof(desc_conf_pn533) +
     93   1.88      manu 					sizeof(desc_iface_pn533) +
     94   1.88      manu 					sizeof(desc_ep_pn533_in) +
     95   1.88      manu 					sizeof(desc_ep_pn533_out)
     96   1.88      manu 				 ),
     97   1.98    andvar 	/* bNumInterface */	 1,
     98   1.88      manu 	/* bConfigurationValue */1,
     99   1.88      manu 	/* iConfiguration */	 0,
    100   1.88      manu 	/* bmAttributes	*/	 UC_ATTR_MBO,
    101   1.88      manu 	/* bMaxPower */		 0x32, /* 100mA */
    102   1.88      manu };
    103   1.88      manu 
    104   1.88      manu static const usb_descriptor_t *desc_pn533[] = {
    105   1.88      manu 	(const usb_descriptor_t *)&desc_conf_pn533,
    106   1.88      manu 	(const usb_descriptor_t *)&desc_iface_pn533,
    107   1.88      manu 	(const usb_descriptor_t *)&desc_ep_pn533_out,
    108   1.88      manu 	(const usb_descriptor_t *)&desc_ep_pn533_in,
    109   1.88      manu 	NULL
    110   1.88      manu };
    111   1.88      manu 
    112   1.88      manu 
    113   1.88      manu usbd_status
    114   1.88      manu usbd_get_desc_fake(struct usbd_device *dev, int type, int index,
    115   1.88      manu 		   int len, void *desc)
    116   1.88      manu {
    117   1.88      manu 	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
    118   1.88      manu #ifdef USB_DEBUG
    119   1.88      manu 	const usb_device_descriptor_t *dd = usbd_get_device_descriptor(dev);
    120   1.88      manu #endif
    121   1.88      manu 	const usb_descriptor_t *ub;
    122   1.88      manu 	int i = 0;
    123   1.88      manu 	int j = 0;
    124   1.88      manu 	usbd_status err = USBD_INVAL;
    125   1.88      manu 
    126   1.88      manu 	if (dev->ud_quirks == NULL || dev->ud_quirks->desc == NULL) {
    127   1.95  christos 		DPRINTF("%04jx/%04j: no fake descriptors",
    128   1.88      manu 		        UGETW(dd->idVendor), UGETW(dd->idProduct), 0, 0);
    129   1.88      manu 		goto out;
    130   1.88      manu 	}
    131   1.88      manu 
    132   1.88      manu 	for (j = 0; dev->ud_quirks->desc[j]; j++) {
    133   1.88      manu 		ub = dev->ud_quirks->desc[j];
    134   1.88      manu 		if (ub->bDescriptorType == type && i++ == index)
    135   1.88      manu 			break;
    136   1.88      manu 	}
    137   1.88      manu 
    138   1.88      manu 	if (dev->ud_quirks->desc[j] == NULL) {
    139   1.95  christos 		DPRINTF("%04jx/%04jx: no fake descriptor type = %jd, len = %jd",
    140   1.88      manu 		       UGETW(dd->idVendor), UGETW(dd->idProduct), type, len);
    141   1.88      manu 		goto out;
    142   1.88      manu 	}
    143   1.88      manu 
    144   1.88      manu 	do {
    145   1.88      manu 		ub = dev->ud_quirks->desc[j];
    146   1.88      manu 
    147   1.88      manu 		if (ub->bLength > len) {
    148   1.95  christos 			DPRINTF("%04jx/%04jx: short buf len = %jd, bLength = %jd",
    149   1.88      manu 			        UGETW(dd->idVendor), UGETW(dd->idProduct),
    150   1.88      manu 			        type, ub->bLength);
    151   1.88      manu 			goto out;
    152   1.88      manu 		}
    153   1.88      manu 
    154   1.88      manu 		memcpy(desc, ub, ub->bLength);
    155   1.95  christos 		DPRINTF("%04jx/%04jx: Use fake descriptor type %jd",
    156   1.88      manu 			UGETW(dd->idVendor), UGETW(dd->idProduct),
    157   1.88      manu 			type, 0);
    158   1.88      manu 
    159   1.88      manu 		desc = (char *)desc + ub->bLength;
    160   1.88      manu 		len -= ub->bLength;
    161   1.88      manu 		j++;
    162   1.88      manu 	} while (len && dev->ud_quirks->desc[j] &&
    163   1.88      manu 		 dev->ud_quirks->desc[j]->bDescriptorType != type);
    164   1.88      manu 
    165   1.88      manu 	err = USBD_NORMAL_COMPLETION;
    166   1.88      manu 
    167   1.95  christos 	DPRINTF("%04jx/%04jx: Using fake USB descriptors\n",
    168   1.88      manu 	        UGETW(dd->idVendor), UGETW(dd->idProduct), 0, 0);
    169   1.88      manu out:
    170   1.95  christos 	DPRINTF("return err = %jd", err, 0, 0, 0);
    171   1.92   msaitoh 	return err;
    172   1.88      manu }
    173   1.37  augustss 
    174   1.36  jdolecek Static const struct usbd_quirk_entry {
    175   1.84     skrll 	uint16_t idVendor;
    176   1.84     skrll 	uint16_t idProduct;
    177   1.84     skrll 	uint16_t bcdDevice;
    178    1.1  augustss 	struct usbd_quirks quirks;
    179   1.15  augustss } usb_quirks[] = {
    180   1.57     veego  /* Devices which should be ignored by uhid */
    181   1.88      manu  { USB_VENDOR_APC,		USB_PRODUCT_APC_UPS,			ANY,
    182   1.88      manu 	{ UQ_HID_IGNORE, NULL }},
    183  1.102    martin  { USB_VENDOR_APC,		USB_PRODUCT_APC_UPS3,			ANY,
    184  1.102    martin 	{ UQ_HID_IGNORE, NULL }},
    185  1.101       mrg  { USB_VENDOR_CYBERPOWER,	USB_PRODUCT_CYBERPOWER_UPS0,		ANY,
    186  1.101       mrg 	{ UQ_HID_IGNORE, NULL }},
    187   1.88      manu  { USB_VENDOR_CYBERPOWER,	USB_PRODUCT_CYBERPOWER_UPS,		ANY,
    188   1.88      manu 	{ UQ_HID_IGNORE, NULL }},
    189  1.101       mrg  { USB_VENDOR_CYBERPOWER,	USB_PRODUCT_CYBERPOWER_UPS2,		ANY,
    190  1.101       mrg 	{ UQ_HID_IGNORE, NULL }},
    191   1.91  jakllsch  { USB_VENDOR_GRETAGMACBETH,	ANY,					ANY,
    192   1.91  jakllsch 	{ UQ_HID_IGNORE, NULL }},
    193   1.88      manu  { USB_VENDOR_MGE,		USB_PRODUCT_MGE_UPS1,			ANY,
    194   1.88      manu 	{ UQ_HID_IGNORE, NULL }},
    195   1.88      manu  { USB_VENDOR_MGE,		USB_PRODUCT_MGE_UPS2,			ANY,
    196   1.88      manu 	{ UQ_HID_IGNORE, NULL }},
    197   1.88      manu  { USB_VENDOR_MICROCHIP,	USB_PRODUCT_MICROCHIP_PICKIT1,		ANY,
    198   1.88      manu 	{ UQ_HID_IGNORE, NULL }},
    199  1.103    bouyer  { USB_VENDOR_MICROCHIP,	USB_PRODUCT_MICROCHIP_PICKIT2,		ANY,
    200  1.103    bouyer 	{ UQ_HID_IGNORE, NULL }},
    201  1.103    bouyer  { USB_VENDOR_MICROCHIP,	USB_PRODUCT_MICROCHIP_PICKIT3,		ANY,
    202  1.103    bouyer 	{ UQ_HID_IGNORE, NULL }},
    203   1.88      manu  { USB_VENDOR_TRIPPLITE2,	ANY,					ANY,
    204   1.88      manu 	{ UQ_HID_IGNORE, NULL }},
    205   1.88      manu  { USB_VENDOR_MISC,		USB_PRODUCT_MISC_WISPY_24X,		ANY,
    206   1.88      manu 	{ UQ_HID_IGNORE, NULL }},
    207   1.88      manu  { USB_VENDOR_WELTREND,	USB_PRODUCT_WELTREND_HID,		ANY,
    208   1.88      manu 	{ UQ_HID_IGNORE, NULL }},
    209   1.88      manu  { USB_VENDOR_SILABS,		USB_PRODUCT_SILABS_EC3,			ANY,
    210   1.88      manu 	{ UQ_HID_IGNORE, NULL }},
    211   1.88      manu  { USB_VENDOR_TI,		USB_PRODUCT_TI_MSP430,			ANY,
    212   1.88      manu 	{ UQ_HID_IGNORE, NULL }},
    213   1.91  jakllsch  { USB_VENDOR_XRITE,		ANY,					ANY,
    214   1.91  jakllsch 	{ UQ_HID_IGNORE, NULL }},
    215   1.96       jym  { USB_VENDOR_WAYTECH,		USB_PRODUCT_WAYTECH_USB2SERIAL,		ANY,
    216   1.96       jym 	{ UQ_HID_IGNORE, NULL }},
    217   1.88      manu  { USB_VENDOR_KYE,		USB_PRODUCT_KYE_NICHE,			0x100,
    218   1.88      manu 	{ UQ_NO_SET_PROTO, NULL }},
    219   1.88      manu  { USB_VENDOR_INSIDEOUT,	USB_PRODUCT_INSIDEOUT_EDGEPORT4,	0x094,
    220   1.88      manu 	{ UQ_SWAP_UNICODE, NULL }},
    221   1.88      manu  { USB_VENDOR_DALLAS,		USB_PRODUCT_DALLAS_J6502,		0x0a2,
    222   1.88      manu 	{ UQ_BAD_ADC, NULL }},
    223   1.88      manu  { USB_VENDOR_DALLAS,		USB_PRODUCT_DALLAS_J6502,		0x0a2,
    224   1.88      manu 	{ UQ_AU_NO_XU, NULL }},
    225   1.88      manu  { USB_VENDOR_ALTEC,		USB_PRODUCT_ALTEC_ADA70,		0x103,
    226   1.88      manu 	{ UQ_BAD_ADC, NULL }},
    227   1.88      manu  { USB_VENDOR_ALTEC,		USB_PRODUCT_ALTEC_ASC495,		0x000,
    228   1.88      manu 	{ UQ_BAD_AUDIO, NULL }},
    229   1.88      manu  { USB_VENDOR_SONY,		USB_PRODUCT_SONY_PS2EYETOY4,		0x000,
    230   1.88      manu 	{ UQ_BAD_AUDIO, NULL }},
    231   1.88      manu  { USB_VENDOR_SONY,		USB_PRODUCT_SONY_PS2EYETOY5,		0x000,
    232   1.88      manu 	{ UQ_BAD_AUDIO, NULL }},
    233   1.88      manu  { USB_VENDOR_PHILIPS,		USB_PRODUCT_PHILIPS_PCVC740K,		ANY,
    234   1.88      manu 	{ UQ_BAD_AUDIO, NULL }},
    235   1.88      manu  { USB_VENDOR_LOGITECH,		USB_PRODUCT_LOGITECH_QUICKCAMPRONB,	0x000,
    236   1.88      manu 	{ UQ_BAD_AUDIO, NULL }},
    237   1.88      manu  { USB_VENDOR_LOGITECH,		USB_PRODUCT_LOGITECH_QUICKCAMPRO4K,	0x000,
    238   1.88      manu 	{ UQ_BAD_AUDIO, NULL }},
    239   1.88      manu  { USB_VENDOR_LOGITECH,		USB_PRODUCT_LOGITECH_QUICKCAMMESS,	0x100,
    240   1.88      manu 	{ UQ_BAD_ADC, NULL }},
    241   1.88      manu  { USB_VENDOR_QTRONIX,		USB_PRODUCT_QTRONIX_980N,		0x110,
    242   1.88      manu 	{ UQ_SPUR_BUT_UP, NULL }},
    243   1.88      manu  { USB_VENDOR_ALCOR2,		USB_PRODUCT_ALCOR2_KBD_HUB,		0x001,
    244   1.88      manu 	{ UQ_SPUR_BUT_UP, NULL }},
    245   1.88      manu  { USB_VENDOR_METRICOM,		USB_PRODUCT_METRICOM_RICOCHET_GS,	0x100,
    246   1.88      manu 	{ UQ_ASSUME_CM_OVER_DATA, NULL }},
    247   1.88      manu  { USB_VENDOR_SANYO,		USB_PRODUCT_SANYO_SCP4900,		0x000,
    248   1.88      manu 	{ UQ_ASSUME_CM_OVER_DATA, NULL }},
    249   1.88      manu  { USB_VENDOR_MOTOROLA2,	USB_PRODUCT_MOTOROLA2_T720C,		0x001,
    250   1.88      manu 	{ UQ_ASSUME_CM_OVER_DATA, NULL }},
    251   1.88      manu  { USB_VENDOR_EICON,		USB_PRODUCT_EICON_DIVA852,		0x100,
    252   1.88      manu 	{ UQ_ASSUME_CM_OVER_DATA, NULL }},
    253   1.88      manu  { USB_VENDOR_SIEMENS2,		USB_PRODUCT_SIEMENS2_MC75,		0x000,
    254   1.88      manu 	{ UQ_ASSUME_CM_OVER_DATA, NULL }},
    255   1.88      manu  { USB_VENDOR_TELEX,		USB_PRODUCT_TELEX_MIC1,			0x009,
    256   1.88      manu 	{ UQ_AU_NO_FRAC, NULL }},
    257   1.88      manu  { USB_VENDOR_SILICONPORTALS,	USB_PRODUCT_SILICONPORTALS_YAPPHONE,	0x100,
    258   1.88      manu 	{ UQ_AU_INP_ASYNC, NULL }},
    259   1.88      manu  { USB_VENDOR_AVANCELOGIC,	USB_PRODUCT_AVANCELOGIC_USBAUDIO,	0x101,
    260   1.88      manu 	{ UQ_AU_INP_ASYNC, NULL }},
    261   1.88      manu  { USB_VENDOR_PLANTRONICS,	USB_PRODUCT_PLANTRONICS_HEADSET,	0x004,
    262   1.88      manu 	{ UQ_AU_INP_ASYNC, NULL }},
    263   1.88      manu  { USB_VENDOR_CMEDIA,		USB_PRODUCT_CMEDIA_USBAUDIO,		ANY,
    264   1.88      manu 	{ UQ_AU_INP_ASYNC, NULL }},
    265   1.88      manu 
    266   1.37  augustss  /* XXX These should have a revision number, but I don't know what they are. */
    267   1.88      manu  { USB_VENDOR_HP,		USB_PRODUCT_HP_895C,			ANY,
    268   1.88      manu 	{ UQ_BROKEN_BIDIR, NULL }},
    269   1.88      manu  { USB_VENDOR_HP,		USB_PRODUCT_HP_880C,			ANY,
    270   1.88      manu 	{ UQ_BROKEN_BIDIR, NULL }},
    271   1.88      manu  { USB_VENDOR_HP,		USB_PRODUCT_HP_815C,			ANY,
    272   1.88      manu 	{ UQ_BROKEN_BIDIR, NULL }},
    273   1.88      manu  { USB_VENDOR_HP,		USB_PRODUCT_HP_810C,			ANY,
    274   1.88      manu 	{ UQ_BROKEN_BIDIR, NULL }},
    275   1.92   msaitoh  { USB_VENDOR_HP,		USB_PRODUCT_HP_830C,			ANY,
    276   1.88      manu 	{ UQ_BROKEN_BIDIR, NULL }},
    277   1.88      manu  { USB_VENDOR_HP,		USB_PRODUCT_HP_885C,			ANY,
    278   1.88      manu 	{ UQ_BROKEN_BIDIR, NULL }},
    279   1.88      manu  { USB_VENDOR_HP,		USB_PRODUCT_HP_840C,			ANY,
    280   1.88      manu 	{ UQ_BROKEN_BIDIR, NULL }},
    281   1.92   msaitoh  { USB_VENDOR_HP,		USB_PRODUCT_HP_816C,			ANY,
    282   1.88      manu 	{ UQ_BROKEN_BIDIR, NULL }},
    283   1.92   msaitoh  { USB_VENDOR_HP,		USB_PRODUCT_HP_959C,			ANY,
    284   1.88      manu 	{ UQ_BROKEN_BIDIR, NULL }},
    285   1.88      manu  { USB_VENDOR_MTK,		USB_PRODUCT_MTK_GPS_RECEIVER,		ANY,
    286   1.88      manu 	{ UQ_NO_UNION_NRM, NULL }},
    287   1.88      manu  { USB_VENDOR_NEC,		USB_PRODUCT_NEC_PICTY900,		ANY,
    288   1.88      manu 	{ UQ_BROKEN_BIDIR, NULL }},
    289   1.88      manu  { USB_VENDOR_NEC,		USB_PRODUCT_NEC_PICTY760,		ANY,
    290   1.88      manu 	{ UQ_BROKEN_BIDIR, NULL }},
    291   1.88      manu  { USB_VENDOR_NEC,		USB_PRODUCT_NEC_PICTY920,		ANY,
    292   1.88      manu 	{ UQ_BROKEN_BIDIR, NULL }},
    293   1.88      manu  { USB_VENDOR_NEC,		USB_PRODUCT_NEC_PICTY800,		ANY,
    294   1.88      manu 	{ UQ_BROKEN_BIDIR, NULL }},
    295   1.88      manu  { USB_VENDOR_HP,		USB_PRODUCT_HP_1220C,			ANY,
    296   1.88      manu 	{ UQ_BROKEN_BIDIR, NULL }},
    297   1.56      salo 
    298   1.70       phx  /* Apple internal notebook ISO keyboards have swapped keys */
    299   1.88      manu  { USB_VENDOR_APPLE,		USB_PRODUCT_APPLE_FOUNTAIN_ISO,		ANY,
    300   1.88      manu 	{ UQ_APPLE_ISO, NULL }},
    301   1.88      manu  { USB_VENDOR_APPLE,		USB_PRODUCT_APPLE_GEYSER_ISO,		ANY,
    302   1.88      manu 	{ UQ_APPLE_ISO, NULL }},
    303   1.70       phx 
    304   1.60  jmcneill  /* HID and audio are both invalid on iPhone/iPod Touch */
    305   1.88      manu  { USB_VENDOR_APPLE,		USB_PRODUCT_APPLE_IPHONE,		ANY,
    306   1.88      manu 	{ UQ_HID_IGNORE | UQ_BAD_AUDIO, NULL }},
    307   1.88      manu  { USB_VENDOR_APPLE,		USB_PRODUCT_APPLE_IPOD_TOUCH,		ANY,
    308   1.88      manu 	{ UQ_HID_IGNORE | UQ_BAD_AUDIO, NULL }},
    309   1.88      manu  { USB_VENDOR_APPLE,		USB_PRODUCT_APPLE_IPOD_TOUCH_4G,	ANY,
    310   1.88      manu 	{ UQ_HID_IGNORE | UQ_BAD_AUDIO, NULL }},
    311   1.88      manu  { USB_VENDOR_APPLE,		USB_PRODUCT_APPLE_IPHONE_3G,		ANY,
    312   1.88      manu 	{ UQ_HID_IGNORE | UQ_BAD_AUDIO, NULL }},
    313   1.88      manu  { USB_VENDOR_APPLE,		USB_PRODUCT_APPLE_IPHONE_3GS,		ANY,
    314   1.88      manu 	{ UQ_HID_IGNORE | UQ_BAD_AUDIO, NULL }},
    315   1.88      manu 
    316   1.97    martin  /*
    317   1.97    martin   * Various devices using serial boot loader protocol, as supported
    318   1.97    martin   * by pkgsrc/sysutils/imx_usb_loader
    319   1.97    martin   */
    320   1.97    martin  { 0x066f,			0x3780,		/* mx23 */		ANY,
    321   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    322   1.97    martin  { 0x15a2,			0x004f,		/* mx28 */		ANY,
    323   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    324   1.97    martin  { 0x15a2,			0x0052,		/* mx50 */		ANY,
    325   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    326   1.97    martin  { 0x15a2,			0x0054,		/* mx6 */		ANY,
    327   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    328   1.97    martin  { 0x15a2,			0x0061,		/* mx6 */		ANY,
    329   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    330   1.97    martin  { 0x15a2,			0x0063,		/* mx6 */		ANY,
    331   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    332   1.97    martin  { 0x15a2,			0x0071,		/* mx6 */		ANY,
    333   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    334   1.97    martin  { 0x15a2,			0x007d,		/* mx6 */		ANY,
    335   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    336   1.97    martin  { 0x15a2,			0x0080,		/* mx6ull */		ANY,
    337   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    338   1.97    martin  { 0x1fc9,			0x0128,		/* mx6 */		ANY,
    339   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    340   1.97    martin  { 0x15a2,			0x0076,		/* mx7 */		ANY,
    341   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    342   1.97    martin  { 0x1fc9,			0x0126,		/* mx7ulp */		ANY,
    343   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    344   1.97    martin  { 0x15a2,			0x0041,		/* mx51 */		ANY,
    345   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    346   1.97    martin  { 0x15a2,			0x004e,		/* mx53 */		ANY,
    347   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    348   1.97    martin  { 0x15a2,			0x006a,		/* vybrid */		ANY,
    349   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    350   1.97    martin  { 0x066f,			0x37ff,		/* linux_gadget */	ANY,
    351   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    352   1.97    martin  { 0x1b67,			0x4fff,		/* mx6 */		ANY,
    353   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    354   1.97    martin  { 0x0525,			0xb4a4,		/* mx6 */		ANY,
    355   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    356   1.97    martin  { 0x1fc9,			0x012b,		/* mx8mq */		ANY,
    357   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    358   1.97    martin  { 0x1fc9,			0x0134,		/* mx8mm */		ANY,
    359   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    360   1.97    martin  { 0x1fc9,			0x013e,		/* mx8mn */		ANY,
    361   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    362   1.97    martin  { 0x3016,			0x1001, 	/* mx8mn */		ANY,
    363   1.97    martin 	{ UQ_HID_IGNORE, NULL }},
    364   1.97    martin 
    365   1.88      manu  { USB_VENDOR_LG,		USB_PRODUCT_LG_CDMA_MSM,		ANY,
    366   1.88      manu 	{ UQ_ASSUME_CM_OVER_DATA, NULL }},
    367   1.88      manu  { USB_VENDOR_QUALCOMM2,	USB_PRODUCT_QUALCOMM2_CDMA_MSM,		ANY,
    368   1.88      manu 	{ UQ_ASSUME_CM_OVER_DATA, NULL }},
    369   1.88      manu  { USB_VENDOR_HYUNDAI,		USB_PRODUCT_HYUNDAI_UM175,		ANY,
    370   1.88      manu 	{ UQ_ASSUME_CM_OVER_DATA, NULL }},
    371   1.88      manu  { USB_VENDOR_ZOOM,		USB_PRODUCT_ZOOM_3095,			ANY,
    372   1.88      manu 	{ UQ_LOST_CS_DESC, NULL }},
    373   1.88      manu 
    374   1.90      manu  /*
    375   1.90      manu   * NXP PN533 bugs
    376   1.90      manu   *
    377   1.90      manu   * 1. It corrupts its USB descriptors. The quirk is to provide hardcoded
    378   1.90      manu   *    descriptors instead of getting them from the device.
    379   1.90      manu   * 2. It mishandles the USB toggle bit. This causes some replies to be
    380  1.105    andvar   *    filtered out by the USB host controller and be reported as timed out.
    381   1.90      manu   *    NFC tool's libnfc workaround this bug by sending a dummy frame to
    382   1.90      manu   *    resync the toggle bit, but in order to succeed, that operation must
    383   1.90      manu   *    not be reported as failed. The quirk is therefore to pretend to
    384   1.90      manu   *    userland that output timeouts are successes.
    385   1.90      manu   */
    386   1.89    martin  { USB_VENDOR_PHILIPSSEMI,	USB_PRODUCT_PHILIPSSEMI_PN533,		ANY,
    387   1.90      manu 	{ UQ_DESC_CORRUPT | UQ_MISS_OUT_ACK, desc_pn533 }},
    388   1.88      manu  { USB_VENDOR_SHUTTLE,		USB_PRODUCT_SHUTTLE_SCL3711,		ANY,
    389   1.90      manu 	{ UQ_DESC_CORRUPT | UQ_MISS_OUT_ACK, desc_pn533 }},
    390   1.88      manu  { USB_VENDOR_SHUTTLE,		USB_PRODUCT_SHUTTLE_SCL3712,		ANY,
    391   1.90      manu 	{ UQ_DESC_CORRUPT | UQ_MISS_OUT_ACK, desc_pn533 }},
    392   1.99  macallan 
    393   1.99  macallan /*
    394   1.99  macallan  * These cheap mice will disconnect after 60 seconds,
    395   1.99  macallan  * reconnect, and then disconnect again (ad nauseum)
    396   1.99  macallan  * unless it's kept open.
    397   1.99  macallan  */
    398   1.99  macallan  { USB_VENDOR_CHICONY,		USB_PRODUCT_CHICONY_OPTMOUSE0939,	ANY,
    399   1.99  macallan 	{ UQ_ALWAYS_ON, NULL }},
    400   1.99  macallan  { USB_VENDOR_PIXART,		USB_PRODUCT_PIXART_RPIMOUSE,		ANY,
    401   1.99  macallan 	{ UQ_ALWAYS_ON, NULL }},
    402  1.108  dholland  { USB_VENDOR_LOGITECH, 	USB_PRODUCT_LOGITECH_B100_1,		ANY,
    403  1.108  dholland 	{ UQ_ALWAYS_ON, NULL }},
    404  1.108  dholland  { USB_VENDOR_LOGITECH, 	USB_PRODUCT_LOGITECH_B100_2,		ANY,
    405  1.100       mrg 	{ UQ_ALWAYS_ON, NULL }},
    406  1.107  pgoyette  { USB_VENDOR_LENOVO,		USB_PRODUCT_LENOVO_OPTUSBMOUSE,		ANY,		{ UQ_ALWAYS_ON, NULL }},
    407   1.99  macallan /*
    408   1.99  macallan  * The HAILUCK USB Keyboard has a built-in touchpad, which
    409   1.99  macallan  * needs to be active for the keyboard to function properly.
    410   1.99  macallan  */
    411   1.99  macallan  { USB_VENDOR_HAILUCK,		USB_PRODUCT_HAILUCK_KEYBOARD,		ANY,
    412   1.99  macallan 	{ UQ_ALWAYS_ON, NULL }},
    413   1.99  macallan 
    414   1.88      manu  { 0, 0, 0, { 0, NULL } }
    415    1.1  augustss };
    416    1.1  augustss 
    417   1.36  jdolecek const struct usbd_quirks usbd_no_quirk = { 0 };
    418    1.1  augustss 
    419   1.36  jdolecek const struct usbd_quirks *
    420   1.27  augustss usbd_find_quirk(usb_device_descriptor_t *d)
    421    1.1  augustss {
    422   1.36  jdolecek 	const struct usbd_quirk_entry *t;
    423   1.84     skrll 	uint16_t vendor = UGETW(d->idVendor);
    424   1.84     skrll 	uint16_t product = UGETW(d->idProduct);
    425   1.84     skrll 	uint16_t revision = UGETW(d->bcdDevice);
    426    1.1  augustss 
    427   1.15  augustss 	for (t = usb_quirks; t->idVendor != 0; t++) {
    428   1.88      manu 		if (t->idVendor == vendor &&
    429   1.79   garbled 		    (t->idProduct == ANY || t->idProduct == product) &&
    430   1.38  augustss 		    (t->bcdDevice == ANY || t->bcdDevice == revision))
    431    1.1  augustss 			break;
    432    1.1  augustss 	}
    433    1.1  augustss #ifdef USB_DEBUG
    434    1.1  augustss 	if (usbdebug && t->quirks.uq_flags)
    435   1.94  christos 		printf("usbd_find_quirk 0x%04x/0x%04x/%x: %d\n",
    436   1.12  augustss 			  UGETW(d->idVendor), UGETW(d->idProduct),
    437   1.12  augustss 			  UGETW(d->bcdDevice), t->quirks.uq_flags);
    438    1.1  augustss #endif
    439   1.84     skrll 	return &t->quirks;
    440    1.1  augustss }
    441