refactor(ext_port): Removed ext_hub dependency

This commit is contained in:
Roman Leonov
2025-03-03 14:55:21 +01:00
parent c391c835c2
commit b2c3c9471e
5 changed files with 189 additions and 105 deletions

View File

@ -146,7 +146,7 @@ typedef struct {
struct { struct {
ext_hub_cb_t proc_req_cb; /**< Process callback */ ext_hub_cb_t proc_req_cb; /**< Process callback */
void *proc_req_cb_arg; /**< Process callback argument */ 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 */ } constant; /**< Constant members. Do not change after installation thus do not require a critical section or mutex */
} ext_hub_driver_t; } ext_hub_driver_t;
@ -397,7 +397,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) 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_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_dev_hdl = ext_hub_dev->constant.dev_hdl,
.parent_port_num = port_idx + 1, .parent_port_num = port_idx + 1,
.port_power_delay_ms = ext_hub_dev->constant.hub_desc->bPwrOn2PwrGood * 2, .port_power_delay_ms = ext_hub_dev->constant.hub_desc->bPwrOn2PwrGood * 2,
@ -1703,52 +1703,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); 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; 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; usb_transfer_t *transfer = &ext_hub_dev->constant.ctrl_urb->transfer;
switch (request) {
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) {
case USB_B_REQUEST_HUB_GET_PORT_STATUS: 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); 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; ext_hub_dev->single_thread.stage = EXT_HUB_STAGE_CHECK_PORT_STATUS;
break; break;
case USB_B_REQUEST_HUB_SET_PORT_FEATURE: 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); transfer->num_bytes = sizeof(usb_setup_packet_t);
ext_hub_dev->single_thread.stage = EXT_HUB_STAGE_CHECK_PORT_FEATURE; ext_hub_dev->single_thread.stage = EXT_HUB_STAGE_CHECK_PORT_FEATURE;
break; break;
case USB_B_REQUEST_HUB_CLEAR_FEATURE: 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); transfer->num_bytes = sizeof(usb_setup_packet_t);
ext_hub_dev->single_thread.stage = EXT_HUB_STAGE_CHECK_PORT_FEATURE; ext_hub_dev->single_thread.stage = EXT_HUB_STAGE_CHECK_PORT_FEATURE;
break; break;
default: 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; return ESP_ERR_NOT_SUPPORTED;
} }
ret = usbh_dev_submit_ctrl_urb(ext_hub_dev->constant.dev_hdl, ext_hub_dev->constant.ctrl_urb); ret = usbh_dev_submit_ctrl_urb(ext_hub_dev->constant.dev_hdl, ext_hub_dev->constant.ctrl_urb);
if (ret != ESP_OK) { if (ret != ESP_OK) {
ESP_LOGE(EXT_HUB_TAG, "Request %X, port %d, feature %d: failed to submit ctrl urb: %s", 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)); esp_err_to_name(ret));
device_error(ext_hub_dev); device_error(ext_hub_dev);
} }
return ret; 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;
}

View File

