mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-29 18:27:20 +02:00
refactor(ext_port): Changed the mechanism for hub class request
Merged all Hub Class specific request to one function. Added a callback for the External Port Driver to break the dependency from ext_hub.h
This commit is contained in:
@ -1707,92 +1707,46 @@ esp_err_t ext_hub_port_get_speed(ext_hub_handle_t ext_hub_hdl, uint8_t port_num,
|
||||
// --------------------------- USB Chapter 11 ----------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
esp_err_t ext_hub_set_port_feature(ext_hub_handle_t ext_hub_hdl, uint8_t port_num, uint8_t feature)
|
||||
esp_err_t ext_hub_class_request(ext_hub_handle_t ext_hub_hdl, ext_hub_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 && ext_hub_hdl != NULL, ESP_ERR_INVALID_ARG);
|
||||
|
||||
esp_err_t ret;
|
||||
EXT_HUB_CHECK(ext_hub_hdl != NULL, ESP_ERR_INVALID_ARG);
|
||||
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(port_num != 0 && port_num <= ext_hub_dev->constant.hub_desc->bNbrPorts, ESP_ERR_INVALID_SIZE);
|
||||
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);
|
||||
|
||||
USB_SETUP_PACKET_INIT_SET_PORT_FEATURE((usb_setup_packet_t *)transfer->data_buffer, port_num, feature);
|
||||
transfer->num_bytes = sizeof(usb_setup_packet_t);
|
||||
switch (data->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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
ext_hub_dev->single_thread.stage = EXT_HUB_STAGE_CHECK_PORT_FEATURE;
|
||||
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, "[%d:%d] Set port feature %#x, failed to submit ctrl urb: %s",
|
||||
ext_hub_dev->constant.dev_addr,
|
||||
port_num,
|
||||
feature,
|
||||
esp_err_to_name(ret));
|
||||
device_error(ext_hub_dev);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t ext_hub_clear_port_feature(ext_hub_handle_t ext_hub_hdl, uint8_t port_num, 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();
|
||||
|
||||
esp_err_t ret;
|
||||
EXT_HUB_CHECK(ext_hub_hdl != NULL, ESP_ERR_INVALID_ARG);
|
||||
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(port_num != 0 && 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);
|
||||
|
||||
USB_SETUP_PACKET_INIT_CLEAR_PORT_FEATURE((usb_setup_packet_t *)transfer->data_buffer, port_num, feature);
|
||||
transfer->num_bytes = sizeof(usb_setup_packet_t);
|
||||
|
||||
ext_hub_dev->single_thread.stage = EXT_HUB_STAGE_CHECK_PORT_FEATURE;
|
||||
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, "[%d:%d] Clear port feature %#x, failed to submit ctrl urb: %s",
|
||||
ext_hub_dev->constant.dev_addr,
|
||||
port_num,
|
||||
feature,
|
||||
esp_err_to_name(ret));
|
||||
device_error(ext_hub_dev);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t ext_hub_get_port_status(ext_hub_handle_t ext_hub_hdl, uint8_t port_num)
|
||||
{
|
||||
EXT_HUB_ENTER_CRITICAL();
|
||||
EXT_HUB_CHECK_FROM_CRIT(p_ext_hub_driver != NULL, ESP_ERR_NOT_ALLOWED);
|
||||
EXT_HUB_EXIT_CRITICAL();
|
||||
|
||||
esp_err_t ret;
|
||||
EXT_HUB_CHECK(ext_hub_hdl != NULL, ESP_ERR_INVALID_ARG);
|
||||
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(port_num != 0 && 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);
|
||||
|
||||
USB_SETUP_PACKET_INIT_GET_PORT_STATUS((usb_setup_packet_t *)transfer->data_buffer, port_num);
|
||||
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;
|
||||
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, "[%d:%d] Get port status, failed to submit ctrl urb: %s",
|
||||
ext_hub_dev->constant.dev_addr,
|
||||
port_num,
|
||||
ESP_LOGE(EXT_HUB_TAG, "Request %X, port %d, feature %d: failed to submit ctrl urb: %s",
|
||||
data->request, data->port_num, data->feature,
|
||||
esp_err_to_name(ret));
|
||||
device_error(ext_hub_dev);
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
@ -102,6 +102,8 @@ 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 */
|
||||
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;
|
||||
|
||||
@ -225,17 +227,25 @@ static inline bool port_has_finished_reset(ext_port_t *ext_port)
|
||||
* - ESP_ERR_INVALID_ARG: The parent hub handle couldn't be NULL
|
||||
* - ESP_ERR_INVALID_SIZE: The port number should be in a range: [1, .. , bNbrPort]
|
||||
* - ESP_ERR_INVALID_STATE: The parent hub device wasn't configured
|
||||
* - ESP_ERR_NOT_SUPPORTED: The request type is not supported by the External Hub Driver
|
||||
* - ESP_OK: Status has been requested
|
||||
*/
|
||||
static esp_err_t port_request_status(ext_port_t* ext_port)
|
||||
{
|
||||
esp_err_t ret = ext_hub_get_port_status(ext_port->constant.ext_hub_hdl, ext_port->constant.port_num);
|
||||
ext_hub_request_data_t req_data = {
|
||||
.request = USB_B_REQUEST_HUB_GET_PORT_STATUS,
|
||||
.port_num = ext_port->constant.port_num,
|
||||
};
|
||||
|
||||
esp_err_t ret = p_ext_port_driver->constant.hub_request_cb(ext_port->constant.ext_hub_hdl,
|
||||
&req_data,
|
||||
p_ext_port_driver->constant.hub_request_cb_arg);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
// Port is requesting status, lock the status
|
||||
ext_port->flags.status_lock = 1;
|
||||
return ret;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -254,9 +264,15 @@ 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)
|
||||
{
|
||||
esp_err_t ret = ext_hub_set_port_feature(ext_port->constant.ext_hub_hdl,
|
||||
ext_port->constant.port_num,
|
||||
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,
|
||||
};
|
||||
|
||||
esp_err_t ret = p_ext_port_driver->constant.hub_request_cb(ext_port->constant.ext_hub_hdl,
|
||||
&req_data,
|
||||
p_ext_port_driver->constant.hub_request_cb_arg);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
@ -293,9 +309,15 @@ 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)
|
||||
{
|
||||
esp_err_t ret = ext_hub_clear_port_feature(ext_port->constant.ext_hub_hdl,
|
||||
ext_port->constant.port_num,
|
||||
feature);
|
||||
ext_hub_request_data_t req_data = {
|
||||
.request = USB_B_REQUEST_HUB_CLEAR_FEATURE,
|
||||
.port_num = ext_port->constant.port_num,
|
||||
.feature = feature,
|
||||
};
|
||||
|
||||
esp_err_t ret = p_ext_port_driver->constant.hub_request_cb(ext_port->constant.ext_hub_hdl,
|
||||
&req_data,
|
||||
p_ext_port_driver->constant.hub_request_cb_arg);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
@ -684,7 +706,7 @@ static void handle_port_state(ext_port_t *ext_port)
|
||||
switch (curr_state) {
|
||||
case USB_PORT_STATE_NOT_CONFIGURED:
|
||||
new_state = USB_PORT_STATE_POWERED_OFF;
|
||||
port_request_status(ext_port);
|
||||
ESP_ERROR_CHECK(port_request_status(ext_port));
|
||||
need_handling = true;
|
||||
break;
|
||||
case USB_PORT_STATE_POWERED_OFF:
|
||||
@ -1302,6 +1324,10 @@ const ext_hub_port_driver_t ext_port_driver = {
|
||||
esp_err_t ext_port_install(const ext_port_driver_config_t *config)
|
||||
{
|
||||
EXT_PORT_CHECK(p_ext_port_driver == NULL, ESP_ERR_NOT_ALLOWED);
|
||||
EXT_PORT_CHECK(config != NULL, ESP_ERR_INVALID_ARG);
|
||||
EXT_PORT_CHECK(config->proc_req_cb != NULL, ESP_ERR_INVALID_ARG);
|
||||
EXT_PORT_CHECK(config->event_cb != NULL, ESP_ERR_INVALID_ARG);
|
||||
EXT_PORT_CHECK(config->hub_request_cb != NULL, ESP_ERR_INVALID_ARG);
|
||||
|
||||
ext_port_driver_t *ext_port_drv = heap_caps_calloc(1, sizeof(ext_port_driver_t), MALLOC_CAP_DEFAULT);
|
||||
EXT_PORT_CHECK(ext_port_drv != NULL, ESP_ERR_NO_MEM);
|
||||
@ -1311,6 +1337,8 @@ esp_err_t ext_port_install(const ext_port_driver_config_t *config)
|
||||
ext_port_drv->constant.proc_req_cb_arg = config->proc_req_cb_arg;
|
||||
ext_port_drv->constant.event_cb = config->event_cb;
|
||||
ext_port_drv->constant.event_cb_arg = config->event_cb_arg;
|
||||
ext_port_drv->constant.hub_request_cb = config->hub_request_cb;
|
||||
ext_port_drv->constant.hub_request_cb_arg = config->hub_request_cb_arg;
|
||||
TAILQ_INIT(&ext_port_drv->single_thread.pending_tailq);
|
||||
|
||||
p_ext_port_driver = ext_port_drv;
|
||||
|
@ -314,7 +314,7 @@ static inline bool _buffer_check_done(pipe_t *pipe)
|
||||
}
|
||||
#if (CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3)
|
||||
// The HW can't handle two transactions with preamble in one frame.
|
||||
// TODO: IDF-15060
|
||||
// TODO: IDF-12986
|
||||
if (pipe->ep_char.ls_via_fs_hub) {
|
||||
esp_rom_delay_us(1000);
|
||||
}
|
||||
@ -1539,7 +1539,7 @@ static void pipe_set_ep_char(const hcd_pipe_config_t *pipe_config, usb_transfer_
|
||||
ep_char->dev_addr = pipe_config->dev_addr;
|
||||
ep_char->ls_via_fs_hub = 0;
|
||||
if (pipe_idx > 0) {
|
||||
// TODO: remove warning after IDF-15060
|
||||
// TODO: remove warning after IDF-12986
|
||||
if (port_speed == USB_SPEED_FULL && pipe_config->dev_speed == USB_SPEED_LOW) {
|
||||
ESP_LOGW(HCD_DWC_TAG, "Low-speed, extra delay will be applied in ISR");
|
||||
ep_char->ls_via_fs_hub = 1;
|
||||
|
@ -536,6 +536,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,
|
||||
};
|
||||
ret = ext_port_install(&ext_port_config);
|
||||
if (ret != ESP_OK) {
|
||||
|
@ -34,6 +34,20 @@ 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 -------------------------
|
||||
|
||||
/**
|
||||
@ -273,54 +287,23 @@ esp_err_t ext_hub_port_get_speed(ext_hub_handle_t ext_hub_hdl, uint8_t port_num,
|
||||
// --------------------------- USB Chapter 11 ----------------------------------
|
||||
|
||||
/**
|
||||
* @brief Set Port Feature request
|
||||
* @brief USB Hub Class specific request
|
||||
*
|
||||
* @param[in] ext_hub_hdl External Hub device handle
|
||||
* @param[in] port_num Port number
|
||||
* @param[in] feature Port Feature to set
|
||||
* @note This function designed to be called from the External Port driver
|
||||
*
|
||||
* @param[in] ext_hub_hdl External Hub handle
|
||||
* @param[in] data Request data
|
||||
* @param[in] user_arg User argument
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Port's feature set successfully
|
||||
* - ESP_ERR_NOT_ALLOWED: External Hub driver is not installed
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
* - ESP_ERR_INVALID_SIZE: External Hub port number out of the hub's range
|
||||
* - ESP_ERR_INVALID_STATE: External Hub is not configured or suspended
|
||||
* - ESP_ERR_NOT_ALLOWED if External Hub Driver is not installed
|
||||
* - ESP_ERR_INVALID_ARG if invalid argument
|
||||
* - ESP_ERR_INVALID_SIZE if port number is out of the hub's range
|
||||
* - ESP_ERR_INVALID_STATE if the hub device wasn't configured
|
||||
* - ESP_ERR_NOT_SUPPORTED if the request is not supported
|
||||
* - ESP_OK if control transfer was successfully submitted
|
||||
*/
|
||||
esp_err_t ext_hub_set_port_feature(ext_hub_handle_t ext_hub_hdl, uint8_t port_num, uint8_t feature);
|
||||
|
||||
/**
|
||||
* @brief Clear Port Feature request
|
||||
*
|
||||
* @param[in] ext_hub_hdl External Hub device handle
|
||||
* @param[in] port_num Port number
|
||||
* @param[in] feature Port Feature to clear
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Port's feature cleared successfully
|
||||
* - ESP_ERR_NOT_ALLOWED: External Hub driver is not installed
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
* - ESP_ERR_INVALID_SIZE: External Hub port number out of the hub's range
|
||||
* - ESP_ERR_INVALID_STATE: External Hub is not configured or suspended
|
||||
*/
|
||||
esp_err_t ext_hub_clear_port_feature(ext_hub_handle_t ext_hub_hdl, uint8_t port_num, uint8_t feature);
|
||||
|
||||
/**
|
||||
* @brief Get Port Status request
|
||||
*
|
||||
* Sends the request to retrieve port status data.
|
||||
* Actual port status data could be requested by calling ext_hub_get_port_status() after request completion.
|
||||
*
|
||||
* @param[in] ext_hub_hdl External Hub device handle
|
||||
* @param[in] port_num Port number
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Port's status obtained successfully
|
||||
* - ESP_ERR_NOT_ALLOWED: External Hub driver is not installed
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
* - ESP_ERR_INVALID_SIZE: External Hub port number out of the hub's range
|
||||
* - ESP_ERR_INVALID_STATE: External Hub is not configured or suspended
|
||||
*/
|
||||
esp_err_t ext_hub_get_port_status(ext_hub_handle_t ext_hub_hdl, uint8_t port_num);
|
||||
esp_err_t ext_hub_class_request(ext_hub_handle_t ext_hub_hdl, ext_hub_request_data_t *data, void *user_arg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
@ -72,6 +72,8 @@ 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 */
|
||||
void *hub_request_cb_arg; /**< External Port Hub request callback argument */
|
||||
} ext_port_driver_config_t;
|
||||
|
||||
/**
|
||||
|
Reference in New Issue
Block a user