Skip to content
Draft
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
8 changes: 5 additions & 3 deletions host/usb/include/usb/usb_types_stack.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
Expand Down Expand Up @@ -74,8 +74,10 @@ typedef bool (*usb_host_enum_filter_cb_t)(const usb_device_desc_t *dev_desc, uin
* @brief Parent device information
*/
typedef struct {
usb_device_handle_t dev_hdl; /**< Device's parent handle */
uint8_t port_num; /**< Device's parent port number */
// IDF-12502: Remove the parent dev_hdl from parent_info structure (breaking change)
usb_device_handle_t dev_hdl __attribute__((deprecated)); /**< Device's parent handle: Deprecated, as dev_hdl only valid when device was opened via usbh_devs_open() */
uint8_t dev_addr; /**< Device's parent bus address */
uint8_t port_num; /**< Device's parent port number */
} usb_parent_dev_info_t;

/**
Expand Down
15 changes: 15 additions & 0 deletions host/usb/private_include/ext_hub.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,21 @@ void *ext_hub_get_client(void);
*/
esp_err_t ext_hub_get_speed(ext_hub_handle_t ext_hub_hdl, usb_speed_t *speed);

/**
* @brief Get the External Hub device USB address
*
* @note Device should be in list of devices
*
* @paramp[in] ext_hub_hdl External Hub device handle
* @param[out] addr USB address
* @return
* - ESP_ERR_NOT_ALLOWED if the External Hub driver is not installed
* - ESP_ERR_INVALID_ARG if the handle or addr is NULL
* - ESP_ERR_NOT_FOUND if the device is not found
* - ESP_OK if the address was obtained
*/
esp_err_t ext_hub_get_dev_addr(ext_hub_handle_t ext_hub_hdl, uint8_t *addr);

/**
* @brief Add new device
*
Expand Down
16 changes: 16 additions & 0 deletions host/usb/private_include/hub.h
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,22 @@ esp_err_t hub_node_active(unsigned int node_uid);
*/
esp_err_t hub_node_disable(unsigned int node_uid);

/**
* @brief Get the node information of the device
*
* @note This function should only be called from the Host Library task
*
* @param[in] node_uid Device's node unique ID
* @param[out] info Device information
*
* @return
* - ESP_ERR_INVALID_STATE if the Hub driver is not installed
* - ESP_ERR_INVALID_ARG if the info pointer is NULL
* - ESP_ERR_NOT_FOUND if the device node is not found
* - ESP_OK if device's information obtained successfully
*/
esp_err_t hub_node_get_info(unsigned int node_uid, usb_parent_dev_info_t *info);

/**
* @brief Notify Hub driver that new device has been attached
*
Expand Down
33 changes: 14 additions & 19 deletions host/usb/private_include/usbh.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ typedef struct {
} dev_gone_data;
struct {
unsigned int dev_uid;
usb_device_handle_t parent_dev_hdl;
uint8_t port_num;
} dev_free_data;
};
} usbh_event_data_t;
Expand Down Expand Up @@ -139,8 +137,6 @@ typedef struct {
unsigned int uid; /**< Unique ID assigned to the device */
usb_speed_t speed; /**< Device's speed */
hcd_port_handle_t root_port_hdl; /**< Handle of the port that the device is connected to */
usb_device_handle_t parent_dev_hdl; /**< Parent's device handle */
uint8_t parent_port_num; /**< Parent's port number */
} usbh_dev_params_t;

// ---------------------- USBH Processing Functions ----------------------------
Expand Down Expand Up @@ -269,21 +265,6 @@ esp_err_t usbh_devs_add(usbh_dev_params_t *params);
*/
esp_err_t usbh_devs_remove(unsigned int uid);

/**
* @brief Get a device's connection information
*
* @note Can be called without opening the device
*
* @param[in] uid Unique ID assigned to the device
* @param[out] parent_info Parent device handle
*
* @return
* - ESP_OK: Device parent info obtained successfully
* - ESP_ERR_INVALID_ARG: Invalid argument
* - ESP_ERR_NOT_FOUND: Device with provided uid not found
*/
esp_err_t usbh_devs_get_parent_info(unsigned int uid, usb_parent_dev_info_t *parent_info);