@ -78,7 +78,7 @@ struct ext_port_s {
usb_device_handle_t parent_dev_hdl; /**< Ports' parent device handle */ usb_device_handle_t parent_dev_hdl; /**< Ports' parent device handle */
uint8_t parent_dev_addr; /**< Ports' parent device bus address */ uint8_t parent_dev_addr; /**< Ports' parent device bus address */
// Port related constant members // 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 */ uint8_t port_num; /**< Ports' parent External Hub Port number */
int power_on_delay_ms; /**< Ports' Power on time to Power Good, ms */ 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 */ } 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 */ void *proc_req_cb_arg; /**< External Port process callback argument */
ext_port_event_cb_t event_cb; /**< External Port event callback */ ext_port_event_cb_t event_cb; /**< External Port event callback */
void *event_cb_arg; /**< External Port event callback argument */ 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 */ 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 */ } constant; /**< Constant members. Do not change after installation thus do not require a critical section or mutex */
} ext_port_driver_t; } 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) static esp_err_t port_request_status(ext_port_t* ext_port)
{ {
ext_hub_request_data_t req_data = { ext_port_parent_request_data_t data = {
.request = USB_B_REQUEST_HUB_GET_PORT_STATUS, .type = EXT_PORT_PARENT_REQ_CONTROL,
.port_num = ext_port->constant.port_num, .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, esp_err_t ret = p_ext_port_driver->constant.hub_request_cb((ext_port_hdl_t)ext_port,
&req_data, &data,
p_ext_port_driver->constant.hub_request_cb_arg); p_ext_port_driver->constant.hub_request_cb_arg);
if (ret != ESP_OK) { if (ret != ESP_OK) {
return ret; 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) 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 = { ext_port_parent_request_data_t data = {
.request = USB_B_REQUEST_HUB_SET_PORT_FEATURE, .type = EXT_PORT_PARENT_REQ_CONTROL,
.port_num = ext_port->constant.port_num, .control = {
.feature = feature, .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, esp_err_t ret = p_ext_port_driver->constant.hub_request_cb((ext_port_hdl_t)ext_port,
&req_data, &data,
p_ext_port_driver->constant.hub_request_cb_arg); p_ext_port_driver->constant.hub_request_cb_arg);
if (ret != ESP_OK) { if (ret != ESP_OK) {
return ret; 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) 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 = { ext_port_parent_request_data_t data = {
.request = USB_B_REQUEST_HUB_CLEAR_FEATURE, .type = EXT_PORT_PARENT_REQ_CONTROL,
.port_num = ext_port->constant.port_num, .control = {
.feature = feature, .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, esp_err_t ret = p_ext_port_driver->constant.hub_request_cb((ext_port_hdl_t)ext_port,
&req_data, &data,
p_ext_port_driver->constant.hub_request_cb_arg); p_ext_port_driver->constant.hub_request_cb_arg);
if (ret != ESP_OK) { if (ret != ESP_OK) {
return ret; return ret;
@ -410,7 +416,6 @@ static void port_event(ext_port_t *ext_port, ext_port_event_t event)
}; };
switch (event) { switch (event) {
case EXT_PORT_CONNECTED: 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_dev_hdl = ext_port->constant.parent_dev_hdl;
event_data.connected.parent_port_num = ext_port->constant.port_num; event_data.connected.parent_port_num = ext_port->constant.port_num;
break; break;
@ -428,7 +433,7 @@ static void port_event(ext_port_t *ext_port, ext_port_event_t event)
break; 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 state: USB_PORT_STATE_NOT_CONFIGURED
* - Port device status: PORT_DEV_NOT_PRESENT * - 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_dev_hdl Ports' parent device handle
* @param[in] parent_port_num Ports' parent port number * @param[in] parent_port_num Ports' parent port number
* @param[in] port_delay_ms Ports' Power on time to Power Good, ms * @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_ERR_NOT_FINISHED: Unable to allocate the port object: parent device is not available
* - ESP_OK: Port object created successfully * - 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; 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. // 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 // 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); 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_hdl = parent_dev_hdl;
ext_port->constant.parent_dev_addr = parent_dev_addr; 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; ext_port->constant.port_num = parent_port_num;
#if (EXT_PORT_POWER_ON_CUSTOM_DELAY) #if (EXT_PORT_POWER_ON_CUSTOM_DELAY)
ext_port->constant.power_on_delay_ms = EXT_PORT_POWER_ON_CUSTOM_DELAY_MS; 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 // When multiply Hubs are attached, we can have ports in pending list, but for another parent
ext_port_t *port = NULL; ext_port_t *port = NULL;
TAILQ_FOREACH(port, &p_ext_port_driver->single_thread.pending_tailq, tailq_entry) { 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 // Port with same parent has been found
all_ports_were_handled = false; all_ports_were_handled = false;
break; break;
@ -559,7 +564,13 @@ static esp_err_t handle_complete(ext_port_t *ext_port)
if (all_ports_were_handled) { if (all_ports_were_handled) {
// Notify parent to enable Interrupt EP // 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) { 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_t *port = NULL;
ext_port_config_t *config = (ext_port_config_t *)port_cfg; 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_dev_hdl,
config->parent_port_num, config->parent_port_num,
config->port_power_delay_ms, 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_CHECK(port_hdl != NULL, ESP_ERR_INVALID_ARG);
ext_port_t *ext_port = (ext_port_t *) port_hdl; 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); 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); 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 * @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, .new = port_new,
.reset = port_reset, .reset = port_reset,
.recycle = port_recycle, .recycle = port_recycle,
@ -1425,8 +1437,24 @@ esp_err_t ext_port_process(void)
return ESP_OK; 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); EXT_PORT_CHECK(p_ext_port_driver != NULL, NULL);
return &ext_port_driver; 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;
}

View File

@ -20,7 +20,7 @@
#include "usb/usb_helpers.h" #include "usb/usb_helpers.h"
#if ENABLE_USB_HUBS #if ENABLE_USB_HUBS
#include "ext_port.h" #include "ext_hub.h"
#endif // ENABLE_USB_HUBS #endif // ENABLE_USB_HUBS
/* /*
@ -326,14 +326,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); 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) { switch (event_data->event) {
case EXT_PORT_CONNECTED: case EXT_PORT_CONNECTED:
// First reset is done by ext_port logic // First reset is done by ext_port logic
usb_speed_t port_speed; 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, event_data->connected.parent_port_num,
&port_speed) != ESP_OK) { &port_speed) != ESP_OK) {
goto new_ds_dev_err; goto new_ds_dev_err;
@ -358,7 +360,7 @@ static void ext_port_event_callback(ext_port_event_data_t *event_data, void *arg
} }
break; break;
new_ds_dev_err: 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; break;
case EXT_PORT_RESET_COMPLETED: 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)); ESP_ERROR_CHECK(dev_tree_node_reset_completed(event_data->reset_completed.parent_dev_hdl, event_data->reset_completed.parent_port_num));
@ -536,7 +538,7 @@ esp_err_t hub_install(hub_config_t *hub_config, void **client_ret)
ext_port_driver_config_t ext_port_config = { ext_port_driver_config_t ext_port_config = {
.proc_req_cb = ext_port_callback, .proc_req_cb = ext_port_callback,
.event_cb = ext_port_event_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); ret = ext_port_install(&ext_port_config);
if (ret != ESP_OK) { if (ret != ESP_OK) {

View File

@ -13,10 +13,7 @@
#include "usb/usb_types_stack.h" #include "usb/usb_types_stack.h"
#include "usb/usb_types_ch9.h" #include "usb/usb_types_ch9.h"
#include "usb/usb_types_ch11.h" #include "usb/usb_types_ch11.h"
#include "ext_port.h"
#if CONFIG_USB_HOST_HUB_MULTI_LEVEL
#define ENABLE_MULTIPLE_HUBS 1
#endif // CONFIG_USB_HOST_HUB_MULTI_LEVEL
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { 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); 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 * @brief External Hub Driver configuration
*/ */
typedef struct { typedef struct {
ext_hub_cb_t proc_req_cb; /**< External Hub process callback */ ext_hub_cb_t proc_req_cb; /**< External Hub process callback */
void *proc_req_cb_arg; /**< External Hub process callback argument */ 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; } ext_hub_config_t;
// ------------------------------ Driver --------------------------------------- // ------------------------------ 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 ---------------------------------- // --------------------------- 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 * @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] data Request data
* @param[in] user_arg User argument * @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_ERR_NOT_SUPPORTED if the request is not supported
* - ESP_OK if control transfer was successfully submitted * - 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 #ifdef __cplusplus
} }

View File

@ -7,15 +7,38 @@
#include <stdint.h> #include <stdint.h>
#include "esp_err.h" #include "esp_err.h"
#include "ext_hub.h"
#include "usb/usb_types_stack.h" #include "usb/usb_types_stack.h"
#include "sdkconfig.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #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; 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 --------------------------------------- // ------------------------------ Events ---------------------------------------
typedef enum { typedef enum {
EXT_PORT_CONNECTED = 0x01, /**< Port has a device connection event */ EXT_PORT_CONNECTED = 0x01, /**< Port has a device connection event */
@ -30,7 +53,6 @@ typedef struct {
ext_port_event_t event; ext_port_event_t event;
union { union {
struct { struct {
ext_hub_handle_t ext_hub_hdl; /**< Ports' parent external Hub handle */
usb_device_handle_t parent_dev_hdl; /**< Ports' parent device handle */ usb_device_handle_t parent_dev_hdl; /**< Ports' parent device handle */
uint8_t parent_port_num; /**< Ports' parent port number */ uint8_t parent_port_num; /**< Ports' parent port number */
} connected; /**< EXT_PORT_CONNECTED event specific data */ } connected; /**< EXT_PORT_CONNECTED event specific data */
@ -47,6 +69,24 @@ typedef struct {
}; };
} ext_port_event_data_t; } 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 ------------------------------------ // ------------------------------ Callbacks ------------------------------------
/** /**
* @brief Callback used to indicate that the External Port Driver requires process callback * @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 * @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 ------------------------ // ----------------- External Port Driver configuration ------------------------
@ -72,7 +117,7 @@ typedef struct {
void *proc_req_cb_arg; /**< External Port process callback argument */ void *proc_req_cb_arg; /**< External Port process callback argument */
ext_port_event_cb_t event_cb; /**< External Port event callback */ ext_port_event_cb_t event_cb; /**< External Port event callback */
void *event_cb_arg; /**< External Port event callback argument */ 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 */ void *hub_request_cb_arg; /**< External Port Hub request callback argument */
} ext_port_driver_config_t; } ext_port_driver_config_t;
@ -82,7 +127,7 @@ typedef struct {
* Structure is used to create new port * Structure is used to create new port
*/ */
typedef struct { 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 */ usb_device_handle_t parent_dev_hdl; /**< Ports' parent device handle */
uint8_t parent_port_num; /**< Ports' parent port number */ uint8_t parent_port_num; /**< Ports' parent port number */
uint16_t port_power_delay_ms; /**< Ports' Power on time to Power Good, ms */ 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 * - NULL: The Driver has not been installed
* - not NULL: Pointer to the External Port Driver API * - 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 #ifdef __cplusplus
} }