From d7771f0c5cd429286c7555360d779d21568e3ba0 Mon Sep 17 00:00:00 2001 From: Bin Meng Date: Sun, 1 Oct 2017 06:19:41 -0700 Subject: [PATCH] usb: emul: hub: Report the actual device speed of the emulation device At present the usb hub emulator always reports its downstream port speed as full speed. Actually it is high speed for sandbox-flash, and low speed for sandbox-keyb. We can determine the device speed by checking its device descriptor bcdUSB field, and do the proper hub port status report based on that. Signed-off-by: Bin Meng --- drivers/usb/emul/sandbox_hub.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/drivers/usb/emul/sandbox_hub.c b/drivers/usb/emul/sandbox_hub.c index 8ed7a0f434..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) { -- 2.30.2