X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=common%2Fusb.c;h=fbaf8ecbe232ce63170228727df1ed7fa23b060f;hb=6e474eab446432e7480394ca3833c89a01dba078;hp=ca384463e00c811f4ccfc2e522c0d5a872477f03;hpb=91398f985460bb8ff47db2b406a5fc7fbc31ab9f;p=u-boot diff --git a/common/usb.c b/common/usb.c index ca384463e0..fbaf8ecbe2 100644 --- a/common/usb.c +++ b/common/usb.c @@ -28,6 +28,7 @@ */ #include #include +#include #include #include #include @@ -41,12 +42,13 @@ #define USB_BUFSIZ 512 -static struct usb_device usb_dev[USB_MAX_DEVICE]; -static int dev_index; static int asynch_allowed; - char usb_started; /* flag for the started/stopped USB status */ +#ifndef CONFIG_DM_USB +static struct usb_device usb_dev[USB_MAX_DEVICE]; +static int dev_index; + #ifndef CONFIG_USB_MAX_CONTROLLER_COUNT #define CONFIG_USB_MAX_CONTROLLER_COUNT 1 #endif @@ -146,6 +148,32 @@ int usb_stop(void) return 0; } +/****************************************************************************** + * Detect if a USB device has been plugged or unplugged. + */ +int usb_detect_change(void) +{ + int i, j; + int change = 0; + + for (j = 0; j < USB_MAX_DEVICE; j++) { + for (i = 0; i < usb_dev[j].maxchild; i++) { + struct usb_port_status status; + + if (usb_get_port_status(&usb_dev[j], i + 1, + &status) < 0) + /* USB request failed */ + continue; + + if (le16_to_cpu(status.wPortChange) & + USB_PORT_STAT_C_CONNECTION) + change++; + } + } + + return change; +} + /* * disables the asynch behaviour of the control message. This is used for data * transfers that uses the exclusiv access to the control and bulk messages. @@ -158,6 +186,7 @@ int usb_disable_asynch(int disable) asynch_allowed = !disable; return old_value; } +#endif /* !CONFIG_DM_USB */ /*------------------------------------------------------------------- @@ -189,6 +218,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, void *data, unsigned short size, int timeout) { ALLOC_CACHE_ALIGN_BUFFER(struct devrequest, setup_packet, 1); + int err; if ((timeout == 0) && (!asynch_allowed)) { /* request for a asynch control pipe is not allowed */ @@ -206,8 +236,9 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe, request, requesttype, value, index, size); dev->status = USB_ST_NOT_PROC; /*not yet processed */ - if (submit_control_msg(dev, pipe, data, size, setup_packet) < 0) - return -EIO; + err = submit_control_msg(dev, pipe, data, size, setup_packet); + if (err < 0) + return err; if (timeout == 0) return (int)size; @@ -821,6 +852,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) * the USB device are static allocated [USB_MAX_DEVICE]. */ +#ifndef CONFIG_DM_USB /* returns a pointer to the device with the index [index]. * if the device is not assigned (dev->devnum==-1) returns NULL @@ -877,31 +909,54 @@ __weak int usb_alloc_device(struct usb_device *udev) { return 0; } +#endif /* !CONFIG_DM_USB */ -int usb_legacy_port_reset(struct usb_device *hub, int portnr) +static int usb_hub_port_reset(struct usb_device *dev, struct usb_device *hub) { if (hub) { unsigned short portstatus; int err; /* reset the port for the second time */ - err = legacy_hub_port_reset(hub, portnr - 1, &portstatus); + err = legacy_hub_port_reset(hub, dev->portnr - 1, &portstatus); if (err < 0) { - printf("\n Couldn't reset port %i\n", portnr); + printf("\n Couldn't reset port %i\n", dev->portnr); return err; } } else { - usb_reset_root_port(); + usb_reset_root_port(dev); } return 0; } -static int usb_setup_descriptor(struct usb_device *dev, bool do_read) +static int get_descriptor_len(struct usb_device *dev, int len, int expect_len) { __maybe_unused struct usb_device_descriptor *desc; ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ); + int err; + + desc = (struct usb_device_descriptor *)tmpbuf; + + err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, len); + if (err < expect_len) { + 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", + expect_len, err); + return -EIO; + } + } + memcpy(&dev->descriptor, tmpbuf, sizeof(dev->descriptor)); + + return 0; +} +static int usb_setup_descriptor(struct usb_device *dev, bool do_read) +{ /* * This is a Windows scheme of initialization sequence, with double * reset of the device (Linux uses the same sequence) @@ -915,19 +970,22 @@ static int usb_setup_descriptor(struct usb_device *dev, bool do_read) * send 64-byte GET-DEVICE-DESCRIPTOR request. Since the descriptor is * only 18 bytes long, this will terminate with a short packet. But if * the maxpacket size is 8 or 16 the device may be waiting to transmit - * some more, or keeps on retransmitting the 8 byte header. */ + * 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; + if (dev->speed == USB_SPEED_LOW) { + dev->descriptor.bMaxPacketSize0 = 8; + dev->maxpacketsize = PACKET_SIZE_8; + } else { + dev->descriptor.bMaxPacketSize0 = 64; + dev->maxpacketsize = PACKET_SIZE_64; + } + dev->epmaxpacketin[0] = dev->descriptor.bMaxPacketSize0; + dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0; if (do_read) { int err; - err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, 64); /* * Validate we've received only at least 8 bytes, not that we've * received the entire descriptor. The reasoning is: @@ -943,18 +1001,9 @@ static int usb_setup_descriptor(struct usb_device *dev, bool do_read) * bytes of data with the maxpacket guessed as 64 (above) yields a * request for 1 packet. */ - if (err < 8) { - 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)); + err = get_descriptor_len(dev, 64, 8); + if (err) + return err; } dev->epmaxpacketin[0] = dev->descriptor.bMaxPacketSize0; @@ -981,7 +1030,7 @@ static int usb_setup_descriptor(struct usb_device *dev, bool do_read) } static int usb_prepare_device(struct usb_device *dev, int addr, bool do_read, - struct usb_device *parent, int portnr) + struct usb_device *parent) { int err; @@ -999,7 +1048,7 @@ static int usb_prepare_device(struct usb_device *dev, int addr, bool do_read, err = usb_setup_descriptor(dev, do_read); if (err) return err; - err = usb_legacy_port_reset(parent, portnr); + err = usb_hub_port_reset(dev, parent); if (err) return err; @@ -1018,71 +1067,41 @@ static int usb_prepare_device(struct usb_device *dev, int addr, bool do_read, 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) +int usb_select_config(struct usb_device *dev) { - bool do_read = true; - int addr, err; - int tmp, ret; ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ); + int err; - /* 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 - ret = usb_prepare_device(dev, addr, do_read, dev->parent, dev->portnr); - if (ret) - return ret; - - tmp = sizeof(dev->descriptor); + err = get_descriptor_len(dev, USB_DT_DEVICE_SIZE, USB_DT_DEVICE_SIZE); + if (err) + return err; - err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, - tmpbuf, sizeof(dev->descriptor)); - if (err < tmp) { - if (err < 0) - printf("unable to get device descriptor (error=%d)\n", - err); - else - printf("USB device descriptor short read " \ - "(expected %i, got %i)\n", tmp, err); - return -EIO; - } - memcpy(&dev->descriptor, tmpbuf, sizeof(dev->descriptor)); /* correct le values */ le16_to_cpus(&dev->descriptor.bcdUSB); le16_to_cpus(&dev->descriptor.idVendor); le16_to_cpus(&dev->descriptor.idProduct); le16_to_cpus(&dev->descriptor.bcdDevice); + /* only support for one config for now */ err = usb_get_configuration_no(dev, tmpbuf, 0); if (err < 0) { printf("usb_new_device: Cannot read configuration, " \ "skipping device %04x:%04x\n", dev->descriptor.idVendor, dev->descriptor.idProduct); - return -EIO; + return err; } usb_parse_config(dev, tmpbuf, 0); usb_set_maxpacket(dev); - /* we set the default configuration here */ - if (usb_set_configuration(dev, dev->config.desc.bConfigurationValue)) { + /* + * we set the default configuration here + * This seems premature. If the driver wants a different configuration + * it will need to select itself. + */ + err = usb_set_configuration(dev, dev->config.desc.bConfigurationValue); + if (err < 0) { printf("failed to set default configuration " \ "len %d, status %lX\n", dev->act_len, dev->status); - return -EIO; + return err; } debug("new device strings: Mfr=%d, Product=%d, SerialNumber=%d\n", dev->descriptor.iManufacturer, dev->descriptor.iProduct, @@ -1102,10 +1121,62 @@ int usb_new_device(struct usb_device *dev) debug("Manufacturer %s\n", dev->mf); debug("Product %s\n", dev->prod); debug("SerialNumber %s\n", dev->serial); - /* now prode if the device is a hub */ - usb_hub_probe(dev, 0); + + return 0; +} + +int usb_setup_device(struct usb_device *dev, bool do_read, + struct usb_device *parent) +{ + int addr; + int ret; + + /* We still haven't set the Address yet */ + addr = dev->devnum; + dev->devnum = 0; + + ret = usb_prepare_device(dev, addr, do_read, parent); + if (ret) + return ret; + ret = usb_select_config(dev); + + return ret; +} + +#ifndef CONFIG_DM_USB +/* + * 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 err; + + /* + * 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_device(dev, do_read, dev->parent); + if (err) + return err; + + /* Now probe if the device is a hub */ + err = usb_hub_probe(dev, 0); + if (err < 0) + return err; + return 0; } +#endif __weak int board_usb_init(int index, enum usb_init_type init) @@ -1118,4 +1189,14 @@ int board_usb_cleanup(int index, enum usb_init_type init) { return 0; } + +bool usb_device_has_child_on_port(struct usb_device *parent, int port) +{ +#ifdef CONFIG_DM_USB + return false; +#else + return parent->children[port] != NULL; +#endif +} + /* EOF */