mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
refactor(usb/host): Refactor USBH function grouping
This commit rearranges the USBH functions into new groupings to provide a clearer abstraction. This is in preparation for refactoring/removing the Hub related functions in the USBH API. This commit DOES NOT MAKE ANY BEHAVIORAL CHANGES to the code. Functions are now grouped into... - USBH Processing: Functions dealing with overall USBH processing - Device Pool: Functions that add/remove/open/close devices from the internal device pool - Device: Functions that pertain to setting/getting a particular device - Endpoints: Functions that pertain to a particular endpoint - Transfer: Functions that pertain to sending transfers
This commit is contained in:
parent
9a24782dd2
commit
4569ac7550
@ -130,7 +130,7 @@ typedef struct {
|
||||
void *event_cb_arg; /**< USBH event callback argument */
|
||||
} usbh_config_t;
|
||||
|
||||
// ------------------------------------------------- USBH Functions ----------------------------------------------------
|
||||
// -------------------------------------------- USBH Processing Functions ----------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Installs the USBH driver
|
||||
@ -169,6 +169,8 @@ esp_err_t usbh_uninstall(void);
|
||||
*/
|
||||
esp_err_t usbh_process(void);
|
||||
|
||||
// ---------------------------------------------- Device Pool Functions ------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Get the current number of devices
|
||||
*
|
||||
@ -178,10 +180,6 @@ esp_err_t usbh_process(void);
|
||||
*/
|
||||
esp_err_t usbh_num_devs(int *num_devs_ret);
|
||||
|
||||
// ------------------------------------------------ Device Functions ---------------------------------------------------
|
||||
|
||||
// --------------------- Device Pool -----------------------
|
||||
|
||||
/**
|
||||
* @brief Fill list with address of currently connected devices
|
||||
*
|
||||
@ -197,6 +195,17 @@ esp_err_t usbh_num_devs(int *num_devs_ret);
|
||||
*/
|
||||
esp_err_t usbh_dev_addr_list_fill(int list_len, uint8_t *dev_addr_list, int *num_dev_ret);
|
||||
|
||||
/**
|
||||
* @brief Mark that all devices should be freed at the next possible opportunity
|
||||
*
|
||||
* A device marked as free will not be freed until the last client using the device has called usbh_dev_close()
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: There were no devices to free to begin with. Current state is all free
|
||||
* - ESP_ERR_NOT_FINISHED: One or more devices still need to be freed (but have been marked "to be freed")
|
||||
*/
|
||||
esp_err_t usbh_dev_mark_all_free(void);
|
||||
|
||||
/**
|
||||
* @brief Open a device by address
|
||||
*
|
||||
@ -218,18 +227,9 @@ esp_err_t usbh_dev_open(uint8_t dev_addr, usb_device_handle_t *dev_hdl);
|
||||
*/
|
||||
esp_err_t usbh_dev_close(usb_device_handle_t dev_hdl);
|
||||
|
||||
/**
|
||||
* @brief Mark that all devices should be freed at the next possible opportunity
|
||||
*
|
||||
* A device marked as free will not be freed until the last client using the device has called usbh_dev_close()
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: There were no devices to free to begin with. Current state is all free
|
||||
* - ESP_ERR_NOT_FINISHED: One or more devices still need to be freed (but have been marked "to be freed")
|
||||
*/
|
||||
esp_err_t usbh_dev_mark_all_free(void);
|
||||
// ------------------------------------------------ Device Functions ---------------------------------------------------
|
||||
|
||||
// ------------------- Single Device ----------------------
|
||||
// ----------------------- Getters -------------------------
|
||||
|
||||
/**
|
||||
* @brief Get a device's address
|
||||
@ -275,15 +275,6 @@ esp_err_t usbh_dev_get_desc(usb_device_handle_t dev_hdl, const usb_device_desc_t
|
||||
*/
|
||||
esp_err_t usbh_dev_get_config_desc(usb_device_handle_t dev_hdl, const usb_config_desc_t **config_desc_ret);
|
||||
|
||||
/**
|
||||
* @brief Submit a control transfer (URB) to a device
|
||||
*
|
||||
* @param[in] dev_hdl Device handle
|
||||
* @param[in] urb URB
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t usbh_dev_submit_ctrl_urb(usb_device_handle_t dev_hdl, urb_t *urb);
|
||||
|
||||
// ----------------------------------------------- Endpoint Functions -------------------------------------------------
|
||||
|
||||
/**
|
||||
@ -334,6 +325,39 @@ esp_err_t usbh_ep_free(usbh_ep_handle_t ep_hdl);
|
||||
*/
|
||||
esp_err_t usbh_ep_get_handle(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress, usbh_ep_handle_t *ep_hdl_ret);
|
||||
|
||||
/**
|
||||
* @brief Execute a command on a particular endpoint
|
||||
*
|
||||
* Endpoint commands allows executing a certain action on an endpoint (e.g., halting, flushing, clearing etc)
|
||||
*
|
||||
* @param[in] ep_hdl Endpoint handle
|
||||
* @param[in] command Endpoint command
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t usbh_ep_command(usbh_ep_handle_t ep_hdl, usbh_ep_cmd_t command);
|
||||
|
||||
/**
|
||||
* @brief Get the context of an endpoint
|
||||
*
|
||||
* Get the context variable assigned to and endpoint on allocation.
|
||||
*
|
||||
* @note This function can block
|
||||
* @param[in] ep_hdl Endpoint handle
|
||||
* @return Endpoint context
|
||||
*/
|
||||
void *usbh_ep_get_context(usbh_ep_handle_t ep_hdl);
|
||||
|
||||
// ----------------------------------------------- Transfer Functions --------------------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Submit a control transfer (URB) to a device
|
||||
*
|
||||
* @param[in] dev_hdl Device handle
|
||||
* @param[in] urb URB
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t usbh_dev_submit_ctrl_urb(usb_device_handle_t dev_hdl, urb_t *urb);
|
||||
|
||||
/**
|
||||
* @brief Enqueue a URB to an endpoint
|
||||
*
|
||||
@ -357,28 +381,6 @@ esp_err_t usbh_ep_enqueue_urb(usbh_ep_handle_t ep_hdl, urb_t *urb);
|
||||
*/
|
||||
esp_err_t usbh_ep_dequeue_urb(usbh_ep_handle_t ep_hdl, urb_t **urb_ret);
|
||||
|
||||
/**
|
||||
* @brief Execute a command on a particular endpoint
|
||||
*
|
||||
* Endpoint commands allows executing a certain action on an endpoint (e.g., halting, flushing, clearing etc)
|
||||
*
|
||||
* @param[in] ep_hdl Endpoint handle
|
||||
* @param[in] command Endpoint command
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t usbh_ep_command(usbh_ep_handle_t ep_hdl, usbh_ep_cmd_t command);
|
||||
|
||||
/**
|
||||
* @brief Get the context of an endpoint
|
||||
*
|
||||
* Get the context variable assigned to and endpoint on allocation.
|
||||
*
|
||||
* @note This function can block
|
||||
* @param[in] ep_hdl Endpoint handle
|
||||
* @return Endpoint context
|
||||
*/
|
||||
void *usbh_ep_get_context(usbh_ep_handle_t ep_hdl);
|
||||
|
||||
// -------------------------------------------------- Hub Functions ----------------------------------------------------
|
||||
|
||||
// ------------------- Device Related ----------------------
|
||||
|
@ -561,7 +561,7 @@ static inline void handle_prop_new_dev(device_t *dev_obj)
|
||||
p_usbh_obj->constant.event_cb(&event_data, p_usbh_obj->constant.event_cb_arg);
|
||||
}
|
||||
|
||||
// ------------------------------------------------- USBH Functions ----------------------------------------------------
|
||||
// -------------------------------------------- USBH Processing Functions ----------------------------------------------
|
||||
|
||||
esp_err_t usbh_install(const usbh_config_t *usbh_config)
|
||||
{
|
||||
@ -700,6 +700,8 @@ esp_err_t usbh_process(void)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// ---------------------------------------------- Device Pool Functions ------------------------------------------------
|
||||
|
||||
esp_err_t usbh_num_devs(int *num_devs_ret)
|
||||
{
|
||||
USBH_CHECK(num_devs_ret != NULL, ESP_ERR_INVALID_ARG);
|
||||
@ -709,10 +711,6 @@ esp_err_t usbh_num_devs(int *num_devs_ret)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// ------------------------------------------------ Device Functions ---------------------------------------------------
|
||||
|
||||
// --------------------- Device Pool -----------------------
|
||||
|
||||
esp_err_t usbh_dev_addr_list_fill(int list_len, uint8_t *dev_addr_list, int *num_dev_ret)
|
||||
{
|
||||
USBH_CHECK(dev_addr_list != NULL && num_dev_ret != NULL, ESP_ERR_INVALID_ARG);
|
||||
@ -743,6 +741,48 @@ esp_err_t usbh_dev_addr_list_fill(int list_len, uint8_t *dev_addr_list, int *num
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t usbh_dev_mark_all_free(void)
|
||||
{
|
||||
USBH_ENTER_CRITICAL();
|
||||
/*
|
||||
Go through the device list and mark each device as waiting to be closed. If the device is not opened at all, we can
|
||||
disable it immediately.
|
||||
Note: We manually traverse the list because we need to add/remove items while traversing
|
||||
*/
|
||||
bool call_proc_req_cb = false;
|
||||
bool wait_for_free = false;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
device_t *dev_obj_cur;
|
||||
device_t *dev_obj_next;
|
||||
// Go through pending list first as it's more efficient
|
||||
if (i == 0) {
|
||||
dev_obj_cur = TAILQ_FIRST(&p_usbh_obj->dynamic.devs_pending_tailq);
|
||||
} else {
|
||||
dev_obj_cur = TAILQ_FIRST(&p_usbh_obj->dynamic.devs_idle_tailq);
|
||||
}
|
||||
while (dev_obj_cur != NULL) {
|
||||
// Keep a copy of the next item first in case we remove the current item
|
||||
dev_obj_next = TAILQ_NEXT(dev_obj_cur, dynamic.tailq_entry);
|
||||
if (dev_obj_cur->dynamic.ref_count == 0) {
|
||||
// Device is not referenced. Can free immediately.
|
||||
call_proc_req_cb |= _dev_set_actions(dev_obj_cur, DEV_ACTION_FREE);
|
||||
} else {
|
||||
// Device is still referenced. Just mark it as waiting to be freed
|
||||
dev_obj_cur->dynamic.flags.waiting_free = 1;
|
||||
}
|
||||
// At least one device needs to be freed. User needs to wait for USBH_EVENT_ALL_FREE event
|
||||
wait_for_free = true;
|
||||
dev_obj_cur = dev_obj_next;
|
||||
}
|
||||
}
|
||||
USBH_EXIT_CRITICAL();
|
||||
|
||||
if (call_proc_req_cb) {
|
||||
p_usbh_obj->constant.proc_req_cb(USB_PROC_REQ_SOURCE_USBH, false, p_usbh_obj->constant.proc_req_cb_arg);
|
||||
}
|
||||
return (wait_for_free) ? ESP_ERR_NOT_FINISHED : ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t usbh_dev_open(uint8_t dev_addr, usb_device_handle_t *dev_hdl)
|
||||
{
|
||||
USBH_CHECK(dev_hdl != NULL, ESP_ERR_INVALID_ARG);
|
||||
@ -808,49 +848,9 @@ esp_err_t usbh_dev_close(usb_device_handle_t dev_hdl)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t usbh_dev_mark_all_free(void)
|
||||
{
|
||||
USBH_ENTER_CRITICAL();
|
||||
/*
|
||||
Go through the device list and mark each device as waiting to be closed. If the device is not opened at all, we can
|
||||
disable it immediately.
|
||||
Note: We manually traverse the list because we need to add/remove items while traversing
|
||||
*/
|
||||
bool call_proc_req_cb = false;
|
||||
bool wait_for_free = false;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
device_t *dev_obj_cur;
|
||||
device_t *dev_obj_next;
|
||||
// Go through pending list first as it's more efficient
|
||||
if (i == 0) {
|
||||
dev_obj_cur = TAILQ_FIRST(&p_usbh_obj->dynamic.devs_pending_tailq);
|
||||
} else {
|
||||
dev_obj_cur = TAILQ_FIRST(&p_usbh_obj->dynamic.devs_idle_tailq);
|
||||
}
|
||||
while (dev_obj_cur != NULL) {
|
||||
// Keep a copy of the next item first in case we remove the current item
|
||||
dev_obj_next = TAILQ_NEXT(dev_obj_cur, dynamic.tailq_entry);
|
||||
if (dev_obj_cur->dynamic.ref_count == 0) {
|
||||
// Device is not referenced. Can free immediately.
|
||||
call_proc_req_cb |= _dev_set_actions(dev_obj_cur, DEV_ACTION_FREE);
|
||||
} else {
|
||||
// Device is still referenced. Just mark it as waiting to be freed
|
||||
dev_obj_cur->dynamic.flags.waiting_free = 1;
|
||||
}
|
||||
// At least one device needs to be freed. User needs to wait for USBH_EVENT_ALL_FREE event
|
||||
wait_for_free = true;
|
||||
dev_obj_cur = dev_obj_next;
|
||||
}
|
||||
}
|
||||
USBH_EXIT_CRITICAL();
|
||||
// ------------------------------------------------ Device Functions ---------------------------------------------------
|
||||
|
||||
if (call_proc_req_cb) {
|
||||
p_usbh_obj->constant.proc_req_cb(USB_PROC_REQ_SOURCE_USBH, false, p_usbh_obj->constant.proc_req_cb_arg);
|
||||
}
|
||||
return (wait_for_free) ? ESP_ERR_NOT_FINISHED : ESP_OK;
|
||||
}
|
||||
|
||||
// ------------------- Single Device ----------------------
|
||||
// ----------------------- Getters -------------------------
|
||||
|
||||
esp_err_t usbh_dev_get_addr(usb_device_handle_t dev_hdl, uint8_t *dev_addr)
|
||||
{
|
||||
@ -928,40 +928,7 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t usbh_dev_submit_ctrl_urb(usb_device_handle_t dev_hdl, urb_t *urb)
|
||||
{
|
||||
USBH_CHECK(dev_hdl != NULL && urb != NULL, ESP_ERR_INVALID_ARG);
|
||||
device_t *dev_obj = (device_t *)dev_hdl;
|
||||
USBH_CHECK(urb_check_args(urb), ESP_ERR_INVALID_ARG);
|
||||
bool xfer_is_in = ((usb_setup_packet_t *)urb->transfer.data_buffer)->bmRequestType & USB_BM_REQUEST_TYPE_DIR_IN;
|
||||
USBH_CHECK(transfer_check_usb_compliance(&(urb->transfer), USB_TRANSFER_TYPE_CTRL, dev_obj->constant.desc->bMaxPacketSize0, xfer_is_in), ESP_ERR_INVALID_ARG);
|
||||
|
||||
USBH_ENTER_CRITICAL();
|
||||
USBH_CHECK_FROM_CRIT(dev_obj->dynamic.state == USB_DEVICE_STATE_CONFIGURED, ESP_ERR_INVALID_STATE);
|
||||
// Increment the control transfer count first
|
||||
dev_obj->dynamic.num_ctrl_xfers_inflight++;
|
||||
USBH_EXIT_CRITICAL();
|
||||
|
||||
esp_err_t ret;
|
||||
if (hcd_pipe_get_state(dev_obj->constant.default_pipe) != HCD_PIPE_STATE_ACTIVE) {
|
||||
ret = ESP_ERR_INVALID_STATE;
|
||||
goto hcd_err;
|
||||
}
|
||||
ret = hcd_urb_enqueue(dev_obj->constant.default_pipe, urb);
|
||||
if (ret != ESP_OK) {
|
||||
goto hcd_err;
|
||||
}
|
||||
ret = ESP_OK;
|
||||
return ret;
|
||||
|
||||
hcd_err:
|
||||
USBH_ENTER_CRITICAL();
|
||||
dev_obj->dynamic.num_ctrl_xfers_inflight--;
|
||||
USBH_EXIT_CRITICAL();
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ----------------------------------------------- Interface Functions -------------------------------------------------
|
||||
// ----------------------------------------------- Endpoint Functions -------------------------------------------------
|
||||
|
||||
esp_err_t usbh_ep_alloc(usb_device_handle_t dev_hdl, usbh_ep_config_t *ep_config, usbh_ep_handle_t *ep_hdl_ret)
|
||||
{
|
||||
@ -1074,6 +1041,57 @@ esp_err_t usbh_ep_get_handle(usb_device_handle_t dev_hdl, uint8_t bEndpointAddre
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t usbh_ep_command(usbh_ep_handle_t ep_hdl, usbh_ep_cmd_t command)
|
||||
{
|
||||
USBH_CHECK(ep_hdl != NULL, ESP_ERR_INVALID_ARG);
|
||||
|
||||
endpoint_t *ep_obj = (endpoint_t *)ep_hdl;
|
||||
// Send the command to the EP's underlying pipe
|
||||
return hcd_pipe_command(ep_obj->constant.pipe_hdl, (hcd_pipe_cmd_t)command);
|
||||
}
|
||||
|
||||
void *usbh_ep_get_context(usbh_ep_handle_t ep_hdl)
|
||||
{
|
||||
assert(ep_hdl);
|
||||
endpoint_t *ep_obj = (endpoint_t *)ep_hdl;
|
||||
return hcd_pipe_get_context(ep_obj->constant.pipe_hdl);
|
||||
}
|
||||
|
||||
// ----------------------------------------------- Transfer Functions --------------------------------------------------
|
||||
|
||||
esp_err_t usbh_dev_submit_ctrl_urb(usb_device_handle_t dev_hdl, urb_t *urb)
|
||||
{
|
||||
USBH_CHECK(dev_hdl != NULL && urb != NULL, ESP_ERR_INVALID_ARG);
|
||||
device_t *dev_obj = (device_t *)dev_hdl;
|
||||
USBH_CHECK(urb_check_args(urb), ESP_ERR_INVALID_ARG);
|
||||
bool xfer_is_in = ((usb_setup_packet_t *)urb->transfer.data_buffer)->bmRequestType & USB_BM_REQUEST_TYPE_DIR_IN;
|
||||
USBH_CHECK(transfer_check_usb_compliance(&(urb->transfer), USB_TRANSFER_TYPE_CTRL, dev_obj->constant.desc->bMaxPacketSize0, xfer_is_in), ESP_ERR_INVALID_ARG);
|
||||
|
||||
USBH_ENTER_CRITICAL();
|
||||
USBH_CHECK_FROM_CRIT(dev_obj->dynamic.state == USB_DEVICE_STATE_CONFIGURED, ESP_ERR_INVALID_STATE);
|
||||
// Increment the control transfer count first
|
||||
dev_obj->dynamic.num_ctrl_xfers_inflight++;
|
||||
USBH_EXIT_CRITICAL();
|
||||
|
||||
esp_err_t ret;
|
||||
if (hcd_pipe_get_state(dev_obj->constant.default_pipe) != HCD_PIPE_STATE_ACTIVE) {
|
||||
ret = ESP_ERR_INVALID_STATE;
|
||||
goto hcd_err;
|
||||
}
|
||||
ret = hcd_urb_enqueue(dev_obj->constant.default_pipe, urb);
|
||||
if (ret != ESP_OK) {
|
||||
goto hcd_err;
|
||||
}
|
||||
ret = ESP_OK;
|
||||
return ret;
|
||||
|
||||
hcd_err:
|
||||
USBH_ENTER_CRITICAL();
|
||||
dev_obj->dynamic.num_ctrl_xfers_inflight--;
|
||||
USBH_EXIT_CRITICAL();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t usbh_ep_enqueue_urb(usbh_ep_handle_t ep_hdl, urb_t *urb)
|
||||
{
|
||||
USBH_CHECK(ep_hdl != NULL && urb != NULL, ESP_ERR_INVALID_ARG);
|
||||
@ -1104,22 +1122,6 @@ esp_err_t usbh_ep_dequeue_urb(usbh_ep_handle_t ep_hdl, urb_t **urb_ret)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t usbh_ep_command(usbh_ep_handle_t ep_hdl, usbh_ep_cmd_t command)
|
||||
{
|
||||
USBH_CHECK(ep_hdl != NULL, ESP_ERR_INVALID_ARG);
|
||||
|
||||
endpoint_t *ep_obj = (endpoint_t *)ep_hdl;
|
||||
// Send the command to the EP's underlying pipe
|
||||
return hcd_pipe_command(ep_obj->constant.pipe_hdl, (hcd_pipe_cmd_t)command);
|
||||
}
|
||||
|
||||
void *usbh_ep_get_context(usbh_ep_handle_t ep_hdl)
|
||||
{
|
||||
assert(ep_hdl);
|
||||
endpoint_t *ep_obj = (endpoint_t *)ep_hdl;
|
||||
return hcd_pipe_get_context(ep_obj->constant.pipe_hdl);
|
||||
}
|
||||
|
||||
// -------------------------------------------------- Hub Functions ----------------------------------------------------
|
||||
|
||||
// ------------------- Device Related ----------------------
|
||||
|
Loading…
Reference in New Issue
Block a user