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
30 changes: 4 additions & 26 deletions host/usb/private_include/enum.h
Original file line number Diff line number Diff line change
@@ -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
*/
Expand Down Expand Up @@ -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 --------------------------------------
Expand Down
49 changes: 25 additions & 24 deletions host/usb/private_include/hub.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 @@ -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
Expand Down
105 changes: 24 additions & 81 deletions host/usb/src/enum.c
Original file line number Diff line number Diff line change
@@ -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
*/
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand Down Expand Up @@ -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]);
}

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -847,31 +834,24 @@ 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));
ESP_ERROR_CHECK(usbh_dev_close(dev_hdl));
}

// 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;
Expand All @@ -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));

Expand All @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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()
Expand Down
Loading
Loading