Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions include/zephyr/usb/usbh.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down
35 changes: 21 additions & 14 deletions subsys/usb/host/usbh_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,42 +46,49 @@
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");
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;
}

if (usbh_device_init(ctx->root)) {
k_mutex_lock(&ctx->mutex, K_FOREVER);
sys_dlist_append(&ctx->udevs, &udev->node);
k_mutex_unlock(&ctx->mutex);

err = usbh_device_init(udev);
if (ret != 0) {
LOG_ERR("Failed to reset new USB device");
sys_dlist_remove(&udev->node);
}
}

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) {

Check warning on line 85 in subsys/usb/host/usbh_core.c

View workflow job for this annotation

GitHub Actions / Run compliance checks on patch series (PR)

CONSTANT_COMPARISON

subsys/usb/host/usbh_core.c:85 Comparisons should place the constant on the right side of the test
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,
Expand Down
38 changes: 33 additions & 5 deletions subsys/usb/host/usbh_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -447,11 +447,33 @@
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;
uint8_t new_addr;
int err;
sys_dnode_t *node;

Check warning on line 475 in subsys/usb/host/usbh_device.c

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

unused variable 'node'

See more on https://sonarcloud.io/project/issues?id=zephyrproject-rtos_zephyr&issues=AZqcEQx4GE3FdZDlQzPc&open=AZqcEQx4GE3FdZDlQzPc&pullRequest=99591
uint8_t device_count = 0;

if (udev->state != USB_STATE_DEFAULT) {
LOG_ERR("USB device is not in default state");
Expand All @@ -464,11 +486,17 @@
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;
}
Comment on lines +494 to +499
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about PORT_RESET hub class feature? Where this should be handled? At high-level Linux solves the issue by having a software-only hub at the top level.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about PORT_RESET hub class feature? Where this should be handled? At high-level Linux solves the issue by having a software-only hub at the top level.

Hi @tmon-nordic
The PORT_RESET of HUB is handled by a set feature request. This is handled in hub class layer. Actually I have finished the first version USB hub class and tested in my local project. Recently I will created one PR about it.

}

/*
Expand Down
7 changes: 7 additions & 0 deletions subsys/usb/host/usbh_device.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Loading