Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/netbsd-8]: src/sys/dev/usb Pull up following revision(s) (requested by m...



details:   https://anonhg.NetBSD.org/src/rev/ce7ef97e7a3e
branches:  netbsd-8
changeset: 445783:ce7ef97e7a3e
user:      martin <martin%NetBSD.org@localhost>
date:      Mon Nov 12 16:01:35 2018 +0000

description:
Pull up following revision(s) (requested by manu in ticket #1091):

        sys/dev/usb/usb_quirks.c: revision 1.88,1.89 (via patch)
        sys/dev/usb/usbdi_util.c: revision 1.72 (via patch)
        sys/dev/usb/usb_quirks.h: revision 1.28 (via patch)
        sys/dev/usb/usbdi_util.h: revision 1.48
        sys/dev/usb/usbdevs: revision 1.760,1.761 (via patch)

Add PN533 based NFC devices

 -

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.

 -

Fix typo

diffstat:

 sys/dev/usb/usb_quirks.c |  345 ++++++++++++++++++++++++++++++++++------------
 sys/dev/usb/usb_quirks.h |    5 +-
 sys/dev/usb/usbdevs      |    5 +-
 sys/dev/usb/usbdi_util.c |   23 ++-
 sys/dev/usb/usbdi_util.h |    4 +-
 5 files changed, 287 insertions(+), 95 deletions(-)

diffs (truncated from 520 to 300 lines):

diff -r f287888cff2d -r ce7ef97e7a3e sys/dev/usb/usb_quirks.c
--- a/sys/dev/usb/usb_quirks.c  Mon Nov 12 12:24:42 2018 +0000
+++ b/sys/dev/usb/usb_quirks.c  Mon Nov 12 16:01:35 2018 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: usb_quirks.c,v 1.86 2016/12/04 10:12:35 skrll Exp $    */
+/*     $NetBSD: usb_quirks.c,v 1.86.8.1 2018/11/12 16:01:35 martin 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.86 2016/12/04 10:12:35 skrll Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usb_quirks.c,v 1.86.8.1 2018/11/12 16:01:35 martin Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_usb.h"
@@ -43,13 +43,137 @@
 
 #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 @@
        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_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_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_HP, USB_PRODUCT_HP_1220C,                    ANY,   { UQ_BROKEN_BIDIR }},
+ { 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,



Home | Main Index | Thread Index | Old Index