Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/usb another iteration in the eternal device enumerat...



details:   https://anonhg.NetBSD.org/src/rev/fcbfb23a0c9b
branches:  trunk
changeset: 756519:fcbfb23a0c9b
user:      drochner <drochner%NetBSD.org@localhost>
date:      Tue Jul 20 20:56:06 2010 +0000

description:
another iteration in the eternal device enumeration struggle:
use a request of 64 bytes for the initial device descriptor fetch.
This is what windows does, and I've seen USB device firmware which
really depends on this. (sends 8 bytes if 64 are requested and
the full descriptor which is more than NetBSD's USB_MAX_IPACKET
otherwise) This is the world...

diffstat:

 sys/dev/usb/usb_subr.c |  57 +++++++++++++++++++++++++++++++++++++------------
 1 files changed, 43 insertions(+), 14 deletions(-)

diffs (108 lines):

diff -r a7eeabab1977 -r fcbfb23a0c9b sys/dev/usb/usb_subr.c
--- a/sys/dev/usb/usb_subr.c    Tue Jul 20 19:24:11 2010 +0000
+++ b/sys/dev/usb/usb_subr.c    Tue Jul 20 20:56:06 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: usb_subr.c,v 1.171 2010/06/06 18:58:26 pgoyette Exp $  */
+/*     $NetBSD: usb_subr.c,v 1.172 2010/07/20 20:56:06 drochner Exp $  */
 /*     $FreeBSD: src/sys/dev/usb/usb_subr.c,v 1.18 1999/11/17 22:33:47 n_hibma Exp $   */
 
 /*
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.171 2010/06/06 18:58:26 pgoyette Exp $");
+__KERNEL_RCSID(0, "$NetBSD: usb_subr.c,v 1.172 2010/07/20 20:56:06 drochner Exp $");
 
 #include "opt_compat_netbsd.h"
 #include "opt_usbverbose.h"
@@ -594,8 +594,10 @@
 
        /* Get the short descriptor. */
        err = usbd_get_config_desc(dev, index, &cd);
-       if (err)
+       if (err) {
+               DPRINTF(("usbd_set_config_index: get_config_desc=%d\n", err));
                return (err);
+       }
        len = UGETW(cd.wTotalLength);
        cdp = malloc(len, M_USB, M_NOWAIT);
        if (cdp == NULL)
@@ -608,9 +610,10 @@
                        break;
                usbd_delay_ms(dev, 200);
        }
-       if (err)
+       if (err) {
+               DPRINTF(("usbd_set_config_index: get_desc=%d\n", err));
                goto bad;
-
+       }
        if (cdp->bDescriptorType != UDESC_CONFIG) {
                DPRINTFN(-1,("usbd_set_config_index: bad desc %d\n",
                             cdp->bDescriptorType));
@@ -1024,6 +1027,34 @@
 }
 
 /*
+ * Get the first 8 bytes of the device descriptor.
+ * Do as Windows does: try to read 64 bytes -- there are devices which
+ * recognize the initial descriptor fetch (before the control endpoint's
+ * MaxPacketSize is known by the host) by exactly this length.
+ */
+static usbd_status
+usbd_get_initial_ddesc(usbd_device_handle dev, usb_device_descriptor_t *desc)
+{
+       usb_device_request_t req;
+       char buf[64];
+       int res, actlen;
+
+       req.bmRequestType = UT_READ_DEVICE;
+       req.bRequest = UR_GET_DESCRIPTOR;
+       USETW2(req.wValue, UDESC_DEVICE, 0);
+       USETW(req.wIndex, 0);
+       USETW(req.wLength, 64);
+       res = usbd_do_request_flags(dev, &req, buf, USBD_SHORT_XFER_OK,
+               &actlen, USBD_DEFAULT_TIMEOUT);
+       if (res)
+               return res;
+       if (actlen < 8)
+               return USBD_SHORT_XFER;
+       memcpy(desc, buf, 8);
+       return USBD_NORMAL_COMPLETION;
+}
+
+/*
  * Called when a new device has been put in the powered state,
  * but not yet in the addressed state.
  * Get initial descriptor, set the address, get full descriptor,
@@ -1065,10 +1096,12 @@
        dev->def_ep_desc.bDescriptorType = UDESC_ENDPOINT;
        dev->def_ep_desc.bEndpointAddress = USB_CONTROL_ENDPOINT;
        dev->def_ep_desc.bmAttributes = UE_CONTROL;
-       if (speed == USB_SPEED_HIGH)
-               USETW(dev->def_ep_desc.wMaxPacketSize, 64);
-       else
-               USETW(dev->def_ep_desc.wMaxPacketSize, USB_MAX_IPACKET);
+       /*
+        * temporary, will be fixed after first descriptor fetch
+        * (which uses 64 bytes so it shouldn't be less),
+        * highspeed devices must support 64 byte packets anyway
+        */
+       USETW(dev->def_ep_desc.wMaxPacketSize, 64);
        dev->def_ep_desc.bInterval = 0;
 
        dev->quirks = &usbd_no_quirk;
@@ -1114,11 +1147,7 @@
        /* Try a few times in case the device is slow (i.e. outside specs.) */
        for (i = 0; i < 10; i++) {
                /* Get the first 8 bytes of the device descriptor. */
-               err = usbd_get_desc(dev, UDESC_DEVICE, 0, 
-                       (speed == USB_SPEED_HIGH) ? USB_DEVICE_DESCRIPTOR_SIZE
-                                                 : USB_MAX_IPACKET,
-                        dd);
-
+               err = usbd_get_initial_ddesc(dev, dd);
                if (!err)
                        break;
                usbd_delay_ms(dev, 200);



Home | Main Index | Thread Index | Old Index