Merge branch 'refactor/usbh_event_callback_api' into 'master'

refactor(usb): Update USBH event callback arguments

See merge request espressif/esp-idf!29199
This commit is contained in:
Darian
2024-03-07 02:55:48 +08:00
3 changed files with 79 additions and 52 deletions

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -29,12 +29,36 @@ typedef struct usbh_ep_handle_s *usbh_ep_handle_t;
// ----------------------- Events -------------------------- // ----------------------- Events --------------------------
/**
* @brief Enumerator for various USBH events
*/
typedef enum { typedef enum {
USBH_EVENT_DEV_NEW, /**< A new device has been enumerated and added to the device pool */ USBH_EVENT_CTRL_XFER, /**< A control transfer has completed */
USBH_EVENT_NEW_DEV, /**< A new device has been enumerated and added to the device pool */
USBH_EVENT_DEV_GONE, /**< A device is gone. Clients should close the device */ USBH_EVENT_DEV_GONE, /**< A device is gone. Clients should close the device */
USBH_EVENT_DEV_ALL_FREE, /**< All devices have been freed */ USBH_EVENT_ALL_FREE, /**< All devices have been freed */
} usbh_event_t; } usbh_event_t;
/**
* @brief Event data object for USBH events
*/
typedef struct {
usbh_event_t event;
union {
struct {
usb_device_handle_t dev_hdl;
urb_t *urb;
} ctrl_xfer_data;
struct {
uint8_t dev_addr;
} new_dev_data;
struct {
uint8_t dev_addr;
usb_device_handle_t dev_hdl;
} dev_gone_data;
};
} usbh_event_data_t;
/** /**
* @brief Endpoint events * @brief Endpoint events
* *
@@ -99,19 +123,12 @@ typedef enum {
// ---------------------- Callbacks ------------------------ // ---------------------- Callbacks ------------------------
/**
* @brief Callback used to indicate completion of control transfers submitted usbh_dev_submit_ctrl_urb()
* @note This callback is called from within usbh_process()
*/
typedef void (*usbh_ctrl_xfer_cb_t)(usb_device_handle_t dev_hdl, urb_t *urb, void *arg);
/** /**
* @brief Callback used to indicate that the USBH has an event * @brief Callback used to indicate that the USBH has an event
* *
* @note This callback is called from within usbh_process() * @note This callback is called from within usbh_process()
* @note On a USBH_EVENT_DEV_ALL_FREE event, the dev_hdl argument is set to NULL
*/ */
typedef void (*usbh_event_cb_t)(usb_device_handle_t dev_hdl, usbh_event_t usbh_event, void *arg); typedef void (*usbh_event_cb_t)(usbh_event_data_t *event_data, void *arg);
/** /**
* @brief Callback used by the USBH to request actions from the Hub driver * @brief Callback used by the USBH to request actions from the Hub driver
@@ -148,8 +165,6 @@ typedef struct {
typedef struct { typedef struct {
usb_proc_req_cb_t proc_req_cb; /**< Processing request callback */ usb_proc_req_cb_t proc_req_cb; /**< Processing request callback */
void *proc_req_cb_arg; /**< Processing request callback argument */ void *proc_req_cb_arg; /**< Processing request callback argument */
usbh_ctrl_xfer_cb_t ctrl_xfer_cb; /**< Control transfer callback */
void *ctrl_xfer_cb_arg; /**< Control transfer callback argument */
usbh_event_cb_t event_cb; /**< USBH event callback */ usbh_event_cb_t event_cb; /**< USBH event callback */
void *event_cb_arg; /**< USBH event callback argument */ void *event_cb_arg; /**< USBH event callback argument */
} usbh_config_t; } usbh_config_t;
@@ -497,7 +512,7 @@ esp_err_t usbh_hub_enum_fill_str_desc(usb_device_handle_t dev_hdl, const usb_str
/** /**
* @brief Indicate the device enumeration is completed * @brief Indicate the device enumeration is completed
* *
* This will all the device to be opened by clients, and also trigger a USBH_EVENT_DEV_NEW event. * This will allow the device to be opened by clients, and also trigger a USBH_EVENT_NEW_DEV event.
* *
* @note Hub Driver only * @note Hub Driver only
* @note Must call in sequence * @note Must call in sequence

View File

@@ -262,46 +262,41 @@ static bool proc_req_callback(usb_proc_req_source_t source, bool in_isr, void *a
return yield; return yield;
} }
static void ctrl_xfer_callback(usb_device_handle_t dev_hdl, urb_t *urb, void *arg) static void usbh_event_callback(usbh_event_data_t *event_data, void *arg)
{ {
assert(urb->usb_host_client != NULL); switch (event_data->event) {
// Redistribute done control transfer to the clients that submitted them case USBH_EVENT_CTRL_XFER: {
client_t *client_obj = (client_t *)urb->usb_host_client; assert(event_data->ctrl_xfer_data.urb != NULL);
assert(event_data->ctrl_xfer_data.urb->usb_host_client != NULL);
// Redistribute done control transfer to the clients that submitted them
client_t *client_obj = (client_t *)event_data->ctrl_xfer_data.urb->usb_host_client;
HOST_ENTER_CRITICAL(); HOST_ENTER_CRITICAL();
TAILQ_INSERT_TAIL(&client_obj->dynamic.done_ctrl_xfer_tailq, urb, tailq_entry); TAILQ_INSERT_TAIL(&client_obj->dynamic.done_ctrl_xfer_tailq, event_data->ctrl_xfer_data.urb, tailq_entry);
client_obj->dynamic.num_done_ctrl_xfer++; client_obj->dynamic.num_done_ctrl_xfer++;
_unblock_client(client_obj, false); _unblock_client(client_obj, false);
HOST_EXIT_CRITICAL(); HOST_EXIT_CRITICAL();
} break;
}
static void dev_event_callback(usb_device_handle_t dev_hdl, usbh_event_t usbh_event, void *arg) case USBH_EVENT_NEW_DEV: {
{
// Check usbh_event. The data type of event_arg depends on the type of event
switch (usbh_event) {
case USBH_EVENT_DEV_NEW: {
// Prepare a NEW_DEV client event message, the send it to all clients // Prepare a NEW_DEV client event message, the send it to all clients
uint8_t dev_addr;
ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr));
usb_host_client_event_msg_t event_msg = { usb_host_client_event_msg_t event_msg = {
.event = USB_HOST_CLIENT_EVENT_NEW_DEV, .event = USB_HOST_CLIENT_EVENT_NEW_DEV,
.new_dev.address = dev_addr, .new_dev.address = event_data->new_dev_data.dev_addr,
}; };
send_event_msg_to_clients(&event_msg, true, 0); send_event_msg_to_clients(&event_msg, true, 0);
break; break;
} }
case USBH_EVENT_DEV_GONE: { case USBH_EVENT_DEV_GONE: {
// Prepare event msg, send only to clients that have opened the device // Prepare event msg, send only to clients that have opened the device
uint8_t dev_addr;
ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr));
usb_host_client_event_msg_t event_msg = { usb_host_client_event_msg_t event_msg = {
.event = USB_HOST_CLIENT_EVENT_DEV_GONE, .event = USB_HOST_CLIENT_EVENT_DEV_GONE,
.dev_gone.dev_hdl = dev_hdl, .dev_gone.dev_hdl = event_data->dev_gone_data.dev_hdl,
}; };
send_event_msg_to_clients(&event_msg, false, dev_addr); send_event_msg_to_clients(&event_msg, false, event_data->dev_gone_data.dev_addr);
break; break;
} }
case USBH_EVENT_DEV_ALL_FREE: { case USBH_EVENT_ALL_FREE: {
// Notify the lib handler that all devices are free // Notify the lib handler that all devices are free
HOST_ENTER_CRITICAL(); HOST_ENTER_CRITICAL();
p_host_lib_obj->dynamic.lib_event_flags |= USB_HOST_LIB_EVENT_FLAGS_ALL_FREE; p_host_lib_obj->dynamic.lib_event_flags |= USB_HOST_LIB_EVENT_FLAGS_ALL_FREE;
@@ -399,9 +394,7 @@ esp_err_t usb_host_install(const usb_host_config_t *config)
usbh_config_t usbh_config = { usbh_config_t usbh_config = {
.proc_req_cb = proc_req_callback, .proc_req_cb = proc_req_callback,
.proc_req_cb_arg = NULL, .proc_req_cb_arg = NULL,
.ctrl_xfer_cb = ctrl_xfer_callback, .event_cb = usbh_event_callback,
.ctrl_xfer_cb_arg = NULL,
.event_cb = dev_event_callback,
.event_cb_arg = NULL, .event_cb_arg = NULL,
}; };
ret = usbh_install(&usbh_config); ret = usbh_install(&usbh_config);

View File

@@ -1,5 +1,5 @@
/* /*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD * SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* *
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
*/ */
@@ -35,7 +35,7 @@ typedef enum {
DEV_ACTION_FREE_AND_RECOVER = (1 << 5), // Free the device object, but send a USBH_HUB_REQ_PORT_RECOVER request afterwards. DEV_ACTION_FREE_AND_RECOVER = (1 << 5), // Free the device object, but send a USBH_HUB_REQ_PORT_RECOVER request afterwards.
DEV_ACTION_FREE = (1 << 6), // Free the device object DEV_ACTION_FREE = (1 << 6), // Free the device object
DEV_ACTION_PORT_DISABLE = (1 << 7), // Request the hub driver to disable the port of the device DEV_ACTION_PORT_DISABLE = (1 << 7), // Request the hub driver to disable the port of the device
DEV_ACTION_PROP_NEW = (1 << 8), // Propagate a USBH_EVENT_DEV_NEW event DEV_ACTION_PROP_NEW = (1 << 8), // Propagate a USBH_EVENT_NEW_DEV event
} dev_action_t; } dev_action_t;
typedef struct device_s device_t; typedef struct device_s device_t;
@@ -110,8 +110,6 @@ typedef struct {
void *hub_req_cb_arg; void *hub_req_cb_arg;
usbh_event_cb_t event_cb; usbh_event_cb_t event_cb;
void *event_cb_arg; void *event_cb_arg;
usbh_ctrl_xfer_cb_t ctrl_xfer_cb;
void *ctrl_xfer_cb_arg;
SemaphoreHandle_t mux_lock; SemaphoreHandle_t mux_lock;
} constant; } constant;
} usbh_t; } usbh_t;
@@ -482,7 +480,14 @@ static inline void handle_ep0_dequeue(device_t *dev_obj)
urb_t *urb = hcd_urb_dequeue(dev_obj->constant.default_pipe); urb_t *urb = hcd_urb_dequeue(dev_obj->constant.default_pipe);
while (urb != NULL) { while (urb != NULL) {
num_urbs++; num_urbs++;
p_usbh_obj->constant.ctrl_xfer_cb((usb_device_handle_t)dev_obj, urb, p_usbh_obj->constant.ctrl_xfer_cb_arg); usbh_event_data_t event_data = {
.event = USBH_EVENT_CTRL_XFER,
.ctrl_xfer_data = {
.dev_hdl = (usb_device_handle_t)dev_obj,
.urb = urb,
},
};
p_usbh_obj->constant.event_cb(&event_data, p_usbh_obj->constant.event_cb_arg);
urb = hcd_urb_dequeue(dev_obj->constant.default_pipe); urb = hcd_urb_dequeue(dev_obj->constant.default_pipe);
} }
USBH_ENTER_CRITICAL(); USBH_ENTER_CRITICAL();
@@ -500,7 +505,14 @@ static inline void handle_prop_gone_evt(device_t *dev_obj)
{ {
// Flush EP0's pipe. Then propagate a USBH_EVENT_DEV_GONE event // Flush EP0's pipe. Then propagate a USBH_EVENT_DEV_GONE event
ESP_LOGE(USBH_TAG, "Device %d gone", dev_obj->constant.address); ESP_LOGE(USBH_TAG, "Device %d gone", dev_obj->constant.address);
p_usbh_obj->constant.event_cb((usb_device_handle_t)dev_obj, USBH_EVENT_DEV_GONE, p_usbh_obj->constant.event_cb_arg); usbh_event_data_t event_data = {
.event = USBH_EVENT_DEV_GONE,
.dev_gone_data = {
.dev_addr = dev_obj->constant.address,
.dev_hdl = (usb_device_handle_t)dev_obj,
},
};
p_usbh_obj->constant.event_cb(&event_data, p_usbh_obj->constant.event_cb_arg);
} }
static void handle_free_and_recover(device_t *dev_obj, bool recover_port) static void handle_free_and_recover(device_t *dev_obj, bool recover_port)
@@ -526,10 +538,13 @@ static void handle_free_and_recover(device_t *dev_obj, bool recover_port)
xSemaphoreGive(p_usbh_obj->constant.mux_lock); xSemaphoreGive(p_usbh_obj->constant.mux_lock);
device_free(dev_obj); device_free(dev_obj);
// If all devices have been freed, propagate a USBH_EVENT_DEV_ALL_FREE event // If all devices have been freed, propagate a USBH_EVENT_ALL_FREE event
if (all_free) { if (all_free) {
ESP_LOGD(USBH_TAG, "Device all free"); ESP_LOGD(USBH_TAG, "Device all free");
p_usbh_obj->constant.event_cb((usb_device_handle_t)NULL, USBH_EVENT_DEV_ALL_FREE, p_usbh_obj->constant.event_cb_arg); usbh_event_data_t event_data = {
.event = USBH_EVENT_ALL_FREE,
};
p_usbh_obj->constant.event_cb(&event_data, p_usbh_obj->constant.event_cb_arg);
} }
// Check if we need to recover the device's port // Check if we need to recover the device's port
if (recover_port) { if (recover_port) {
@@ -547,7 +562,13 @@ static inline void handle_port_disable(device_t *dev_obj)
static inline void handle_prop_new_evt(device_t *dev_obj) static inline void handle_prop_new_evt(device_t *dev_obj)
{ {
ESP_LOGD(USBH_TAG, "New device %d", dev_obj->constant.address); ESP_LOGD(USBH_TAG, "New device %d", dev_obj->constant.address);
p_usbh_obj->constant.event_cb((usb_device_handle_t)dev_obj, USBH_EVENT_DEV_NEW, p_usbh_obj->constant.event_cb_arg); usbh_event_data_t event_data = {
.event = USBH_EVENT_NEW_DEV,
.new_dev_data = {
.dev_addr = dev_obj->constant.address,
},
};
p_usbh_obj->constant.event_cb(&event_data, p_usbh_obj->constant.event_cb_arg);
} }
// ------------------------------------------------- USBH Functions ---------------------------------------------------- // ------------------------------------------------- USBH Functions ----------------------------------------------------
@@ -573,8 +594,6 @@ esp_err_t usbh_install(const usbh_config_t *usbh_config)
usbh_obj->constant.proc_req_cb_arg = usbh_config->proc_req_cb_arg; usbh_obj->constant.proc_req_cb_arg = usbh_config->proc_req_cb_arg;
usbh_obj->constant.event_cb = usbh_config->event_cb; usbh_obj->constant.event_cb = usbh_config->event_cb;
usbh_obj->constant.event_cb_arg = usbh_config->event_cb_arg; usbh_obj->constant.event_cb_arg = usbh_config->event_cb_arg;
usbh_obj->constant.ctrl_xfer_cb = usbh_config->ctrl_xfer_cb;
usbh_obj->constant.ctrl_xfer_cb_arg = usbh_config->ctrl_xfer_cb_arg;
usbh_obj->constant.mux_lock = mux_lock; usbh_obj->constant.mux_lock = mux_lock;
// Assign USBH object pointer // Assign USBH object pointer