usb_new_device() is far too long and does far too much. As a first step, move the code that does initial setup and reads a descriptor into its own function called usb_setup_descriptor().
For XHCI the init order is different - we set up the device but don't actually read the descriptor until after we set an address. Support this option as a parameter to usb_setup_descriptor(). Avoid changing this torturous code more than necessary to make it easy to review. Signed-off-by: Simon Glass <s...@chromium.org> --- Changes in v3: - Fix polarity of CONFIG_XHCI check (which broke USB keyboards) common/usb.c | 117 ++++++++++++++++++++++++++++++++++------------------------- 1 file changed, 67 insertions(+), 50 deletions(-) diff --git a/common/usb.c b/common/usb.c index 4ab2213..e5df98f 100644 --- a/common/usb.c +++ b/common/usb.c @@ -891,35 +891,12 @@ int usb_legacy_port_reset(struct usb_device *hub, int portnr) return 0; } -/* - * By the time we get here, the device has gotten a new device ID - * and is in the default state. We need to identify the thing and - * get the ball rolling.. - * - * Returns 0 for success, != 0 for error. - */ -int usb_new_device(struct usb_device *dev) +static int usb_setup_descriptor(struct usb_device *dev, bool do_read) { - int addr, err; - int tmp; + __maybe_unused struct usb_device_descriptor *desc; ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ); /* - * Allocate usb 3.0 device context. - * USB 3.0 (xHCI) protocol tries to allocate device slot - * and related data structures first. This call does that. - * Refer to sec 4.3.2 in xHCI spec rev1.0 - */ - if (usb_alloc_device(dev)) { - printf("Cannot allocate device context to get SLOT_ID\n"); - return -1; - } - - /* We still haven't set the Address yet */ - addr = dev->devnum; - dev->devnum = 0; - - /* * This is a Windows scheme of initialization sequence, with double * reset of the device (Linux uses the same sequence) * Some equipment is said to work only with such init sequence; this @@ -934,40 +911,31 @@ int usb_new_device(struct usb_device *dev) * the maxpacket size is 8 or 16 the device may be waiting to transmit * some more, or keeps on retransmitting the 8 byte header. */ + desc = (struct usb_device_descriptor *)tmpbuf; dev->descriptor.bMaxPacketSize0 = 64; /* Start off at 64 bytes */ /* Default to 64 byte max packet size */ dev->maxpacketsize = PACKET_SIZE_64; dev->epmaxpacketin[0] = 64; dev->epmaxpacketout[0] = 64; - /* - * XHCI needs to issue a Address device command to setup - * proper device context structures, before it can interact - * with the device. So a get_descriptor will fail before any - * of that is done for XHCI unlike EHCI. - */ -#ifndef CONFIG_USB_XHCI - struct usb_device_descriptor *desc; + if (do_read) { + int err; - desc = (struct usb_device_descriptor *)tmpbuf; - err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, 64); - if (err < 0) { - debug("usb_new_device: usb_get_descriptor() failed\n"); - return 1; + err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, 64); + if (err < sizeof(dev->descriptor)) { + if (err < 0) { + printf("unable to get device descriptor (error=%d)\n", + err); + return err; + } else { + printf("USB device descriptor short read (expected %i, got %i)\n", + (int)sizeof(dev->descriptor), err); + return -EIO; + } + } + memcpy(&dev->descriptor, tmpbuf, sizeof(dev->descriptor)); } - dev->descriptor.bMaxPacketSize0 = desc->bMaxPacketSize0; - /* - * Fetch the device class, driver can use this info - * to differentiate between HUB and DEVICE. - */ - dev->descriptor.bDeviceClass = desc->bDeviceClass; -#endif - - err = usb_legacy_port_reset(dev->parent, dev->portnr); - if (err) - return err; - dev->epmaxpacketin[0] = dev->descriptor.bMaxPacketSize0; dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; switch (dev->descriptor.bMaxPacketSize0) { @@ -984,6 +952,55 @@ int usb_new_device(struct usb_device *dev) dev->maxpacketsize = PACKET_SIZE_64; break; } + + return 0; +} + +/* + * By the time we get here, the device has gotten a new device ID + * and is in the default state. We need to identify the thing and + * get the ball rolling.. + * + * Returns 0 for success, != 0 for error. + */ +int usb_new_device(struct usb_device *dev) +{ + bool do_read = true; + int addr, err; + int tmp; + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ); + + /* + * Allocate usb 3.0 device context. + * USB 3.0 (xHCI) protocol tries to allocate device slot + * and related data structures first. This call does that. + * Refer to sec 4.3.2 in xHCI spec rev1.0 + */ + if (usb_alloc_device(dev)) { + printf("Cannot allocate device context to get SLOT_ID\n"); + return -1; + } + + /* We still haven't set the Address yet */ + addr = dev->devnum; + dev->devnum = 0; + + /* + * XHCI needs to issue a Address device command to setup + * proper device context structures, before it can interact + * with the device. So a get_descriptor will fail before any + * of that is done for XHCI unlike EHCI. + */ +#ifdef CONFIG_USB_XHCI + do_read = false; +#endif + err = usb_setup_descriptor(dev, do_read); + if (err) + return err; + err = usb_legacy_port_reset(dev->parent, dev->portnr); + if (err) + return err; + dev->devnum = addr; err = usb_set_address(dev); /* set address */ -- 2.2.0.rc0.207.ga3a616c _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot