From 8785093a2f7328bbad79367cca83bb349ddb7a46 Mon Sep 17 00:00:00 2001 From: Aiden Hu Date: Tue, 18 Nov 2025 22:12:25 +0800 Subject: [PATCH 1/2] subsys: usb: host: support multiple devices under hub When hub is used, need to consider about multiple devices are attached. Signed-off-by: Aiden Hu --- subsys/usb/host/usbh_core.c | 27 ++++++++++++++++----------- subsys/usb/host/usbh_device.c | 18 +++++++++++++----- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/subsys/usb/host/usbh_core.c b/subsys/usb/host/usbh_core.c index 1b654b5041133..834139a83bbac 100644 --- a/subsys/usb/host/usbh_core.c +++ b/subsys/usb/host/usbh_core.c @@ -46,30 +46,35 @@ static int usbh_event_carrier(const struct device *dev, static void dev_connected_handler(struct usbh_context *const ctx, const struct uhc_event *const event) { + struct usb_device *udev; LOG_DBG("Device connected event"); - if (ctx->root != NULL) { - LOG_ERR("Device already connected"); - usbh_device_free(ctx->root); - ctx->root = NULL; - } - ctx->root = usbh_device_alloc(ctx); - if (ctx->root == NULL) { + udev = usbh_device_alloc(ctx); + if (udev == NULL) { LOG_ERR("Failed allocate new device"); return; } - ctx->root->state = USB_STATE_DEFAULT; + udev->state = USB_STATE_DEFAULT; if (event->type == UHC_EVT_DEV_CONNECTED_HS) { - ctx->root->speed = USB_SPEED_SPEED_HS; + udev->speed = USB_SPEED_SPEED_HS; } else { - ctx->root->speed = USB_SPEED_SPEED_FS; + udev->speed = USB_SPEED_SPEED_FS; + } + + k_mutex_lock(&ctx->mutex, K_FOREVER); + sys_dlist_append(&ctx->udevs, &udev->node); + + if (ctx->root == NULL) { + ctx->root = udev; } + k_mutex_unlock(&ctx->mutex); - if (usbh_device_init(ctx->root)) { + if (usbh_device_init(udev)) { LOG_ERR("Failed to reset new USB device"); + sys_dlist_remove(&udev->node); } } diff --git a/subsys/usb/host/usbh_device.c b/subsys/usb/host/usbh_device.c index 92ecf6ae7aee1..f4fa245bb4b72 100644 --- a/subsys/usb/host/usbh_device.c +++ b/subsys/usb/host/usbh_device.c @@ -452,6 +452,8 @@ int usbh_device_init(struct usb_device *const udev) struct usbh_context *const uhs_ctx = udev->ctx; uint8_t new_addr; int err; + sys_dnode_t *node; + uint8_t device_count = 0; if (udev->state != USB_STATE_DEFAULT) { LOG_ERR("USB device is not in default state"); @@ -464,11 +466,17 @@ int usbh_device_init(struct usb_device *const udev) return err; } - /* FIXME: The port to which the device is connected should be reset. */ - err = uhc_bus_reset(uhs_ctx->dev); - if (err) { - LOG_ERR("Failed to signal bus reset"); - return err; + k_mutex_lock(&uhs_ctx->mutex, K_FOREVER); + device_count = sys_dlist_len(&uhs_ctx->udevs); + k_mutex_unlock(&uhs_ctx->mutex); + + /* Only reset bus if this is the root device. */ + if (device_count == 1U) { + err = uhc_bus_reset(uhs_ctx->dev); + if (err) { + LOG_ERR("Failed to signal bus reset"); + return err; + } } /* From 4f2a48f002263d1ee1e683c81c0c3c790758641a Mon Sep 17 00:00:00 2001 From: Aiden Hu Date: Wed, 19 Nov 2025 20:23:12 +0800 Subject: [PATCH 2/2] subsys: usb: host: remove root member for usbh_context add usbh_device_get_root and usbh_device_is_root function to check root device Signed-off-by: Aiden Hu --- include/zephyr/usb/usbh.h | 2 -- subsys/usb/host/usbh_core.c | 18 ++++++++++-------- subsys/usb/host/usbh_device.c | 20 ++++++++++++++++++++ subsys/usb/host/usbh_device.h | 7 +++++++ 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/include/zephyr/usb/usbh.h b/include/zephyr/usb/usbh.h index e2e6f3074000e..748da72b19027 100644 --- a/include/zephyr/usb/usbh.h +++ b/include/zephyr/usb/usbh.h @@ -45,8 +45,6 @@ struct usbh_context { const struct device *dev; /** USB device list */ sys_dlist_t udevs; - /** USB root device */ - struct usb_device *root; /** Allocated device addresses bit array */ struct sys_bitarray *addr_ba; }; diff --git a/subsys/usb/host/usbh_core.c b/subsys/usb/host/usbh_core.c index 834139a83bbac..18d02b9ff0610 100644 --- a/subsys/usb/host/usbh_core.c +++ b/subsys/usb/host/usbh_core.c @@ -46,6 +46,7 @@ static int usbh_event_carrier(const struct device *dev, static void dev_connected_handler(struct usbh_context *const ctx, const struct uhc_event *const event) { + int err; struct usb_device *udev; LOG_DBG("Device connected event"); @@ -66,13 +67,10 @@ static void dev_connected_handler(struct usbh_context *const ctx, k_mutex_lock(&ctx->mutex, K_FOREVER); sys_dlist_append(&ctx->udevs, &udev->node); - - if (ctx->root == NULL) { - ctx->root = udev; - } k_mutex_unlock(&ctx->mutex); - if (usbh_device_init(udev)) { + err = usbh_device_init(udev); + if (ret != 0) { LOG_ERR("Failed to reset new USB device"); sys_dlist_remove(&udev->node); } @@ -80,13 +78,17 @@ static void dev_connected_handler(struct usbh_context *const ctx, static void dev_removed_handler(struct usbh_context *const ctx) { - if (ctx->root != NULL) { - usbh_device_free(ctx->root); - ctx->root = NULL; + struct usb_device *udev = NULL; + + udev = usbh_device_get_root(ctx); + + if (NULL != udev) { + usbh_device_free(udev); LOG_DBG("Device removed"); } else { LOG_DBG("Spurious device removed event"); } + /* TODO: handle remove for all of classes for the unattached device */ } static int discard_ep_request(struct usbh_context *const ctx, diff --git a/subsys/usb/host/usbh_device.c b/subsys/usb/host/usbh_device.c index f4fa245bb4b72..1da536a5d9e42 100644 --- a/subsys/usb/host/usbh_device.c +++ b/subsys/usb/host/usbh_device.c @@ -447,6 +447,26 @@ int usbh_device_set_configuration(struct usb_device *const udev, const uint8_t n return err; } +struct usb_device *usbh_device_get_root(struct usbh_context *const ctx) +{ + sys_dnode_t *node; + + node = sys_dlist_peek_head(&ctx->udevs); + if (node == NULL) { + /* No devices in the list */ + return NULL; + } + + /* Get the usb_device structure from the node */ + return CONTAINER_OF(node, struct usb_device, node); +} + +bool usbh_device_is_root(struct usbh_context *const ctx, + struct usb_device *const udev) +{ + return sys_dlist_peek_head(&ctx->udevs) == &udev->node; +} + int usbh_device_init(struct usb_device *const udev) { struct usbh_context *const uhs_ctx = udev->ctx; diff --git a/subsys/usb/host/usbh_device.h b/subsys/usb/host/usbh_device.h index 5c5637fb0bee8..d45257c58b975 100644 --- a/subsys/usb/host/usbh_device.h +++ b/subsys/usb/host/usbh_device.h @@ -36,6 +36,13 @@ int usbh_device_interface_set(struct usb_device *const udev, const uint8_t iface, const uint8_t alt, const bool dry); +/* Get root USB device */ +struct usb_device *usbh_device_get_root(struct usbh_context *const ctx); + +/* Check if USB device is root */ +bool usbh_device_is_root(struct usbh_context *const ctx, + struct usb_device *const udev); + /* Wrappers around to avoid glue UHC calls. */ static inline struct uhc_transfer *usbh_xfer_alloc(struct usb_device *udev, const uint8_t ep,