From 37de6d7465ebea4001cc5dcef51c948c8cbc53f6 Mon Sep 17 00:00:00 2001 From: Roman Leonov Date: Fri, 14 Feb 2025 11:47:13 +0100 Subject: [PATCH] refactor(enum): Removed parent_dev_hdl and parent_port_num, replaced with node uid --- host/usb/private_include/enum.h | 30 ++------- host/usb/private_include/hub.h | 49 +++++++-------- host/usb/src/enum.c | 105 ++++++++------------------------ host/usb/src/hub.c | 62 +++++++++++++------ host/usb/src/usb_host.c | 16 +++-- 5 files changed, 104 insertions(+), 158 deletions(-) diff --git a/host/usb/private_include/enum.h b/host/usb/private_include/enum.h index 59b708d5..e4adc382 100644 --- a/host/usb/private_include/enum.h +++ b/host/usb/private_include/enum.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2024-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -44,31 +44,9 @@ typedef enum { } enum_event_t; typedef struct { - enum_event_t event; /**< Enumerator driver event */ - union { - struct { - unsigned int uid; /**< Device unique ID */ - usb_device_handle_t parent_dev_hdl; /**< Parent of the enumerating device */ - uint8_t parent_port_num; /**< Parent port number of the enumerating device */ - } started; /**< ENUM_EVENT_STARTED specific data */ - - struct { - usb_device_handle_t parent_dev_hdl; /**< Parent of the enumerating device */ - uint8_t parent_port_num; /**< Parent port number of the enumerating device */ - } reset_req; /**< ENUM_EVENT_RESET_REQUIRED specific data */ - - struct { - usb_device_handle_t parent_dev_hdl; /**< Parent of the enumerating device */ - uint8_t parent_port_num; /**< Parent port number of the enumerating device */ - usb_device_handle_t dev_hdl; /**< Handle of the enumerating device */ - uint8_t dev_addr; /**< Address of the enumerating device */ - } complete; /**< ENUM_EVENT_COMPLETED specific data */ - - struct { - usb_device_handle_t parent_dev_hdl; /**< Parent of the enumerating device */ - uint8_t parent_port_num; /**< Parent port number of the enumerating device */ - } canceled; /**< ENUM_EVENT_CANCELED specific data */ - }; + enum_event_t event; /**< Enumerator driver event */ + unsigned int node_uid; /**< Unique node ID */ + usb_device_handle_t dev_hdl; /**< Handle of the enumerating device */ } enum_event_data_t; // ---------------------------- Callbacks -------------------------------------- diff --git a/host/usb/private_include/hub.h b/host/usb/private_include/hub.h index e47e11c1..5bb8c784 100644 --- a/host/usb/private_include/hub.h +++ b/host/usb/private_include/hub.h @@ -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 */ @@ -131,66 +131,67 @@ esp_err_t hub_root_stop(void); /** * @brief Indicate to the Hub driver that a device's port can be recycled * - * The device connected to the port has been freed. The Hub driver can now recycled the port + * The device connected to the port has been freed. + * The Hub driver can now recycle the port, related to the node. * * @note This function should only be called from the Host Library task * - * @param[in] parent_dev_hdl Parent device handle (is used to get the External Hub handle) - * @param[in] parent_port_num Parent number (is used to specify the External Port) - * @param[in] dev_uid Device's unique ID + * @param[in] node_uid Device's node unique ID * * @return - * - ESP_OK: device's port can be recycled + * - ESP_OK: Device's port can be recycled * - ESP_ERR_INVALID_STATE: Hub driver is not installed * - ESP_ERR_NOT_SUPPORTED: Recycling External Port is not available (External Hub support disabled), * or ext hub port error + * - ESP_ERR_NOT_FOUND: Device's node is not found */ -esp_err_t hub_port_recycle(usb_device_handle_t parent_dev_hdl, uint8_t parent_port_num, unsigned int dev_uid); +esp_err_t hub_node_recycle(unsigned int node_uid); /** - * @brief Reset the port + * @brief Reset the device in the port, related to the specific Device Tree node * * @note This function should only be called from the Host Library task * - * @param[in] parent_dev_hdl Parent device handle (is used to get the External Hub handle) - * @param[in] parent_port_num Parent number (is used to specify the External Port) + * @param[in] node_uid Device's node unique ID + * * @return - * - ESP_OK: Port reset successful + * - ESP_OK: If port reset was successful * - ESP_ERR_INVALID_STATE: Hub driver is not installed * - ESP_ERR_NOT_SUPPORTED: Resetting External Port is not available (External Hub support disabled), * or ext hub port error + * - ESP_ERR_NOT_FOUND: Device's node is not found */ -esp_err_t hub_port_reset(usb_device_handle_t parent_dev_hdl, uint8_t parent_port_num); +esp_err_t hub_node_reset(unsigned int node_uid); /** - * @brief Activate the port + * @brief Port, related to the specific Device Tree node, has an active device * * @note This function should only be called from the Host Library task * - * @param[in] parent_dev_hdl Parent device handle (is used to get the External Hub handle) - * @param[in] parent_port_num Parent number (is used to specify the External Port) + * @param[in] node_uid Device's node unique ID * * @return - * - ESP_OK: Port activated successfully - * - ESP_ERR_NOT_SUPPORTED: Activating External Port is not available (External Hub support disabled), - * or ext hub port error + * - ESP_OK: If Port, related to the Device Tree node was activated successfully + * - ESP_ERR_NOT_SUPPORTED: If activating Port is not available (External Hub support disabled), +* or ext hub port error + * - ESP_ERR_NOT_FOUND: If Device's node is not found */ -esp_err_t hub_port_active(usb_device_handle_t parent_dev_hdl, uint8_t parent_port_num); +esp_err_t hub_node_active(unsigned int node_uid); /** - * @brief Disable the port + * @brief Disable the port, related to the specific Device Tree node * * @note This function should only be called from the Host Library task * - * @param[in] parent_dev_hdl Parent device handle (is used to get the External Hub handle) - * @param[in] parent_port_num Parent number (is used to specify the External Port) + * @param[in] node_uid Device's node unique ID * * @return * - ESP_OK: Port has been disabled without error * - ESP_ERR_INVALID_STATE: Port can't be disabled in current state - * - ESP_ERR_NOT_SUPPORTED: This function is not support by the selected port + * - ESP_ERR_NOT_SUPPORTED: This function is not supported by the selected port + * - ESP_ERR_NOT_FOUND: Device's node is not found */ -esp_err_t hub_port_disable(usb_device_handle_t parent_dev_hdl, uint8_t parent_port_num); +esp_err_t hub_node_disable(unsigned int node_uid); /** * @brief Notify Hub driver that new device has been attached diff --git a/host/usb/src/enum.c b/host/usb/src/enum.c index 7d76e3ae..9d4f7cde 100644 --- a/host/usb/src/enum.c +++ b/host/usb/src/enum.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -132,12 +132,8 @@ typedef struct { typedef struct { struct { // Device related objects, initialized at start of a particular enumeration - unsigned int dev_uid; /**< Unique device ID being enumerated */ + unsigned int node_uid; /**< Unique node ID of device being enumerated */ usb_device_handle_t dev_hdl; /**< Handle of device being enumerated */ - // Parent info for optimization and more clean debug output - usb_device_handle_t parent_dev_hdl; /**< Device's parent handle */ - uint8_t parent_dev_addr; /**< Device's parent address */ - uint8_t parent_port_num; /**< Device's parent port number */ // Parameters, updated during enumeration enum_stage_t stage; /**< Current enumeration stage */ enum_device_params_t dev_params; /**< Parameters of device under enumeration */ @@ -253,12 +249,11 @@ static esp_err_t select_active_configuration(void) // User's request NOT to enumerate the USB device if (!enum_proceed) { - ESP_LOGW(ENUM_TAG, "[%d:%d] Abort request of enumeration process (%#x:%#x)", - p_enum_driver->single_thread.parent_dev_addr, - p_enum_driver->single_thread.parent_port_num, + ESP_LOGW(ENUM_TAG, "Canceled enumeration of the device %#x:%#x, configuration value=%d", dev_desc->idProduct, - dev_desc->idVendor); - enum_cancel(p_enum_driver->single_thread.dev_uid); + dev_desc->idVendor, + bConfigurationValue); + enum_cancel(p_enum_driver->single_thread.node_uid); return ESP_OK; } @@ -279,13 +274,9 @@ static esp_err_t second_reset_request(void) // Notify USB Host enum_event_data_t event_data = { .event = ENUM_EVENT_RESET_REQUIRED, - .reset_req = { - .parent_dev_hdl = p_enum_driver->single_thread.parent_dev_hdl, - .parent_port_num = p_enum_driver->single_thread.parent_port_num, - }, + .node_uid = p_enum_driver->single_thread.node_uid, }; p_enum_driver->constant.enum_event_cb(&event_data, p_enum_driver->constant.enum_event_cb_arg); - return ESP_OK; } @@ -739,10 +730,8 @@ static esp_err_t control_request(enum_stage_t stage) ret = usbh_dev_submit_ctrl_urb(p_enum_driver->single_thread.dev_hdl, p_enum_driver->constant.urb); if (ret != ESP_OK) { - ESP_LOGE(ENUM_TAG, "[%d:%d] Control transfer submit error (%#x), stage '%s'", - p_enum_driver->single_thread.parent_dev_addr, - p_enum_driver->single_thread.parent_port_num, - ret, + ESP_LOGE(ENUM_TAG, "Control transfer submit error %s, stage '%s'", + esp_err_to_name(ret), enum_stage_strings[stage]); } @@ -781,9 +770,7 @@ static esp_err_t control_response_handling(enum_stage_t stage) // Check Control IN transfer returned the expected correct number of bytes if (expected_num_bytes != 0 && expected_num_bytes != ctrl_xfer->actual_num_bytes) { - ESP_LOGW(ENUM_TAG, "[%d:%d] Unexpected (%d) device response length (expected %d)", - p_enum_driver->single_thread.parent_dev_addr, - p_enum_driver->single_thread.parent_port_num, + ESP_LOGW(ENUM_TAG, "Unexpected (%d) device response length (expected %d)", ctrl_xfer->actual_num_bytes, expected_num_bytes); if (ctrl_xfer->actual_num_bytes < expected_num_bytes) { @@ -847,9 +834,8 @@ static esp_err_t control_response_handling(enum_stage_t stage) static esp_err_t stage_cancel(void) { // There should be device under enumeration + const unsigned int node_uid = p_enum_driver->single_thread.node_uid; usb_device_handle_t dev_hdl = p_enum_driver->single_thread.dev_hdl; - usb_device_handle_t parent_dev_hdl = p_enum_driver->single_thread.parent_dev_hdl; - uint8_t parent_port_num = p_enum_driver->single_thread.parent_port_num; if (dev_hdl) { ESP_ERROR_CHECK(usbh_dev_enum_unlock(dev_hdl)); @@ -857,21 +843,15 @@ static esp_err_t stage_cancel(void) } // Clean up variables device from enumerator - p_enum_driver->single_thread.dev_uid = 0; + p_enum_driver->single_thread.node_uid = 0; p_enum_driver->single_thread.dev_hdl = NULL; - p_enum_driver->single_thread.parent_dev_hdl = NULL; - p_enum_driver->single_thread.parent_dev_addr = 0; - p_enum_driver->single_thread.parent_port_num = 0; p_enum_driver->constant.urb->transfer.context = NULL; // Propagate the event enum_event_data_t event_data = { .event = ENUM_EVENT_CANCELED, - .canceled = { - .parent_dev_hdl = parent_dev_hdl, - .parent_port_num = parent_port_num, - }, + .node_uid = node_uid, }; p_enum_driver->constant.enum_event_cb(&event_data, p_enum_driver->constant.enum_event_cb_arg); return ESP_OK; @@ -884,10 +864,8 @@ static esp_err_t stage_cancel(void) */ static esp_err_t stage_complete(void) { + unsigned int node_uid = p_enum_driver->single_thread.node_uid; usb_device_handle_t dev_hdl = p_enum_driver->single_thread.dev_hdl; - usb_device_handle_t parent_dev_hdl = p_enum_driver->single_thread.parent_dev_hdl; - uint8_t parent_dev_addr = p_enum_driver->single_thread.parent_dev_addr; - uint8_t parent_port_num = p_enum_driver->single_thread.parent_port_num; uint8_t dev_addr = 0; ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr)); @@ -896,11 +874,8 @@ static esp_err_t stage_complete(void) ESP_ERROR_CHECK(usbh_dev_close(dev_hdl)); // Release device from enumerator - p_enum_driver->single_thread.dev_uid = 0; + p_enum_driver->single_thread.node_uid = 0; p_enum_driver->single_thread.dev_hdl = NULL; - p_enum_driver->single_thread.parent_dev_hdl = NULL; - p_enum_driver->single_thread.parent_dev_addr = 0; - p_enum_driver->single_thread.parent_port_num = 0; // Release device from enumerator p_enum_driver->constant.urb->transfer.context = NULL; @@ -912,19 +887,12 @@ static esp_err_t stage_complete(void) // Increase device address to use new value during the next enumeration process get_next_dev_addr(); - ESP_LOGD(ENUM_TAG, "[%d:%d] Processing complete, new device address %d", - parent_dev_addr, - parent_port_num, - dev_addr); + ESP_LOGD(ENUM_TAG, "Processing complete, new device address %d", dev_addr); enum_event_data_t event_data = { .event = ENUM_EVENT_COMPLETED, - .complete = { - .dev_hdl = dev_hdl, - .dev_addr = dev_addr, - .parent_dev_hdl = parent_dev_hdl, - .parent_port_num = parent_port_num, - }, + .node_uid = node_uid, + .dev_hdl = dev_hdl, }; p_enum_driver->constant.enum_event_cb(&event_data, p_enum_driver->constant.enum_event_cb_arg); return ESP_OK; @@ -1005,10 +973,7 @@ static bool set_next_stage(bool last_stage_pass) // Find the next stage if (last_stage_pass) { // Last stage was successful - ESP_LOGD(ENUM_TAG, "[%d:%d] %s OK", - p_enum_driver->single_thread.parent_dev_addr, - p_enum_driver->single_thread.parent_port_num, - enum_stage_strings[last_stage]); + ESP_LOGD(ENUM_TAG, "%s OK", enum_stage_strings[last_stage]); // Get next stage if (last_stage == ENUM_STAGE_COMPLETE || last_stage == ENUM_STAGE_CANCEL) { @@ -1055,10 +1020,7 @@ static bool set_next_stage(bool last_stage_pass) break; default: // Stage is not allowed to failed. Cancel enumeration. - ESP_LOGE(ENUM_TAG, "[%d:%d] %s FAILED", - p_enum_driver->single_thread.parent_dev_addr, - p_enum_driver->single_thread.parent_port_num, - enum_stage_strings[last_stage]); + ESP_LOGE(ENUM_TAG, "%s FAILED", enum_stage_strings[last_stage]); next_stage = ENUM_STAGE_CANCEL; break; } @@ -1211,25 +1173,14 @@ esp_err_t enum_start(unsigned int uid) // Get device info usb_device_info_t dev_info; - uint8_t parent_dev_addr = 0; ESP_ERROR_CHECK(usbh_dev_get_info(dev_hdl, &dev_info)); - if (dev_info.parent.dev_hdl) { - ESP_ERROR_CHECK(usbh_dev_get_addr(dev_info.parent.dev_hdl, &parent_dev_addr)); - } - // Stage ENUM_STAGE_GET_SHORT_DEV_DESC - ESP_LOGD(ENUM_TAG, "[%d:%d] Start processing, device address %d", - parent_dev_addr, - dev_info.parent.port_num, - 0); + ESP_LOGD(ENUM_TAG, "Start processing device with address %d", 0); p_enum_driver->single_thread.stage = ENUM_STAGE_GET_SHORT_DEV_DESC; - p_enum_driver->single_thread.dev_uid = uid; + p_enum_driver->single_thread.node_uid = uid; p_enum_driver->single_thread.dev_hdl = dev_hdl; - p_enum_driver->single_thread.parent_dev_hdl = dev_info.parent.dev_hdl; - p_enum_driver->single_thread.parent_dev_addr = parent_dev_addr; - p_enum_driver->single_thread.parent_port_num = dev_info.parent.port_num; // Save device handle to the URB transfer context p_enum_driver->constant.urb->transfer.context = (void *) dev_hdl; // Device params @@ -1241,14 +1192,9 @@ esp_err_t enum_start(unsigned int uid) // Notify USB Host about starting enumeration process enum_event_data_t event_data = { .event = ENUM_EVENT_STARTED, - .started = { - .uid = uid, - .parent_dev_hdl = dev_info.parent.dev_hdl, - .parent_port_num = dev_info.parent.port_num, - }, + .node_uid = uid, }; p_enum_driver->constant.enum_event_cb(&event_data, p_enum_driver->constant.enum_event_cb_arg); - // Request processing p_enum_driver->constant.proc_req_cb(USB_PROC_REQ_SOURCE_ENUM, false, p_enum_driver->constant.proc_req_cb_arg); return ret; @@ -1276,10 +1222,7 @@ esp_err_t enum_cancel(unsigned int uid) p_enum_driver->single_thread.stage = ENUM_STAGE_CANCEL; - ESP_LOGV(ENUM_TAG, "[%d:%d] Cancel at %s", - p_enum_driver->single_thread.parent_dev_addr, - p_enum_driver->single_thread.parent_port_num, - enum_stage_strings[old_stage]); + ESP_LOGV(ENUM_TAG, "Cancel at %s", enum_stage_strings[old_stage]); if (stage_need_process(old_stage)) { // These stages are required to trigger processing in the enum_process() diff --git a/host/usb/src/hub.c b/host/usb/src/hub.c index 8af9d09b..70f4dff1 100644 --- a/host/usb/src/hub.c +++ b/host/usb/src/hub.c @@ -145,6 +145,20 @@ static bool root_port_callback(hcd_port_handle_t port_hdl, hcd_port_event_t port // ---------------------- Internal Logic ------------------------ +dev_tree_node_t *dev_tree_node_get_by_uid(unsigned int node_uid) +{ + 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) { + if (dev_tree_iter->uid == node_uid) { + dev_tree_node = dev_tree_iter; + break; + } + } + return dev_tree_node; +} + /** * @brief Creates new device tree node and propagate HUB_EVENT_CONNECTED event * @@ -667,20 +681,23 @@ esp_err_t hub_root_stop(void) return ret; } -esp_err_t hub_port_recycle(usb_device_handle_t parent_dev_hdl, uint8_t parent_port_num, unsigned int dev_uid) +esp_err_t hub_node_recycle(unsigned int node_uid) { HUB_DRIVER_ENTER_CRITICAL(); HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj != NULL, ESP_ERR_INVALID_STATE); HUB_DRIVER_EXIT_CRITICAL(); esp_err_t ret; - if (parent_port_num == 0) { + 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); + + if (dev_tree_node->parent_dev_hdl == NULL) { ret = root_port_recycle(); } else { #if ENABLE_USB_HUBS ext_hub_handle_t ext_hub_hdl = NULL; - ext_hub_get_handle(parent_dev_hdl, &ext_hub_hdl); - ret = ext_hub_port_recycle(ext_hub_hdl, parent_port_num); + ext_hub_get_handle(dev_tree_node->parent_dev_hdl, &ext_hub_hdl); + ret = ext_hub_port_recycle(ext_hub_hdl, dev_tree_node->parent_port_num); if (ret != ESP_OK) { ESP_LOGE(HUB_DRIVER_TAG, "Ext hub port recycle error: %s", esp_err_to_name(ret)); } @@ -691,20 +708,23 @@ esp_err_t hub_port_recycle(usb_device_handle_t parent_dev_hdl, uint8_t parent_po } if (ret == ESP_OK) { - ESP_ERROR_CHECK(dev_tree_node_remove_by_parent(parent_dev_hdl, parent_port_num)); + ESP_ERROR_CHECK(dev_tree_node_remove_by_parent(dev_tree_node->parent_dev_hdl, dev_tree_node->parent_port_num)); } return ret; } -esp_err_t hub_port_reset(usb_device_handle_t parent_dev_hdl, uint8_t parent_port_num) +esp_err_t hub_node_reset(unsigned int node_uid) { HUB_DRIVER_ENTER_CRITICAL(); HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj != NULL, ESP_ERR_INVALID_STATE); HUB_DRIVER_EXIT_CRITICAL(); esp_err_t ret; - if (parent_port_num == 0) { + 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); + + if (dev_tree_node->parent_dev_hdl == NULL) { ret = hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_RESET); if (ret != ESP_OK) { ESP_LOGE(HUB_DRIVER_TAG, "Failed to issue root port reset"); @@ -714,8 +734,8 @@ esp_err_t hub_port_reset(usb_device_handle_t parent_dev_hdl, uint8_t parent_port } else { #if ENABLE_USB_HUBS ext_hub_handle_t ext_hub_hdl = NULL; - ext_hub_get_handle(parent_dev_hdl, &ext_hub_hdl); - ret = ext_hub_port_reset(ext_hub_hdl, parent_port_num); + ext_hub_get_handle(dev_tree_node->parent_dev_hdl, &ext_hub_hdl); + ret = ext_hub_port_reset(ext_hub_hdl, dev_tree_node->parent_port_num); if (ret != ESP_OK) { ESP_LOGE(HUB_DRIVER_TAG, "Ext hub port reset error: %s", esp_err_to_name(ret)); } @@ -727,19 +747,22 @@ esp_err_t hub_port_reset(usb_device_handle_t parent_dev_hdl, uint8_t parent_port return ret; } -esp_err_t hub_port_active(usb_device_handle_t parent_dev_hdl, uint8_t parent_port_num) +esp_err_t hub_node_active(unsigned int node_uid) { esp_err_t ret; - if (parent_port_num == 0) { + 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); + + if (dev_tree_node->parent_dev_hdl == NULL) { // Root port no need to be activated ret = ESP_OK; } else { #if ENABLE_USB_HUBS // External Hub port ext_hub_handle_t ext_hub_hdl = NULL; - ext_hub_get_handle(parent_dev_hdl, &ext_hub_hdl); - ret = ext_hub_port_active(ext_hub_hdl, parent_port_num); + ext_hub_get_handle(dev_tree_node->parent_dev_hdl, &ext_hub_hdl); + ret = ext_hub_port_active(ext_hub_hdl, dev_tree_node->parent_port_num); if (ret != ESP_OK) { ESP_LOGE(HUB_DRIVER_TAG, "Ext hub port activation error: %s", esp_err_to_name(ret)); } @@ -751,20 +774,23 @@ esp_err_t hub_port_active(usb_device_handle_t parent_dev_hdl, uint8_t parent_por return ret; } -esp_err_t hub_port_disable(usb_device_handle_t parent_dev_hdl, uint8_t parent_port_num) +esp_err_t hub_node_disable(unsigned int node_uid) { esp_err_t ret; - if (parent_port_num == 0) { + 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); + + if (dev_tree_node->parent_dev_hdl == NULL) { ret = root_port_disable(); } else { #if ENABLE_USB_HUBS // External Hub port ext_hub_handle_t ext_hub_hdl = NULL; - ext_hub_get_handle(parent_dev_hdl, &ext_hub_hdl); - ret = ext_hub_port_disable(ext_hub_hdl, parent_port_num); + ext_hub_get_handle(dev_tree_node->parent_dev_hdl, &ext_hub_hdl); + ret = ext_hub_port_disable(ext_hub_hdl, dev_tree_node->parent_port_num); #else - ESP_LOGW(HUB_DRIVER_TAG, "Activating External Port is not available (External Hub support disabled)"); + ESP_LOGW(HUB_DRIVER_TAG, "Disabling External Port is not available (External Hub support disabled)"); ret = ESP_ERR_NOT_SUPPORTED; #endif // ENABLE_USB_HUBS } diff --git a/host/usb/src/usb_host.c b/host/usb/src/usb_host.c index a7e774c1..64559b94 100644 --- a/host/usb/src/usb_host.c +++ b/host/usb/src/usb_host.c @@ -344,11 +344,9 @@ static void usbh_event_callback(usbh_event_data_t *event_data, void *arg) break; } case USBH_EVENT_DEV_FREE: { - // Let the Hub driver know that the device is free and its port can be recycled - // Port could be absent, no need to verify - hub_port_recycle(event_data->dev_free_data.parent_dev_hdl, - event_data->dev_free_data.port_num, - event_data->dev_free_data.dev_uid); + // Let the Hub driver know that the device is free and its node can be free and port re-enabled + // Node could be already freed on device disconnect (when clients still holding the device opened), no need to verify result + hub_node_recycle(event_data->dev_free_data.dev_uid); break; } case USBH_EVENT_ALL_FREE: { @@ -397,16 +395,16 @@ static void enum_event_callback(enum_event_data_t *event_data, void *arg) break; case ENUM_EVENT_RESET_REQUIRED: // Device may be gone, don't need to verify result - hub_port_reset(event_data->reset_req.parent_dev_hdl, event_data->reset_req.parent_port_num); + hub_node_reset(event_data->node_uid); break; case ENUM_EVENT_COMPLETED: // Notify port that device completed enumeration - hub_port_active(event_data->complete.parent_dev_hdl, event_data->complete.parent_port_num); + hub_node_active(event_data->node_uid); // Propagate a new device event - ESP_ERROR_CHECK(usbh_devs_new_dev_event(event_data->complete.dev_hdl)); + ESP_ERROR_CHECK(usbh_devs_new_dev_event(event_data->dev_hdl)); break; case ENUM_EVENT_CANCELED: - hub_port_disable(event_data->canceled.parent_dev_hdl, event_data->canceled.parent_port_num); + hub_node_disable(event_data->node_uid); break; default: abort(); // Should never occur