summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsakumisu <[email protected]>2024-07-07 11:54:04 +0800
committersakumisu <[email protected]>2024-07-07 12:07:12 +0800
commite4b56cee898db47bf884bfcaf265601f6d3491aa (patch)
tree88feb17f0bb05328e354e9402ff76adf59a8d216
parent53114c0f16527bb6fd076e133cefde195697d5f3 (diff)
update(hub): update hub macros and hub params for usb3.0
-rw-r--r--README.md1
-rw-r--r--README_zh.md1
-rw-r--r--class/hub/usb_hub.h96
-rw-r--r--class/hub/usbh_hub.c155
-rw-r--r--class/hub/usbh_hub.h4
-rw-r--r--core/usbh_core.c14
-rw-r--r--core/usbh_core.h14
7 files changed, 198 insertions, 87 deletions
diff --git a/README.md b/README.md
index d79df887..10ed83a8 100644
--- a/README.md
+++ b/README.md
@@ -87,6 +87,7 @@ The CherryUSB Host Stack has a standard enumeration implementation for devices m
CherryUSB Host Stack has the following functions:
+- Support low speed, full speed, high speed and super speed devices
- Automatic loading of supported Class drivers
- Support blocking transfers and asynchronous transfers
- Support Composite Device
diff --git a/README_zh.md b/README_zh.md
index 0aee5a75..cce81939 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -87,6 +87,7 @@ CherryUSB Host 协议栈对挂载在 roothub、外部 hub 上的设备规范了�
CherryUSB Host 协议栈当前实现以下功能:
+- 支持 low speed, full speed, high speed 和 super speed 设备
- 自动加载支持的Class 驱动
- 支持阻塞式传输和异步传输
- 支持复合设备
diff --git a/class/hub/usb_hub.h b/class/hub/usb_hub.h
index 7956b163..68e0ecf1 100644
--- a/class/hub/usb_hub.h
+++ b/class/hub/usb_hub.h
@@ -10,6 +10,12 @@
#define HUB_DESCRIPTOR_TYPE_HUB 0x29
#define HUB_DESCRIPTOR_TYPE_HUB3 0x2A
+#define HUB_MAX_DEPTH 5
+
+#define HUB_SUBCLASS 0x00
+#define HUB_PROTOCOL_STT 0x01
+#define HUB_PROTOCOL_MTT 0x02
+
/* Hub class requests */
#define HUB_REQUEST_GET_STATUS USB_REQUEST_GET_STATUS
#define HUB_REQUEST_CLEAR_FEATURE USB_REQUEST_CLEAR_FEATURE
@@ -27,23 +33,31 @@
#define HUB_FEATURE_HUB_C_OVERCURRENT (0x1)
/* Port features */
-#define HUB_PORT_FEATURE_CONNECTION (0x00)
-#define HUB_PORT_FEATURE_ENABLE (0x01)
-#define HUB_PORT_FEATURE_SUSPEND (0x02)
-#define HUB_PORT_FEATURE_OVERCURRENT (0x03)
-#define HUB_PORT_FEATURE_RESET (0x04)
-#define HUB_PORT_FEATURE_L1 (0x05)
-#define HUB_PORT_FEATURE_POWER (0x08)
-#define HUB_PORT_FEATURE_LOWSPEED (0x09)
-#define HUB_PORT_FEATURE_HIGHSPEED (0x0a)
+#define HUB_PORT_FEATURE_CONNECTION (0x00)
+#define HUB_PORT_FEATURE_ENABLE (0x01)
+#define HUB_PORT_FEATURE_SUSPEND (0x02)
+#define HUB_PORT_FEATURE_OVERCURRENT (0x03)
+#define HUB_PORT_FEATURE_RESET (0x04)
+#define HUB_PORT_FEATURE_L1 (0x05) /* USB 2.0 only */
+
+#define HUB_PORT_FEATURE_POWER (0x08) /* USB 2.0 only */
+#define HUB_PORT_FEATURE_POWER_SS (0x09) /* USB 3.0 only */
+/* This is a bit tricky because HUB_PORT_FEATURE_POWER_SS and
+ HUB_PORT_FEATURE_LOWSPEED share the same bit. */
+#define HUB_PORT_FEATURE_LOWSPEED (0x09) /* USB 2.0 only */
+#define HUB_PORT_FEATURE_HIGHSPEED (0x0a) /* USB 2.0 only */
+#define HUB_PORT_FEATURE_TEST (0x0b) /* USB 2.0 only */
+#define HUB_PORT_FEATURE_INDICATOR (0x0c) /* USB 2.0 only */
+
+/* Port status change (wPortChange) */
#define HUB_PORT_FEATURE_C_CONNECTION (0x10)
-#define HUB_PORT_FEATURE_C_ENABLE (0x11)
-#define HUB_PORT_FEATURE_C_SUSPEND (0x12)
+#define HUB_PORT_FEATURE_C_ENABLE (0x11) /* USB 2.0 only */
+#define HUB_PORT_FEATURE_C_SUSPEND (0x12) /* USB 2.0 only */
#define HUB_PORT_FEATURE_C_OVER_CURREN (0x13)
#define HUB_PORT_FEATURE_C_RESET (0x14)
-#define HUB_PORT_FEATURE_TEST (0x15)
-#define HUB_PORT_FEATURE_INDICATOR (0x16)
-#define HUB_PORT_FEATURE_C_PORTL1 (0x17)
+#define HUB_PORT_FEATURE_C_BH_RESET (0x15) /* USB 3.0 only */
+#define HUB_PORT_FEATURE_C_LINK_STATE (0x16) /* USB 3.0 only */
+#define HUB_PORT_FEATURE_C_CONFIG_ERR (0x17) /* USB 3.0 only */
/* Hub status */
#define HUB_STATUS_LOCALPOWER (1 << 0)
@@ -56,23 +70,42 @@
/* Hub port status */
#define HUB_PORT_STATUS_CONNECTION (1 << 0)
#define HUB_PORT_STATUS_ENABLE (1 << 1)
-#define HUB_PORT_STATUS_SUSPEND (1 << 2)
+#define HUB_PORT_STATUS_SUSPEND (1 << 2) /* USB 2.0 only */
#define HUB_PORT_STATUS_OVERCURRENT (1 << 3)
#define HUB_PORT_STATUS_RESET (1 << 4)
-#define HUB_PORT_STATUS_L1 (1 << 5)
-#define HUB_PORT_STATUS_POWER (1 << 8)
-#define HUB_PORT_STATUS_LOW_SPEED (1 << 9)
-#define HUB_PORT_STATUS_HIGH_SPEED (1 << 10)
-#define HUB_PORT_STATUS_TEST (1 << 11)
-#define HUB_PORT_STATUS_INDICATOR (1 << 12)
+#define HUB_PORT_STATUS_L1 (1 << 5) /* USB 2.0 only */
+
+/* Port Link State (PORT_LINK_STATE), USB 3.0 only */
+#define HUB_PORT_STATUS_LS_U0 (0x00 << 5)
+#define HUB_PORT_STATUS_LS_U1 (0x01 << 5)
+#define HUB_PORT_STATUS_LS_U2 (0x02 << 5)
+#define HUB_PORT_STATUS_LS_U3 (0x03 << 5)
+#define HUB_PORT_STATUS_LS_SS_DISABLED (0x04 << 5)
+#define HUB_PORT_STATUS_LS_RX_DETECT (0x05 << 5)
+#define HUB_PORT_STATUS_LS_SS_INACTIVE (0x06 << 5)
+#define HUB_PORT_STATUS_LS_POLLING (0x07 << 5)
+#define HUB_PORT_STATUS_LS_RECOVERY (0x08 << 5)
+#define HUB_PORT_STATUS_LS_HOT_RESET (0x09 << 5)
+#define HUB_PORT_STATUS_LS_COMP_MOD (0x0a << 5)
+#define HUB_PORT_STATUS_LS_LOOPBACK (0x0b << 5)
+
+#define HUB_PORT_STATUS_POWER (1 << 8)
+#define HUB_PORT_STATUS_POWER_SS (1 << 9) /* USB 3.0 only */
+#define HUB_PORT_STATUS_LOW_SPEED (1 << 9) /* USB 2.0 only */
+#define HUB_PORT_STATUS_HIGH_SPEED (1 << 10) /* USB 2.0 only */
+#define HUB_PORT_STATUS_TEST (1 << 11) /* USB 2.0 only */
+#define HUB_PORT_STATUS_INDICATOR (1 << 12) /* USB 2.0 only */
/* Hub port status change */
#define HUB_PORT_STATUS_C_CONNECTION (1 << 0)
-#define HUB_PORT_STATUS_C_ENABLE (1 << 1)
-#define HUB_PORT_STATUS_C_SUSPEND (1 << 2)
+#define HUB_PORT_STATUS_C_ENABLE (1 << 1) /* USB 2.0 only */
+#define HUB_PORT_STATUS_C_SUSPEND (1 << 2) /* USB 2.0 only */
#define HUB_PORT_STATUS_C_OVERCURRENT (1 << 3)
#define HUB_PORT_STATUS_C_RESET (1 << 4)
-#define HUB_PORT_STATUS_C_L1 (1 << 5)
+#define HUB_PORT_STATUS_C_L1 (1 << 5) /* USB 2.0 only */
+#define HUB_PORT_STATUS_C_BH_RESET (1 << 5) /* USB 3.0 only */
+#define HUB_PORT_STATUS_C_PORTLINK (1 << 6) /* USB 3.0 only */
+#define HUB_PORT_STATUS_C_CONFIGERR (1 << 7) /* USB 3.0 only */
/* Hub characteristics */
#define HUB_CHAR_LPSM_SHIFT (0) /* Bits 0-1: Logical Power Switching Mode */
@@ -106,6 +139,21 @@ struct usb_hub_descriptor {
#define USB_SIZEOF_HUB_DESC 9
+/* Super speed Hub descriptor */
+struct usb_hub_ss_descriptor {
+ uint8_t bLength;
+ uint8_t bDescriptorType;
+ uint8_t bNbrPorts;
+ uint16_t wHubCharacteristics;
+ uint8_t bPwrOn2PwrGood;
+ uint8_t bHubContrCurrent;
+ uint8_t bHubHdrDecLat;
+ uint16_t wHubDelay;
+ uint8_t DeviceRemovable;
+} __PACKED;
+
+#define USB_SIZEOF_HUB_SS_DESC 11
+
/* Hub status */
struct hub_status {
uint16_t wPortStatus;
diff --git a/class/hub/usbh_hub.c b/class/hub/usbh_hub.c
index 1745d8c0..d0974a02 100644
--- a/class/hub/usbh_hub.c
+++ b/class/hub/usbh_hub.c
@@ -55,9 +55,7 @@ static void usbh_hub_class_free(struct usbh_hub *hub_class)
}
memset(hub_class, 0, sizeof(struct usbh_hub));
}
-#endif
-#if CONFIG_USBHOST_MAX_EXTHUBS > 0
static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
{
struct usb_setup_packet *setup;
@@ -67,15 +65,7 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
-
- /* TODO: hub descriptor has some difference between USB 2.0 and USB 3.x,
- and we havn't handle the difference here */
- if ((hub->parent->speed == USB_SPEED_SUPER) ||
- (hub->parent->speed == USB_SPEED_SUPER_PLUS)) {
- setup->wValue = HUB_DESCRIPTOR_TYPE_HUB3 << 8;
- } else {
- setup->wValue = HUB_DESCRIPTOR_TYPE_HUB << 8;
- }
+ setup->wValue = HUB_DESCRIPTOR_TYPE_HUB << 8;
setup->wIndex = 0;
setup->wLength = USB_SIZEOF_HUB_DESC;
@@ -87,8 +77,8 @@ static int _usbh_hub_get_hub_descriptor(struct usbh_hub *hub, uint8_t *buffer)
memcpy(buffer, g_hub_buf[hub->bus->busid], USB_SIZEOF_HUB_DESC);
return ret;
}
-#if 0
-static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
+
+static int _usbh_hub_get_hub_ss_descriptor(struct usbh_hub *hub, uint8_t *buffer)
{
struct usb_setup_packet *setup;
int ret;
@@ -96,20 +86,20 @@ static int _usbh_hub_get_status(struct usbh_hub *hub, uint8_t *buffer)
setup = hub->parent->setup;
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_CLASS | USB_REQUEST_RECIPIENT_DEVICE;
- setup->bRequest = HUB_REQUEST_GET_STATUS;
- setup->wValue = 0;
+ setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
+ setup->wValue = HUB_DESCRIPTOR_TYPE_HUB3 << 8;
+
setup->wIndex = 0;
- setup->wLength = 2;
+ setup->wLength = USB_SIZEOF_HUB_SS_DESC;
ret = usbh_control_transfer(hub->parent, setup, g_hub_buf[hub->bus->busid]);
if (ret < 0) {
return ret;
}
- memcpy(buffer, g_hub_buf[hub->bus->busid], 2);
+ memcpy(buffer, g_hub_buf[hub->bus->busid], USB_SIZEOF_HUB_SS_DESC);
return ret;
}
#endif
-#endif
static int _usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
{
@@ -199,6 +189,27 @@ static int parse_hub_descriptor(struct usb_hub_descriptor *desc, uint16_t length
}
return 0;
}
+
+static int parse_hub_ss_descriptor(struct usb_hub_ss_descriptor *desc, uint16_t length)
+{
+ if (desc->bLength < USB_SIZEOF_HUB_SS_DESC) {
+ USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
+ return -1;
+ } else if (desc->bDescriptorType != HUB_DESCRIPTOR_TYPE_HUB3) {
+ USB_LOG_ERR("unexpected descriptor 0x%02x\r\n", desc->bDescriptorType);
+ return -2;
+ } else {
+ USB_LOG_RAW("SuperSpeed Hub Descriptor:\r\n");
+ USB_LOG_RAW("bLength: 0x%02x \r\n", desc->bLength);
+ USB_LOG_RAW("bDescriptorType: 0x%02x \r\n", desc->bDescriptorType);
+ USB_LOG_RAW("bNbrPorts: 0x%02x \r\n", desc->bNbrPorts);
+ USB_LOG_RAW("wHubCharacteristics: 0x%04x \r\n", desc->wHubCharacteristics);
+ USB_LOG_RAW("bPwrOn2PwrGood: 0x%02x \r\n", desc->bPwrOn2PwrGood);
+ USB_LOG_RAW("bHubContrCurrent: 0x%02x \r\n", desc->bHubContrCurrent);
+ USB_LOG_RAW("DeviceRemovable: 0x%02x \r\n", desc->DeviceRemovable);
+ }
+ return 0;
+}
#endif
static int usbh_hub_get_portstatus(struct usbh_hub *hub, uint8_t port, struct hub_port_status *port_status)
@@ -311,22 +322,65 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
hub->hub_addr = hport->dev_addr;
hub->parent = hport;
hub->bus = hport->bus;
+ hub->speed = hport->speed;
+ hport->self = hub;
hport->config.intf[intf].priv = hub;
- ret = _usbh_hub_get_hub_descriptor(hub, (uint8_t *)&hub->hub_desc);
- if (ret < 0) {
- return ret;
+ if (hport->depth > HUB_MAX_DEPTH) {
+ USB_LOG_ERR("Hub depth(%d) is overflow\r\n", hport->depth);
+ return -USB_ERR_INVAL;
}
- parse_hub_descriptor(&hub->hub_desc, USB_SIZEOF_HUB_DESC);
+ /*
+ * Super-Speed hubs need to know their depth to be able to
+ * parse the bits of the route-string that correspond to
+ * their downstream port number.
+ *
+ */
+ if ((hport->depth != 0) && (hport->speed == USB_SPEED_SUPER)) {
+ ret = usbh_hub_set_depth(hub, hport->depth - 1);
+ if (ret < 0) {
+ USB_LOG_ERR("Unable to set hub depth \r\n");
+ return ret;
+ }
+ }
- for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
+ /* Get hub descriptor. */
+ if (hport->speed == USB_SPEED_SUPER) {
+ ret = _usbh_hub_get_hub_ss_descriptor(hub, (uint8_t *)&hub->hub_ss_desc);
+ if (ret < 0) {
+ return ret;
+ }
+
+ parse_hub_ss_descriptor(&hub->hub_ss_desc, USB_SIZEOF_HUB_SS_DESC);
+ hub->nports = hub->hub_ss_desc.bNbrPorts;
+ hub->powerdelay = hub->hub_ss_desc.bPwrOn2PwrGood * 2;
+ hub->tt_think = 0U;
+ } else {
+ ret = _usbh_hub_get_hub_descriptor(hub, (uint8_t *)&hub->hub_desc);
+ if (ret < 0) {
+ return ret;
+ }
+
+ parse_hub_descriptor(&hub->hub_desc, USB_SIZEOF_HUB_DESC);
+ hub->nports = hub->hub_desc.bNbrPorts;
+ hub->powerdelay = hub->hub_desc.bPwrOn2PwrGood * 2;
+ hub->tt_think = ((hub->hub_desc.wHubCharacteristics & HUB_CHAR_TTTT_MASK) >> 5);
+ }
+
+ for (uint8_t port = 0; port < hub->nports; port++) {
hub->child[port].port = port + 1;
hub->child[port].parent = hub;
hub->child[port].bus = hport->bus;
}
+ if (hport->device_desc.bDeviceProtocol == HUB_PROTOCOL_MTT) {
+ hub->ismtt = 1;
+ } else {
+ hub->ismtt = 0;
+ }
+
ep_desc = &hport->config.intf[intf].altsetting[0].ep[0].ep_desc;
if (ep_desc->bEndpointAddress & 0x80) {
USBH_EP_INIT(hub->intin, ep_desc);
@@ -334,28 +388,16 @@ static int usbh_hub_connect(struct usbh_hubport *hport, uint8_t intf)
return -1;
}
- if (hport->speed == USB_SPEED_SUPER) {
- uint16_t depth = 0;
- struct usbh_hubport *parent = hport->parent->parent;
- while (parent) {
- depth++;
- parent = parent->parent->parent;
- }
-
- ret = usbh_hub_set_depth(hub, depth);
- if (ret < 0) {
- return ret;
- }
- }
-
- for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
+ for (uint8_t port = 0; port < hub->nports; port++) {
ret = usbh_hub_set_feature(hub, port + 1, HUB_PORT_FEATURE_POWER);
if (ret < 0) {
return ret;
}
}
- for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
+ usb_osal_msleep(hub->powerdelay);
+
+ for (uint8_t port = 0; port < hub->nports; port++) {
ret = usbh_hub_get_portstatus(hub, port + 1, &port_status);
USB_LOG_INFO("port %u, status:0x%02x, change:0x%02x\r\n", port + 1, port_status.wPortStatus, port_status.wPortChange);
if (ret < 0) {
@@ -395,7 +437,7 @@ static int usbh_hub_disconnect(struct usbh_hubport *hport, uint8_t intf)
usb_osal_timer_delete(hub->int_timer);
}
- for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
+ for (uint8_t port = 0; port < hub->nports; port++) {
child = &hub->child[port];
usbh_hubport_release(child);
child->parent = NULL;
@@ -415,7 +457,7 @@ static void usbh_hub_events(struct usbh_hub *hub)
{
struct usbh_hubport *child;
struct hub_port_status port_status;
- uint8_t portchange_index;
+ uint16_t portchange_index;
uint16_t portstatus;
uint16_t portchange;
uint16_t mask;
@@ -429,11 +471,10 @@ static void usbh_hub_events(struct usbh_hub *hub)
}
flags = usb_osal_enter_critical_section();
- portchange_index = hub->int_buffer[0];
- hub->int_buffer[0] &= ~portchange_index;
+ memcpy(&portchange_index, hub->int_buffer, 2);
usb_osal_leave_critical_section(flags);
- for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
+ for (uint8_t port = 0; port < hub->nports; port++) {
USB_LOG_DBG("Port change:0x%02x\r\n", portchange_index);
if (!(portchange_index & (1 << (port + 1)))) {
@@ -539,12 +580,23 @@ static void usbh_hub_events(struct usbh_hub *hub)
}
}
- if (portstatus & HUB_PORT_STATUS_HIGH_SPEED) {
- speed = USB_SPEED_HIGH;
- } else if (portstatus & HUB_PORT_STATUS_LOW_SPEED) {
- speed = USB_SPEED_LOW;
+ /*
+ * Figure out device speed. This is a bit tricky because
+ * HUB_PORT_STATUS_POWER_SS and HUB_PORT_STATUS_LOW_SPEED share the same bit.
+ */
+ if (portstatus & HUB_PORT_STATUS_POWER) {
+ if (portstatus & HUB_PORT_STATUS_HIGH_SPEED) {
+ speed = USB_SPEED_HIGH;
+ } else if (portstatus & HUB_PORT_STATUS_LOW_SPEED) {
+ speed = USB_SPEED_LOW;
+ } else {
+ speed = USB_SPEED_FULL;
+ }
+ } else if (portstatus & HUB_PORT_STATUS_POWER_SS) {
+ speed = USB_SPEED_SUPER;
} else {
- speed = USB_SPEED_FULL;
+ USB_LOG_WRN("Port %u does not enable power\r\n", port + 1);
+ continue;
}
child = &hub->child[port];
@@ -553,6 +605,7 @@ static void usbh_hub_events(struct usbh_hub *hub)
memset(child, 0, sizeof(struct usbh_hubport));
child->parent = hub;
+ child->depth = (hub->parent ? hub->parent->depth : 0) + 1;
child->connected = true;
child->port = port + 1;
child->speed = speed;
@@ -624,7 +677,7 @@ int usbh_hub_initialize(struct usbh_bus *bus)
hub->is_roothub = true;
hub->parent = NULL;
hub->hub_addr = 1;
- hub->hub_desc.bNbrPorts = CONFIG_USBHOST_MAX_RHPORTS;
+ hub->nports = CONFIG_USBHOST_MAX_RHPORTS;
hub->int_buffer = bus->hcd.roothub_intbuf;
hub->bus = bus;
@@ -652,7 +705,7 @@ int usbh_hub_deinitialize(struct usbh_bus *bus)
flags = usb_osal_enter_critical_section();
hub = &bus->hcd.roothub;
- for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
+ for (uint8_t port = 0; port < hub->nports; port++) {
hport = &hub->child[port];
usbh_hubport_release(hport);
diff --git a/class/hub/usbh_hub.h b/class/hub/usbh_hub.h
index 1f34c53b..dcce6606 100644
--- a/class/hub/usbh_hub.h
+++ b/class/hub/usbh_hub.h
@@ -10,10 +10,6 @@
struct usbh_hub;
-#define USBH_HUB_MAX_PORTS 4
-/* Maximum size of an interrupt IN transfer */
-#define USBH_HUB_INTIN_BUFSIZE ((USBH_HUB_MAX_PORTS + 8) >> 3)
-
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/core/usbh_core.c b/core/usbh_core.c
index d1fc769d..24964137 100644
--- a/core/usbh_core.c
+++ b/core/usbh_core.c
@@ -731,7 +731,7 @@ static void *usbh_list_all_interface_name(struct usbh_hub *hub, const char *devn
struct usbh_hub *hub_next;
void *priv;
- for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
+ for (uint8_t port = 0; port < hub->nports; port++) {
hport = &hub->child[port];
if (hport->connected) {
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
@@ -760,8 +760,9 @@ static void usbh_list_all_interface_driver(struct usbh_hub *hub)
{
struct usbh_hubport *hport;
struct usbh_hub *hub_next;
+ const char *speed_table[] = { "error-speed", "low-speed", "full-speed", "high-speed", "wireless-speed", "super-speed", "superplus-speed" };
- for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
+ for (uint8_t port = 0; port < hub->nports; port++) {
hport = &hub->child[port];
if (hport->connected) {
for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
@@ -770,11 +771,12 @@ static void usbh_list_all_interface_driver(struct usbh_hub *hub)
USB_LOG_RAW("\t");
}
- USB_LOG_RAW("|__Port %u, dev addr:0x%02x, If %u, ClassDriver=%s\r\n",
+ USB_LOG_RAW("|__Port %u, dev addr:0x%02x, If %u, ClassDriver=%s, %s\r\n",
hport->port,
hport->dev_addr,
itf,
- hport->config.intf[itf].class_driver->driver_name);
+ hport->config.intf[itf].class_driver->driver_name,
+ speed_table[hport->speed]);
if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) {
hub_next = hport->config.intf[itf].priv;
@@ -794,7 +796,7 @@ static void usbh_list_all_interface_desc(struct usbh_bus *bus, struct usbh_hub *
struct usbh_hubport *hport;
struct usbh_hub *hub_next;
- for (uint8_t port = 0; port < hub->hub_desc.bNbrPorts; port++) {
+ for (uint8_t port = 0; port < hub->nports; port++) {
hport = &hub->child[port];
if (hport->connected) {
USB_LOG_RAW("\r\nBus %u, Hub %u, Port %u, dev addr:0x%02x, VID:PID 0x%04x:0x%04x\r\n",
@@ -888,7 +890,7 @@ int lsusb(int argc, char **argv)
USB_LOG_RAW("/: Bus %u, Hub %u, ports=%u, is roothub\r\n",
bus->busid,
hub->index,
- hub->hub_desc.bNbrPorts);
+ hub->nports);
usbh_list_all_interface_driver(hub);
}
}
diff --git a/core/usbh_core.h b/core/usbh_core.h
index 32109885..ab805ec7 100644
--- a/core/usbh_core.h
+++ b/core/usbh_core.h
@@ -101,6 +101,9 @@ struct usbh_hubport {
uint8_t port; /* Hub port index */
uint8_t dev_addr; /* device address */
uint8_t speed; /* device speed */
+ uint8_t depth; /* distance from root hub */
+ uint8_t route; /* route string */
+ uint8_t slot_id; /* slot id */
struct usb_device_descriptor device_desc;
struct usbh_configuration config;
const char *iManufacturer;
@@ -109,6 +112,7 @@ struct usbh_hubport {
uint8_t *raw_config_desc;
struct usb_setup_packet *setup;
struct usbh_hub *parent;
+ struct usbh_hub *self; /* if this hubport is a hub */
struct usbh_bus *bus;
struct usb_endpoint_descriptor ep0;
struct usbh_urb ep0_urb;
@@ -120,7 +124,13 @@ struct usbh_hub {
bool is_roothub;
uint8_t index;
uint8_t hub_addr;
- struct usb_hub_descriptor hub_desc;
+ uint8_t speed;
+ uint8_t nports;
+ uint8_t powerdelay;
+ uint8_t tt_think;
+ bool ismtt;
+ struct usb_hub_descriptor hub_desc; /* USB 2.0 only */
+ struct usb_hub_ss_descriptor hub_ss_desc; /* USB 3.0 only */
struct usbh_hubport child[CONFIG_USBHOST_MAX_EHPORTS];
struct usbh_hubport *parent;
struct usbh_bus *bus;
@@ -145,7 +155,7 @@ struct usbh_devaddr_map {
struct usbh_hcd {
uint32_t reg_base;
uint8_t hcd_id;
- uint8_t roothub_intbuf[1];
+ uint8_t roothub_intbuf[2]; /* at most 15 roothub ports */
struct usbh_hub roothub;
};