/**
* @brief Mark that all devices should be freed at the next possible opportunity
*
Expand Down Expand Up @@ -342,6 +323,20 @@ esp_err_t usbh_devs_new_dev_event(usb_device_handle_t dev_hdl);
esp_err_t usbh_dev_close(usb_device_handle_t dev_hdl);

// ------------------------------ Getters --------------------------------------
/**
* @brief Get a device's UID
*
* @note Callers of this function must have opened the device via usbh_devs_open()
*
* @param[in] dev_hdl Device handle
* @param[out] uid Device's UID
*
* @return
* - ESP_ERR_INVALID_ARG if invalid argument
* - ESP_OK if Device's UID obtained successfully
*/
esp_err_t usbh_dev_get_uid(usb_device_handle_t dev_hdl, unsigned int *uid);

/**
* @brief Get a device's address
*
Expand Down
12 changes: 12 additions & 0 deletions host/usb/src/ext_hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -1298,6 +1298,18 @@ esp_err_t ext_hub_get_speed(ext_hub_handle_t ext_hub_hdl, usb_speed_t *speed)
return ESP_OK;
}

esp_err_t ext_hub_get_dev_addr(ext_hub_handle_t ext_hub_hdl, uint8_t *addr)
{
EXT_HUB_ENTER_CRITICAL();
EXT_HUB_CHECK_FROM_CRIT(p_ext_hub_driver != NULL, ESP_ERR_NOT_ALLOWED);
EXT_HUB_EXIT_CRITICAL();
EXT_HUB_CHECK(ext_hub_hdl != NULL && addr != NULL, ESP_ERR_INVALID_ARG);
EXT_HUB_CHECK(dev_is_in_list(ext_hub_hdl), ESP_ERR_NOT_FOUND);
ext_hub_dev_t *ext_hub_dev = (ext_hub_dev_t *)ext_hub_hdl;
*addr = ext_hub_dev->constant.dev_addr;
return ESP_OK;
}

esp_err_t ext_hub_new_dev(uint8_t dev_addr)
{
EXT_HUB_ENTER_CRITICAL();
Expand Down
59 changes: 42 additions & 17 deletions host/usb/src/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,8 @@
} flags; /**< Hub flags */
root_port_state_t root_port_state; /**< Root port state */
unsigned int port_reqs; /**< Root port request flag */
} dynamic; /**< Dynamic members. Require a critical section */

struct {
TAILQ_HEAD(tailhead_devs, dev_tree_node_s) dev_nodes_tailq; /**< Tailq of attached devices */
} single_thread; /**< Single thread members don't require a critical section so long as they are never accessed from multiple threads */
} dynamic; /**< Dynamic members. Require a critical section */

struct {
hcd_port_handle_t root_port_hdl; /**< Root port HCD handle */
Expand Down Expand Up @@ -150,12 +147,14 @@
dev_tree_node_t *dev_tree_node = NULL;
dev_tree_node_t *dev_tree_iter;
// Search the device tree nodes list for a device node with the specified parent
TAILQ_FOREACH(dev_tree_iter, &p_hub_driver_obj->single_thread.dev_nodes_tailq, tailq_entry) {
HUB_DRIVER_ENTER_CRITICAL();
TAILQ_FOREACH(dev_tree_iter, &p_hub_driver_obj->dynamic.dev_nodes_tailq, tailq_entry) {
if (dev_tree_iter->uid == node_uid) {
dev_tree_node = dev_tree_iter;
break;
}
}
HUB_DRIVER_EXIT_CRITICAL();
return dev_tree_node;
}

Expand Down Expand Up @@ -190,19 +189,16 @@
.uid = dev_tree_node->uid,
.speed = speed,
.root_port_hdl = p_hub_driver_obj->constant.root_port_hdl, // Always the same for all devices
// TODO: IDF-10023 Move parent-child tree management responsibility to Hub Driver
.parent_dev_hdl = NULL,
.parent_port_num = port_num,
};

