diff options
Diffstat (limited to 'drivers/usb/emul')
-rw-r--r-- | drivers/usb/emul/sandbox_flash.c | 3 | ||||
-rw-r--r-- | drivers/usb/emul/sandbox_hub.c | 38 | ||||
-rw-r--r-- | drivers/usb/emul/sandbox_keyb.c | 3 | ||||
-rw-r--r-- | drivers/usb/emul/usb-emul-uclass.c | 59 |
4 files changed, 76 insertions, 27 deletions
diff --git a/drivers/usb/emul/sandbox_flash.c b/drivers/usb/emul/sandbox_flash.c index 98d20c0bc1..2f84b360ec 100644 --- a/drivers/usb/emul/sandbox_flash.c +++ b/drivers/usb/emul/sandbox_flash.c @@ -390,8 +390,7 @@ static int sandbox_flash_bind(struct udevice *dev) fs[2].id = STRINGID_SERIAL; fs[2].s = dev->name; - return usb_emul_setup_device(dev, PACKET_SIZE_64, plat->flash_strings, - flash_desc_list); + return usb_emul_setup_device(dev, plat->flash_strings, flash_desc_list); } static int sandbox_flash_probe(struct udevice *dev) diff --git a/drivers/usb/emul/sandbox_hub.c b/drivers/usb/emul/sandbox_hub.c index 1432858fd5..9a0f47b81c 100644 --- a/drivers/usb/emul/sandbox_hub.c +++ b/drivers/usb/emul/sandbox_hub.c @@ -121,9 +121,12 @@ struct sandbox_hub_priv { int change[SANDBOX_NUM_PORTS]; }; -static struct udevice *hub_find_device(struct udevice *hub, int port) +static struct udevice *hub_find_device(struct udevice *hub, int port, + enum usb_device_speed *speed) { struct udevice *dev; + struct usb_generic_descriptor **gen_desc; + struct usb_device_descriptor **dev_desc; for (device_find_first_child(hub, &dev); dev; @@ -131,8 +134,27 @@ static struct udevice *hub_find_device(struct udevice *hub, int port) struct sandbox_hub_platdata *plat; plat = dev_get_parent_platdata(dev); - if (plat->port == port) + if (plat->port == port) { + gen_desc = plat->plat.desc_list; + gen_desc = usb_emul_find_descriptor(gen_desc, + USB_DT_DEVICE, 0); + dev_desc = (struct usb_device_descriptor **)gen_desc; + + switch (le16_to_cpu((*dev_desc)->bcdUSB)) { + case 0x0100: + *speed = USB_SPEED_LOW; + break; + case 0x0101: + *speed = USB_SPEED_FULL; + break; + case 0x0200: + default: + *speed = USB_SPEED_HIGH; + break; + } + return dev; + } } return NULL; @@ -146,7 +168,8 @@ static int clrset_post_state(struct udevice *hub, int port, int clear, int set) int ret = 0; if ((clear | set) & USB_PORT_STAT_POWER) { - struct udevice *dev = hub_find_device(hub, port); + enum usb_device_speed speed; + struct udevice *dev = hub_find_device(hub, port, &speed); if (dev) { if (set & USB_PORT_STAT_POWER) { @@ -156,6 +179,10 @@ static int clrset_post_state(struct udevice *hub, int port, int clear, int set) if (!ret) { set |= USB_PORT_STAT_CONNECTION | USB_PORT_STAT_ENABLE; + if (speed == USB_SPEED_LOW) + set |= USB_PORT_STAT_LOW_SPEED; + else if (speed == USB_SPEED_HIGH) + set |= USB_PORT_STAT_HIGH_SPEED; } } else if (clear & USB_PORT_STAT_POWER) { @@ -274,15 +301,16 @@ static int sandbox_hub_submit_control_msg(struct udevice *bus, static int sandbox_hub_bind(struct udevice *dev) { - return usb_emul_setup_device(dev, PACKET_SIZE_64, hub_strings, - hub_desc_list); + return usb_emul_setup_device(dev, hub_strings, hub_desc_list); } static int sandbox_child_post_bind(struct udevice *dev) { struct sandbox_hub_platdata *plat = dev_get_parent_platdata(dev); + struct usb_emul_platdata *emul = dev_get_uclass_platdata(dev); plat->port = dev_read_u32_default(dev, "reg", -1); + emul->port1 = plat->port + 1; return 0; } diff --git a/drivers/usb/emul/sandbox_keyb.c b/drivers/usb/emul/sandbox_keyb.c index 27359851df..cff017668f 100644 --- a/drivers/usb/emul/sandbox_keyb.c +++ b/drivers/usb/emul/sandbox_keyb.c @@ -208,8 +208,7 @@ static int sandbox_keyb_bind(struct udevice *dev) fs[2].id = STRINGID_SERIAL; fs[2].s = dev->name; - return usb_emul_setup_device(dev, PACKET_SIZE_8, plat->keyb_strings, - keyb_desc_list); + return usb_emul_setup_device(dev, plat->keyb_strings, keyb_desc_list); } static int sandbox_keyb_probe(struct udevice *dev) diff --git a/drivers/usb/emul/usb-emul-uclass.c b/drivers/usb/emul/usb-emul-uclass.c index 6e03c1e0d9..fbe11f3135 100644 --- a/drivers/usb/emul/usb-emul-uclass.c +++ b/drivers/usb/emul/usb-emul-uclass.c @@ -52,7 +52,7 @@ static int usb_emul_get_string(struct usb_string *strings, int index, return -EINVAL; } -static struct usb_generic_descriptor **find_descriptor( +struct usb_generic_descriptor **usb_emul_find_descriptor( struct usb_generic_descriptor **ptr, int type, int index) { debug("%s: type=%x, index=%d\n", __func__, type, index); @@ -91,8 +91,7 @@ static int usb_emul_get_descriptor(struct usb_dev_platdata *plat, int value, length); } - ptr = find_descriptor((struct usb_generic_descriptor **)plat->desc_list, - type, index); + ptr = usb_emul_find_descriptor(plat->desc_list, type, index); if (!ptr) { debug("%s: Could not find descriptor type %d, index %d\n", __func__, type, index); @@ -107,7 +106,7 @@ static int usb_emul_get_descriptor(struct usb_dev_platdata *plat, int value, return upto ? upto : length ? -EIO : 0; } -static int usb_emul_find_devnum(int devnum, struct udevice **emulp) +static int usb_emul_find_devnum(int devnum, int port1, struct udevice **emulp) { struct udevice *dev; struct uclass *uc; @@ -120,7 +119,37 @@ static int usb_emul_find_devnum(int devnum, struct udevice **emulp) uclass_foreach_dev(dev, uc) { struct usb_dev_platdata *udev = dev_get_parent_platdata(dev); - if (udev->devnum == devnum) { + /* + * devnum is initialzied to zero at the beginning of the + * enumeration process in usb_setup_device(). At this + * point, udev->devnum has not been assigned to any valid + * USB address either, so we can't rely on the comparison + * result between udev->devnum and devnum to select an + * emulator device. + */ + if (!devnum) { + struct usb_emul_platdata *plat; + + /* + * If the parent is sandbox USB controller, we are + * the root hub. And there is only one root hub + * in the system. + */ + if (device_get_uclass_id(dev->parent) == UCLASS_USB) { + debug("%s: Found emulator '%s'\n", + __func__, dev->name); + *emulp = dev; + return 0; + } + + plat = dev_get_uclass_platdata(dev); + if (plat->port1 == port1) { + debug("%s: Found emulator '%s', port %d\n", + __func__, dev->name, port1); + *emulp = dev; + return 0; + } + } else if (udev->devnum == devnum) { debug("%s: Found emulator '%s', addr %d\n", __func__, dev->name, udev->devnum); *emulp = dev; @@ -132,18 +161,19 @@ static int usb_emul_find_devnum(int devnum, struct udevice **emulp) return -ENOENT; } -int usb_emul_find(struct udevice *bus, ulong pipe, struct udevice **emulp) +int usb_emul_find(struct udevice *bus, ulong pipe, int port1, + struct udevice **emulp) { int devnum = usb_pipedevice(pipe); - return usb_emul_find_devnum(devnum, emulp); + return usb_emul_find_devnum(devnum, port1, emulp); } int usb_emul_find_for_dev(struct udevice *dev, struct udevice **emulp) { struct usb_dev_platdata *udev = dev_get_parent_platdata(dev); - return usb_emul_find_devnum(udev->devnum, emulp); + return usb_emul_find_devnum(udev->devnum, 0, emulp); } int usb_emul_control(struct udevice *emul, struct usb_device *udev, @@ -229,8 +259,8 @@ int usb_emul_int(struct udevice *emul, struct usb_device *udev, return ops->interrupt(emul, udev, pipe, buffer, length, interval); } -int usb_emul_setup_device(struct udevice *dev, int maxpacketsize, - struct usb_string *strings, void **desc_list) +int usb_emul_setup_device(struct udevice *dev, struct usb_string *strings, + void **desc_list) { struct usb_dev_platdata *plat = dev_get_parent_platdata(dev); struct usb_generic_descriptor **ptr; @@ -264,18 +294,11 @@ int usb_emul_setup_device(struct udevice *dev, int maxpacketsize, return 0; } -void usb_emul_reset(struct udevice *dev) -{ - struct usb_dev_platdata *plat = dev_get_parent_platdata(dev); - - plat->devnum = 0; - plat->configno = 0; -} - UCLASS_DRIVER(usb_emul) = { .id = UCLASS_USB_EMUL, .name = "usb_emul", .post_bind = dm_scan_fdt_dev, + .per_device_platdata_auto_alloc_size = sizeof(struct usb_emul_platdata), .per_child_auto_alloc_size = sizeof(struct usb_device), .per_child_platdata_auto_alloc_size = sizeof(struct usb_dev_platdata), }; |