Module Name:    src
Committed By:   manu
Date:           Thu Nov  8 02:11:54 UTC 2018

Modified Files:
        src/sys/dev/usb: usb_quirks.c usb_quirks.h usbdi_util.c usbdi_util.h

Log Message:
Workaround PN533 USB descriptor corruption

During normal operation, the PN533 chip may corrupt its USB configuration,
interface and endpoint descriptors. The device descriptor remains unaffected.

Since the descriptors are documented to be immutable, we can work around
the problem by providing hard-coded descriptors instead of pulling them
from the device.

Userland implementation such as NFC tools' libnfc use the same approach,
but this kernel quirk is still necessary so that the device can be
attached on reboot, after its USB descriptors got corrupted.


To generate a diff of this commit:
cvs rdiff -u -r1.87 -r1.88 src/sys/dev/usb/usb_quirks.c
cvs rdiff -u -r1.27 -r1.28 src/sys/dev/usb/usb_quirks.h
cvs rdiff -u -r1.71 -r1.72 src/sys/dev/usb/usbdi_util.c
cvs rdiff -u -r1.47 -r1.48 src/sys/dev/usb/usbdi_util.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/usb/usb_quirks.c
diff -u src/sys/dev/usb/usb_quirks.c:1.87 src/sys/dev/usb/usb_quirks.c:1.88
--- src/sys/dev/usb/usb_quirks.c:1.87	Tue Jul 24 08:15:57 2018
+++ src/sys/dev/usb/usb_quirks.c	Thu Nov  8 02:11:54 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: usb_quirks.c,v 1.87 2018/07/24 08:15:57 msaitoh Exp $	*/
+/*	$NetBSD: usb_quirks.c,v 1.88 2018/11/08 02:11:54 manu Exp $	*/
 /*	$FreeBSD: src/sys/dev/usb/usb_quirks.c,v 1.30 2003/01/02 04:15:55 imp Exp $	*/
 
 /*
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usb_quirks.c,v 1.87 2018/07/24 08:15:57 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usb_quirks.c,v 1.88 2018/11/08 02:11:54 manu Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -43,13 +43,137 @@ __KERNEL_RCSID(0, "$NetBSD: usb_quirks.c
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdevs.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdivar.h>
+#include <dev/usb/usbhist.h>
 #include <dev/usb/usb_quirks.h>
 
 #ifdef USB_DEBUG
 extern int usbdebug;
 #endif
 
+#define DPRINTF(FMT,A,B,C,D)    USBHIST_LOG(usbdebug,FMT,A,B,C,D)
+
 #define ANY 0xffff
+#define _USETW(w) { (w) & 0x00ff, ((w) & 0xff00) >> 8 }
+
+/*
+ * NXP PN533 NFC chip descriptors
+ */
+static const usb_endpoint_descriptor_t desc_ep_pn533_in = {
+	/* bLength */		sizeof(desc_ep_pn533_in),
+	/* bDescriptorType */	UDESC_ENDPOINT,
+	/* bEndpointAddress */	UE_DIR_IN | 0x04,
+	/* bmAttributes */	UE_BULK,
+	/* wMaxPacketSize */	_USETW(0x0040),
+	/* bInterval */		0x04, /* 255ms */
+};
+
+static const usb_endpoint_descriptor_t desc_ep_pn533_out = {
+	/* bLength */		sizeof(desc_ep_pn533_in),
+	/* bDescriptorType */	UDESC_ENDPOINT,
+	/* bEndpointAddress */	UE_DIR_OUT | 0x04,
+	/* bmAttributes */	UE_BULK,
+	/* wMaxPacketSize */	_USETW(0x0040),
+	/* bInterval */		0x04, /* 255ms */
+};
+
+static const usb_interface_descriptor_t desc_iface_pn533 = {
+	/* bLength */		sizeof(desc_iface_pn533),
+	/* bDescriptorType */	 UDESC_INTERFACE,
+	/* bInterfaceNumber */	 0,
+	/* bAlternateSetting */	 0,
+	/* bNumEndpoints */	 2,
+	/* bInterfaceClass */	 0xff,
+	/* bInterfaceSubClass */ 0xff,
+	/* bInterfaceProtocol */ 0xff,
+	/* iInterface */	 0,
+};
+
+static const usb_config_descriptor_t desc_conf_pn533 = {
+	/* bLength */		 sizeof(desc_conf_pn533),
+	/* bDescriptorType */	 UDESC_CONFIG,
+	/* wTotalLength	 */	 _USETW(sizeof(desc_conf_pn533) +
+					sizeof(desc_iface_pn533) +
+					sizeof(desc_ep_pn533_in) +
+					sizeof(desc_ep_pn533_out)
+				 ),
+	/* bNumInterfac	*/	 1,
+	/* bConfigurationValue */1,
+	/* iConfiguration */	 0,
+	/* bmAttributes	*/	 UC_ATTR_MBO,
+	/* bMaxPower */		 0x32, /* 100mA */
+};
+
+static const usb_descriptor_t *desc_pn533[] = {
+	(const usb_descriptor_t *)&desc_conf_pn533,
+	(const usb_descriptor_t *)&desc_iface_pn533,
+	(const usb_descriptor_t *)&desc_ep_pn533_out,
+	(const usb_descriptor_t *)&desc_ep_pn533_in,
+	NULL
+};
+
+
+usbd_status
+usbd_get_desc_fake(struct usbd_device *dev, int type, int index,
+		   int len, void *desc)
+{
+	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
+#ifdef USB_DEBUG
+	const usb_device_descriptor_t *dd = usbd_get_device_descriptor(dev);
+#endif
+	const usb_descriptor_t *ub;
+	int i = 0;
+	int j = 0;
+	usbd_status err = USBD_INVAL;
+
+	if (dev->ud_quirks == NULL || dev->ud_quirks->desc == NULL) {
+		DPRINTF("%04x/%04x: no fake descriptors",
+		        UGETW(dd->idVendor), UGETW(dd->idProduct), 0, 0);
+		goto out;
+	}
+
+	for (j = 0; dev->ud_quirks->desc[j]; j++) {
+		ub = dev->ud_quirks->desc[j];
+		if (ub->bDescriptorType == type && i++ == index)
+			break;
+	}
+
+	if (dev->ud_quirks->desc[j] == NULL) {
+		DPRINTF("%04x/%04x: no fake descriptor type = %d, len = %d",
+		       UGETW(dd->idVendor), UGETW(dd->idProduct), type, len);
+		goto out;
+	}
+
+	do {
+		ub = dev->ud_quirks->desc[j];
+
+		if (ub->bLength > len) {
+			DPRINTF("%04x/%04x: short buf len = %d, bLength = %d",
+			        UGETW(dd->idVendor), UGETW(dd->idProduct),
+			        type, ub->bLength);
+			goto out;
+		}
+
+		memcpy(desc, ub, ub->bLength);
+		DPRINTF("%04x/%04x: Use fake descriptor type %d",
+			UGETW(dd->idVendor), UGETW(dd->idProduct),
+			type, 0);
+
+		desc = (char *)desc + ub->bLength;
+		len -= ub->bLength;
+		j++;
+	} while (len && dev->ud_quirks->desc[j] &&
+		 dev->ud_quirks->desc[j]->bDescriptorType != type);
+
+	err = USBD_NORMAL_COMPLETION;
+
+	DPRINTF("%04x/%04x: Using fake USB descriptors\n",
+	        UGETW(dd->idVendor), UGETW(dd->idProduct), 0, 0);
+out:
+	DPRINTF("return err = %d", err, 0, 0, 0);
+	return err;	
+}
 
 Static const struct usbd_quirk_entry {
 	uint16_t idVendor;
@@ -58,99 +182,142 @@ Static const struct usbd_quirk_entry {
 	struct usbd_quirks quirks;
 } usb_quirks[] = {
  /* Devices which should be ignored by uhid */
- { USB_VENDOR_APC, USB_PRODUCT_APC_UPS,		    ANY,   { UQ_HID_IGNORE }},
- { USB_VENDOR_CYBERPOWER, USB_PRODUCT_CYBERPOWER_UPS, ANY, { UQ_HID_IGNORE }},
- { USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS1,	    ANY,   { UQ_HID_IGNORE }},
- { USB_VENDOR_MGE, USB_PRODUCT_MGE_UPS2,	    ANY,   { UQ_HID_IGNORE }},
- { USB_VENDOR_MICROCHIP,  USB_PRODUCT_MICROCHIP_PICKIT1,
-	ANY,	{ UQ_HID_IGNORE }},
- { USB_VENDOR_TRIPPLITE2, ANY,			    ANY,   { UQ_HID_IGNORE }},
- { USB_VENDOR_MISC, USB_PRODUCT_MISC_WISPY_24X, ANY, { UQ_HID_IGNORE }},
- { USB_VENDOR_WELTREND, USB_PRODUCT_WELTREND_HID,   ANY,   { UQ_HID_IGNORE }},
- { USB_VENDOR_SILABS, USB_PRODUCT_SILABS_EC3,       ANY,   { UQ_HID_IGNORE }},
- { USB_VENDOR_TI, USB_PRODUCT_TI_MSP430,            ANY,   { UQ_HID_IGNORE }},
-
- { USB_VENDOR_KYE, USB_PRODUCT_KYE_NICHE,	    0x100, { UQ_NO_SET_PROTO}},
- { USB_VENDOR_INSIDEOUT, USB_PRODUCT_INSIDEOUT_EDGEPORT4,
-						    0x094, { UQ_SWAP_UNICODE}},
- { USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502,	    0x0a2, { UQ_BAD_ADC }},
- { USB_VENDOR_DALLAS, USB_PRODUCT_DALLAS_J6502,	    0x0a2, { UQ_AU_NO_XU }},
- { USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ADA70,	    0x103, { UQ_BAD_ADC }},
- { USB_VENDOR_ALTEC, USB_PRODUCT_ALTEC_ASC495,      0x000, { UQ_BAD_AUDIO }},
- { USB_VENDOR_SONY, USB_PRODUCT_SONY_PS2EYETOY4,    0x000, { UQ_BAD_AUDIO }},
- { USB_VENDOR_SONY, USB_PRODUCT_SONY_PS2EYETOY5,    0x000, { UQ_BAD_AUDIO }},
- { USB_VENDOR_PHILIPS, USB_PRODUCT_PHILIPS_PCVC740K,  ANY, { UQ_BAD_AUDIO }},
- { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMPRONB,
-	0x000, { UQ_BAD_AUDIO }},
- { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMPRO4K,
-	0x000, { UQ_BAD_AUDIO }},
- { USB_VENDOR_LOGITECH, USB_PRODUCT_LOGITECH_QUICKCAMMESS,
-	0x100, { UQ_BAD_ADC }},
- { USB_VENDOR_QTRONIX, USB_PRODUCT_QTRONIX_980N,    0x110, { UQ_SPUR_BUT_UP }},
- { USB_VENDOR_ALCOR2, USB_PRODUCT_ALCOR2_KBD_HUB,   0x001, { UQ_SPUR_BUT_UP }},
- { USB_VENDOR_METRICOM, USB_PRODUCT_METRICOM_RICOCHET_GS,
-	0x100, { UQ_ASSUME_CM_OVER_DATA }},
- { USB_VENDOR_SANYO, USB_PRODUCT_SANYO_SCP4900,
-	0x000, { UQ_ASSUME_CM_OVER_DATA }},
- { USB_VENDOR_MOTOROLA2, USB_PRODUCT_MOTOROLA2_T720C,
-	0x001, { UQ_ASSUME_CM_OVER_DATA }},
- { USB_VENDOR_EICON, USB_PRODUCT_EICON_DIVA852,
-	0x100, { UQ_ASSUME_CM_OVER_DATA }},
- { USB_VENDOR_SIEMENS2, USB_PRODUCT_SIEMENS2_MC75,
-	0x000, { UQ_ASSUME_CM_OVER_DATA }},
- { USB_VENDOR_TELEX, USB_PRODUCT_TELEX_MIC1,	    0x009, { UQ_AU_NO_FRAC }},
- { USB_VENDOR_SILICONPORTALS, USB_PRODUCT_SILICONPORTALS_YAPPHONE,
-						    0x100, { UQ_AU_INP_ASYNC }},
- { USB_VENDOR_AVANCELOGIC, USB_PRODUCT_AVANCELOGIC_USBAUDIO,
-						    0x101, { UQ_AU_INP_ASYNC }},
- { USB_VENDOR_PLANTRONICS, USB_PRODUCT_PLANTRONICS_HEADSET,
-						    0x004, { UQ_AU_INP_ASYNC }},
- { USB_VENDOR_CMEDIA, USB_PRODUCT_CMEDIA_USBAUDIO,  ANY,   { UQ_AU_INP_ASYNC }},
- /* XXX These should have a revision number, but I don't know what they are. */
- { USB_VENDOR_HP, USB_PRODUCT_HP_895C,		    ANY,   { UQ_BROKEN_BIDIR }},
- { USB_VENDOR_HP, USB_PRODUCT_HP_880C,		    ANY,   { UQ_BROKEN_BIDIR }},
- { USB_VENDOR_HP, USB_PRODUCT_HP_815C,		    ANY,   { UQ_BROKEN_BIDIR }},
- { USB_VENDOR_HP, USB_PRODUCT_HP_810C,		    ANY,   { UQ_BROKEN_BIDIR }},
- { USB_VENDOR_HP, USB_PRODUCT_HP_830C,		    ANY,   { UQ_BROKEN_BIDIR }},
- { USB_VENDOR_HP, USB_PRODUCT_HP_885C,		    ANY,   { UQ_BROKEN_BIDIR }},
- { USB_VENDOR_HP, USB_PRODUCT_HP_840C,		    ANY,   { UQ_BROKEN_BIDIR }},
- { USB_VENDOR_HP, USB_PRODUCT_HP_816C,		    ANY,   { UQ_BROKEN_BIDIR }},
- { USB_VENDOR_HP, USB_PRODUCT_HP_959C,		    ANY,   { UQ_BROKEN_BIDIR }},
- { USB_VENDOR_MTK, USB_PRODUCT_MTK_GPS_RECEIVER,    ANY,   { UQ_NO_UNION_NRM }},
- { USB_VENDOR_NEC, USB_PRODUCT_NEC_PICTY900,	    ANY,   { UQ_BROKEN_BIDIR }},
- { USB_VENDOR_NEC, USB_PRODUCT_NEC_PICTY760,	    ANY,   { UQ_BROKEN_BIDIR }},
- { USB_VENDOR_NEC, USB_PRODUCT_NEC_PICTY920,	    ANY,   { UQ_BROKEN_BIDIR }},
- { USB_VENDOR_NEC, USB_PRODUCT_NEC_PICTY800,	    ANY,   { UQ_BROKEN_BIDIR }},
+ { USB_VENDOR_APC,		USB_PRODUCT_APC_UPS,			ANY,
+	{ UQ_HID_IGNORE, NULL }},
+ { USB_VENDOR_CYBERPOWER,	USB_PRODUCT_CYBERPOWER_UPS,		ANY,
+	{ UQ_HID_IGNORE, NULL }},
+ { USB_VENDOR_MGE,		USB_PRODUCT_MGE_UPS1,			ANY,
+	{ UQ_HID_IGNORE, NULL }},
+ { USB_VENDOR_MGE,		USB_PRODUCT_MGE_UPS2,			ANY,
+	{ UQ_HID_IGNORE, NULL }},
+ { USB_VENDOR_MICROCHIP,	USB_PRODUCT_MICROCHIP_PICKIT1,		ANY,
+	{ UQ_HID_IGNORE, NULL }},
+ { USB_VENDOR_TRIPPLITE2,	ANY,					ANY,
+	{ UQ_HID_IGNORE, NULL }},
+ { USB_VENDOR_MISC,		USB_PRODUCT_MISC_WISPY_24X,		ANY,
+	{ UQ_HID_IGNORE, NULL }},
+ { USB_VENDOR_WELTREND,	USB_PRODUCT_WELTREND_HID,		ANY,
+	{ UQ_HID_IGNORE, NULL }},
+ { USB_VENDOR_SILABS,		USB_PRODUCT_SILABS_EC3,			ANY,
+	{ UQ_HID_IGNORE, NULL }},
+ { USB_VENDOR_TI,		USB_PRODUCT_TI_MSP430,			ANY,
+	{ UQ_HID_IGNORE, NULL }},
+ { USB_VENDOR_KYE,		USB_PRODUCT_KYE_NICHE,			0x100,
+	{ UQ_NO_SET_PROTO, NULL }},
+ { USB_VENDOR_INSIDEOUT,	USB_PRODUCT_INSIDEOUT_EDGEPORT4,	0x094,
+	{ UQ_SWAP_UNICODE, NULL }},
+ { USB_VENDOR_DALLAS,		USB_PRODUCT_DALLAS_J6502,		0x0a2,
+	{ UQ_BAD_ADC, NULL }},
+ { USB_VENDOR_DALLAS,		USB_PRODUCT_DALLAS_J6502,		0x0a2,
+	{ UQ_AU_NO_XU, NULL }},
+ { USB_VENDOR_ALTEC,		USB_PRODUCT_ALTEC_ADA70,		0x103,
+	{ UQ_BAD_ADC, NULL }},
+ { USB_VENDOR_ALTEC,		USB_PRODUCT_ALTEC_ASC495,		0x000,
+	{ UQ_BAD_AUDIO, NULL }},
+ { USB_VENDOR_SONY,		USB_PRODUCT_SONY_PS2EYETOY4,		0x000,
+	{ UQ_BAD_AUDIO, NULL }},
+ { USB_VENDOR_SONY,		USB_PRODUCT_SONY_PS2EYETOY5,		0x000,
+	{ UQ_BAD_AUDIO, NULL }},
+ { USB_VENDOR_PHILIPS,		USB_PRODUCT_PHILIPS_PCVC740K,		ANY,
+	{ UQ_BAD_AUDIO, NULL }},
+ { USB_VENDOR_LOGITECH,		USB_PRODUCT_LOGITECH_QUICKCAMPRONB,	0x000,
+	{ UQ_BAD_AUDIO, NULL }},
+ { USB_VENDOR_LOGITECH,		USB_PRODUCT_LOGITECH_QUICKCAMPRO4K,	0x000,
+	{ UQ_BAD_AUDIO, NULL }},
+ { USB_VENDOR_LOGITECH,		USB_PRODUCT_LOGITECH_QUICKCAMMESS,	0x100,
+	{ UQ_BAD_ADC, NULL }},
+ { USB_VENDOR_QTRONIX,		USB_PRODUCT_QTRONIX_980N,		0x110,
+	{ UQ_SPUR_BUT_UP, NULL }},
+ { USB_VENDOR_ALCOR2,		USB_PRODUCT_ALCOR2_KBD_HUB,		0x001,
+	{ UQ_SPUR_BUT_UP, NULL }},
+ { USB_VENDOR_METRICOM,		USB_PRODUCT_METRICOM_RICOCHET_GS,	0x100,
+	{ UQ_ASSUME_CM_OVER_DATA, NULL }},
+ { USB_VENDOR_SANYO,		USB_PRODUCT_SANYO_SCP4900,		0x000,
+	{ UQ_ASSUME_CM_OVER_DATA, NULL }},
+ { USB_VENDOR_MOTOROLA2,	USB_PRODUCT_MOTOROLA2_T720C,		0x001,
+	{ UQ_ASSUME_CM_OVER_DATA, NULL }},
+ { USB_VENDOR_EICON,		USB_PRODUCT_EICON_DIVA852,		0x100,
+	{ UQ_ASSUME_CM_OVER_DATA, NULL }},
+ { USB_VENDOR_SIEMENS2,		USB_PRODUCT_SIEMENS2_MC75,		0x000,
+	{ UQ_ASSUME_CM_OVER_DATA, NULL }},
+ { USB_VENDOR_TELEX,		USB_PRODUCT_TELEX_MIC1,			0x009,
+	{ UQ_AU_NO_FRAC, NULL }},
+ { USB_VENDOR_SILICONPORTALS,	USB_PRODUCT_SILICONPORTALS_YAPPHONE,	0x100,
+	{ UQ_AU_INP_ASYNC, NULL }},
+ { USB_VENDOR_AVANCELOGIC,	USB_PRODUCT_AVANCELOGIC_USBAUDIO,	0x101,
+	{ UQ_AU_INP_ASYNC, NULL }},
+ { USB_VENDOR_PLANTRONICS,	USB_PRODUCT_PLANTRONICS_HEADSET,	0x004,
+	{ UQ_AU_INP_ASYNC, NULL }},
+ { USB_VENDOR_CMEDIA,		USB_PRODUCT_CMEDIA_USBAUDIO,		ANY,
+	{ UQ_AU_INP_ASYNC, NULL }},
 
- { USB_VENDOR_HP, USB_PRODUCT_HP_1220C,		    ANY,   { UQ_BROKEN_BIDIR }},
+ /* XXX These should have a revision number, but I don't know what they are. */
+ { USB_VENDOR_HP,		USB_PRODUCT_HP_895C,			ANY,
+	{ UQ_BROKEN_BIDIR, NULL }},
+ { USB_VENDOR_HP,		USB_PRODUCT_HP_880C,			ANY,
+	{ UQ_BROKEN_BIDIR, NULL }},
+ { USB_VENDOR_HP,		USB_PRODUCT_HP_815C,			ANY,
+	{ UQ_BROKEN_BIDIR, NULL }},
+ { USB_VENDOR_HP,		USB_PRODUCT_HP_810C,			ANY,
+	{ UQ_BROKEN_BIDIR, NULL }},
+ { USB_VENDOR_HP,		USB_PRODUCT_HP_830C,			ANY,	
+	{ UQ_BROKEN_BIDIR, NULL }},
+ { USB_VENDOR_HP,		USB_PRODUCT_HP_885C,			ANY,
+	{ UQ_BROKEN_BIDIR, NULL }},
+ { USB_VENDOR_HP,		USB_PRODUCT_HP_840C,			ANY,
+	{ UQ_BROKEN_BIDIR, NULL }},
+ { USB_VENDOR_HP,		USB_PRODUCT_HP_816C,			ANY,	
+	{ UQ_BROKEN_BIDIR, NULL }},
+ { USB_VENDOR_HP,		USB_PRODUCT_HP_959C,			ANY,	
+	{ UQ_BROKEN_BIDIR, NULL }},
+ { USB_VENDOR_MTK,		USB_PRODUCT_MTK_GPS_RECEIVER,		ANY,
+	{ UQ_NO_UNION_NRM, NULL }},
+ { USB_VENDOR_NEC,		USB_PRODUCT_NEC_PICTY900,		ANY,
+	{ UQ_BROKEN_BIDIR, NULL }},
+ { USB_VENDOR_NEC,		USB_PRODUCT_NEC_PICTY760,		ANY,
+	{ UQ_BROKEN_BIDIR, NULL }},
+ { USB_VENDOR_NEC,		USB_PRODUCT_NEC_PICTY920,		ANY,
+	{ UQ_BROKEN_BIDIR, NULL }},
+ { USB_VENDOR_NEC,		USB_PRODUCT_NEC_PICTY800,		ANY,
+	{ UQ_BROKEN_BIDIR, NULL }},
+ { USB_VENDOR_HP,		USB_PRODUCT_HP_1220C,			ANY,
+	{ UQ_BROKEN_BIDIR, NULL }},
 
  /* Apple internal notebook ISO keyboards have swapped keys */
- { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_FOUNTAIN_ISO,
-	ANY, { UQ_APPLE_ISO }},
- { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_GEYSER_ISO,
-	ANY, { UQ_APPLE_ISO }},
+ { USB_VENDOR_APPLE,		USB_PRODUCT_APPLE_FOUNTAIN_ISO,		ANY,
+	{ UQ_APPLE_ISO, NULL }},
+ { USB_VENDOR_APPLE,		USB_PRODUCT_APPLE_GEYSER_ISO,		ANY,
+	{ UQ_APPLE_ISO, NULL }},
 
  /* HID and audio are both invalid on iPhone/iPod Touch */
- { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE,
-	ANY, { UQ_HID_IGNORE | UQ_BAD_AUDIO }},
- { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPOD_TOUCH,
-	ANY, { UQ_HID_IGNORE | UQ_BAD_AUDIO }},
- { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPOD_TOUCH_4G,
-	ANY, { UQ_HID_IGNORE | UQ_BAD_AUDIO }},
- { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3G,
-	ANY, { UQ_HID_IGNORE | UQ_BAD_AUDIO }},
- { USB_VENDOR_APPLE, USB_PRODUCT_APPLE_IPHONE_3GS,
-	ANY, { UQ_HID_IGNORE | UQ_BAD_AUDIO }},
-
- { USB_VENDOR_LG, USB_PRODUCT_LG_CDMA_MSM,
-	ANY, { UQ_ASSUME_CM_OVER_DATA }},
- { USB_VENDOR_QUALCOMM2, USB_PRODUCT_QUALCOMM2_CDMA_MSM,
-	ANY, { UQ_ASSUME_CM_OVER_DATA }},
- { USB_VENDOR_HYUNDAI, USB_PRODUCT_HYUNDAI_UM175,
-	ANY, { UQ_ASSUME_CM_OVER_DATA }},
- { USB_VENDOR_ZOOM, USB_PRODUCT_ZOOM_3095,
-	ANY, { UQ_LOST_CS_DESC }},
- { 0, 0, 0, { 0 } }
+ { USB_VENDOR_APPLE,		USB_PRODUCT_APPLE_IPHONE,		ANY,
+	{ UQ_HID_IGNORE | UQ_BAD_AUDIO, NULL }},
+ { USB_VENDOR_APPLE,		USB_PRODUCT_APPLE_IPOD_TOUCH,		ANY,
+	{ UQ_HID_IGNORE | UQ_BAD_AUDIO, NULL }},
+ { USB_VENDOR_APPLE,		USB_PRODUCT_APPLE_IPOD_TOUCH_4G,	ANY,
+	{ UQ_HID_IGNORE | UQ_BAD_AUDIO, NULL }},
+ { USB_VENDOR_APPLE,		USB_PRODUCT_APPLE_IPHONE_3G,		ANY,
+	{ UQ_HID_IGNORE | UQ_BAD_AUDIO, NULL }},
+ { USB_VENDOR_APPLE,		USB_PRODUCT_APPLE_IPHONE_3GS,		ANY,
+	{ UQ_HID_IGNORE | UQ_BAD_AUDIO, NULL }},
+
+ { USB_VENDOR_LG,		USB_PRODUCT_LG_CDMA_MSM,		ANY,
+	{ UQ_ASSUME_CM_OVER_DATA, NULL }},
+ { USB_VENDOR_QUALCOMM2,	USB_PRODUCT_QUALCOMM2_CDMA_MSM,		ANY,
+	{ UQ_ASSUME_CM_OVER_DATA, NULL }},
+ { USB_VENDOR_HYUNDAI,		USB_PRODUCT_HYUNDAI_UM175,		ANY,
+	{ UQ_ASSUME_CM_OVER_DATA, NULL }},
+ { USB_VENDOR_ZOOM,		USB_PRODUCT_ZOOM_3095,			ANY,
+	{ UQ_LOST_CS_DESC, NULL }},
+
+ /* NXP PN533 corrupts its USB configuration descriptors */
+ { USB_VENDOR_PHILIPSSEMI,	USB_PRODUCT_PHILIPSSEMT_PN533,		ANY,
+	{ UQ_DESC_CORRUPT, desc_pn533 }},
+ { USB_VENDOR_SHUTTLE,		USB_PRODUCT_SHUTTLE_SCL3711,		ANY,
+	{ UQ_DESC_CORRUPT, desc_pn533 }},
+ { USB_VENDOR_SHUTTLE,		USB_PRODUCT_SHUTTLE_SCL3712,		ANY,
+	{ UQ_DESC_CORRUPT, desc_pn533 }},
+ { 0, 0, 0, { 0, NULL } }
 };
 
 const struct usbd_quirks usbd_no_quirk = { 0 };
@@ -164,7 +331,7 @@ usbd_find_quirk(usb_device_descriptor_t 
 	uint16_t revision = UGETW(d->bcdDevice);
 
 	for (t = usb_quirks; t->idVendor != 0; t++) {
-		if (t->idVendor  == vendor &&
+		if (t->idVendor == vendor &&
 		    (t->idProduct == ANY || t->idProduct == product) &&
 		    (t->bcdDevice == ANY || t->bcdDevice == revision))
 			break;

Index: src/sys/dev/usb/usb_quirks.h
diff -u src/sys/dev/usb/usb_quirks.h:1.27 src/sys/dev/usb/usb_quirks.h:1.28
--- src/sys/dev/usb/usb_quirks.h:1.27	Sat Apr 23 10:15:32 2016
+++ src/sys/dev/usb/usb_quirks.h	Thu Nov  8 02:11:54 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: usb_quirks.h,v 1.27 2016/04/23 10:15:32 skrll Exp $	*/
+/*	$NetBSD: usb_quirks.h,v 1.28 2018/11/08 02:11:54 manu Exp $	*/
 /*	$FreeBSD: src/sys/dev/usb/usb_quirks.h,v 1.9 1999/11/12 23:31:03 n_hibma Exp $	*/
 
 /*
@@ -49,8 +49,11 @@ struct usbd_quirks {
 #define UQ_NO_UNION_NRM 0x8000  /* has no normal UNION descriptor */
 #define UQ_LOST_CS_DESC 0x10000 /* look everywhere for the CS descriptors */
 #define UQ_APPLE_ISO	0x20000	/* force ISO layout on Apple keyboards */
+#define UQ_DESC_CORRUPT	0x40000	/* may corrupt its config descriptors */
+	const usb_descriptor_t **desc;	/* Replacement for UQ_DESC_CORRUPT */
 };
 
 extern const struct usbd_quirks usbd_no_quirk;
 
+usbd_status usbd_get_desc_fake(struct usbd_device *, int, int, int, void *);
 const struct usbd_quirks *usbd_find_quirk(usb_device_descriptor_t *);

Index: src/sys/dev/usb/usbdi_util.c
diff -u src/sys/dev/usb/usbdi_util.c:1.71 src/sys/dev/usb/usbdi_util.c:1.72
--- src/sys/dev/usb/usbdi_util.c:1.71	Tue Jul 24 03:58:36 2018
+++ src/sys/dev/usb/usbdi_util.c	Thu Nov  8 02:11:54 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: usbdi_util.c,v 1.71 2018/07/24 03:58:36 msaitoh Exp $	*/
+/*	$NetBSD: usbdi_util.c,v 1.72 2018/11/08 02:11:54 manu Exp $	*/
 
 /*
  * Copyright (c) 1998, 2012 The NetBSD Foundation, Inc.
@@ -31,7 +31,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usbdi_util.c,v 1.71 2018/07/24 03:58:36 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usbdi_util.c,v 1.72 2018/11/08 02:11:54 manu Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -50,6 +50,7 @@ __KERNEL_RCSID(0, "$NetBSD: usbdi_util.c
 #include <dev/usb/usbdi.h>
 #include <dev/usb/usbdivar.h>
 #include <dev/usb/usbdi_util.h>
+#include <dev/usb/usb_quirks.h>
 #include <dev/usb/usbhist.h>
 
 #define	DPRINTF(FMT,A,B,C,D)	USBHIST_LOGN(usbdebug,1,FMT,A,B,C,D)
@@ -59,17 +60,33 @@ usbd_status
 usbd_get_desc(struct usbd_device *dev, int type, int index, int len, void *desc)
 {
 	usb_device_request_t req;
+	usbd_status err;
 
 	USBHIST_FUNC(); USBHIST_CALLED(usbdebug);
 
 	DPRINTFN(3,"type=%jd, index=%jd, len=%jd", type, index, len, 0);
 
+	/*
+	 * Provide hard-coded configuration descriptors
+	 * for devices that may corrupt it. This cannot
+	 * be done for device descriptors which are used
+	 * to identify the device.
+	 */
+	if (type != UDESC_DEVICE &&
+	    dev->ud_quirks->uq_flags & UQ_DESC_CORRUPT) {
+		err = usbd_get_desc_fake(dev, type, index, len, desc);
+		goto out;
+	}
+
 	req.bmRequestType = UT_READ_DEVICE;
 	req.bRequest = UR_GET_DESCRIPTOR;
 	USETW2(req.wValue, type, index);
 	USETW(req.wIndex, 0);
 	USETW(req.wLength, len);
-	return usbd_do_request(dev, &req, desc);
+	err = usbd_do_request(dev, &req, desc);
+
+out:
+	return err;
 }
 
 usbd_status

Index: src/sys/dev/usb/usbdi_util.h
diff -u src/sys/dev/usb/usbdi_util.h:1.47 src/sys/dev/usb/usbdi_util.h:1.48
--- src/sys/dev/usb/usbdi_util.h:1.47	Sat Apr 23 10:15:32 2016
+++ src/sys/dev/usb/usbdi_util.h	Thu Nov  8 02:11:54 2018
@@ -1,4 +1,4 @@
-/*	$NetBSD: usbdi_util.h,v 1.47 2016/04/23 10:15:32 skrll Exp $	*/
+/*	$NetBSD: usbdi_util.h,v 1.48 2018/11/08 02:11:54 manu Exp $	*/
 
 /*
  * Copyright (c) 1998, 2004 The NetBSD Foundation, Inc.
@@ -45,6 +45,8 @@ usbd_status	usbd_get_bos_desc(struct usb
 usbd_status	usbd_get_bos_desc_full(struct usbd_device *, int, void *, int);
 usbd_status	usbd_get_device_desc(struct usbd_device *,
 				     usb_device_descriptor_t *);
+usbd_status	usbd_get_desc_fake(struct usbd_device *, int,
+				   int, int, void *);
 usbd_status	usbd_set_address(struct usbd_device *, int);
 usbd_status	usbd_get_port_status(struct usbd_device *,
 				     int, usb_port_status_t *);

Reply via email to