mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'refactor/usb_host_usbh_api_prereq_for_enum_driver' into 'master'
refactor(usbh): Updated USBH api for ENUM driver Closes IDF-9723 See merge request espressif/esp-idf!29913
This commit is contained in:
commit
7b7b8680ca
@ -606,15 +606,15 @@ static bool enum_stage_transfer_check(enum_ctrl_t *enum_ctrl)
|
||||
break;
|
||||
} else {
|
||||
// Fill the string descriptor into the device object
|
||||
int select;
|
||||
int str_index;
|
||||
if (enum_ctrl->stage == ENUM_STAGE_CHECK_FULL_MANU_STR_DESC) {
|
||||
select = 0;
|
||||
str_index = 0;
|
||||
} else if (enum_ctrl->stage == ENUM_STAGE_CHECK_FULL_PROD_STR_DESC) {
|
||||
select = 1;
|
||||
str_index = 1;
|
||||
} else { // ENUM_STAGE_CHECK_FULL_PROD_STR_DESC
|
||||
select = 2;
|
||||
str_index = 2;
|
||||
}
|
||||
ESP_ERROR_CHECK(usbh_dev_set_str_desc(enum_ctrl->dev_hdl, str_desc, select));
|
||||
ESP_ERROR_CHECK(usbh_dev_set_str_desc(enum_ctrl->dev_hdl, str_desc, str_index));
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
@ -634,7 +634,7 @@ static void enum_stage_cleanup(enum_ctrl_t *enum_ctrl)
|
||||
// Propagate a new device event
|
||||
ESP_ERROR_CHECK(usbh_devs_new_dev_event(enum_ctrl->dev_hdl));
|
||||
// We are done with using the device. Close it.
|
||||
ESP_ERROR_CHECK(usbh_devs_close(enum_ctrl->dev_hdl));
|
||||
ESP_ERROR_CHECK(usbh_dev_close(enum_ctrl->dev_hdl));
|
||||
// Clear values in enum_ctrl
|
||||
enum_ctrl->dev_hdl = NULL;
|
||||
}
|
||||
@ -644,7 +644,7 @@ static void enum_stage_cleanup_failed(enum_ctrl_t *enum_ctrl)
|
||||
if (enum_ctrl->dev_hdl) {
|
||||
// Close the device and unlock it as we done with enumeration
|
||||
ESP_ERROR_CHECK(usbh_dev_enum_unlock(enum_ctrl->dev_hdl));
|
||||
ESP_ERROR_CHECK(usbh_devs_close(enum_ctrl->dev_hdl));
|
||||
ESP_ERROR_CHECK(usbh_dev_close(enum_ctrl->dev_hdl));
|
||||
// We allow this to fail in case the device object was already freed
|
||||
usbh_devs_remove(ENUM_DEV_UID);
|
||||
}
|
||||
@ -791,8 +791,15 @@ static void root_port_handle_events(hcd_port_handle_t root_port_hdl)
|
||||
if (hcd_port_get_speed(p_hub_driver_obj->constant.root_port_hdl, &speed) != ESP_OK) {
|
||||
goto new_dev_err;
|
||||
}
|
||||
|
||||
// Allocate a new device. We use a fixed ENUM_DEV_UID for now since we only support a single device
|
||||
if (usbh_devs_add(ENUM_DEV_UID, speed, p_hub_driver_obj->constant.root_port_hdl) != ESP_OK) {
|
||||
usbh_dev_params_t params = {
|
||||
.uid = ENUM_DEV_UID,
|
||||
.speed = speed,
|
||||
.root_port_hdl = p_hub_driver_obj->constant.root_port_hdl,
|
||||
};
|
||||
|
||||
if (usbh_devs_add(¶ms) != ESP_OK) {
|
||||
ESP_LOGE(HUB_DRIVER_TAG, "Failed to add device");
|
||||
goto new_dev_err;
|
||||
}
|
||||
|
@ -70,10 +70,19 @@ typedef struct usb_device_handle_s *usb_device_handle_t;
|
||||
*/
|
||||
typedef bool (*usb_host_enum_filter_cb_t)(const usb_device_desc_t *dev_desc, uint8_t *bConfigurationValue);
|
||||
|
||||
/**
|
||||
* @brief Parent device information
|
||||
*/
|
||||
typedef struct {
|
||||
usb_device_handle_t dev_hdl; /**< Device's parent handle */
|
||||
uint8_t port_num; /**< Device's parent port number */
|
||||
} usb_parent_dev_info_t;
|
||||
|
||||
/**
|
||||
* @brief Basic information of an enumerated device
|
||||
*/
|
||||
typedef struct {
|
||||
usb_parent_dev_info_t parent; /**< Device's parent information */
|
||||
usb_speed_t speed; /**< Device's speed */
|
||||
uint8_t dev_addr; /**< Device's address */
|
||||
uint8_t bMaxPacketSize0; /**< The maximum packet size of the device's default endpoint */
|
||||
|
@ -59,6 +59,8 @@ typedef struct {
|
||||
} dev_gone_data;
|
||||
struct {
|
||||
unsigned int dev_uid;
|
||||
usb_device_handle_t parent_dev_hdl;
|
||||
uint8_t port_num;
|
||||
} dev_free_data;
|
||||
};
|
||||
} usbh_event_data_t;
|
||||
@ -130,7 +132,18 @@ typedef struct {
|
||||
void *event_cb_arg; /**< USBH event callback argument */
|
||||
} usbh_config_t;
|
||||
|
||||
// -------------------------------------------- USBH Processing Functions ----------------------------------------------
|
||||
/**
|
||||
* @brief USBH device parameters used in usbh_devs_add()
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned int uid; /**< Unique ID assigned to the device */
|
||||
usb_speed_t speed; /**< Device's speed */
|
||||
hcd_port_handle_t root_port_hdl; /**< Handle of the port that the device is connected to */
|
||||
usb_device_handle_t parent_dev_hdl; /**< Parent's device handle */
|
||||
uint8_t parent_port_num; /**< Parent's port number */
|
||||
} usbh_dev_params_t;
|
||||
|
||||
// ---------------------- USBH Processing Functions ----------------------------
|
||||
|
||||
/**
|
||||
* @brief Installs the USBH driver
|
||||
@ -169,7 +182,7 @@ esp_err_t usbh_uninstall(void);
|
||||
*/
|
||||
esp_err_t usbh_process(void);
|
||||
|
||||
// ---------------------------------------------- Device Pool Functions ------------------------------------------------
|
||||
// ---------------------- Device Pool Functions --------------------------------
|
||||
|
||||
/**
|
||||
* @brief Get the current number of devices
|
||||
@ -206,12 +219,10 @@ esp_err_t usbh_devs_addr_list_fill(int list_len, uint8_t *dev_addr_list, int *nu
|
||||
* - Call usbh_dev_enum_lock() before enumerating the device via the various
|
||||
* usbh_dev_set_...() functions.
|
||||
*
|
||||
* @param[in] uid Unique ID assigned to the device
|
||||
* @param[in] dev_speed Device's speed
|
||||
* @param[in] port_hdl Handle of the port that the device is connected to
|
||||
* @param[in] params Device parameters, using for device creation
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t usbh_devs_add(unsigned int uid, usb_speed_t dev_speed, hcd_port_handle_t port_hdl);
|
||||
esp_err_t usbh_devs_add(usbh_dev_params_t *params);
|
||||
|
||||
/**
|
||||
* @brief Indicates to the USBH that a device is gone
|
||||
@ -221,6 +232,18 @@ esp_err_t usbh_devs_add(unsigned int uid, usb_speed_t dev_speed, hcd_port_handle
|
||||
*/
|
||||
esp_err_t usbh_devs_remove(unsigned int uid);
|
||||
|
||||
/**
|
||||
* @brief Get a device's connection information
|
||||
*
|
||||
* @note Can be called without opening the device
|
||||
*
|
||||
* @param[in] uid Unique ID assigned to the device
|
||||
* @param[out] parent_info Parent device handle
|
||||
* @param[out] port_num Parent port number
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t usbh_devs_get_parent_info(unsigned int uid, usb_parent_dev_info_t *parent_info);
|
||||
|
||||
/**
|
||||
* @brief Mark that all devices should be freed at the next possible opportunity
|
||||
*
|
||||
@ -243,16 +266,6 @@ esp_err_t usbh_devs_mark_all_free(void);
|
||||
*/
|
||||
esp_err_t usbh_devs_open(uint8_t dev_addr, usb_device_handle_t *dev_hdl);
|
||||
|
||||
/**
|
||||
* @brief CLose a device
|
||||
*
|
||||
* Device can be opened by calling usbh_devs_open()
|
||||
*
|
||||
* @param[in] dev_hdl Device handle
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t usbh_devs_close(usb_device_handle_t dev_hdl);
|
||||
|
||||
/**
|
||||
* @brief Trigger a USBH_EVENT_NEW_DEV event for the device
|
||||
*
|
||||
@ -263,14 +276,23 @@ esp_err_t usbh_devs_close(usb_device_handle_t dev_hdl);
|
||||
*/
|
||||
esp_err_t usbh_devs_new_dev_event(usb_device_handle_t dev_hdl);
|
||||
|
||||
// ------------------------------------------------ Device Functions ---------------------------------------------------
|
||||
// ------------------------ Device Functions -----------------------------------
|
||||
|
||||
// ----------------------- Getters -------------------------
|
||||
/**
|
||||
* @brief Close a device
|
||||
*
|
||||
* @note Callers of this function must have opened the device via usbh_devs_open()
|
||||
* *
|
||||
* @param[in] dev_hdl Device handle
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t usbh_dev_close(usb_device_handle_t dev_hdl);
|
||||
|
||||
// ------------------------------ Getters --------------------------------------
|
||||
/**
|
||||
* @brief Get a device's address
|
||||
*
|
||||
* @note Can be called without opening the device
|
||||
* @note Callers of this function must have opened the device via usbh_devs_open()
|
||||
*
|
||||
* @param[in] dev_hdl Device handle
|
||||
* @param[out] dev_addr Device's address
|
||||
@ -281,8 +303,10 @@ esp_err_t usbh_dev_get_addr(usb_device_handle_t dev_hdl, uint8_t *dev_addr);
|
||||
/**
|
||||
* @brief Get a device's information
|
||||
*
|
||||
* @note Callers of this function must have opened the device via usbh_devs_open()
|
||||
* @note It is possible that the device has not been enumerated yet, thus some
|
||||
* fields may be NULL.
|
||||
*
|
||||
* @param[in] dev_hdl Device handle
|
||||
* @param[out] dev_info Device information
|
||||
* @return esp_err_t
|
||||
@ -292,7 +316,7 @@ esp_err_t usbh_dev_get_info(usb_device_handle_t dev_hdl, usb_device_info_t *dev_
|
||||
/**
|
||||
* @brief Get a device's device descriptor
|
||||
*
|
||||
* - The device descriptor is cached when the device is created by the Hub driver
|
||||
* The device descriptor is cached when the device is created by the Hub driver
|
||||
*
|
||||
* @note It is possible that the device has not been enumerated yet, thus the
|
||||
* device descriptor could be NULL.
|
||||
@ -305,6 +329,7 @@ esp_err_t usbh_dev_get_desc(usb_device_handle_t dev_hdl, const usb_device_desc_t
|
||||
/**
|
||||
* @brief Get a device's active configuration descriptor
|
||||
*
|
||||
* @note Callers of this function must have opened the device via usbh_devs_open()
|
||||
* Simply returns a reference to the internally cached configuration descriptor
|
||||
*
|
||||
* @note It is possible that the device has not been enumerated yet, thus the
|
||||
@ -315,11 +340,13 @@ 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);
|
||||
|
||||
// ----------------------- Setters -------------------------
|
||||
// ------------------------------- Setters -------------------------------------
|
||||
|
||||
/**
|
||||
* @brief Lock a device for enumeration
|
||||
*
|
||||
* @note Callers of this function must have opened the device via usbh_devs_open()
|
||||
*
|
||||
* - A device's enumeration lock must be set before any of its enumeration fields
|
||||
* (e.g., address, device/config descriptors) can be set/updated.
|
||||
* - The caller must be the sole opener of the device (see 'usbh_devs_open()')
|
||||
@ -333,6 +360,8 @@ esp_err_t usbh_dev_enum_lock(usb_device_handle_t dev_hdl);
|
||||
/**
|
||||
* @brief Release a device's enumeration lock
|
||||
*
|
||||
* @note Callers of this function must have opened the device via usbh_devs_open()
|
||||
*
|
||||
* @param[in] dev_hdl Device handle
|
||||
* @return esp_err_t
|
||||
*/
|
||||
@ -344,8 +373,11 @@ esp_err_t usbh_dev_enum_unlock(usb_device_handle_t dev_hdl);
|
||||
* Typically called during enumeration after obtaining the first 8 bytes of the
|
||||
* device's descriptor.
|
||||
*
|
||||
* @note Callers of this function must have opened the device via usbh_devs_open()
|
||||
*
|
||||
* @note The device's enumeration lock must be set before calling this function
|
||||
* (see 'usbh_dev_enum_lock()')
|
||||
*
|
||||
* @param[in] dev_hdl Device handle
|
||||
* @param[in] wMaxPacketSize Maximum packet size
|
||||
* @return esp_err_t
|
||||
@ -355,13 +387,15 @@ esp_err_t usbh_dev_set_ep0_mps(usb_device_handle_t dev_hdl, uint16_t wMaxPacketS
|
||||
/**
|
||||
* @brief Set a device's address
|
||||
*
|
||||
* Typically called during enumeration after a SET_ADDRESSS request has be
|
||||
* Typically called during enumeration after a SET_ADDRESS request has been
|
||||
* sent to the device.
|
||||
*
|
||||
* @note Callers of this function must have opened the device via usbh_devs_open()
|
||||
*
|
||||
* @note The device's enumeration lock must be set before calling this function
|
||||
* (see 'usbh_dev_enum_lock()')
|
||||
* @param[in] dev_hdl Device handle
|
||||
* @param[in] dev_addr
|
||||
* @param[in] dev_addr Device address to set
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t usbh_dev_set_addr(usb_device_handle_t dev_hdl, uint8_t dev_addr);
|
||||
@ -372,8 +406,11 @@ esp_err_t usbh_dev_set_addr(usb_device_handle_t dev_hdl, uint8_t dev_addr);
|
||||
* Typically called during enumeration after obtaining the device's descriptor
|
||||
* via a GET_DESCRIPTOR request.
|
||||
*
|
||||
* @note Callers of this function must have opened the device via usbh_devs_open()
|
||||
*
|
||||
* @note The device's enumeration lock must be set before calling this function
|
||||
* (see 'usbh_dev_enum_lock()')
|
||||
*
|
||||
* @param[in] dev_hdl Device handle
|
||||
* @param[in] device_desc Device descriptor to copy
|
||||
* @return esp_err_t
|
||||
@ -386,8 +423,11 @@ esp_err_t usbh_dev_set_desc(usb_device_handle_t dev_hdl, const usb_device_desc_t
|
||||
* Typically called during enumeration after obtaining the device's configuration
|
||||
* descriptor via a GET_DESCRIPTOR request.
|
||||
*
|
||||
* @note Callers of this function must have opened the device via usbh_devs_open()
|
||||
*
|
||||
* @note The device's enumeration lock must be set before calling this function
|
||||
* (see 'usbh_dev_enum_lock()')
|
||||
*
|
||||
* @param[in] dev_hdl Device handle
|
||||
* @param[in] config_desc_full Configuration descriptor to copy
|
||||
* @return esp_err_t
|
||||
@ -400,8 +440,11 @@ esp_err_t usbh_dev_set_config_desc(usb_device_handle_t dev_hdl, const usb_config
|
||||
* Typically called during enumeration after obtaining one of the device's string
|
||||
* descriptor via a GET_DESCRIPTOR request.
|
||||
*
|
||||
* @note Callers of this function must have opened the device via usbh_devs_open()
|
||||
*
|
||||
* @note The device's enumeration lock must be set before calling this function
|
||||
* (see 'usbh_dev_enum_lock()')
|
||||
*
|
||||
* @param[in] dev_hdl Device handle
|
||||
* @param[in] str_desc String descriptor to copy
|
||||
* @param[in] select Select string descriptor. 0/1/2 for Manufacturer/Product/Serial
|
||||
@ -410,7 +453,7 @@ esp_err_t usbh_dev_set_config_desc(usb_device_handle_t dev_hdl, const usb_config
|
||||
*/
|
||||
esp_err_t usbh_dev_set_str_desc(usb_device_handle_t dev_hdl, const usb_str_desc_t *str_desc, int select);
|
||||
|
||||
// ----------------------------------------------- Endpoint Functions -------------------------------------------------
|
||||
// ----------------------- Endpoint Functions ----------------------------------
|
||||
|
||||
/**
|
||||
* @brief Allocate an endpoint on a device
|
||||
@ -482,7 +525,7 @@ esp_err_t usbh_ep_command(usbh_ep_handle_t ep_hdl, usbh_ep_cmd_t command);
|
||||
*/
|
||||
void *usbh_ep_get_context(usbh_ep_handle_t ep_hdl);
|
||||
|
||||
// ----------------------------------------------- Transfer Functions --------------------------------------------------
|
||||
// ------------------------- Transfer Functions --------------------------------
|
||||
|
||||
/**
|
||||
* @brief Submit a control transfer (URB) to a device
|
||||
|
@ -853,7 +853,7 @@ esp_err_t usb_host_device_open(usb_host_client_handle_t client_hdl, uint8_t dev_
|
||||
return ret;
|
||||
|
||||
already_opened:
|
||||
ESP_ERROR_CHECK(usbh_devs_close(dev_hdl));
|
||||
ESP_ERROR_CHECK(usbh_dev_close(dev_hdl));
|
||||
exit:
|
||||
return ret;
|
||||
}
|
||||
@ -895,7 +895,7 @@ esp_err_t usb_host_device_close(usb_host_client_handle_t client_hdl, usb_device_
|
||||
_clear_client_opened_device(client_obj, dev_addr);
|
||||
HOST_EXIT_CRITICAL();
|
||||
|
||||
ESP_ERROR_CHECK(usbh_devs_close(dev_hdl));
|
||||
ESP_ERROR_CHECK(usbh_dev_close(dev_hdl));
|
||||
ret = ESP_OK;
|
||||
exit:
|
||||
xSemaphoreGive(p_host_lib_obj->constant.mux_lock);
|
||||
|
@ -40,78 +40,79 @@ typedef struct device_s device_t;
|
||||
|
||||
typedef struct {
|
||||
struct {
|
||||
usbh_ep_cb_t ep_cb;
|
||||
void *ep_cb_arg;
|
||||
hcd_pipe_handle_t pipe_hdl;
|
||||
device_t *dev; // Pointer to the device object that this endpoint is contained in
|
||||
const usb_ep_desc_t *ep_desc; // This just stores a pointer endpoint descriptor inside the device's "config_desc"
|
||||
} constant;
|
||||
usbh_ep_cb_t ep_cb; /**< Endpoint callback is called when transfer in complete or error occurred */
|
||||
void *ep_cb_arg; /**< Endpoint callback argument */
|
||||
hcd_pipe_handle_t pipe_hdl; /**< Endpoint HCD pipe handle */
|
||||
device_t *dev; /**< Pointer to the device object that this endpoint is contained in */
|
||||
const usb_ep_desc_t *ep_desc; /**< This just stores a pointer endpoint descriptor inside the device's "config_desc" */
|
||||
} constant; /**< Constant members. Do not change after installation thus do not require a critical section or mutex */
|
||||
} endpoint_t;
|
||||
|
||||
struct device_s {
|
||||
// Dynamic members require a critical section
|
||||
struct {
|
||||
TAILQ_ENTRY(device_s) tailq_entry;
|
||||
TAILQ_ENTRY(device_s) tailq_entry; /**< Entry for the device object tailq */
|
||||
union {
|
||||
struct {
|
||||
uint32_t in_pending_list: 1;
|
||||
uint32_t is_gone: 1; // Device is gone (disconnected or port error)
|
||||
uint32_t waiting_free: 1; // Device object is awaiting to be freed
|
||||
uint32_t enum_lock: 1; // Device is locked for enumeration. Enum information (e.g., address, device/config desc etc) may change
|
||||
uint32_t reserved28: 28;
|
||||
uint32_t in_pending_list: 1; /**< Device is in pending list */
|
||||
uint32_t is_gone: 1; /**< Device is gone (disconnected or port error) */
|
||||
uint32_t waiting_free: 1; /**< Device object is awaiting to be freed */
|
||||
uint32_t enum_lock: 1; /**< Device is locked for enumeration. Enum information (e.g., address, device/config desc etc) may change */
|
||||
uint32_t reserved28: 28; /**< Reserved */
|
||||
};
|
||||
uint32_t val;
|
||||
uint32_t val; /**< Device flags value */
|
||||
} flags;
|
||||
uint32_t action_flags;
|
||||
int num_ctrl_xfers_inflight;
|
||||
usb_device_state_t state;
|
||||
uint32_t open_count;
|
||||
} dynamic;
|
||||
// Mux protected members must be protected by the USBH mux_lock when accessed
|
||||
uint32_t action_flags; /**< Device action flags */
|
||||
int num_ctrl_xfers_inflight; /**< Amount of ongoing Control transfers */
|
||||
usb_device_state_t state; /**< Device state */
|
||||
uint32_t open_count; /**< Amount of clients which opened this device */
|
||||
} dynamic; /**< Dynamic members. Require a critical section */
|
||||
|
||||
struct {
|
||||
/*
|
||||
- Endpoint object pointers for each possible non-default endpoint
|
||||
- All OUT EPs are listed before IN EPs (i.e., EP_NUM_MIN OUT ... EP_NUM_MAX OUT ... EP_NUM_MIN IN ... EP_NUM_MAX)
|
||||
*/
|
||||
endpoint_t *endpoints[NUM_NON_DEFAULT_EP];
|
||||
} mux_protected;
|
||||
} mux_protected; /**< Mutex protected members. Must be protected by the USBH mux_lock when accessed */
|
||||
|
||||
// Constant members do not require a critical section
|
||||
struct {
|
||||
// Assigned on device allocation and remain constant for the device's lifetime
|
||||
hcd_pipe_handle_t default_pipe;
|
||||
hcd_port_handle_t port_hdl;
|
||||
usb_speed_t speed;
|
||||
unsigned int uid;
|
||||
hcd_pipe_handle_t default_pipe; /**< Pipe handle for Control EP0 */
|
||||
hcd_port_handle_t port_hdl; /**< HCD port handle */
|
||||
usb_device_handle_t parent_dev_hdl; /**< Device's parent device handle. NULL if device is connected to the root port */
|
||||
uint8_t parent_port_num; /**< Device's parent port number. 0 if device connected to the root port */
|
||||
usb_speed_t speed; /**< Device's speed */
|
||||
unsigned int uid; /**< Device's Unique ID */
|
||||
/*
|
||||
These fields are can only be changed when enum_lock is set, thus can be treated as constant
|
||||
*/
|
||||
uint8_t address;
|
||||
usb_device_desc_t *desc;
|
||||
usb_config_desc_t *config_desc;
|
||||
usb_str_desc_t *str_desc_manu;
|
||||
usb_str_desc_t *str_desc_product;
|
||||
usb_str_desc_t *str_desc_ser_num;
|
||||
} constant;
|
||||
uint8_t address; /**< Device's bus address */
|
||||
usb_device_desc_t *desc; /**< Device's descriptor pointer */
|
||||
usb_config_desc_t *config_desc; /**< Device's configuration descriptor pointer. NULL if not configured. */
|
||||
usb_str_desc_t *str_desc_manu; /**< Device's Manufacturer string descriptor pointer */
|
||||
usb_str_desc_t *str_desc_product; /**< Device's Product string descriptor pointer */
|
||||
usb_str_desc_t *str_desc_ser_num; /**< Device's Serial string descriptor pointer */
|
||||
} constant; /**< Constant members. Do not change after installation thus do not require a critical section or mutex */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
// Dynamic members require a critical section
|
||||
struct {
|
||||
TAILQ_HEAD(tailhead_devs, device_s) devs_idle_tailq; // Tailq of all enum and configured devices
|
||||
TAILQ_HEAD(tailhead_devs_cb, device_s) devs_pending_tailq; // Tailq of devices that need to have their cb called
|
||||
} dynamic;
|
||||
// Mux protected members must be protected by the USBH mux_lock when accessed
|
||||
TAILQ_HEAD(tailhead_devs, device_s) devs_idle_tailq; /**< Tailq of all enum and configured devices */
|
||||
TAILQ_HEAD(tailhead_devs_cb, device_s) devs_pending_tailq; /**< Tailq of devices that need to have their cb called */
|
||||
} dynamic; /**< Dynamic members. Require a critical section */
|
||||
|
||||
struct {
|
||||
uint8_t num_device; // Number of enumerated devices
|
||||
} mux_protected;
|
||||
// Constant members do no change after installation thus do not require a critical section
|
||||
uint8_t num_device; /**< Current number of device objects */
|
||||
} mux_protected; /**< Mutex protected members. Must be protected by the USBH mux_lock when accessed */
|
||||
|
||||
struct {
|
||||
usb_proc_req_cb_t proc_req_cb;
|
||||
void *proc_req_cb_arg;
|
||||
usbh_event_cb_t event_cb;
|
||||
void *event_cb_arg;
|
||||
SemaphoreHandle_t mux_lock;
|
||||
} constant;
|
||||
usb_proc_req_cb_t proc_req_cb; /**< USB Host process request callback. Refer to proc_req_callback() in usb_host.c */
|
||||
void *proc_req_cb_arg; /**< USB Host process request callback argument */
|
||||
usbh_event_cb_t event_cb; /**< USBH event callback */
|
||||
void *event_cb_arg; /**< USBH event callback argument */
|
||||
SemaphoreHandle_t mux_lock; /**< Mutex for protected members */
|
||||
} constant; /**< Constant members. Do not change after installation thus do not require a critical section or mutex */
|
||||
} usbh_t;
|
||||
|
||||
static usbh_t *p_usbh_obj = NULL;
|
||||
@ -147,7 +148,9 @@ static bool epN_pipe_callback(hcd_pipe_handle_t pipe_hdl, hcd_pipe_event_t pipe_
|
||||
|
||||
static bool _dev_set_actions(device_t *dev_obj, uint32_t action_flags);
|
||||
|
||||
// ----------------------------------------------------- Helpers -------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
// ---------------------------- Helpers ----------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
static device_t *_find_dev_from_uid(unsigned int uid)
|
||||
{
|
||||
@ -305,7 +308,9 @@ static bool transfer_check_usb_compliance(usb_transfer_t *transfer, usb_transfer
|
||||
return true;
|
||||
}
|
||||
|
||||
// --------------------------------------------------- Allocation ------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
// ----------------------------- Allocation ------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
static esp_err_t endpoint_alloc(device_t *dev_obj, const usb_ep_desc_t *ep_desc, usbh_ep_config_t *ep_config, endpoint_t **ep_obj_ret)
|
||||
{
|
||||
@ -358,10 +363,7 @@ static void endpoint_free(endpoint_t *ep_obj)
|
||||
heap_caps_free(ep_obj);
|
||||
}
|
||||
|
||||
static esp_err_t device_alloc(unsigned int uid,
|
||||
usb_speed_t speed,
|
||||
hcd_port_handle_t port_hdl,
|
||||
device_t **dev_obj_ret)
|
||||
static esp_err_t device_alloc(usbh_dev_params_t *params, device_t **dev_obj_ret)
|
||||
{
|
||||
device_t *dev_obj = heap_caps_calloc(1, sizeof(device_t), MALLOC_CAP_DEFAULT);
|
||||
if (dev_obj == NULL) {
|
||||
@ -375,22 +377,23 @@ static esp_err_t device_alloc(unsigned int uid,
|
||||
.callback_arg = (void *)dev_obj,
|
||||
.context = (void *)dev_obj,
|
||||
.ep_desc = NULL, // No endpoint descriptor means we're allocating a pipe for EP0
|
||||
.dev_speed = speed,
|
||||
.dev_speed = params->speed,
|
||||
.dev_addr = 0,
|
||||
};
|
||||
hcd_pipe_handle_t default_pipe_hdl;
|
||||
ret = hcd_pipe_alloc(port_hdl, &pipe_config, &default_pipe_hdl);
|
||||
ret = hcd_pipe_alloc(params->root_port_hdl, &pipe_config, &default_pipe_hdl);
|
||||
if (ret != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// Initialize device object
|
||||
dev_obj->dynamic.state = USB_DEVICE_STATE_DEFAULT;
|
||||
dev_obj->constant.default_pipe = default_pipe_hdl;
|
||||
dev_obj->constant.port_hdl = port_hdl;
|
||||
dev_obj->constant.speed = speed;
|
||||
dev_obj->constant.uid = uid;
|
||||
dev_obj->constant.port_hdl = params->root_port_hdl;
|
||||
dev_obj->constant.parent_dev_hdl = params->parent_dev_hdl;
|
||||
dev_obj->constant.parent_port_num = params->parent_port_num;
|
||||
dev_obj->constant.speed = params->speed;
|
||||
dev_obj->constant.uid = params->uid;
|
||||
// Note: Enumeration related dev_obj->constant fields are initialized later using usbh_dev_set_...() functions
|
||||
|
||||
// Write-back device object
|
||||
*dev_obj_ret = dev_obj;
|
||||
ret = ESP_OK;
|
||||
@ -407,11 +410,11 @@ static void device_free(device_t *dev_obj)
|
||||
if (dev_obj == NULL) {
|
||||
return;
|
||||
}
|
||||
// Device descriptor might not have been set yet
|
||||
// Device descriptor might not have been allocated (in case of early enumeration failure)
|
||||
if (dev_obj->constant.desc) {
|
||||
heap_caps_free(dev_obj->constant.desc);
|
||||
}
|
||||
// Configuration descriptor might not have been set yet
|
||||
// Configuration might not have been allocated (in case of early enumeration failure)
|
||||
if (dev_obj->constant.config_desc) {
|
||||
heap_caps_free(dev_obj->constant.config_desc);
|
||||
}
|
||||
@ -429,7 +432,9 @@ static void device_free(device_t *dev_obj)
|
||||
heap_caps_free(dev_obj);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------- Callbacks ------------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
// -------------------------- Callbacks ----------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
static bool ep0_pipe_callback(hcd_pipe_handle_t pipe_hdl, hcd_pipe_event_t pipe_event, void *user_arg, bool in_isr)
|
||||
{
|
||||
@ -487,7 +492,9 @@ static bool epN_pipe_callback(hcd_pipe_handle_t pipe_hdl, hcd_pipe_event_t pipe_
|
||||
in_isr);
|
||||
}
|
||||
|
||||
// -------------------------------------------------- Event Related ----------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
// ------------------------- Event Related -------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
static bool _dev_set_actions(device_t *dev_obj, uint32_t action_flags)
|
||||
{
|
||||
@ -581,6 +588,8 @@ static inline void handle_free(device_t *dev_obj)
|
||||
{
|
||||
// Cache a copy of the device's address as we are about to free the device object
|
||||
const unsigned int dev_uid = dev_obj->constant.uid;
|
||||
usb_device_handle_t parent_dev_hdl = dev_obj->constant.parent_dev_hdl;
|
||||
const uint8_t parent_port_num = dev_obj->constant.parent_port_num;
|
||||
bool all_free;
|
||||
ESP_LOGD(USBH_TAG, "Freeing device %d", dev_obj->constant.address);
|
||||
|
||||
@ -605,6 +614,8 @@ static inline void handle_free(device_t *dev_obj)
|
||||
.event = USBH_EVENT_DEV_FREE,
|
||||
.dev_free_data = {
|
||||
.dev_uid = dev_uid,
|
||||
.parent_dev_hdl = parent_dev_hdl,
|
||||
.port_num = parent_port_num,
|
||||
}
|
||||
};
|
||||
p_usbh_obj->constant.event_cb(&event_data, p_usbh_obj->constant.event_cb_arg);
|
||||
@ -629,7 +640,9 @@ 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 Processing Functions ----------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
// ------------------------- USBH Processing Functions -------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
esp_err_t usbh_install(const usbh_config_t *usbh_config)
|
||||
{
|
||||
@ -766,7 +779,9 @@ esp_err_t usbh_process(void)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// ---------------------------------------------- Device Pool Functions ------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
// ------------------------- Device Pool Functions -----------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
esp_err_t usbh_devs_num(int *num_devs_ret)
|
||||
{
|
||||
@ -825,14 +840,15 @@ esp_err_t usbh_devs_addr_list_fill(int list_len, uint8_t *dev_addr_list, int *nu
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t usbh_devs_add(unsigned int uid, usb_speed_t dev_speed, hcd_port_handle_t port_hdl)
|
||||
esp_err_t usbh_devs_add(usbh_dev_params_t *params)
|
||||
{
|
||||
USBH_CHECK(port_hdl != NULL, ESP_ERR_INVALID_ARG);
|
||||
USBH_CHECK(params != NULL, ESP_ERR_NOT_ALLOWED);
|
||||
USBH_CHECK(params->root_port_hdl != NULL, ESP_ERR_INVALID_ARG);
|
||||
esp_err_t ret;
|
||||
device_t *dev_obj;
|
||||
|
||||
// Allocate a device object (initialized to address 0)
|
||||
ret = device_alloc(uid, dev_speed, port_hdl, &dev_obj);
|
||||
ret = device_alloc(params, &dev_obj);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
@ -842,7 +858,7 @@ esp_err_t usbh_devs_add(unsigned int uid, usb_speed_t dev_speed, hcd_port_handle
|
||||
USBH_ENTER_CRITICAL();
|
||||
|
||||
// Check that there is not already a device with the same uid
|
||||
if (_find_dev_from_uid(uid) != NULL) {
|
||||
if (_find_dev_from_uid(params->uid) != NULL) {
|
||||
ret = ESP_ERR_INVALID_ARG;
|
||||
goto exit;
|
||||
}
|
||||
@ -860,6 +876,11 @@ exit:
|
||||
USBH_EXIT_CRITICAL();
|
||||
xSemaphoreGive(p_usbh_obj->constant.mux_lock);
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
// Free dev_obj for memory not to leak
|
||||
device_free(dev_obj);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -901,6 +922,27 @@ exit:
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t usbh_devs_get_parent_info(unsigned int uid, usb_parent_dev_info_t *parent_info)
|
||||
{
|
||||
USBH_CHECK(parent_info, ESP_ERR_INVALID_ARG);
|
||||
esp_err_t ret = ESP_FAIL;
|
||||
device_t *dev_obj = NULL;
|
||||
|
||||
USBH_ENTER_CRITICAL();
|
||||
dev_obj = _find_dev_from_uid(uid);
|
||||
if (dev_obj == NULL) {
|
||||
ret = ESP_ERR_NOT_FOUND;
|
||||
goto exit;
|
||||
} else {
|
||||
parent_info->dev_hdl = dev_obj->constant.parent_dev_hdl;
|
||||
parent_info->port_num = dev_obj->constant.parent_port_num;
|
||||
ret = ESP_OK;
|
||||
}
|
||||
exit:
|
||||
USBH_EXIT_CRITICAL();
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t usbh_devs_mark_all_free(void)
|
||||
{
|
||||
USBH_ENTER_CRITICAL();
|
||||
@ -971,7 +1013,30 @@ esp_err_t usbh_devs_open(uint8_t dev_addr, usb_device_handle_t *dev_hdl)
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t usbh_devs_close(usb_device_handle_t dev_hdl)
|
||||
esp_err_t usbh_devs_new_dev_event(usb_device_handle_t dev_hdl)
|
||||
{
|
||||
device_t *dev_obj = (device_t *)dev_hdl;
|
||||
bool call_proc_req_cb = false;
|
||||
|
||||
USBH_ENTER_CRITICAL();
|
||||
// Device must be in the configured state
|
||||
USBH_CHECK_FROM_CRIT(dev_obj->dynamic.state == USB_DEVICE_STATE_CONFIGURED, ESP_ERR_INVALID_STATE);
|
||||
call_proc_req_cb = _dev_set_actions(dev_obj, DEV_ACTION_PROP_NEW_DEV);
|
||||
USBH_EXIT_CRITICAL();
|
||||
|
||||
// Call the processing request callback
|
||||
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 ESP_OK;
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// ---------------------------- Device Functions -------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
esp_err_t usbh_dev_close(usb_device_handle_t dev_hdl)
|
||||
{
|
||||
USBH_CHECK(dev_hdl != NULL, ESP_ERR_INVALID_ARG);
|
||||
device_t *dev_obj = (device_t *)dev_hdl;
|
||||
@ -1000,28 +1065,9 @@ esp_err_t usbh_devs_close(usb_device_handle_t dev_hdl)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t usbh_devs_new_dev_event(usb_device_handle_t dev_hdl)
|
||||
{
|
||||
device_t *dev_obj = (device_t *)dev_hdl;
|
||||
bool call_proc_req_cb = false;
|
||||
|
||||
USBH_ENTER_CRITICAL();
|
||||
// Device must be in the configured state
|
||||
USBH_CHECK_FROM_CRIT(dev_obj->dynamic.state == USB_DEVICE_STATE_CONFIGURED, ESP_ERR_INVALID_STATE);
|
||||
call_proc_req_cb = _dev_set_actions(dev_obj, DEV_ACTION_PROP_NEW_DEV);
|
||||
USBH_EXIT_CRITICAL();
|
||||
|
||||
// Call the processing request callback
|
||||
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 ESP_OK;
|
||||
}
|
||||
|
||||
// ------------------------------------------------ Device Functions ---------------------------------------------------
|
||||
|
||||
// ----------------------- Getters -------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
// ---------------------------- Getters ----------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
esp_err_t usbh_dev_get_addr(usb_device_handle_t dev_hdl, uint8_t *dev_addr)
|
||||
{
|
||||
@ -1029,7 +1075,6 @@ esp_err_t usbh_dev_get_addr(usb_device_handle_t dev_hdl, uint8_t *dev_addr)
|
||||
device_t *dev_obj = (device_t *)dev_hdl;
|
||||
|
||||
USBH_ENTER_CRITICAL();
|
||||
USBH_CHECK_FROM_CRIT(dev_obj->constant.address > 0, ESP_ERR_INVALID_STATE);
|
||||
*dev_addr = dev_obj->constant.address;
|
||||
USBH_EXIT_CRITICAL();
|
||||
|
||||
@ -1041,6 +1086,8 @@ esp_err_t usbh_dev_get_info(usb_device_handle_t dev_hdl, usb_device_info_t *dev_
|
||||
USBH_CHECK(dev_hdl != NULL && dev_info != NULL, ESP_ERR_INVALID_ARG);
|
||||
device_t *dev_obj = (device_t *)dev_hdl;
|
||||
|
||||
dev_info->parent.dev_hdl = dev_obj->constant.parent_dev_hdl;
|
||||
dev_info->parent.port_num = dev_obj->constant.parent_port_num;
|
||||
dev_info->speed = dev_obj->constant.speed;
|
||||
dev_info->dev_addr = dev_obj->constant.address;
|
||||
// Device descriptor might not have been set yet
|
||||
@ -1067,7 +1114,6 @@ esp_err_t usbh_dev_get_desc(usb_device_handle_t dev_hdl, const usb_device_desc_t
|
||||
{
|
||||
USBH_CHECK(dev_hdl != NULL && dev_desc_ret != NULL, ESP_ERR_INVALID_ARG);
|
||||
device_t *dev_obj = (device_t *)dev_hdl;
|
||||
|
||||
*dev_desc_ret = dev_obj->constant.desc;
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -1082,7 +1128,9 @@ esp_err_t usbh_dev_get_config_desc(usb_device_handle_t dev_hdl, const usb_config
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// ----------------------- Setters -------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
// -------------------------------- Setters ------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
esp_err_t usbh_dev_enum_lock(usb_device_handle_t dev_hdl)
|
||||
{
|
||||
@ -1330,7 +1378,9 @@ err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
// ----------------------------------------------- Endpoint 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)
|
||||
{
|
||||
@ -1460,7 +1510,9 @@ void *usbh_ep_get_context(usbh_ep_handle_t ep_hdl)
|
||||
return hcd_pipe_get_context(ep_obj->constant.pipe_hdl);
|
||||
}
|
||||
|
||||
// ----------------------------------------------- Transfer Functions --------------------------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
// ------------------------ Transfer Functions ---------------------------------
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
esp_err_t usbh_dev_submit_ctrl_urb(usb_device_handle_t dev_hdl, urb_t *urb)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user