From a807fe7940f55ba766ac263635b8b7461ad4de75 Mon Sep 17 00:00:00 2001 From: Roman Leonov Date: Mon, 3 Mar 2025 14:55:21 +0100 Subject: [PATCH 1/2] refactor(ext_port): Removed ext_hub dependency --- components/usb/ext_hub.c | 70 ++++++++++++------ components/usb/ext_port.c | 88 +++++++++++++++-------- components/usb/hub.c | 12 ++-- components/usb/private_include/ext_hub.h | 46 ++---------- components/usb/private_include/ext_port.h | 78 ++++++++++++++++++-- 5 files changed, 189 insertions(+), 105 deletions(-) diff --git a/components/usb/ext_hub.c b/components/usb/ext_hub.c index f8dbc85850..dbfdd43df2 100644 --- a/components/usb/ext_hub.c +++ b/components/usb/ext_hub.c @@ -145,7 +145,7 @@ typedef struct { struct { ext_hub_cb_t proc_req_cb; /**< Process callback */ void *proc_req_cb_arg; /**< Process callback argument */ - const ext_hub_port_driver_t* port_driver; /**< External Port Driver */ + const ext_port_driver_api_t* port_driver; /**< External Port Driver */ } constant; /**< Constant members. Do not change after installation thus do not require a critical section or mutex */ } ext_hub_driver_t; @@ -396,7 +396,7 @@ static void device_error(ext_hub_dev_t *ext_hub_dev) static esp_err_t device_port_new(ext_hub_dev_t *ext_hub_dev, uint8_t port_idx) { ext_port_config_t port_config = { - .ext_hub_hdl = (ext_hub_handle_t) ext_hub_dev, + .context = (void*) ext_hub_dev, .parent_dev_hdl = ext_hub_dev->constant.dev_hdl, .parent_port_num = port_idx + 1, .port_power_delay_ms = ext_hub_dev->constant.hub_desc->bPwrOn2PwrGood * 2, @@ -1702,52 +1702,76 @@ esp_err_t ext_hub_port_get_speed(ext_hub_handle_t ext_hub_hdl, uint8_t port_num, return p_ext_hub_driver->constant.port_driver->get_speed(ext_hub_dev->constant.ports[port_idx], speed); } -// ----------------------------------------------------------------------------- -// --------------------------- USB Chapter 11 ---------------------------------- -// ----------------------------------------------------------------------------- +// ------------------------------------------------------------------------------------------------- +// ---------------------------------- USB Chapter 11 ----------------------------------------------- +// ------------------------------------------------------------------------------------------------- -esp_err_t ext_hub_class_request(ext_hub_handle_t ext_hub_hdl, ext_hub_request_data_t *data, void *user_arg) +static esp_err_t ext_hub_control_request(ext_hub_dev_t *ext_hub_dev, uint8_t port1, uint8_t request, uint8_t feature) { - 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(data != NULL && ext_hub_hdl != NULL, ESP_ERR_INVALID_ARG); - esp_err_t ret; - ext_hub_dev_t *ext_hub_dev = (ext_hub_dev_t *)ext_hub_hdl; usb_transfer_t *transfer = &ext_hub_dev->constant.ctrl_urb->transfer; - - EXT_HUB_CHECK(data->port_num != 0 && data->port_num <= ext_hub_dev->constant.hub_desc->bNbrPorts, ESP_ERR_INVALID_SIZE); - EXT_HUB_CHECK(ext_hub_dev->single_thread.state == EXT_HUB_STATE_CONFIGURED || - ext_hub_dev->single_thread.state == EXT_HUB_STATE_SUSPENDED, ESP_ERR_INVALID_STATE); - - switch (data->request) { + switch (request) { case USB_B_REQUEST_HUB_GET_PORT_STATUS: - USB_SETUP_PACKET_INIT_GET_PORT_STATUS((usb_setup_packet_t *)transfer->data_buffer, data->port_num); + USB_SETUP_PACKET_INIT_GET_PORT_STATUS((usb_setup_packet_t *)transfer->data_buffer, port1); transfer->num_bytes = sizeof(usb_setup_packet_t) + sizeof(usb_port_status_t); ext_hub_dev->single_thread.stage = EXT_HUB_STAGE_CHECK_PORT_STATUS; break; case USB_B_REQUEST_HUB_SET_PORT_FEATURE: - USB_SETUP_PACKET_INIT_SET_PORT_FEATURE((usb_setup_packet_t *)transfer->data_buffer, data->port_num, data->feature); + USB_SETUP_PACKET_INIT_SET_PORT_FEATURE((usb_setup_packet_t *)transfer->data_buffer, port1, feature); transfer->num_bytes = sizeof(usb_setup_packet_t); ext_hub_dev->single_thread.stage = EXT_HUB_STAGE_CHECK_PORT_FEATURE; break; case USB_B_REQUEST_HUB_CLEAR_FEATURE: - USB_SETUP_PACKET_INIT_CLEAR_PORT_FEATURE((usb_setup_packet_t *)transfer->data_buffer, data->port_num, data->feature); + USB_SETUP_PACKET_INIT_CLEAR_PORT_FEATURE((usb_setup_packet_t *)transfer->data_buffer, port1, feature); transfer->num_bytes = sizeof(usb_setup_packet_t); ext_hub_dev->single_thread.stage = EXT_HUB_STAGE_CHECK_PORT_FEATURE; break; default: - ESP_LOGE(EXT_HUB_TAG, "Request %X not supported", data->request); + ESP_LOGE(EXT_HUB_TAG, "Request %X not supported", request); return ESP_ERR_NOT_SUPPORTED; } ret = usbh_dev_submit_ctrl_urb(ext_hub_dev->constant.dev_hdl, ext_hub_dev->constant.ctrl_urb); if (ret != ESP_OK) { ESP_LOGE(EXT_HUB_TAG, "Request %X, port %d, feature %d: failed to submit ctrl urb: %s", - data->request, data->port_num, data->feature, + request, port1, feature, esp_err_to_name(ret)); device_error(ext_hub_dev); } return ret; } + +// ------------------------------------------------------------------------------------------------- +// ---------------------------------- Parent Request ----------------------------------------------- +// ------------------------------------------------------------------------------------------------- + +esp_err_t ext_hub_request(ext_port_hdl_t port_hdl, ext_port_parent_request_data_t *data, void *user_arg) +{ + 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(data != NULL && port_hdl != NULL, ESP_ERR_INVALID_ARG); + + uint8_t port1; + ext_hub_handle_t ext_hub_hdl = (ext_hub_handle_t)ext_port_get_context(port_hdl); + ext_hub_dev_t *ext_hub_dev = (ext_hub_dev_t *)ext_hub_hdl; + + ESP_ERROR_CHECK(ext_port_get_port_num(port_hdl, &port1)); + EXT_HUB_CHECK(port1 != 0 && port1 <= ext_hub_dev->constant.hub_desc->bNbrPorts, ESP_ERR_INVALID_SIZE); + EXT_HUB_CHECK(ext_hub_dev->single_thread.state == EXT_HUB_STATE_CONFIGURED || + ext_hub_dev->single_thread.state == EXT_HUB_STATE_SUSPENDED, ESP_ERR_INVALID_STATE); + + switch (data->type) { + case EXT_PORT_PARENT_REQ_CONTROL: + return ext_hub_control_request(ext_hub_dev, port1, data->control.req, data->control.feature); + + case EXT_PORT_PARENT_REQ_PROC_COMPLETED: + return ext_hub_status_handle_complete(ext_hub_hdl); + + default: + break; + } + + ESP_LOGE(EXT_HUB_TAG, "Request type %d not supported", data->type); + return ESP_ERR_NOT_SUPPORTED; +} diff --git a/components/usb/ext_port.c b/components/usb/ext_port.c index e807dcbb38..5fedc49ae3 100644 --- a/components/usb/ext_port.c +++ b/components/usb/ext_port.c @@ -78,7 +78,7 @@ struct ext_port_s { usb_device_handle_t parent_dev_hdl; /**< Ports' parent device handle */ uint8_t parent_dev_addr; /**< Ports' parent device bus address */ // Port related constant members - ext_hub_handle_t ext_hub_hdl; /**< Ports' parent External Hub handle */ + void* context; /**< Ports' parent External Hub handle */ uint8_t port_num; /**< Ports' parent External Hub Port number */ int power_on_delay_ms; /**< Ports' Power on time to Power Good, ms */ } constant; /**< Constant members. Do not change after installation thus do not require a critical section or mutex */ @@ -102,7 +102,7 @@ typedef struct { void *proc_req_cb_arg; /**< External Port process callback argument */ ext_port_event_cb_t event_cb; /**< External Port event callback */ void *event_cb_arg; /**< External Port event callback argument */ - ext_hub_request_cb_t hub_request_cb; /**< External Port Hub request callback */ + ext_port_parent_request_cb_t hub_request_cb; /**< External Port Hub request callback */ void *hub_request_cb_arg; /**< External Port Hub request callback argument */ } constant; /**< Constant members. Do not change after installation thus do not require a critical section or mutex */ } ext_port_driver_t; @@ -232,13 +232,15 @@ static inline bool port_has_finished_reset(ext_port_t *ext_port) */ static esp_err_t port_request_status(ext_port_t* ext_port) { - ext_hub_request_data_t req_data = { - .request = USB_B_REQUEST_HUB_GET_PORT_STATUS, - .port_num = ext_port->constant.port_num, + ext_port_parent_request_data_t data = { + .type = EXT_PORT_PARENT_REQ_CONTROL, + .control = { + .req = USB_B_REQUEST_HUB_GET_PORT_STATUS, + } }; - esp_err_t ret = p_ext_port_driver->constant.hub_request_cb(ext_port->constant.ext_hub_hdl, - &req_data, + esp_err_t ret = p_ext_port_driver->constant.hub_request_cb((ext_port_hdl_t)ext_port, + &data, p_ext_port_driver->constant.hub_request_cb_arg); if (ret != ESP_OK) { return ret; @@ -264,14 +266,16 @@ static esp_err_t port_request_status(ext_port_t* ext_port) */ static esp_err_t port_set_feature(ext_port_t *ext_port, const usb_hub_port_feature_t feature) { - ext_hub_request_data_t req_data = { - .request = USB_B_REQUEST_HUB_SET_PORT_FEATURE, - .port_num = ext_port->constant.port_num, - .feature = feature, + ext_port_parent_request_data_t data = { + .type = EXT_PORT_PARENT_REQ_CONTROL, + .control = { + .req = USB_B_REQUEST_HUB_SET_PORT_FEATURE, + .feature = feature, + } }; - esp_err_t ret = p_ext_port_driver->constant.hub_request_cb(ext_port->constant.ext_hub_hdl, - &req_data, + esp_err_t ret = p_ext_port_driver->constant.hub_request_cb((ext_port_hdl_t)ext_port, + &data, p_ext_port_driver->constant.hub_request_cb_arg); if (ret != ESP_OK) { return ret; @@ -309,14 +313,16 @@ static esp_err_t port_set_feature(ext_port_t *ext_port, const usb_hub_port_featu */ static esp_err_t port_clear_feature(ext_port_t *ext_port, const usb_hub_port_feature_t feature) { - ext_hub_request_data_t req_data = { - .request = USB_B_REQUEST_HUB_CLEAR_FEATURE, - .port_num = ext_port->constant.port_num, - .feature = feature, + ext_port_parent_request_data_t data = { + .type = EXT_PORT_PARENT_REQ_CONTROL, + .control = { + .req = USB_B_REQUEST_HUB_CLEAR_FEATURE, + .feature = feature, + } }; - esp_err_t ret = p_ext_port_driver->constant.hub_request_cb(ext_port->constant.ext_hub_hdl, - &req_data, + esp_err_t ret = p_ext_port_driver->constant.hub_request_cb((ext_port_hdl_t)ext_port, + &data, p_ext_port_driver->constant.hub_request_cb_arg); if (ret != ESP_OK) { return ret; @@ -410,7 +416,6 @@ static void port_event(ext_port_t *ext_port, ext_port_event_t event) }; switch (event) { case EXT_PORT_CONNECTED: - event_data.connected.ext_hub_hdl = ext_port->constant.ext_hub_hdl; event_data.connected.parent_dev_hdl = ext_port->constant.parent_dev_hdl; event_data.connected.parent_port_num = ext_port->constant.port_num; break; @@ -428,7 +433,7 @@ static void port_event(ext_port_t *ext_port, ext_port_event_t event) break; } - p_ext_port_driver->constant.event_cb(&event_data, p_ext_port_driver->constant.event_cb_arg); + p_ext_port_driver->constant.event_cb((ext_port_hdl_t)ext_port, &event_data, p_ext_port_driver->constant.event_cb_arg); } /** @@ -453,7 +458,7 @@ static ext_port_t *get_port_from_pending_list(void) * - Port state: USB_PORT_STATE_NOT_CONFIGURED * - Port device status: PORT_DEV_NOT_PRESENT * - * @param[in] ext_hub_hdl Ports' parent hub handle + * @param[in] context Ports' parent hub handle * @param[in] parent_dev_hdl Ports' parent device handle * @param[in] parent_port_num Ports' parent port number * @param[in] port_delay_ms Ports' Power on time to Power Good, ms @@ -464,10 +469,10 @@ static ext_port_t *get_port_from_pending_list(void) * - ESP_ERR_NOT_FINISHED: Unable to allocate the port object: parent device is not available * - ESP_OK: Port object created successfully */ -static esp_err_t port_alloc(ext_hub_handle_t ext_hub_hdl, usb_device_handle_t parent_dev_hdl, uint8_t parent_port_num, uint16_t port_delay_ms, ext_port_t **port_obj) +static esp_err_t port_alloc(void* context, usb_device_handle_t parent_dev_hdl, uint8_t parent_port_num, uint16_t port_delay_ms, ext_port_t **port_obj) { uint8_t parent_dev_addr = 0; - EXT_PORT_CHECK(ext_hub_hdl != NULL && parent_dev_hdl != NULL, ESP_ERR_INVALID_ARG); + EXT_PORT_CHECK(context != NULL && parent_dev_hdl != NULL, ESP_ERR_INVALID_ARG); // This is the one exception from the requirement to use only the Ext Hub Driver API. // TODO: IDF-10023 Move responsibility of parent-child tree building to Hub Driver instead of USBH EXT_PORT_CHECK(usbh_dev_get_addr(parent_dev_hdl, &parent_dev_addr) == ESP_OK, ESP_ERR_NOT_FINISHED); @@ -479,7 +484,7 @@ static esp_err_t port_alloc(ext_hub_handle_t ext_hub_hdl, usb_device_handle_t pa ext_port->constant.parent_dev_hdl = parent_dev_hdl; ext_port->constant.parent_dev_addr = parent_dev_addr; - ext_port->constant.ext_hub_hdl = ext_hub_hdl; + ext_port->constant.context = context; ext_port->constant.port_num = parent_port_num; #if (EXT_PORT_POWER_ON_CUSTOM_DELAY) ext_port->constant.power_on_delay_ms = EXT_PORT_POWER_ON_CUSTOM_DELAY_MS; @@ -545,7 +550,7 @@ static esp_err_t handle_complete(ext_port_t *ext_port) // When multiply Hubs are attached, we can have ports in pending list, but for another parent ext_port_t *port = NULL; TAILQ_FOREACH(port, &p_ext_port_driver->single_thread.pending_tailq, tailq_entry) { - if (port->constant.ext_hub_hdl == ext_port->constant.ext_hub_hdl) { + if (port->constant.context == ext_port->constant.context) { // Port with same parent has been found all_ports_were_handled = false; break; @@ -559,7 +564,13 @@ static esp_err_t handle_complete(ext_port_t *ext_port) if (all_ports_were_handled) { // Notify parent to enable Interrupt EP - ext_hub_status_handle_complete(ext_port->constant.ext_hub_hdl); + ext_port_parent_request_data_t data = { + .type = EXT_PORT_PARENT_REQ_PROC_COMPLETED, + }; + + ESP_ERROR_CHECK(p_ext_port_driver->constant.hub_request_cb((ext_port_hdl_t)ext_port, + &data, + p_ext_port_driver->constant.hub_request_cb_arg)); } if (has_pending_ports) { @@ -965,7 +976,7 @@ static esp_err_t port_new(void *port_cfg, void **port_hdl) ext_port_t *port = NULL; ext_port_config_t *config = (ext_port_config_t *)port_cfg; - esp_err_t ret = port_alloc(config->ext_hub_hdl, + esp_err_t ret = port_alloc(config->context, config->parent_dev_hdl, config->parent_port_num, config->port_power_delay_ms, @@ -1002,6 +1013,7 @@ static esp_err_t port_recycle(void *port_hdl) EXT_PORT_CHECK(port_hdl != NULL, ESP_ERR_INVALID_ARG); ext_port_t *ext_port = (ext_port_t *) port_hdl; + EXT_PORT_CHECK(ext_port->flags.is_gone == 0, ESP_ERR_INVALID_STATE); ESP_LOGD(EXT_PORT_TAG, "Port %d request recycle, state=%d", ext_port->constant.port_num, ext_port->state); port_set_actions(ext_port, PORT_ACTION_RECYCLE); @@ -1307,7 +1319,7 @@ static esp_err_t port_req_process(void* port_hdl) /** * @brief External Port Driver API */ -const ext_hub_port_driver_t ext_port_driver = { +const ext_port_driver_api_t ext_port_driver = { .new = port_new, .reset = port_reset, .recycle = port_recycle, @@ -1425,8 +1437,24 @@ esp_err_t ext_port_process(void) return ESP_OK; } -const ext_hub_port_driver_t *ext_port_get_driver(void) +const ext_port_driver_api_t *ext_port_get_driver(void) { EXT_PORT_CHECK(p_ext_port_driver != NULL, NULL); return &ext_port_driver; } + +void* ext_port_get_context(ext_port_hdl_t port_hdl) +{ + EXT_PORT_CHECK(p_ext_port_driver != NULL, NULL); + ext_port_t *ext_port = (ext_port_t *)port_hdl; + return ext_port->constant.context; +} + +esp_err_t ext_port_get_port_num(ext_port_hdl_t port_hdl, uint8_t *port1) +{ + EXT_PORT_CHECK(p_ext_port_driver != NULL, ESP_ERR_NOT_ALLOWED); + EXT_PORT_CHECK(port_hdl != NULL && port1 != NULL, ESP_ERR_INVALID_ARG); + ext_port_t *ext_port = (ext_port_t *)port_hdl; + *port1 = ext_port->constant.port_num; + return ESP_OK; +} diff --git a/components/usb/hub.c b/components/usb/hub.c index 695a86ae5f..67c9b0a53f 100644 --- a/components/usb/hub.c +++ b/components/usb/hub.c @@ -19,7 +19,7 @@ #include "usb/usb_helpers.h" #if ENABLE_USB_HUBS -#include "ext_port.h" +#include "ext_hub.h" #endif // ENABLE_USB_HUBS /* @@ -325,14 +325,16 @@ static void ext_port_callback(void *user_arg) p_hub_driver_obj->constant.proc_req_cb(USB_PROC_REQ_SOURCE_HUB, false, p_hub_driver_obj->constant.proc_req_cb_arg); } -static void ext_port_event_callback(ext_port_event_data_t *event_data, void *arg) +static void ext_port_event_callback(ext_port_hdl_t port_hdl, ext_port_event_data_t *event_data, void *arg) { + ext_hub_handle_t ext_hub_hdl = (ext_hub_handle_t) ext_port_get_context(port_hdl); + switch (event_data->event) { case EXT_PORT_CONNECTED: // First reset is done by ext_port logic usb_speed_t port_speed; - if (ext_hub_port_get_speed(event_data->connected.ext_hub_hdl, + if (ext_hub_port_get_speed(ext_hub_hdl, event_data->connected.parent_port_num, &port_speed) != ESP_OK) { goto new_ds_dev_err; @@ -357,7 +359,7 @@ static void ext_port_event_callback(ext_port_event_data_t *event_data, void *arg } break; new_ds_dev_err: - ext_hub_port_disable(event_data->connected.ext_hub_hdl, event_data->connected.parent_port_num); + ext_hub_port_disable(ext_hub_hdl, event_data->connected.parent_port_num); break; case EXT_PORT_RESET_COMPLETED: ESP_ERROR_CHECK(dev_tree_node_reset_completed(event_data->reset_completed.parent_dev_hdl, event_data->reset_completed.parent_port_num)); @@ -535,7 +537,7 @@ esp_err_t hub_install(hub_config_t *hub_config, void **client_ret) ext_port_driver_config_t ext_port_config = { .proc_req_cb = ext_port_callback, .event_cb = ext_port_event_callback, - .hub_request_cb = ext_hub_class_request, + .hub_request_cb = ext_hub_request, }; ret = ext_port_install(&ext_port_config); if (ret != ESP_OK) { diff --git a/components/usb/private_include/ext_hub.h b/components/usb/private_include/ext_hub.h index 35ed928c09..be95dbefe3 100644 --- a/components/usb/private_include/ext_hub.h +++ b/components/usb/private_include/ext_hub.h @@ -13,10 +13,7 @@ #include "usb/usb_types_stack.h" #include "usb/usb_types_ch9.h" #include "usb/usb_types_ch11.h" - -#if CONFIG_USB_HOST_HUB_MULTI_LEVEL -#define ENABLE_MULTIPLE_HUBS 1 -#endif // CONFIG_USB_HOST_HUB_MULTI_LEVEL +#include "ext_port.h" #ifdef __cplusplus extern "C" { @@ -34,46 +31,13 @@ typedef struct ext_hub_s *ext_hub_handle_t; */ typedef bool (*ext_hub_cb_t)(bool in_isr, void *user_arg); -/** - * @brief Specific data for Hub class specific request - */ -typedef struct { - usb_hub_class_request_t request; - uint8_t port_num; - uint8_t feature; -} ext_hub_request_data_t; - -/** - * @brief Callback used to indicate that the External Port driver requires a Hub class specific request - */ -typedef esp_err_t (*ext_hub_request_cb_t)(ext_hub_handle_t ext_hub_hdl, ext_hub_request_data_t *request_data, void *user_arg); - -// ------------------------ External Port API typedefs ------------------------- - -/** - * @brief External Hub Port driver - */ -typedef struct { - esp_err_t (*new)(void *port_cfg, void **port_hdl); - esp_err_t (*reset)(void *port_hdl); - esp_err_t (*recycle)(void *port_hdl); - esp_err_t (*active)(void *port_hdl); - esp_err_t (*disable)(void *port_hdl); - esp_err_t (*gone)(void *port_hdl); - esp_err_t (*del)(void *port_hdl); - esp_err_t (*get_speed)(void *por_hdl, usb_speed_t *speed); - esp_err_t (*get_status)(void *port_hdl); - esp_err_t (*set_status)(void *port_hdl, const usb_port_status_t *status); - esp_err_t (*req_process)(void *port_hdl); -} ext_hub_port_driver_t; - /** * @brief External Hub Driver configuration */ typedef struct { ext_hub_cb_t proc_req_cb; /**< External Hub process callback */ void *proc_req_cb_arg; /**< External Hub process callback argument */ - const ext_hub_port_driver_t* port_driver; /**< External Port Driver */ + const ext_port_driver_api_t* port_driver; /**< External Port Driver */ } ext_hub_config_t; // ------------------------------ Driver --------------------------------------- @@ -287,11 +251,11 @@ esp_err_t ext_hub_port_get_speed(ext_hub_handle_t ext_hub_hdl, uint8_t port_num, // --------------------------- USB Chapter 11 ---------------------------------- /** - * @brief USB Hub Class specific request + * @brief USB Hub Request * * @note This function designed to be called from the External Port driver * - * @param[in] ext_hub_hdl External Hub handle + * @param[in] port_hdl External Port handle * @param[in] data Request data * @param[in] user_arg User argument * @@ -303,7 +267,7 @@ esp_err_t ext_hub_port_get_speed(ext_hub_handle_t ext_hub_hdl, uint8_t port_num, * - ESP_ERR_NOT_SUPPORTED if the request is not supported * - ESP_OK if control transfer was successfully submitted */ -esp_err_t ext_hub_class_request(ext_hub_handle_t ext_hub_hdl, ext_hub_request_data_t *data, void *user_arg); +esp_err_t ext_hub_request(ext_port_hdl_t port_hdl, ext_port_parent_request_data_t *data, void *user_arg); #ifdef __cplusplus } diff --git a/components/usb/private_include/ext_port.h b/components/usb/private_include/ext_port.h index 002bb68fe2..1758b0c140 100644 --- a/components/usb/private_include/ext_port.h +++ b/components/usb/private_include/ext_port.h @@ -7,15 +7,38 @@ #include #include "esp_err.h" -#include "ext_hub.h" #include "usb/usb_types_stack.h" +#include "sdkconfig.h" #ifdef __cplusplus extern "C" { #endif +#if CONFIG_USB_HOST_HUB_MULTI_LEVEL +#define ENABLE_MULTIPLE_HUBS 1 +#endif // CONFIG_USB_HOST_HUB_MULTI_LEVEL + typedef struct ext_port_s *ext_port_hdl_t; +// ------------------------ External Port API typedefs ------------------------- + +/** + * @brief External Hub Port driver + */ +typedef struct { + esp_err_t (*new)(void *port_cfg, void **port_hdl); + esp_err_t (*reset)(void *port_hdl); + esp_err_t (*recycle)(void *port_hdl); + esp_err_t (*active)(void *port_hdl); + esp_err_t (*disable)(void *port_hdl); + esp_err_t (*gone)(void *port_hdl); + esp_err_t (*del)(void *port_hdl); + esp_err_t (*get_speed)(void *por_hdl, usb_speed_t *speed); + esp_err_t (*get_status)(void *port_hdl); + esp_err_t (*set_status)(void *port_hdl, const usb_port_status_t *status); + esp_err_t (*req_process)(void *port_hdl); +} ext_port_driver_api_t; + // ------------------------------ Events --------------------------------------- typedef enum { EXT_PORT_CONNECTED = 0x01, /**< Port has a device connection event */ @@ -30,7 +53,6 @@ typedef struct { ext_port_event_t event; union { struct { - ext_hub_handle_t ext_hub_hdl; /**< Ports' parent external Hub handle */ usb_device_handle_t parent_dev_hdl; /**< Ports' parent device handle */ uint8_t parent_port_num; /**< Ports' parent port number */ } connected; /**< EXT_PORT_CONNECTED event specific data */ @@ -47,6 +69,24 @@ typedef struct { }; } ext_port_event_data_t; +typedef enum { + EXT_PORT_PARENT_REQ_CONTROL = 0x01, /** Port requires action from the parent Hub */ + EXT_PORT_PARENT_REQ_PROC_COMPLETED /** All ports were handled */ +} ext_port_parent_request_type_t; + +/** + * @brief Specific data for External Port parent Hub class specific request + */ +typedef struct { + ext_port_parent_request_type_t type; + union { + struct { + usb_hub_class_request_t req; + uint8_t feature; + } control; + }; +} ext_port_parent_request_data_t; + // ------------------------------ Callbacks ------------------------------------ /** * @brief Callback used to indicate that the External Port Driver requires process callback @@ -60,7 +100,12 @@ typedef void (*ext_port_cb_t)(void *user_arg); * * @note For the Hub Driver only */ -typedef void (*ext_port_event_cb_t)(ext_port_event_data_t *event_data, void *arg); +typedef void (*ext_port_event_cb_t)(ext_port_hdl_t port_hdl, ext_port_event_data_t *event_data, void *arg); + +/** + * @brief Callback used to indicate that the External Port driver requires a Hub class specific request + */ +typedef esp_err_t (*ext_port_parent_request_cb_t)(ext_port_hdl_t port_hdl, ext_port_parent_request_data_t *data, void *user_arg); // ----------------- External Port Driver configuration ------------------------ @@ -72,7 +117,7 @@ typedef struct { void *proc_req_cb_arg; /**< External Port process callback argument */ ext_port_event_cb_t event_cb; /**< External Port event callback */ void *event_cb_arg; /**< External Port event callback argument */ - ext_hub_request_cb_t hub_request_cb; /**< External Port Hub request callback */ + ext_port_parent_request_cb_t hub_request_cb;/**< External Port Hub request callback */ void *hub_request_cb_arg; /**< External Port Hub request callback argument */ } ext_port_driver_config_t; @@ -82,7 +127,7 @@ typedef struct { * Structure is used to create new port */ typedef struct { - ext_hub_handle_t ext_hub_hdl; /**< Ports' parent external Hub handle */ + void* context; /**< Ports' parent external Hub handle */ usb_device_handle_t parent_dev_hdl; /**< Ports' parent device handle */ uint8_t parent_port_num; /**< Ports' parent port number */ uint16_t port_power_delay_ms; /**< Ports' Power on time to Power Good, ms */ @@ -138,7 +183,28 @@ esp_err_t ext_port_process(void); * - NULL: The Driver has not been installed * - not NULL: Pointer to the External Port Driver API */ -const ext_hub_port_driver_t *ext_port_get_driver(void); +const ext_port_driver_api_t *ext_port_get_driver(void); + +/** + * @brief Returns External Port Driver's context + * + * @param[in] port_hdl Port object handle + * @return + * - Pointer to the External Port Driver context + */ +void* ext_port_get_context(ext_port_hdl_t port_hdl); + +/** + * @brief Returns External Port's port number + * + * @param[in] port_hdl Port object handle + * @param[out] port1 Port number, starting from 1 + * @return + * - ESP_ERR_NOT_ALLOWED if the External Port Driver has not been installed + * - ESP_ERR_INVALID_ARG if the Port handle is NULL + * - ESP_OK if the port number was successfully returned + */ +esp_err_t ext_port_get_port_num(ext_port_hdl_t port_hdl, uint8_t *port1); #ifdef __cplusplus } From 178ac8ee0f7bc84cbc07c5eee1b4c1d1f0449ee3 Mon Sep 17 00:00:00 2001 From: Roman Leonov Date: Tue, 4 Mar 2025 09:55:12 +0100 Subject: [PATCH 2/2] refactor(ext_port): Removed ext_hub dependency: update test_app --- components/usb/private_include/ext_port.h | 1 + .../test_apps/ext_port/main/ext_port_common.c | 155 +++++++++--------- .../test_apps/ext_port/main/ext_port_common.h | 17 +- .../test_apps/ext_port/main/test_ext_port.c | 78 ++++++--- 4 files changed, 151 insertions(+), 100 deletions(-) diff --git a/components/usb/private_include/ext_port.h b/components/usb/private_include/ext_port.h index 1758b0c140..0d12a68071 100644 --- a/components/usb/private_include/ext_port.h +++ b/components/usb/private_include/ext_port.h @@ -8,6 +8,7 @@ #include #include "esp_err.h" #include "usb/usb_types_stack.h" +#include "usb/usb_types_ch11.h" #include "sdkconfig.h" #ifdef __cplusplus diff --git a/components/usb/test_apps/ext_port/main/ext_port_common.c b/components/usb/test_apps/ext_port/main/ext_port_common.c index eb4e87e6c7..294c1642aa 100644 --- a/components/usb/test_apps/ext_port/main/ext_port_common.c +++ b/components/usb/test_apps/ext_port/main/ext_port_common.c @@ -73,11 +73,11 @@ const char *const ext_port_event_string[] = { }; typedef struct { - ext_hub_handle_t hub_hdl; - ext_hub_request_data_t data; + ext_port_hdl_t port_hdl; + ext_port_parent_request_data_t data; } ext_port_hub_request_msg_t; -static const ext_hub_port_driver_t* port_api; +static const ext_port_driver_api_t* port_api; SemaphoreHandle_t _process_cd_req = NULL; QueueHandle_t _ext_port_hub_req_queue = NULL; QueueHandle_t _ext_port_event_queue = NULL; @@ -89,22 +89,24 @@ static void test_ext_port_callback(void *user_arg) xSemaphoreGive(process_req_cb); } -static void test_ext_port_event_callback(ext_port_event_data_t *event_data, void *arg) +static void test_ext_port_event_callback(ext_port_hdl_t port_hdl, ext_port_event_data_t *event_data, void *arg) { QueueHandle_t ext_port_event_queue = (QueueHandle_t)arg; ext_port_event_data_t msg = *event_data; xQueueSend(ext_port_event_queue, &msg, portMAX_DELAY); } -static esp_err_t test_ext_port_hub_class_request(ext_hub_handle_t ext_hub_hdl, ext_hub_request_data_t *request_data, void *user_arg) +static esp_err_t test_ext_port_hub_request(ext_port_hdl_t port_hdl, ext_port_parent_request_data_t *data, void *user_arg) { QueueHandle_t hub_req_queue = (QueueHandle_t)user_arg; ext_port_hub_request_msg_t msg = { - .hub_hdl = ext_hub_hdl, + .port_hdl = port_hdl, .data = { - .request = request_data->request, - .port_num = request_data->port_num, - .feature = request_data->feature, + .type = data->type, + .control = { + .req = data->control.req, + .feature = data->control.feature, + }, }, }; xQueueSend(hub_req_queue, &msg, portMAX_DELAY); @@ -130,7 +132,7 @@ static void test_wait_ext_port_event(ext_port_event_t event) TEST_ASSERT_EQUAL_MESSAGE(event, msg.event, "Unexpected External Hub port event"); } -static esp_err_t test_wait_ext_port_hub_request(void *ext_hub_hdl, uint8_t port_num, usb_hub_class_request_t request) +static esp_err_t test_wait_ext_port_hub_request(ext_port_hdl_t port_hdl, ext_port_parent_request_type_t type, usb_hub_class_request_t request) { // Get the hub request queue TEST_ASSERT_NOT_NULL(_ext_port_hub_req_queue); @@ -142,16 +144,24 @@ static esp_err_t test_wait_ext_port_hub_request(void *ext_hub_hdl, uint8_t port_ return ESP_ERR_TIMEOUT; } // Check the contents of that event message - // TEST_ASSERT_EQUAL(ext_hub_hdl, msg.hub_hdl); // TODO: Enable verification after closing IDF-10023 - TEST_ASSERT_EQUAL(port_num, msg.data.port_num); - printf("\tCallback for class request: %s %s\n", hub_request_string[msg.data.request], - (msg.data.request == USB_B_REQUEST_HUB_SET_PORT_FEATURE || - msg.data.request == USB_B_REQUEST_HUB_CLEAR_FEATURE) - ? hub_feature_string[msg.data.feature] - : " "); - // Verify the request if it is not USB_B_REQUEST_ANY - if (msg.data.request != USB_B_REQUEST_ANY) { - TEST_ASSERT_EQUAL_MESSAGE(request, msg.data.request, "Unexpected request"); + // TEST_ASSERT_EQUAL(port_hdl, msg.port_hdl); // TODO: Enable verification after closing IDF-10023 + TEST_ASSERT_EQUAL(type, msg.data.type); + switch (type) { + case EXT_PORT_PARENT_REQ_CONTROL: + printf("\tCallback for class request: %s %s\n", hub_request_string[msg.data.control.req], + (msg.data.control.req == USB_B_REQUEST_HUB_SET_PORT_FEATURE || + msg.data.control.req == USB_B_REQUEST_HUB_CLEAR_FEATURE) + ? hub_feature_string[msg.data.control.feature] + : " "); + // Verify the request if it is not USB_B_REQUEST_ANY + if (msg.data.control.req != USB_B_REQUEST_ANY) { + TEST_ASSERT_EQUAL_MESSAGE(request, msg.data.control.req, "Unexpected request"); + } + break; + + default: + break; + } return ESP_OK; } @@ -173,7 +183,7 @@ void test_ext_port_setup(void) .proc_req_cb_arg = (void*)_process_cd_req, .event_cb = test_ext_port_event_callback, .event_cb_arg = (void*)_ext_port_event_queue, - .hub_request_cb = test_ext_port_hub_class_request, + .hub_request_cb = test_ext_port_hub_request, .hub_request_cb_arg = (void*)_ext_port_hub_req_queue, }; TEST_ASSERT_EQUAL(ESP_OK, ext_port_install(&ext_port_config)); @@ -200,8 +210,8 @@ ext_port_hdl_t test_ext_port_new(ext_port_config_t *config) // Process the port TEST_ASSERT_EQUAL(ESP_OK, ext_port_process()); // Newly added port should trigger the Get Port Status request on the parent hub - TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(NULL, - config->parent_port_num, + TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(port, + EXT_PORT_PARENT_REQ_CONTROL, USB_B_REQUEST_HUB_GET_PORT_STATUS)); // Process the port return port; } @@ -221,8 +231,8 @@ void test_ext_port_power_on(uint8_t port1, ext_port_hdl_t port_hdl) // Process the port TEST_ASSERT_EQUAL(ESP_OK, ext_port_process()); // Wait Set Feature - Port Power - TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(NULL, - port1, + TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(port_hdl, + EXT_PORT_PARENT_REQ_CONTROL, USB_B_REQUEST_HUB_SET_PORT_FEATURE)); // Power on the port hub_port_power_on(port1); @@ -233,8 +243,8 @@ void test_ext_port_power_on(uint8_t port1, ext_port_hdl_t port_hdl) // Process the port TEST_ASSERT_EQUAL(ESP_OK, ext_port_process()); // Wait Get Port Status - TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(NULL, - port1, + TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(port_hdl, + EXT_PORT_PARENT_REQ_CONTROL, USB_B_REQUEST_HUB_GET_PORT_STATUS)); // Get Port Status hub_get_port_status(port1, &port_status); @@ -260,11 +270,7 @@ void test_ext_port_disconnected(uint8_t port1, ext_port_hdl_t port_hdl) // Process the port TEST_ASSERT_EQUAL(ESP_OK, ext_port_process()); // Disconnected port doesn't require any processing, so there should be no process request - TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, test_wait_ext_port_hub_request(NULL, - port1, - USB_B_REQUEST_ANY)); - // Port doesn't require any processing, so there should debug message "No more ports to handle" - TEST_ASSERT_EQUAL(ESP_OK, ext_port_process()); // TODO: IDF-12562 replace with Enable INTR EP event await + TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(port_hdl, EXT_PORT_PARENT_REQ_PROC_COMPLETED, 0)); // Port is idle } @@ -285,8 +291,8 @@ usb_speed_t test_ext_port_connected(uint8_t port1, ext_port_hdl_t port_hdl) // Process the port TEST_ASSERT_EQUAL(ESP_OK, ext_port_process()); // Setting the status of the port with C_CONNECTION should trigger the Clear Port Connection - TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(NULL, - port1, + TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(port_hdl, + EXT_PORT_PARENT_REQ_CONTROL, USB_B_REQUEST_HUB_CLEAR_FEATURE)); // Clear Port Connection @@ -297,8 +303,8 @@ usb_speed_t test_ext_port_connected(uint8_t port1, ext_port_hdl_t port_hdl) // Process the port TEST_ASSERT_EQUAL(ESP_OK, ext_port_process()); // Powered port with connection should trigger the status update - TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(NULL, - port1, + TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(port_hdl, + EXT_PORT_PARENT_REQ_CONTROL, USB_B_REQUEST_HUB_GET_PORT_STATUS)); // Get Port Status hub_get_port_status(port1, &port_status); @@ -313,8 +319,8 @@ usb_speed_t test_ext_port_connected(uint8_t port1, ext_port_hdl_t port_hdl) // Setting the port status should trigger the process request callback TEST_ASSERT_EQUAL(ESP_OK, ext_port_process()); // Powered port with connection should trigger the Port Reset request on the parent hub - TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(NULL, - port1, + TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(port_hdl, + EXT_PORT_PARENT_REQ_CONTROL, USB_B_REQUEST_HUB_SET_PORT_FEATURE)); // Port Reset hub_port_reset(port1); @@ -326,8 +332,8 @@ usb_speed_t test_ext_port_connected(uint8_t port1, ext_port_hdl_t port_hdl) // Process the port TEST_ASSERT_EQUAL(ESP_OK, ext_port_process()); // Powered port with connection should trigger the Get Port Status request on the parent hub - TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(NULL, - port1, + TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(port_hdl, + EXT_PORT_PARENT_REQ_CONTROL, USB_B_REQUEST_HUB_GET_PORT_STATUS)); // Get Port Status hub_get_port_status(port1, &port_status); @@ -343,8 +349,8 @@ usb_speed_t test_ext_port_connected(uint8_t port1, ext_port_hdl_t port_hdl) // Process the port TEST_ASSERT_EQUAL(ESP_OK, ext_port_process()); // Powered port with connection after reset should trigger the Clear Port Reset request on the parent hub - TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(NULL, - port1, + TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(port_hdl, + EXT_PORT_PARENT_REQ_CONTROL, USB_B_REQUEST_HUB_CLEAR_FEATURE)); // Clear Port reset request hub_port_clear_reset(port1); @@ -355,8 +361,8 @@ usb_speed_t test_ext_port_connected(uint8_t port1, ext_port_hdl_t port_hdl) // Process the port TEST_ASSERT_EQUAL(ESP_OK, ext_port_process()); // Powered port with connection after reset should trigger the Get Port Status request on the parent hub - TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(NULL, - port1, + TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(port_hdl, + EXT_PORT_PARENT_REQ_CONTROL, USB_B_REQUEST_HUB_GET_PORT_STATUS)); // Get Port Status @@ -407,8 +413,8 @@ void test_ext_port_imitate_disconnection(uint8_t port1, ext_port_hdl_t port_hdl) // Process the port TEST_ASSERT_EQUAL(ESP_OK, ext_port_process()); // Setting the status of the port with connection should trigger the Clear Port Connection - TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(NULL, - port1, + TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(port_hdl, + EXT_PORT_PARENT_REQ_CONTROL, USB_B_REQUEST_HUB_CLEAR_FEATURE)); // Assume that clear connection done successfully, but we do not need actually change the port status // Clear Port Feature: C_CONNECTION - assume we done it, ESP_OK @@ -420,8 +426,8 @@ void test_ext_port_imitate_disconnection(uint8_t port1, ext_port_hdl_t port_hdl) // Process the port TEST_ASSERT_EQUAL(ESP_OK, ext_port_process()); // Cleared port connection should trigger the Get Port Status request on the parent hub - TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(NULL, - port1, + TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(port_hdl, + EXT_PORT_PARENT_REQ_CONTROL, USB_B_REQUEST_HUB_GET_PORT_STATUS)); // We don't need to request actual port status, proceed with cached status @@ -453,8 +459,8 @@ void test_ext_port_disable(uint8_t port1, ext_port_hdl_t port_hdl) test_wait_ext_port_process_request(); // Process the port TEST_ASSERT_EQUAL(ESP_OK, ext_port_process()); - TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(NULL, - port1, + TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(port_hdl, + EXT_PORT_PARENT_REQ_CONTROL, USB_B_REQUEST_HUB_CLEAR_FEATURE)); // When port is not gone, it should create a DISCONNECTION event test_wait_ext_port_event(EXT_PORT_DISCONNECTED); @@ -467,8 +473,8 @@ void test_ext_port_disable(uint8_t port1, ext_port_hdl_t port_hdl) // Process the port TEST_ASSERT_EQUAL(ESP_OK, ext_port_process()); // Cleared port enable should trigger the Get Port Status request on the parent hub - TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(NULL, - port1, + TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(port_hdl, + EXT_PORT_PARENT_REQ_CONTROL, USB_B_REQUEST_HUB_GET_PORT_STATUS)); // Get Port Status hub_get_port_status(port1, &port_status); @@ -481,25 +487,19 @@ void test_ext_port_disable(uint8_t port1, ext_port_hdl_t port_hdl) // Wait for the process request callback test_wait_ext_port_process_request(); // Port doesn't require any processing, so there should debug message "No more ports to handle" - TEST_ASSERT_EQUAL(ESP_OK, ext_port_process()); // TODO: IDF-12562 replace with Enable INTR EP event await - // Disabled port doesn't require any processing, so there should be no process request - TEST_ASSERT_EQUAL(ESP_ERR_TIMEOUT, test_wait_ext_port_hub_request(NULL, - port1, - USB_B_REQUEST_HUB_GET_PORT_STATUS)); + TEST_ASSERT_EQUAL(ESP_OK, ext_port_process()); + // Disabled port doesn't require any processing, handling should be completed + TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(port_hdl, EXT_PORT_PARENT_REQ_PROC_COMPLETED, 0)); // Port is disabled and wait device to be detached. // Terminal state } -void test_ext_port_gone(ext_port_hdl_t port_hdl, bool has_device) +void test_ext_port_gone(ext_port_hdl_t port_hdl, test_gone_flag_t flag) { - if (has_device) { + if (flag == GONE_DEVICE_PRESENT) { // Port is enabled, port gone returns ESP_ERR_NOT_FINISHED TEST_ASSERT_EQUAL(ESP_ERR_NOT_FINISHED, port_api->gone(port_hdl)); - // Wait for the process request callback - // test_ext_port_wait_process_request(); - // Port doesn't require any processing, so there should debug message "No more ports to handle" - // TEST_ASSERT_EQUAL(ESP_OK, ext_port_process()); // TODO: IDF-12562 replace with Enable INTR EP event await - // Get Disconnect event + // Mark the connected port as gone should trigger disconnect event if the port has a device test_wait_ext_port_event(EXT_PORT_DISCONNECTED); return; } @@ -512,14 +512,23 @@ void test_ext_port_delete(ext_port_hdl_t port_hdl) TEST_ASSERT_EQUAL(ESP_OK, port_api->del(port_hdl)); } -void test_ext_port_recycle(ext_port_hdl_t port_hdl) +void test_ext_port_recycle(ext_port_hdl_t port_hdl, test_recycle_flag_t flag) { - TEST_ASSERT_EQUAL(ESP_OK, port_api->recycle(port_hdl)); - // Recycling the port for the process request callback - test_wait_ext_port_process_request(); - // Process the port - TEST_ASSERT_EQUAL(ESP_OK, ext_port_process()); - // Port gone - // ? Port delete - // : Port is IDLE + switch (flag) { + case RECYCLE_PORT_IS_GONE: + // Recycling in not available for the gone port + TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, port_api->recycle(port_hdl)); + break; + case RECYCLE_PORT_PRESENT: + TEST_ASSERT_EQUAL(ESP_OK, port_api->recycle(port_hdl)); + // Recycling the port for the process request callback + test_wait_ext_port_process_request(); + // Process the port + TEST_ASSERT_EQUAL(ESP_OK, ext_port_process()); + TEST_ASSERT_EQUAL(ESP_OK, test_wait_ext_port_hub_request(port_hdl, EXT_PORT_PARENT_REQ_PROC_COMPLETED, 0)); + break; + default: + TEST_ASSERT(0); // Invalid flag + break; + } } diff --git a/components/usb/test_apps/ext_port/main/ext_port_common.h b/components/usb/test_apps/ext_port/main/ext_port_common.h index 83e7f7b772..8f95b448cf 100644 --- a/components/usb/test_apps/ext_port/main/ext_port_common.h +++ b/components/usb/test_apps/ext_port/main/ext_port_common.h @@ -6,6 +6,16 @@ #include "ext_port.h" +typedef enum { + RECYCLE_PORT_PRESENT = 0, + RECYCLE_PORT_IS_GONE +} test_recycle_flag_t; + +typedef enum { + GONE_DEVICE_PRESENT = 0, + GONE_DEVICE_NOT_PRESENT +} test_gone_flag_t; + /** * @brief External Port setup test * Create queues for events/callbacks and install External Port driver @@ -88,9 +98,9 @@ void test_ext_port_disable(uint8_t port1, ext_port_hdl_t port_hdl); * @brief Test External Port recycle * * @param[in] port_hdl External Port handle - * @param[in] has_device Device presence + * @param[in] flag Device presence */ -void test_ext_port_gone(ext_port_hdl_t port_hdl, bool has_device); +void test_ext_port_gone(ext_port_hdl_t port_hdl, test_gone_flag_t flag); /** * @brief Test External Port delete @@ -103,5 +113,6 @@ void test_ext_port_delete(ext_port_hdl_t port_hdl); * @brief Test External Port recycle * * @param[in] port_hdl External Port handle + * @param[in] flag Port recycle flag */ -void test_ext_port_recycle(ext_port_hdl_t port_hdl); +void test_ext_port_recycle(ext_port_hdl_t port_hdl, test_recycle_flag_t flag); diff --git a/components/usb/test_apps/ext_port/main/test_ext_port.c b/components/usb/test_apps/ext_port/main/test_ext_port.c index 55c66d7289..05658073f0 100644 --- a/components/usb/test_apps/ext_port/main/test_ext_port.c +++ b/components/usb/test_apps/ext_port/main/test_ext_port.c @@ -92,7 +92,7 @@ TEST_CASE("Port: disconnected", "[low_speed][full_speed][high_speed]") TEST_ASSERT_TRUE(TEST_PORT_NUM_EMPTY <= port_num); // Create External Port ext_port_config_t port_config = { - .ext_hub_hdl = (void*) hub_get_context() /* use any before IDF-10023 */, + .context = (void*) hub_get_context() /* use any before IDF-10023 */, .parent_dev_hdl = (void*) hub_get_context() /* use any before IDF-10023 */, .parent_port_num = TEST_PORT_NUM_EMPTY, .port_power_delay_ms = hub_get_port_poweron_delay_ms(), @@ -105,7 +105,7 @@ TEST_CASE("Port: disconnected", "[low_speed][full_speed][high_speed]") // Detach parent hub hub_detach(); // Notify port - test_ext_port_gone(port_hdl, false); + test_ext_port_gone(port_hdl, GONE_DEVICE_NOT_PRESENT); test_ext_port_delete(port_hdl); } @@ -136,7 +136,7 @@ TEST_CASE("Port: enumerate child device Low-speed", "[ext_port][low_speed]") TEST_ASSERT_TRUE(TEST_PORT_NUM_DEVICE_LS <= port_num); // Create External Port ext_port_config_t port_config = { - .ext_hub_hdl = (void*) hub_get_context() /* use any before IDF-10023 */, + .context = (void*) hub_get_context() /* use any before IDF-10023 */, .parent_dev_hdl = (void*) hub_get_context() /* use any before IDF-10023 */, .parent_port_num = TEST_PORT_NUM_DEVICE_LS, .port_power_delay_ms = hub_get_port_poweron_delay_ms(), @@ -157,12 +157,12 @@ TEST_CASE("Port: enumerate child device Low-speed", "[ext_port][low_speed]") hub_child_pipe_free(ctrl_pipe); // Wait disconnection test_ext_port_imitate_disconnection(TEST_PORT_NUM_DEVICE_LS, port_hdl); - // Recycle the port - test_ext_port_recycle(port_hdl); + // Recylce the port + test_ext_port_recycle(port_hdl, RECYCLE_PORT_PRESENT); // Detach hub hub_detach(); // Notify port - test_ext_port_gone(port_hdl, false); + test_ext_port_gone(port_hdl, GONE_DEVICE_NOT_PRESENT); test_ext_port_delete(port_hdl); } @@ -193,7 +193,7 @@ TEST_CASE("Port: enumerate child device Full-speed", "[ext_port][full_speed]") TEST_ASSERT_TRUE(TEST_PORT_NUM_DEVICE_FSHS <= port_num); // Create External Port ext_port_config_t port_config = { - .ext_hub_hdl = (void*) hub_get_context() /* use any before IDF-10023 */, + .context = (void*) hub_get_context() /* use any before IDF-10023 */, .parent_dev_hdl = (void*) hub_get_context() /* use any before IDF-10023 */, .parent_port_num = TEST_PORT_NUM_DEVICE_FSHS, .port_power_delay_ms = hub_get_port_poweron_delay_ms(), @@ -214,12 +214,12 @@ TEST_CASE("Port: enumerate child device Full-speed", "[ext_port][full_speed]") hub_child_pipe_free(ctrl_pipe); // Wait disconnection test_ext_port_imitate_disconnection(TEST_PORT_NUM_DEVICE_FSHS, port_hdl); - // Recycle the port - test_ext_port_recycle(port_hdl); + // Recylce the port + test_ext_port_recycle(port_hdl, RECYCLE_PORT_PRESENT); // Detach hub hub_detach(); // Notify port - test_ext_port_gone(port_hdl, false); + test_ext_port_gone(port_hdl, GONE_DEVICE_NOT_PRESENT); test_ext_port_delete(port_hdl); } @@ -250,7 +250,7 @@ TEST_CASE("Port: enumerate child device High-speed", "[ext_port][high_speed]") TEST_ASSERT_TRUE(TEST_PORT_NUM_DEVICE_FSHS <= port_num); // Create External Port ext_port_config_t port_config = { - .ext_hub_hdl = (void*) hub_get_context() /* use any before IDF-10023 */, + .context = (void*) hub_get_context() /* use any before IDF-10023 */, .parent_dev_hdl = (void*) hub_get_context() /* use any before IDF-10023 */, .parent_port_num = TEST_PORT_NUM_DEVICE_FSHS, .port_power_delay_ms = hub_get_port_poweron_delay_ms(), @@ -271,12 +271,12 @@ TEST_CASE("Port: enumerate child device High-speed", "[ext_port][high_speed]") hub_child_pipe_free(ctrl_pipe); // Wait disconnection test_ext_port_imitate_disconnection(TEST_PORT_NUM_DEVICE_FSHS, port_hdl); - // Recycle the port - test_ext_port_recycle(port_hdl); + // Recylce the port + test_ext_port_recycle(port_hdl, RECYCLE_PORT_PRESENT); // Detach hub hub_detach(); // Notify port - test_ext_port_gone(port_hdl, false); + test_ext_port_gone(port_hdl, GONE_DEVICE_NOT_PRESENT); test_ext_port_delete(port_hdl); } @@ -307,7 +307,7 @@ TEST_CASE("Port: recycle", "[ext_port][full_speed][high_speed]") TEST_ASSERT_TRUE(TEST_PORT_NUM_DEVICE_FSHS <= port_num); // Create External Port ext_port_config_t port_config = { - .ext_hub_hdl = (void*) hub_get_context() /* use any before IDF-10023 */, + .context = (void*) hub_get_context() /* use any before IDF-10023 */, .parent_dev_hdl = (void*) hub_get_context() /* use any before IDF-10023 */, .parent_port_num = TEST_PORT_NUM_DEVICE_FSHS, .port_power_delay_ms = hub_get_port_poweron_delay_ms(), @@ -324,7 +324,7 @@ TEST_CASE("Port: recycle", "[ext_port][full_speed][high_speed]") test_ext_port_imitate_disconnection(TEST_PORT_NUM_DEVICE_FSHS, port_hdl); // Recylce the port printf("Recycle the port...\n"); - test_ext_port_recycle(port_hdl); + test_ext_port_recycle(port_hdl, RECYCLE_PORT_PRESENT); // Repower the port as we use imitation for disconnection. Port state in the External Port Driver is not changed during that. hub_port_power_off(TEST_PORT_NUM_DEVICE_FSHS); hub_port_power_on(TEST_PORT_NUM_DEVICE_FSHS); @@ -337,14 +337,44 @@ TEST_CASE("Port: recycle", "[ext_port][full_speed][high_speed]") // Wait disconnection test_ext_port_imitate_disconnection(TEST_PORT_NUM_DEVICE_FSHS, port_hdl); // Recylce the port - test_ext_port_recycle(port_hdl); + test_ext_port_recycle(port_hdl, RECYCLE_PORT_PRESENT); // Detach hub hub_detach(); // Notify port - test_ext_port_gone(port_hdl, false); + test_ext_port_gone(port_hdl, GONE_DEVICE_NOT_PRESENT); test_ext_port_delete(port_hdl); } +TEST_CASE("Port: recycle when port is gone", "[ext_port][low_speed][full_speed][high_speed]") +{ + hub_attach(); + uint8_t port_num = hub_get_port_num(); + TEST_ASSERT_TRUE(TEST_PORT_NUM_DEVICE_FSHS <= port_num); + // Create External Port + ext_port_config_t port_config = { + .context = (void*) hub_get_context() /* use any before IDF-10023 */, + .parent_dev_hdl = (void*) hub_get_context() /* use any before IDF-10023 */, + .parent_port_num = TEST_PORT_NUM_DEVICE_FSHS, + .port_power_delay_ms = hub_get_port_poweron_delay_ms(), + }; + ext_port_hdl_t port_hdl = test_ext_port_new(&port_config); + // After adding the port, it is in POWERED_OFF state + test_ext_port_power_on(TEST_PORT_NUM_DEVICE_FSHS, port_hdl); + // Wait connection + usb_speed_t port_speed = test_ext_port_connected(TEST_PORT_NUM_DEVICE_FSHS, port_hdl); + printf("Hub port: %s speed device \n", (char*[]) { + "Low", "Full", "High" + }[port_speed]); + + // Detach hub + hub_detach(); + // Notify port + test_ext_port_gone(port_hdl, GONE_DEVICE_PRESENT); + // Recylce the port + test_ext_port_recycle(port_hdl, RECYCLE_PORT_IS_GONE); + // test_ext_port_delete(port_hdl); +} + /* Test the port disable procedure. @@ -367,7 +397,7 @@ TEST_CASE("Port: disable", "[ext_port][full_speed][high_speed]") TEST_ASSERT_TRUE(TEST_PORT_NUM_DEVICE_FSHS <= port_num); // Create External Port ext_port_config_t port_config = { - .ext_hub_hdl = (void*) hub_get_context() /* use any before IDF-10023 */, + .context = (void*) hub_get_context() /* use any before IDF-10023 */, .parent_dev_hdl = (void*) hub_get_context() /* use any before IDF-10023 */, .parent_port_num = TEST_PORT_NUM_DEVICE_FSHS, .port_power_delay_ms = hub_get_port_poweron_delay_ms(), @@ -385,7 +415,7 @@ TEST_CASE("Port: disable", "[ext_port][full_speed][high_speed]") // Detach hub hub_detach(); // Notify port - test_ext_port_gone(port_hdl, false); + test_ext_port_gone(port_hdl, GONE_DEVICE_NOT_PRESENT); test_ext_port_delete(port_hdl); } @@ -410,7 +440,7 @@ TEST_CASE("Port: gone in state - powered on", "[ext_port][full_speed][high_speed TEST_ASSERT_TRUE(TEST_PORT_NUM_DEVICE_FSHS <= port_num); // Create External Port ext_port_config_t port_config = { - .ext_hub_hdl = (void*) hub_get_context() /* use any before IDF-10023 */, + .context = (void*) hub_get_context() /* use any before IDF-10023 */, .parent_dev_hdl = (void*) hub_get_context() /* use any before IDF-10023 */, .parent_port_num = TEST_PORT_NUM_DEVICE_FSHS, .port_power_delay_ms = hub_get_port_poweron_delay_ms(), @@ -422,7 +452,7 @@ TEST_CASE("Port: gone in state - powered on", "[ext_port][full_speed][high_speed printf("Port Gone...\n"); hub_detach(); // Notify port - test_ext_port_gone(port_hdl, false); + test_ext_port_gone(port_hdl, GONE_DEVICE_NOT_PRESENT); test_ext_port_delete(port_hdl); } @@ -448,7 +478,7 @@ TEST_CASE("Port: gone in state - enabled", "[ext_port][full_speed][high_speed]") TEST_ASSERT_TRUE(TEST_PORT_NUM_DEVICE_FSHS <= port_num); // Create External Port ext_port_config_t port_config = { - .ext_hub_hdl = (void*) hub_get_context() /* use any before IDF-10023 */, + .context = (void*) hub_get_context() /* use any before IDF-10023 */, .parent_dev_hdl = (void*) hub_get_context() /* use any before IDF-10023 */, .parent_port_num = TEST_PORT_NUM_DEVICE_FSHS, .port_power_delay_ms = hub_get_port_poweron_delay_ms(), @@ -465,6 +495,6 @@ TEST_CASE("Port: gone in state - enabled", "[ext_port][full_speed][high_speed]") printf("Port Gone...\n"); hub_detach(); // Notify port - test_ext_port_gone(port_hdl, true); + test_ext_port_gone(port_hdl, GONE_DEVICE_PRESENT); test_ext_port_delete(port_hdl); }