Skip to content
Snippets Groups Projects
usb.c 34 KiB
Newer Older
  • Learn to ignore specific revisions
  • 		dev->maxpacketsize  = PACKET_SIZE_8;
    		break;
    	case 16:
    		dev->maxpacketsize = PACKET_SIZE_16;
    		break;
    	case 32:
    		dev->maxpacketsize = PACKET_SIZE_32;
    		break;
    	case 64:
    		dev->maxpacketsize = PACKET_SIZE_64;
    		break;
    
    		printf("%s: invalid max packet size\n", __func__);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	}
    
    static int usb_prepare_device(struct usb_device *dev, int addr, bool do_read,
    
    
    	/*
    	 * 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
    	 */
    
    	err = usb_alloc_device(dev);
    	if (err) {
    
    		printf("Cannot allocate device context to get SLOT_ID\n");
    
    	}
    	err = usb_setup_descriptor(dev, do_read);
    	if (err)
    		return err;
    
    	err = usb_hub_port_reset(dev, parent);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	dev->devnum = addr;
    
    	err = usb_set_address(dev); /* set address */
    
    	if (err < 0) {
    
    		printf("\n      USB device not accepting new address " \
    			"(error=%lX)\n", dev->status);
    
    	mdelay(10);	/* Let the SET_ADDRESS settle */
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    
    	/*
    	 * If we haven't read device descriptor before, read it here
    	 * after device is assigned an address. This is only applicable
    	 * to xHCI so far.
    	 */
    	if (!do_read) {
    		err = usb_setup_descriptor(dev, true);
    		if (err)
    			return err;
    	}
    
    
    int usb_select_config(struct usb_device *dev)
    
    	unsigned char *tmpbuf = NULL;
    
    	err = get_descriptor_len(dev, USB_DT_DEVICE_SIZE, USB_DT_DEVICE_SIZE);
    	if (err)
    		return err;
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    	/* 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);
    
    	/*
    	 * Kingston DT Ultimate 32GB USB 3.0 seems to be extremely sensitive
    	 * about this first Get Descriptor request. If there are any other
    	 * requests in the first microframe, the stick crashes. Wait about
    	 * one microframe duration here (1mS for USB 1.x , 125uS for USB 2.0).
    	 */
    	mdelay(1);
    
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	/* only support for one config for now */
    
    	err = usb_get_configuration_len(dev, 0);
    	if (err >= 0) {
    		tmpbuf = (unsigned char *)malloc_cache_aligned(err);
    		if (!tmpbuf)
    			err = -ENOMEM;
    		else
    			err = usb_get_configuration_no(dev, 0, tmpbuf, err);
    	}
    
    	if (err < 0) {
    		printf("usb_new_device: Cannot read configuration, " \
    		       "skipping device %04x:%04x\n",
    		       dev->descriptor.idVendor, dev->descriptor.idProduct);
    
    	usb_parse_config(dev, tmpbuf, 0);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	usb_set_maxpacket(dev);
    
    	/*
    	 * 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);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	}
    
    
    	/*
    	 * Wait until the Set Configuration request gets processed by the
    	 * device. This is required by at least SanDisk Cruzer Pop USB 2.0
    	 * and Kingston DT Ultimate 32GB USB 3.0 on DWC2 OTG controller.
    	 */
    	mdelay(10);
    
    
    	debug("new device strings: Mfr=%d, Product=%d, SerialNumber=%d\n",
    	      dev->descriptor.iManufacturer, dev->descriptor.iProduct,
    	      dev->descriptor.iSerialNumber);
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	memset(dev->mf, 0, sizeof(dev->mf));
    	memset(dev->prod, 0, sizeof(dev->prod));
    	memset(dev->serial, 0, sizeof(dev->serial));
    	if (dev->descriptor.iManufacturer)
    
    		usb_string(dev, dev->descriptor.iManufacturer,
    			   dev->mf, sizeof(dev->mf));
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	if (dev->descriptor.iProduct)
    
    		usb_string(dev, dev->descriptor.iProduct,
    			   dev->prod, sizeof(dev->prod));
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	if (dev->descriptor.iSerialNumber)
    
    		usb_string(dev, dev->descriptor.iSerialNumber,
    			   dev->serial, sizeof(dev->serial));
    
    	debug("Manufacturer %s\n", dev->mf);
    	debug("Product      %s\n", dev->prod);
    	debug("SerialNumber %s\n", dev->serial);
    
    int usb_setup_device(struct usb_device *dev, bool do_read,
    
    {
    	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;
    }
    
    
    /*
     * 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_HCD
    
    	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;
    
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    	return 0;
    }
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    
    
    int board_usb_init(int index, enum usb_init_type init)
    
    
    __weak
    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
    }
    
    
    #ifdef CONFIG_DM_USB
    void usb_find_usb2_hub_address_port(struct usb_device *udev,
    			       uint8_t *hub_address, uint8_t *hub_port)
    {
    	struct udevice *parent;
    	struct usb_device *uparent, *ttdev;
    
    	/*
    	 * When called from usb-uclass.c: usb_scan_device() udev->dev points
    	 * to the parent udevice, not the actual udevice belonging to the
    	 * udev as the device is not instantiated yet. So when searching
    	 * for the first usb-2 parent start with udev->dev not
    	 * udev->dev->parent .
    	 */
    	ttdev = udev;
    	parent = udev->dev;
    	uparent = dev_get_parent_priv(parent);
    
    	while (uparent->speed != USB_SPEED_HIGH) {
    		struct udevice *dev = parent;
    
    		if (device_get_uclass_id(dev->parent) != UCLASS_USB_HUB) {
    			printf("Error: Cannot find high speed parent of usb-1 device\n");
    			*hub_address = 0;
    			*hub_port = 0;
    			return;
    		}
    
    		ttdev = dev_get_parent_priv(dev);
    		parent = dev->parent;
    		uparent = dev_get_parent_priv(parent);
    	}
    	*hub_address = uparent->devnum;
    	*hub_port = ttdev->portnr;
    }
    #else
    void usb_find_usb2_hub_address_port(struct usb_device *udev,
    			       uint8_t *hub_address, uint8_t *hub_port)
    {
    	/* Find out the nearest parent which is high speed */
    	while (udev->parent->parent != NULL)
    		if (udev->parent->speed != USB_SPEED_HIGH) {
    			udev = udev->parent;
    		} else {
    			*hub_address = udev->parent->devnum;
    			*hub_port = udev->portnr;
    			return;
    		}
    
    	printf("Error: Cannot find high speed parent of usb-1 device\n");
    	*hub_address = 0;
    	*hub_port = 0;
    }
    #endif
    
    
    
    Wolfgang Denk's avatar
    Wolfgang Denk committed
    /* EOF */