ret = usbh_devs_add(&params);
if (ret != ESP_OK) {
// Device registration may fail if there are no available HCD channels.
goto fail;
}

TAILQ_INSERT_TAIL(&p_hub_driver_obj->single_thread.dev_nodes_tailq, dev_tree_node, tailq_entry);

HUB_DRIVER_ENTER_CRITICAL();
TAILQ_INSERT_TAIL(&p_hub_driver_obj->dynamic.dev_nodes_tailq, dev_tree_node, tailq_entry);
HUB_DRIVER_EXIT_CRITICAL();
ESP_LOGD(HUB_DRIVER_TAG, "Device tree node (port %d, uid %d): new", dev_tree_node->port_num, dev_tree_node->uid);

hub_event_data_t event_data = {
Expand All @@ -225,13 +221,15 @@
dev_tree_node_t *dev_tree_node = NULL;
dev_tree_node_t *dev_tree_iter;
// Search the device tree nodes list for a device node with the specified parent
TAILQ_FOREACH(dev_tree_iter, &p_hub_driver_obj->single_thread.dev_nodes_tailq, tailq_entry) {
HUB_DRIVER_ENTER_CRITICAL();
TAILQ_FOREACH(dev_tree_iter, &p_hub_driver_obj->dynamic.dev_nodes_tailq, tailq_entry) {
if (dev_tree_iter->parent == parent &&
dev_tree_iter->port_num == port_num) {
dev_tree_node = dev_tree_iter;
break;
}
}
HUB_DRIVER_EXIT_CRITICAL();

if (dev_tree_node == NULL) {
ESP_LOGE(HUB_DRIVER_TAG, "Reset completed, but device tree node (port %d) not found", port_num);
Expand All @@ -253,13 +251,15 @@
dev_tree_node_t *dev_tree_node = NULL;
dev_tree_node_t *dev_tree_iter;
// Search the device tree nodes list for a device node with the specified parent
TAILQ_FOREACH(dev_tree_iter, &p_hub_driver_obj->single_thread.dev_nodes_tailq, tailq_entry) {
HUB_DRIVER_ENTER_CRITICAL();
TAILQ_FOREACH(dev_tree_iter, &p_hub_driver_obj->dynamic.dev_nodes_tailq, tailq_entry) {
if (dev_tree_iter->parent == parent &&
dev_tree_iter->port_num == port_num) {
dev_tree_node = dev_tree_iter;
break;
}
}
HUB_DRIVER_EXIT_CRITICAL();

if (dev_tree_node == NULL) {
ESP_LOGW(HUB_DRIVER_TAG, "Device tree node (port %d): not found", port_num);
Expand Down Expand Up @@ -289,22 +289,25 @@
dev_tree_node_t *dev_tree_node = NULL;
dev_tree_node_t *dev_tree_iter;
// Search the device tree nodes list for a device node with the specified parent
TAILQ_FOREACH(dev_tree_iter, &p_hub_driver_obj->single_thread.dev_nodes_tailq, tailq_entry) {
HUB_DRIVER_ENTER_CRITICAL();
TAILQ_FOREACH(dev_tree_iter, &p_hub_driver_obj->dynamic.dev_nodes_tailq, tailq_entry) {
if (dev_tree_iter->parent == parent &&
dev_tree_iter->port_num == port_num) {
dev_tree_node = dev_tree_iter;
break;
}
}
if (dev_tree_node) {
TAILQ_REMOVE(&p_hub_driver_obj->dynamic.dev_nodes_tailq, dev_tree_node, tailq_entry);
}
HUB_DRIVER_EXIT_CRITICAL();

if (dev_tree_node == NULL) {
ESP_LOGW(HUB_DRIVER_TAG, "Device tree node (port %d): not found", port_num);
return ESP_ERR_NOT_FOUND;
}

ESP_LOGD(HUB_DRIVER_TAG, "Device tree node (port %d, uid %d): freeing", port_num, dev_tree_node->uid);

TAILQ_REMOVE(&p_hub_driver_obj->single_thread.dev_nodes_tailq, dev_tree_node, tailq_entry);
heap_caps_free(dev_tree_node);
return ESP_OK;
}
Expand Down Expand Up @@ -596,8 +599,8 @@
hub_driver_obj->constant.proc_req_cb_arg = hub_config->proc_req_cb_arg;
hub_driver_obj->constant.event_cb = hub_config->event_cb;
hub_driver_obj->constant.event_cb_arg = hub_config->event_cb_arg;
TAILQ_INIT(&hub_driver_obj->single_thread.dev_nodes_tailq);
// Driver is not installed, we can modify dynamic section outside of the critical section
TAILQ_INIT(&hub_driver_obj->dynamic.dev_nodes_tailq);
hub_driver_obj->dynamic.root_port_state = ROOT_PORT_STATE_NOT_POWERED;

HUB_DRIVER_ENTER_CRITICAL();
Expand Down Expand Up @@ -795,6 +798,28 @@
return ret;
}

esp_err_t hub_node_get_info(unsigned int node_uid, usb_parent_dev_info_t *parent_info)
{
HUB_DRIVER_ENTER_CRITICAL();
HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj != NULL, ESP_ERR_INVALID_STATE);
HUB_DRIVER_EXIT_CRITICAL();
HUB_DRIVER_CHECK(parent_info != NULL, ESP_ERR_INVALID_ARG);

dev_tree_node_t *dev_tree_node = dev_tree_node_get_by_uid(node_uid);
HUB_DRIVER_CHECK(dev_tree_node != NULL, ESP_ERR_NOT_FOUND);
uint8_t parent_dev_addr = 0;
#if (ENABLE_USB_HUBS)
if (dev_tree_node->parent) {
ESP_ERROR_CHECK(ext_hub_get_dev_addr((ext_hub_handle_t) dev_tree_node->parent, &parent_dev_addr));
}
#endif // ENABLE_USB_HUBS

memset(parent_info, 0, sizeof(usb_parent_dev_info_t));

Check warning

Code scanning / clang-tidy

Call to function 'memset' is insecure as it does not provide security checks introduced in the C11 standard. Replace with analogous functions that support length arguments or provides boundary checks such as 'memset_s' in case of C11 [clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling] Warning

Call to function 'memset' is insecure as it does not provide security checks introduced in the C11 standard. Replace with analogous functions that support length arguments or provides boundary checks such as 'memset_s' in case of C11 [clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling]
parent_info->dev_addr = parent_dev_addr;
parent_info->port_num = dev_tree_node->port_num;
return ESP_OK;
}

esp_err_t hub_dev_new(uint8_t dev_addr)
{
HUB_DRIVER_ENTER_CRITICAL();
Expand Down
10 changes: 10 additions & 0 deletions host/usb/src/usb_host.c
Original file line number Diff line number Diff line change
Expand Up @@ -1094,7 +1094,17 @@ esp_err_t usb_host_device_addr_list_fill(int list_len, uint8_t *dev_addr_list, i

esp_err_t usb_host_device_info(usb_device_handle_t dev_hdl, usb_device_info_t *dev_info)
{
unsigned int uid;
HOST_CHECK(dev_hdl != NULL && dev_info != NULL, ESP_ERR_INVALID_ARG);
esp_err_t ret;

ESP_ERROR_CHECK(usbh_dev_get_uid(dev_hdl, &uid));

ret = hub_node_get_info(uid, &dev_info->parent);
if (ret != ESP_OK) {
ESP_LOGE(USB_HOST_TAG, "Unable to get dev tree node info, parent information not available");
return ret;
}
return usbh_dev_get_info(dev_hdl, dev_info);
}

Expand Down
Loading
Loading