Module Name: src Committed By: drochner Date: Tue Jul 20 20:56:06 UTC 2010
Modified Files: src/sys/dev/usb: usb_subr.c Log Message: 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... To generate a diff of this commit: cvs rdiff -u -r1.171 -r1.172 src/sys/dev/usb/usb_subr.c 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_subr.c diff -u src/sys/dev/usb/usb_subr.c:1.171 src/sys/dev/usb/usb_subr.c:1.172 --- src/sys/dev/usb/usb_subr.c:1.171 Sun Jun 6 18:58:26 2010 +++ src/sys/dev/usb/usb_subr.c Tue Jul 20 20:56:06 2010 @@ -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);