Index: sys/dev/usb/usb_subr.c =================================================================== RCS file: /cvsroot/src/sys/dev/usb/usb_subr.c,v retrieving revision 1.194 diff -u -p -u -r1.194 usb_subr.c --- sys/dev/usb/usb_subr.c 26 Sep 2013 07:25:31 -0000 1.194 +++ sys/dev/usb/usb_subr.c 28 Sep 2013 20:51:19 -0000 @@ -1055,34 +1055,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. - */ -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, @@ -1131,7 +1103,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) @@ -1184,14 +1155,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) {