[U-Boot] [PATCH 06/10] usb: emul: hub: Report the actual device speed of the emulation device

Bin Meng bmeng.cn at gmail.com
Sun Oct 1 13:19:41 UTC 2017


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 <bmeng.cn at gmail.com>
---

 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 8ed7a0f..9a0f47b 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.7.4



More information about the U-Boot mailing list