Skip to content

Commit b46bfac

Browse files
committed
subsys: usb: host: support multiple devices under hub
1. When hub is used, need to consider about multiple devices are attached. Remove the root member of usbh_context. 2. Add usbh_device_get_root and usbh_device_is_root function to check root device. Signed-off-by: Aiden Hu <[email protected]>
1 parent 0473e94 commit b46bfac

File tree

4 files changed

+69
-23
lines changed

4 files changed

+69
-23
lines changed

include/zephyr/usb/usbh.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,6 @@ struct usbh_context {
5858
struct usbh_status status;
5959
/** USB device list */
6060
sys_dlist_t udevs;
61-
/** USB root device */
62-
struct usb_device *root;
6361
/** Allocated device addresses bit array */
6462
struct sys_bitarray *addr_ba;
6563
};

subsys/usb/host/usbh_core.c

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -50,44 +50,52 @@ static void dev_connected_handler(struct usbh_context *const ctx,
5050
const struct uhc_event *const event)
5151
{
5252
int ret;
53+
struct usb_device *udev;
5354

5455
LOG_DBG("Device connected event");
55-
if (ctx->root != NULL) {
56-
LOG_ERR("Device already connected");
57-
usbh_device_free(ctx->root);
58-
ctx->root = NULL;
59-
}
6056

61-
ctx->root = usbh_device_alloc(ctx);
62-
if (ctx->root == NULL) {
57+
udev = usbh_device_alloc(ctx);
58+
if (udev == NULL) {
6359
LOG_ERR("Failed allocate new device");
6460
return;
6561
}
6662

67-
ctx->root->state = USB_STATE_DEFAULT;
63+
udev->state = USB_STATE_DEFAULT;
6864

6965
if (event->type == UHC_EVT_DEV_CONNECTED_HS) {
70-
ctx->root->speed = USB_SPEED_SPEED_HS;
66+
udev->speed = USB_SPEED_SPEED_HS;
7167
} else {
72-
ctx->root->speed = USB_SPEED_SPEED_FS;
68+
udev->speed = USB_SPEED_SPEED_FS;
7369
}
7470

75-
if (usbh_device_init(ctx->root)) {
71+
k_mutex_lock(&ctx->mutex, K_FOREVER);
72+
sys_dlist_append(&ctx->udevs, &udev->node);
73+
k_mutex_unlock(&ctx->mutex);
74+
75+
if (usbh_device_init(udev)) {
7676
LOG_ERR("Failed to reset new USB device");
77+
sys_dlist_remove(&udev->node);
7778
}
7879

79-
ret = usbh_class_probe_all(ctx->root);
80+
ret = usbh_class_probe_all(udev);
8081
if (ret != 0) {
8182
LOG_ERR("Failed to probe classes for this new USB device, %d", ret);
8283
}
8384
}
8485

8586
static void dev_removed_handler(struct usbh_context *const ctx)
8687
{
87-
if (ctx->root != NULL) {
88-
usbh_class_remove_all(ctx->root);
89-
usbh_device_free(ctx->root);
90-
ctx->root = NULL;
88+
struct usb_device *udev = NULL;
89+
90+
udev = usbh_device_get_root(ctx);
91+
if (udev != NULL) {
92+
usbh_class_remove_all(udev);
93+
94+
k_mutex_lock(&ctx->mutex, K_FOREVER);
95+
sys_dlist_remove(&udev->node);
96+
k_mutex_unlock(&ctx->mutex);
97+
98+
usbh_device_free(udev);
9199
LOG_DBG("Device removed");
92100
} else {
93101
LOG_DBG("Spurious device removed event");

subsys/usb/host/usbh_device.c

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -447,10 +447,39 @@ int usbh_device_set_configuration(struct usb_device *const udev, const uint8_t n
447447
return err;
448448
}
449449

450+
struct usb_device *usbh_device_get_root(struct usbh_context *const ctx)
451+
{
452+
sys_dnode_t *node;
453+
454+
if (ctx == NULL) {
455+
return NULL;
456+
}
457+
458+
node = sys_dlist_peek_head(&ctx->udevs);
459+
if (node == NULL) {
460+
/* No devices in the list */
461+
return NULL;
462+
}
463+
464+
/* Get the usb_device structure from the node */
465+
return CONTAINER_OF(node, struct usb_device, node);
466+
}
467+
468+
bool usbh_device_is_root(struct usbh_context *const ctx,
469+
struct usb_device *const udev)
470+
{
471+
if (ctx == NULL || udev == NULL) {
472+
return false;
473+
}
474+
475+
return sys_dlist_peek_head(&ctx->udevs) == &udev->node;
476+
}
477+
450478
int usbh_device_init(struct usb_device *const udev)
451479
{
452480
struct usbh_context *const uhs_ctx = udev->ctx;
453481
uint8_t new_addr;
482+
uint8_t device_count = 0;
454483
int err;
455484

456485
if (udev->state != USB_STATE_DEFAULT) {
@@ -464,11 +493,15 @@ int usbh_device_init(struct usb_device *const udev)
464493
return err;
465494
}
466495

467-
/* FIXME: The port to which the device is connected should be reset. */
468-
err = uhc_bus_reset(uhs_ctx->dev);
469-
if (err) {
470-
LOG_ERR("Failed to signal bus reset");
471-
return err;
496+
device_count = sys_dlist_len(&uhs_ctx->udevs);
497+
498+
/* Only reset bus if this is the root device. */
499+
if (device_count == 1U) {
500+
err = uhc_bus_reset(uhs_ctx->dev);
501+
if (err) {
502+
LOG_ERR("Failed to signal bus reset");
503+
return err;
504+
}
472505
}
473506

474507
/*

subsys/usb/host/usbh_device.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ int usbh_device_interface_set(struct usb_device *const udev,
3636
const uint8_t iface, const uint8_t alt,
3737
const bool dry);
3838

39+
/* Get root USB device */
40+
struct usb_device *usbh_device_get_root(struct usbh_context *const ctx);
41+
42+
/* Check if USB device is root */
43+
bool usbh_device_is_root(struct usbh_context *const ctx,
44+
struct usb_device *const udev);
45+
3946
/* Wrappers around to avoid glue UHC calls. */
4047
static inline struct uhc_transfer *usbh_xfer_alloc(struct usb_device *udev,
4148
const uint8_t ep,

0 commit comments

Comments
 (0)