NetBSD-Bugs archive

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

Re: kern/46696 (uhub disables port where USB keyboard attached)



Can you test today's -current again and then try -current with this patch and report results.

Thanks,
Nick

Index: sys/dev/usb/usb_subr.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/usb_subr.c,v
retrieving revision 1.192
diff -u -p -r1.192 usb_subr.c
--- sys/dev/usb/usb_subr.c      7 Sep 2013 16:39:15 -0000       1.192
+++ sys/dev/usb/usb_subr.c      12 Sep 2013 09:01:29 -0000
@@ -1059,34 +1059,6 @@ usbd_reattach_device(device_t parent, us
 }
 
 /*
- * 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,
@@ -1130,7 +1102,6 @@ usbd_new_device(device_t parent, usbd_bu
        dev->def_ep_desc.bmAttributes = UE_CONTROL;
        /*
         * 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
         */
        if (speed == USB_SPEED_HIGH || speed == USB_SPEED_FULL)
@@ -1183,14 +1154,44 @@ usbd_new_device(device_t parent, usbd_bu
        }
 
        dd = &dev->ddesc;
-       /* 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_initial_ddesc(dev, dd);
+
+       /*
+        * Get the first 8 bytes of the device descriptor.
+        *
+        * Try a few times in case the device is slow (i.e. outside specs.),
+        * and alternate between read lengths.
+        *
+        * 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.
+        *
+        * If this doesn't work, then attempt to read just the 8 bytes.
+        *
+        * Throw in a reset after 3 read attempts so that the device
+        * will see an initial read after reset of both 64 and 8 over
+        * time.
+        */
+       for (i = 0; i < 12; i++) {
+               usb_device_request_t req;
+               char buf[64];
+               int actlen;
+
+               req.bmRequestType = UT_READ_DEVICE;
+               req.bRequest = UR_GET_DESCRIPTOR;
+               USETW2(req.wValue, UDESC_DEVICE, 0);
+               USETW(req.wIndex, 0);
+               USETW(req.wLength, (i % 2 == 0 ? 64 : 8));
+               err = usbd_do_request_flags(dev, &req, buf, USBD_SHORT_XFER_OK,
+                       &actlen, USBD_DEFAULT_TIMEOUT);
+               if (actlen < 8)
+                       continue;
+               memcpy(dd, buf, 8);
+
                if (!err)
                        break;
                usbd_delay_ms(dev, 200);
-               if ((i & 3) == 3)
+               if ((i % 3) == 2)
                        usbd_reset_port(up->parent, port, &ps);
        }
        if (err) {


Home | Main Index | Thread Index | Old Index