mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-31 19:24:33 +02:00
Merge branch 'refactor/usb_host_usbh_interface_v5.1' into 'release/v5.1'
USB Host: Refactor USBH interface (v5.1) See merge request espressif/esp-idf!24210
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -23,28 +23,28 @@ Implementation of the HUB driver that only supports the Root Hub with a single p
|
|||||||
implement the bare minimum to control the root HCD port.
|
implement the bare minimum to control the root HCD port.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define HUB_ROOT_PORT_NUM 1 //HCD only supports one port
|
#define HUB_ROOT_PORT_NUM 1 // HCD only supports one port
|
||||||
#ifdef CONFIG_USB_HOST_HW_BUFFER_BIAS_IN
|
#ifdef CONFIG_USB_HOST_HW_BUFFER_BIAS_IN
|
||||||
#define HUB_ROOT_HCD_PORT_FIFO_BIAS HCD_PORT_FIFO_BIAS_RX
|
#define HUB_ROOT_HCD_PORT_FIFO_BIAS HCD_PORT_FIFO_BIAS_RX
|
||||||
#elif CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT
|
#elif CONFIG_USB_HOST_HW_BUFFER_BIAS_PERIODIC_OUT
|
||||||
#define HUB_ROOT_HCD_PORT_FIFO_BIAS HCD_PORT_FIFO_BIAS_PTX
|
#define HUB_ROOT_HCD_PORT_FIFO_BIAS HCD_PORT_FIFO_BIAS_PTX
|
||||||
#else //CONFIG_USB_HOST_HW_BUFFER_BIAS_BALANCED
|
#else // CONFIG_USB_HOST_HW_BUFFER_BIAS_BALANCED
|
||||||
#define HUB_ROOT_HCD_PORT_FIFO_BIAS HCD_PORT_FIFO_BIAS_BALANCED
|
#define HUB_ROOT_HCD_PORT_FIFO_BIAS HCD_PORT_FIFO_BIAS_BALANCED
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SET_ADDR_RECOVERY_INTERVAL_MS CONFIG_USB_HOST_SET_ADDR_RECOVERY_MS
|
#define SET_ADDR_RECOVERY_INTERVAL_MS CONFIG_USB_HOST_SET_ADDR_RECOVERY_MS
|
||||||
|
|
||||||
#define ENUM_CTRL_TRANSFER_MAX_DATA_LEN CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE
|
#define ENUM_CTRL_TRANSFER_MAX_DATA_LEN CONFIG_USB_HOST_CONTROL_TRANSFER_MAX_SIZE
|
||||||
#define ENUM_DEV_ADDR 1 //Device address used in enumeration
|
#define ENUM_DEV_ADDR 1 // Device address used in enumeration
|
||||||
#define ENUM_CONFIG_INDEX 0 //Index used to get the first configuration descriptor of the device
|
#define ENUM_CONFIG_INDEX 0 // Index used to get the first configuration descriptor of the device
|
||||||
#define ENUM_SHORT_DESC_REQ_LEN 8 //Number of bytes to request when getting a short descriptor (just enough to get bMaxPacketSize0 or wTotalLength)
|
#define ENUM_SHORT_DESC_REQ_LEN 8 // Number of bytes to request when getting a short descriptor (just enough to get bMaxPacketSize0 or wTotalLength)
|
||||||
#define ENUM_WORST_CASE_MPS_LS 8 //The worst case MPS of EP0 for a LS device
|
#define ENUM_WORST_CASE_MPS_LS 8 // The worst case MPS of EP0 for a LS device
|
||||||
#define ENUM_WORST_CASE_MPS_FS 64 //The worst case MPS of EP0 for a FS device
|
#define ENUM_WORST_CASE_MPS_FS 64 // The worst case MPS of EP0 for a FS device
|
||||||
#define ENUM_LOW_SPEED_MPS 8 //Worst case MPS for the default endpoint of a low-speed device
|
#define ENUM_LOW_SPEED_MPS 8 // Worst case MPS for the default endpoint of a low-speed device
|
||||||
#define ENUM_FULL_SPEED_MPS 64 //Worst case MPS for the default endpoint of a full-speed device
|
#define ENUM_FULL_SPEED_MPS 64 // Worst case MPS for the default endpoint of a full-speed device
|
||||||
#define ENUM_LANGID 0x409 //Current enumeration only supports English (United States) string descriptors
|
#define ENUM_LANGID 0x409 // Current enumeration only supports English (United States) string descriptors
|
||||||
|
|
||||||
//Hub driver action flags. LISTED IN THE ORDER THEY SHOULD BE HANDLED IN within hub_process(). Some actions are mutually exclusive
|
// Hub driver action flags. LISTED IN THE ORDER THEY SHOULD BE HANDLED IN within hub_process(). Some actions are mutually exclusive
|
||||||
#define HUB_DRIVER_FLAG_ACTION_ROOT_EVENT 0x01
|
#define HUB_DRIVER_FLAG_ACTION_ROOT_EVENT 0x01
|
||||||
#define HUB_DRIVER_FLAG_ACTION_PORT_DISABLE 0x02
|
#define HUB_DRIVER_FLAG_ACTION_PORT_DISABLE 0x02
|
||||||
#define HUB_DRIVER_FLAG_ACTION_PORT_RECOVER 0x04
|
#define HUB_DRIVER_FLAG_ACTION_PORT_RECOVER 0x04
|
||||||
@@ -75,7 +75,7 @@ typedef enum {
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
ENUM_STAGE_NONE = 0, /**< There is no device awaiting enumeration. Start requires device connection and first reset. */
|
ENUM_STAGE_NONE = 0, /**< There is no device awaiting enumeration. Start requires device connection and first reset. */
|
||||||
ENUM_STAGE_START, /**< A device has connected and has already been reset once. Allocate a device object in USBH */
|
ENUM_STAGE_START, /**< A device has connected and has already been reset once. Allocate a device object in USBH */
|
||||||
//Basic device enumeration
|
// Basic device enumeration
|
||||||
ENUM_STAGE_GET_SHORT_DEV_DESC, /**< Getting short dev desc (wLength is ENUM_SHORT_DESC_REQ_LEN) */
|
ENUM_STAGE_GET_SHORT_DEV_DESC, /**< Getting short dev desc (wLength is ENUM_SHORT_DESC_REQ_LEN) */
|
||||||
ENUM_STAGE_CHECK_SHORT_DEV_DESC, /**< Save bMaxPacketSize0 from the short dev desc. Update the MPS of the enum pipe */
|
ENUM_STAGE_CHECK_SHORT_DEV_DESC, /**< Save bMaxPacketSize0 from the short dev desc. Update the MPS of the enum pipe */
|
||||||
ENUM_STAGE_SECOND_RESET, /**< Reset the device again (Workaround for old USB devices that get confused by the previous short dev desc request). */
|
ENUM_STAGE_SECOND_RESET, /**< Reset the device again (Workaround for old USB devices that get confused by the previous short dev desc request). */
|
||||||
@@ -90,7 +90,7 @@ typedef enum {
|
|||||||
ENUM_STAGE_CHECK_FULL_CONFIG_DESC, /**< Check the full config desc, fill it into the device object in USBH */
|
ENUM_STAGE_CHECK_FULL_CONFIG_DESC, /**< Check the full config desc, fill it into the device object in USBH */
|
||||||
ENUM_STAGE_SET_CONFIG, /**< Send SET_CONFIGURATION request */
|
ENUM_STAGE_SET_CONFIG, /**< Send SET_CONFIGURATION request */
|
||||||
ENUM_STAGE_CHECK_CONFIG, /**< Check that SET_CONFIGURATION request was successful */
|
ENUM_STAGE_CHECK_CONFIG, /**< Check that SET_CONFIGURATION request was successful */
|
||||||
//Get string descriptors
|
// Get string descriptors
|
||||||
ENUM_STAGE_GET_SHORT_LANGID_TABLE, /**< Get the header of the LANGID table string descriptor */
|
ENUM_STAGE_GET_SHORT_LANGID_TABLE, /**< Get the header of the LANGID table string descriptor */
|
||||||
ENUM_STAGE_CHECK_SHORT_LANGID_TABLE, /**< Save the bLength of the LANGID table string descriptor */
|
ENUM_STAGE_CHECK_SHORT_LANGID_TABLE, /**< Save the bLength of the LANGID table string descriptor */
|
||||||
ENUM_STAGE_GET_FULL_LANGID_TABLE, /**< Get the full LANGID table string descriptor */
|
ENUM_STAGE_GET_FULL_LANGID_TABLE, /**< Get the full LANGID table string descriptor */
|
||||||
@@ -107,7 +107,7 @@ typedef enum {
|
|||||||
ENUM_STAGE_CHECK_SHORT_SER_STR_DESC, /**< Save the bLength of the iSerialNumber string descriptor */
|
ENUM_STAGE_CHECK_SHORT_SER_STR_DESC, /**< Save the bLength of the iSerialNumber string descriptor */
|
||||||
ENUM_STAGE_GET_FULL_SER_STR_DESC, /**< Get the full iSerialNumber string descriptor */
|
ENUM_STAGE_GET_FULL_SER_STR_DESC, /**< Get the full iSerialNumber string descriptor */
|
||||||
ENUM_STAGE_CHECK_FULL_SER_STR_DESC, /**< Check and fill the full iSerialNumber string descriptor */
|
ENUM_STAGE_CHECK_FULL_SER_STR_DESC, /**< Check and fill the full iSerialNumber string descriptor */
|
||||||
//Cleanup
|
// Cleanup
|
||||||
ENUM_STAGE_CLEANUP, /**< Clean up after successful enumeration. Adds enumerated device to USBH */
|
ENUM_STAGE_CLEANUP, /**< Clean up after successful enumeration. Adds enumerated device to USBH */
|
||||||
ENUM_STAGE_CLEANUP_FAILED, /**< Cleanup failed enumeration. Free device resources */
|
ENUM_STAGE_CLEANUP_FAILED, /**< Cleanup failed enumeration. Free device resources */
|
||||||
} enum_stage_t;
|
} enum_stage_t;
|
||||||
@@ -150,12 +150,12 @@ const char *const enum_stage_strings[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
//Constant
|
// Constant
|
||||||
urb_t *urb; /**< URB used for enumeration control transfers. Max data length of ENUM_CTRL_TRANSFER_MAX_DATA_LEN */
|
urb_t *urb; /**< URB used for enumeration control transfers. Max data length of ENUM_CTRL_TRANSFER_MAX_DATA_LEN */
|
||||||
//Initialized at start of a particular enumeration
|
// Initialized at start of a particular enumeration
|
||||||
usb_device_handle_t dev_hdl; /**< Handle of device being enumerated */
|
usb_device_handle_t dev_hdl; /**< Handle of device being enumerated */
|
||||||
hcd_pipe_handle_t pipe; /**< Default pipe handle of the device being enumerated */
|
hcd_pipe_handle_t pipe; /**< Default pipe handle of the device being enumerated */
|
||||||
//Updated during enumeration
|
// Updated during enumeration
|
||||||
enum_stage_t stage; /**< Current enumeration stage */
|
enum_stage_t stage; /**< Current enumeration stage */
|
||||||
int expect_num_bytes; /**< Expected number of bytes for IN transfers stages. Set to 0 for OUT transfer */
|
int expect_num_bytes; /**< Expected number of bytes for IN transfers stages. Set to 0 for OUT transfer */
|
||||||
uint8_t bMaxPacketSize0; /**< Max packet size of the device's EP0. Read from bMaxPacketSize0 field of device descriptor */
|
uint8_t bMaxPacketSize0; /**< Max packet size of the device's EP0. Read from bMaxPacketSize0 field of device descriptor */
|
||||||
@@ -168,7 +168,7 @@ typedef struct {
|
|||||||
} enum_ctrl_t;
|
} enum_ctrl_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
//Dynamic members require a critical section
|
// Dynamic members require a critical section
|
||||||
struct {
|
struct {
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
@@ -179,16 +179,16 @@ typedef struct {
|
|||||||
} flags;
|
} flags;
|
||||||
hub_driver_state_t driver_state;
|
hub_driver_state_t driver_state;
|
||||||
} dynamic;
|
} dynamic;
|
||||||
//Single thread members don't require a critical section so long as they are never accessed from multiple threads
|
// Single thread members don't require a critical section so long as they are never accessed from multiple threads
|
||||||
struct {
|
struct {
|
||||||
usb_device_handle_t root_dev_hdl; //Indicates if an enumerated device is connected to the root port
|
usb_device_handle_t root_dev_hdl; // Indicates if an enumerated device is connected to the root port
|
||||||
enum_ctrl_t enum_ctrl;
|
enum_ctrl_t enum_ctrl;
|
||||||
} single_thread;
|
} single_thread;
|
||||||
//Constant members do no change after installation thus do not require a critical section
|
// Constant members do no change after installation thus do not require a critical section
|
||||||
struct {
|
struct {
|
||||||
hcd_port_handle_t root_port_hdl;
|
hcd_port_handle_t root_port_hdl;
|
||||||
usb_notif_cb_t notif_cb;
|
usb_proc_req_cb_t proc_req_cb;
|
||||||
void *notif_cb_arg;
|
void *proc_req_cb_arg;
|
||||||
} constant;
|
} constant;
|
||||||
} hub_driver_t;
|
} hub_driver_t;
|
||||||
|
|
||||||
@@ -223,7 +223,7 @@ const char *HUB_DRIVER_TAG = "HUB";
|
|||||||
*
|
*
|
||||||
* - This callback is called from the context of the HCD, so any event handling should be deferred to hub_process()
|
* - This callback is called from the context of the HCD, so any event handling should be deferred to hub_process()
|
||||||
* - Under the current HCD implementation, this callback should only be ever be called in an ISR
|
* - Under the current HCD implementation, this callback should only be ever be called in an ISR
|
||||||
* - This callback needs to call the notification to ensure hub_process() gets a chance to run
|
* - This callback needs to call proc_req_cb to ensure that hub_process() gets a chance to run
|
||||||
*
|
*
|
||||||
* @param port_hdl HCD port handle
|
* @param port_hdl HCD port handle
|
||||||
* @param port_event HCD port event
|
* @param port_event HCD port event
|
||||||
@@ -237,7 +237,7 @@ static bool root_port_callback(hcd_port_handle_t port_hdl, hcd_port_event_t port
|
|||||||
* @brief HCD pipe callback for the default pipe of the device under enumeration
|
* @brief HCD pipe callback for the default pipe of the device under enumeration
|
||||||
*
|
*
|
||||||
* - This callback is called from the context of the HCD, so any event handling should be deferred to hub_process()
|
* - This callback is called from the context of the HCD, so any event handling should be deferred to hub_process()
|
||||||
* - This callback needs to call the notification to ensure hub_process() gets a chance to run
|
* - This callback needs to call proc_req_cb to ensure that hub_process() gets a chance to run
|
||||||
*
|
*
|
||||||
* @param pipe_hdl HCD pipe handle
|
* @param pipe_hdl HCD pipe handle
|
||||||
* @param pipe_event Pipe event
|
* @param pipe_event Pipe event
|
||||||
@@ -251,7 +251,7 @@ static bool enum_dflt_pipe_callback(hcd_pipe_handle_t pipe_hdl, hcd_pipe_event_t
|
|||||||
* @brief USBH Hub driver request callback
|
* @brief USBH Hub driver request callback
|
||||||
*
|
*
|
||||||
* - This callback is called from the context of the USBH, so so any event handling should be deferred to hub_process()
|
* - This callback is called from the context of the USBH, so so any event handling should be deferred to hub_process()
|
||||||
* - This callback needs to call the notification to ensure hub_process() gets a chance to run
|
* - This callback needs to call proc_req_cb to ensure that hub_process() gets a chance to run
|
||||||
*
|
*
|
||||||
* @param port_hdl HCD port handle
|
* @param port_hdl HCD port handle
|
||||||
* @param hub_req Hub driver request
|
* @param hub_req Hub driver request
|
||||||
@@ -263,20 +263,20 @@ static void usbh_hub_req_callback(hcd_port_handle_t port_hdl, usbh_hub_req_t hub
|
|||||||
|
|
||||||
static bool enum_stage_start(enum_ctrl_t *enum_ctrl)
|
static bool enum_stage_start(enum_ctrl_t *enum_ctrl)
|
||||||
{
|
{
|
||||||
//Get the speed of the device, and set the enum MPS to the worst case size for now
|
// Get the speed of the device, and set the enum MPS to the worst case size for now
|
||||||
usb_speed_t speed;
|
usb_speed_t speed;
|
||||||
if (hcd_port_get_speed(p_hub_driver_obj->constant.root_port_hdl, &speed) != ESP_OK) {
|
if (hcd_port_get_speed(p_hub_driver_obj->constant.root_port_hdl, &speed) != ESP_OK) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
enum_ctrl->bMaxPacketSize0 = (speed == USB_SPEED_LOW) ? ENUM_WORST_CASE_MPS_LS : ENUM_WORST_CASE_MPS_FS;
|
enum_ctrl->bMaxPacketSize0 = (speed == USB_SPEED_LOW) ? ENUM_WORST_CASE_MPS_LS : ENUM_WORST_CASE_MPS_FS;
|
||||||
//Try to add the device to USBH
|
// Try to add the device to USBH
|
||||||
usb_device_handle_t enum_dev_hdl;
|
usb_device_handle_t enum_dev_hdl;
|
||||||
hcd_pipe_handle_t enum_dflt_pipe_hdl;
|
hcd_pipe_handle_t enum_dflt_pipe_hdl;
|
||||||
//We use NULL as the parent device to indicate the Root Hub port 1. We currently only support a single device
|
// We use NULL as the parent device to indicate the Root Hub port 1. We currently only support a single device
|
||||||
if (usbh_hub_add_dev(p_hub_driver_obj->constant.root_port_hdl, speed, &enum_dev_hdl, &enum_dflt_pipe_hdl) != ESP_OK) {
|
if (usbh_hub_add_dev(p_hub_driver_obj->constant.root_port_hdl, speed, &enum_dev_hdl, &enum_dflt_pipe_hdl) != ESP_OK) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//Set our own default pipe callback
|
// Set our own default pipe callback
|
||||||
ESP_ERROR_CHECK(hcd_pipe_update_callback(enum_dflt_pipe_hdl, enum_dflt_pipe_callback, NULL));
|
ESP_ERROR_CHECK(hcd_pipe_update_callback(enum_dflt_pipe_hdl, enum_dflt_pipe_callback, NULL));
|
||||||
enum_ctrl->dev_hdl = enum_dev_hdl;
|
enum_ctrl->dev_hdl = enum_dev_hdl;
|
||||||
enum_ctrl->pipe = enum_dflt_pipe_hdl;
|
enum_ctrl->pipe = enum_dflt_pipe_hdl;
|
||||||
@@ -285,7 +285,7 @@ static bool enum_stage_start(enum_ctrl_t *enum_ctrl)
|
|||||||
|
|
||||||
static bool enum_stage_second_reset(enum_ctrl_t *enum_ctrl)
|
static bool enum_stage_second_reset(enum_ctrl_t *enum_ctrl)
|
||||||
{
|
{
|
||||||
ESP_ERROR_CHECK(hcd_pipe_set_persist_reset(enum_ctrl->pipe)); //Persist the default pipe through the reset
|
ESP_ERROR_CHECK(hcd_pipe_set_persist_reset(enum_ctrl->pipe)); // Persist the default pipe through the reset
|
||||||
if (hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_RESET) != ESP_OK) {
|
if (hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_RESET) != ESP_OK) {
|
||||||
ESP_LOGE(HUB_DRIVER_TAG, "Failed to issue second reset");
|
ESP_LOGE(HUB_DRIVER_TAG, "Failed to issue second reset");
|
||||||
return false;
|
return false;
|
||||||
@@ -298,26 +298,26 @@ static void get_string_desc_index_and_langid(enum_ctrl_t *enum_ctrl, uint8_t *in
|
|||||||
switch (enum_ctrl->stage) {
|
switch (enum_ctrl->stage) {
|
||||||
case ENUM_STAGE_GET_SHORT_LANGID_TABLE:
|
case ENUM_STAGE_GET_SHORT_LANGID_TABLE:
|
||||||
case ENUM_STAGE_GET_FULL_LANGID_TABLE:
|
case ENUM_STAGE_GET_FULL_LANGID_TABLE:
|
||||||
*index = 0; //The LANGID table uses an index of 0
|
*index = 0; // The LANGID table uses an index of 0
|
||||||
*langid = 0; //Getting the LANGID table itself should use a LANGID of 0
|
*langid = 0; // Getting the LANGID table itself should use a LANGID of 0
|
||||||
break;
|
break;
|
||||||
case ENUM_STAGE_GET_SHORT_MANU_STR_DESC:
|
case ENUM_STAGE_GET_SHORT_MANU_STR_DESC:
|
||||||
case ENUM_STAGE_GET_FULL_MANU_STR_DESC:
|
case ENUM_STAGE_GET_FULL_MANU_STR_DESC:
|
||||||
*index = enum_ctrl->iManufacturer;
|
*index = enum_ctrl->iManufacturer;
|
||||||
*langid = ENUM_LANGID; //Use the default LANGID
|
*langid = ENUM_LANGID; // Use the default LANGID
|
||||||
break;
|
break;
|
||||||
case ENUM_STAGE_GET_SHORT_PROD_STR_DESC:
|
case ENUM_STAGE_GET_SHORT_PROD_STR_DESC:
|
||||||
case ENUM_STAGE_GET_FULL_PROD_STR_DESC:
|
case ENUM_STAGE_GET_FULL_PROD_STR_DESC:
|
||||||
*index = enum_ctrl->iProduct;
|
*index = enum_ctrl->iProduct;
|
||||||
*langid = ENUM_LANGID; //Use the default LANGID
|
*langid = ENUM_LANGID; // Use the default LANGID
|
||||||
break;
|
break;
|
||||||
case ENUM_STAGE_GET_SHORT_SER_STR_DESC:
|
case ENUM_STAGE_GET_SHORT_SER_STR_DESC:
|
||||||
case ENUM_STAGE_GET_FULL_SER_STR_DESC:
|
case ENUM_STAGE_GET_FULL_SER_STR_DESC:
|
||||||
*index = enum_ctrl->iSerialNumber;
|
*index = enum_ctrl->iSerialNumber;
|
||||||
*langid = ENUM_LANGID; //Use the default LANGID
|
*langid = ENUM_LANGID; // Use the default LANGID
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
//Should not occur
|
// Should not occur
|
||||||
abort();
|
abort();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -328,47 +328,47 @@ static bool enum_stage_transfer(enum_ctrl_t *enum_ctrl)
|
|||||||
usb_transfer_t *transfer = &enum_ctrl->urb->transfer;
|
usb_transfer_t *transfer = &enum_ctrl->urb->transfer;
|
||||||
switch (enum_ctrl->stage) {
|
switch (enum_ctrl->stage) {
|
||||||
case ENUM_STAGE_GET_SHORT_DEV_DESC: {
|
case ENUM_STAGE_GET_SHORT_DEV_DESC: {
|
||||||
//Initialize a short device descriptor request
|
// Initialize a short device descriptor request
|
||||||
USB_SETUP_PACKET_INIT_GET_DEVICE_DESC((usb_setup_packet_t *)transfer->data_buffer);
|
USB_SETUP_PACKET_INIT_GET_DEVICE_DESC((usb_setup_packet_t *)transfer->data_buffer);
|
||||||
((usb_setup_packet_t *)transfer->data_buffer)->wLength = ENUM_SHORT_DESC_REQ_LEN;
|
((usb_setup_packet_t *)transfer->data_buffer)->wLength = ENUM_SHORT_DESC_REQ_LEN;
|
||||||
transfer->num_bytes = sizeof(usb_setup_packet_t) + usb_round_up_to_mps(ENUM_SHORT_DESC_REQ_LEN, enum_ctrl->bMaxPacketSize0);
|
transfer->num_bytes = sizeof(usb_setup_packet_t) + usb_round_up_to_mps(ENUM_SHORT_DESC_REQ_LEN, enum_ctrl->bMaxPacketSize0);
|
||||||
//IN data stage should return exactly ENUM_SHORT_DESC_REQ_LEN bytes
|
// IN data stage should return exactly ENUM_SHORT_DESC_REQ_LEN bytes
|
||||||
enum_ctrl->expect_num_bytes = sizeof(usb_setup_packet_t) + ENUM_SHORT_DESC_REQ_LEN;
|
enum_ctrl->expect_num_bytes = sizeof(usb_setup_packet_t) + ENUM_SHORT_DESC_REQ_LEN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ENUM_STAGE_SET_ADDR: {
|
case ENUM_STAGE_SET_ADDR: {
|
||||||
USB_SETUP_PACKET_INIT_SET_ADDR((usb_setup_packet_t *)transfer->data_buffer, ENUM_DEV_ADDR);
|
USB_SETUP_PACKET_INIT_SET_ADDR((usb_setup_packet_t *)transfer->data_buffer, ENUM_DEV_ADDR);
|
||||||
transfer->num_bytes = sizeof(usb_setup_packet_t); //No data stage
|
transfer->num_bytes = sizeof(usb_setup_packet_t); // No data stage
|
||||||
enum_ctrl->expect_num_bytes = 0; //OUT transfer. No need to check number of bytes returned
|
enum_ctrl->expect_num_bytes = 0; // OUT transfer. No need to check number of bytes returned
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ENUM_STAGE_GET_FULL_DEV_DESC: {
|
case ENUM_STAGE_GET_FULL_DEV_DESC: {
|
||||||
USB_SETUP_PACKET_INIT_GET_DEVICE_DESC((usb_setup_packet_t *)transfer->data_buffer);
|
USB_SETUP_PACKET_INIT_GET_DEVICE_DESC((usb_setup_packet_t *)transfer->data_buffer);
|
||||||
transfer->num_bytes = sizeof(usb_setup_packet_t) + usb_round_up_to_mps(sizeof(usb_device_desc_t), enum_ctrl->bMaxPacketSize0);
|
transfer->num_bytes = sizeof(usb_setup_packet_t) + usb_round_up_to_mps(sizeof(usb_device_desc_t), enum_ctrl->bMaxPacketSize0);
|
||||||
//IN data stage should return exactly sizeof(usb_device_desc_t) bytes
|
// IN data stage should return exactly sizeof(usb_device_desc_t) bytes
|
||||||
enum_ctrl->expect_num_bytes = sizeof(usb_setup_packet_t) + sizeof(usb_device_desc_t);
|
enum_ctrl->expect_num_bytes = sizeof(usb_setup_packet_t) + sizeof(usb_device_desc_t);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ENUM_STAGE_GET_SHORT_CONFIG_DESC: {
|
case ENUM_STAGE_GET_SHORT_CONFIG_DESC: {
|
||||||
//Get a short config descriptor at index 0
|
// Get a short config descriptor at index 0
|
||||||
USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)transfer->data_buffer, ENUM_CONFIG_INDEX, ENUM_SHORT_DESC_REQ_LEN);
|
USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)transfer->data_buffer, ENUM_CONFIG_INDEX, ENUM_SHORT_DESC_REQ_LEN);
|
||||||
transfer->num_bytes = sizeof(usb_setup_packet_t) + usb_round_up_to_mps(ENUM_SHORT_DESC_REQ_LEN, enum_ctrl->bMaxPacketSize0);
|
transfer->num_bytes = sizeof(usb_setup_packet_t) + usb_round_up_to_mps(ENUM_SHORT_DESC_REQ_LEN, enum_ctrl->bMaxPacketSize0);
|
||||||
//IN data stage should return exactly ENUM_SHORT_DESC_REQ_LEN bytes
|
// IN data stage should return exactly ENUM_SHORT_DESC_REQ_LEN bytes
|
||||||
enum_ctrl->expect_num_bytes = sizeof(usb_setup_packet_t) + ENUM_SHORT_DESC_REQ_LEN;
|
enum_ctrl->expect_num_bytes = sizeof(usb_setup_packet_t) + ENUM_SHORT_DESC_REQ_LEN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ENUM_STAGE_GET_FULL_CONFIG_DESC: {
|
case ENUM_STAGE_GET_FULL_CONFIG_DESC: {
|
||||||
//Get the full configuration descriptor at index 0, requesting its exact length.
|
// Get the full configuration descriptor at index 0, requesting its exact length.
|
||||||
USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)transfer->data_buffer, ENUM_CONFIG_INDEX, enum_ctrl->wTotalLength);
|
USB_SETUP_PACKET_INIT_GET_CONFIG_DESC((usb_setup_packet_t *)transfer->data_buffer, ENUM_CONFIG_INDEX, enum_ctrl->wTotalLength);
|
||||||
transfer->num_bytes = sizeof(usb_setup_packet_t) + usb_round_up_to_mps(enum_ctrl->wTotalLength, enum_ctrl->bMaxPacketSize0);
|
transfer->num_bytes = sizeof(usb_setup_packet_t) + usb_round_up_to_mps(enum_ctrl->wTotalLength, enum_ctrl->bMaxPacketSize0);
|
||||||
//IN data stage should return exactly wTotalLength bytes
|
// IN data stage should return exactly wTotalLength bytes
|
||||||
enum_ctrl->expect_num_bytes = sizeof(usb_setup_packet_t) + enum_ctrl->wTotalLength;
|
enum_ctrl->expect_num_bytes = sizeof(usb_setup_packet_t) + enum_ctrl->wTotalLength;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ENUM_STAGE_SET_CONFIG: {
|
case ENUM_STAGE_SET_CONFIG: {
|
||||||
USB_SETUP_PACKET_INIT_SET_CONFIG((usb_setup_packet_t *)transfer->data_buffer, enum_ctrl->bConfigurationValue);
|
USB_SETUP_PACKET_INIT_SET_CONFIG((usb_setup_packet_t *)transfer->data_buffer, enum_ctrl->bConfigurationValue);
|
||||||
transfer->num_bytes = sizeof(usb_setup_packet_t); //No data stage
|
transfer->num_bytes = sizeof(usb_setup_packet_t); // No data stage
|
||||||
enum_ctrl->expect_num_bytes = 0; //OUT transfer. No need to check number of bytes returned
|
enum_ctrl->expect_num_bytes = 0; // OUT transfer. No need to check number of bytes returned
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ENUM_STAGE_GET_SHORT_LANGID_TABLE:
|
case ENUM_STAGE_GET_SHORT_LANGID_TABLE:
|
||||||
@@ -378,13 +378,13 @@ static bool enum_stage_transfer(enum_ctrl_t *enum_ctrl)
|
|||||||
uint8_t index;
|
uint8_t index;
|
||||||
uint16_t langid;
|
uint16_t langid;
|
||||||
get_string_desc_index_and_langid(enum_ctrl, &index, &langid);
|
get_string_desc_index_and_langid(enum_ctrl, &index, &langid);
|
||||||
//Get only the header of the string descriptor
|
// Get only the header of the string descriptor
|
||||||
USB_SETUP_PACKET_INIT_GET_STR_DESC((usb_setup_packet_t *)transfer->data_buffer,
|
USB_SETUP_PACKET_INIT_GET_STR_DESC((usb_setup_packet_t *)transfer->data_buffer,
|
||||||
index,
|
index,
|
||||||
langid,
|
langid,
|
||||||
sizeof(usb_str_desc_t));
|
sizeof(usb_str_desc_t));
|
||||||
transfer->num_bytes = sizeof(usb_setup_packet_t) + usb_round_up_to_mps(sizeof(usb_str_desc_t), enum_ctrl->bMaxPacketSize0);
|
transfer->num_bytes = sizeof(usb_setup_packet_t) + usb_round_up_to_mps(sizeof(usb_str_desc_t), enum_ctrl->bMaxPacketSize0);
|
||||||
//IN data stage should return exactly sizeof(usb_str_desc_t) bytes
|
// IN data stage should return exactly sizeof(usb_str_desc_t) bytes
|
||||||
enum_ctrl->expect_num_bytes = sizeof(usb_setup_packet_t) + sizeof(usb_str_desc_t);
|
enum_ctrl->expect_num_bytes = sizeof(usb_setup_packet_t) + sizeof(usb_str_desc_t);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -395,17 +395,17 @@ static bool enum_stage_transfer(enum_ctrl_t *enum_ctrl)
|
|||||||
uint8_t index;
|
uint8_t index;
|
||||||
uint16_t langid;
|
uint16_t langid;
|
||||||
get_string_desc_index_and_langid(enum_ctrl, &index, &langid);
|
get_string_desc_index_and_langid(enum_ctrl, &index, &langid);
|
||||||
//Get the full string descriptor at a particular index, requesting the descriptors exact length
|
// Get the full string descriptor at a particular index, requesting the descriptors exact length
|
||||||
USB_SETUP_PACKET_INIT_GET_STR_DESC((usb_setup_packet_t *)transfer->data_buffer,
|
USB_SETUP_PACKET_INIT_GET_STR_DESC((usb_setup_packet_t *)transfer->data_buffer,
|
||||||
index,
|
index,
|
||||||
langid,
|
langid,
|
||||||
enum_ctrl->str_desc_bLength);
|
enum_ctrl->str_desc_bLength);
|
||||||
transfer->num_bytes = sizeof(usb_setup_packet_t) + usb_round_up_to_mps(enum_ctrl->str_desc_bLength, enum_ctrl->bMaxPacketSize0);
|
transfer->num_bytes = sizeof(usb_setup_packet_t) + usb_round_up_to_mps(enum_ctrl->str_desc_bLength, enum_ctrl->bMaxPacketSize0);
|
||||||
//IN data stage should return exactly str_desc_bLength bytes
|
// IN data stage should return exactly str_desc_bLength bytes
|
||||||
enum_ctrl->expect_num_bytes = sizeof(usb_setup_packet_t) + enum_ctrl->str_desc_bLength;
|
enum_ctrl->expect_num_bytes = sizeof(usb_setup_packet_t) + enum_ctrl->str_desc_bLength;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: //Should never occur
|
default: // Should never occur
|
||||||
abort();
|
abort();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -424,7 +424,7 @@ static bool enum_stage_wait(enum_ctrl_t *enum_ctrl)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
default: //Should never occur
|
default: // Should never occur
|
||||||
abort();
|
abort();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -434,57 +434,57 @@ static bool enum_stage_wait(enum_ctrl_t *enum_ctrl)
|
|||||||
|
|
||||||
static bool enum_stage_transfer_check(enum_ctrl_t *enum_ctrl)
|
static bool enum_stage_transfer_check(enum_ctrl_t *enum_ctrl)
|
||||||
{
|
{
|
||||||
//Dequeue the URB
|
// Dequeue the URB
|
||||||
urb_t *dequeued_enum_urb = hcd_urb_dequeue(enum_ctrl->pipe);
|
urb_t *dequeued_enum_urb = hcd_urb_dequeue(enum_ctrl->pipe);
|
||||||
assert(dequeued_enum_urb == enum_ctrl->urb);
|
assert(dequeued_enum_urb == enum_ctrl->urb);
|
||||||
|
|
||||||
//Check transfer status
|
// Check transfer status
|
||||||
usb_transfer_t *transfer = &dequeued_enum_urb->transfer;
|
usb_transfer_t *transfer = &dequeued_enum_urb->transfer;
|
||||||
if (transfer->status != USB_TRANSFER_STATUS_COMPLETED) {
|
if (transfer->status != USB_TRANSFER_STATUS_COMPLETED) {
|
||||||
ESP_LOGE(HUB_DRIVER_TAG, "Bad transfer status %d: %s", transfer->status, enum_stage_strings[enum_ctrl->stage]);
|
ESP_LOGE(HUB_DRIVER_TAG, "Bad transfer status %d: %s", transfer->status, enum_stage_strings[enum_ctrl->stage]);
|
||||||
if (transfer->status == USB_TRANSFER_STATUS_STALL) {
|
if (transfer->status == USB_TRANSFER_STATUS_STALL) {
|
||||||
//EP stalled, clearing the pipe to execute further stages
|
// EP stalled, clearing the pipe to execute further stages
|
||||||
ESP_ERROR_CHECK(hcd_pipe_command(enum_ctrl->pipe, HCD_PIPE_CMD_CLEAR));
|
ESP_ERROR_CHECK(hcd_pipe_command(enum_ctrl->pipe, HCD_PIPE_CMD_CLEAR));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//Check IN transfer returned the expected correct number of bytes
|
// Check IN transfer returned the expected correct number of bytes
|
||||||
if (enum_ctrl->expect_num_bytes != 0 && enum_ctrl->expect_num_bytes != transfer->actual_num_bytes) {
|
if (enum_ctrl->expect_num_bytes != 0 && enum_ctrl->expect_num_bytes != transfer->actual_num_bytes) {
|
||||||
ESP_LOGE(HUB_DRIVER_TAG, "Incorrect number of bytes returned %d: %s", transfer->actual_num_bytes, enum_stage_strings[enum_ctrl->stage]);
|
ESP_LOGE(HUB_DRIVER_TAG, "Incorrect number of bytes returned %d: %s", transfer->actual_num_bytes, enum_stage_strings[enum_ctrl->stage]);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Stage specific checks and updates
|
// Stage specific checks and updates
|
||||||
bool ret;
|
bool ret;
|
||||||
switch (enum_ctrl->stage) {
|
switch (enum_ctrl->stage) {
|
||||||
case ENUM_STAGE_CHECK_SHORT_DEV_DESC: {
|
case ENUM_STAGE_CHECK_SHORT_DEV_DESC: {
|
||||||
const usb_device_desc_t *device_desc = (usb_device_desc_t *)(transfer->data_buffer + sizeof(usb_setup_packet_t));
|
const usb_device_desc_t *device_desc = (usb_device_desc_t *)(transfer->data_buffer + sizeof(usb_setup_packet_t));
|
||||||
//Check if the returned descriptor is corrupted
|
// Check if the returned descriptor is corrupted
|
||||||
if (device_desc->bDescriptorType != USB_B_DESCRIPTOR_TYPE_DEVICE) {
|
if (device_desc->bDescriptorType != USB_B_DESCRIPTOR_TYPE_DEVICE) {
|
||||||
ESP_LOGE(HUB_DRIVER_TAG, "Short dev desc corrupt");
|
ESP_LOGE(HUB_DRIVER_TAG, "Short dev desc corrupt");
|
||||||
ret = false;
|
ret = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//Update and save the MPS of the default pipe
|
// Update and save the MPS of the default pipe
|
||||||
if (hcd_pipe_update_mps(enum_ctrl->pipe, device_desc->bMaxPacketSize0) != ESP_OK) {
|
if (hcd_pipe_update_mps(enum_ctrl->pipe, device_desc->bMaxPacketSize0) != ESP_OK) {
|
||||||
ESP_LOGE(HUB_DRIVER_TAG, "Failed to update MPS");
|
ESP_LOGE(HUB_DRIVER_TAG, "Failed to update MPS");
|
||||||
ret = false;
|
ret = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//Save the actual MPS of EP0
|
// Save the actual MPS of EP0
|
||||||
enum_ctrl->bMaxPacketSize0 = device_desc->bMaxPacketSize0;
|
enum_ctrl->bMaxPacketSize0 = device_desc->bMaxPacketSize0;
|
||||||
ret = true;
|
ret = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ENUM_STAGE_CHECK_ADDR: {
|
case ENUM_STAGE_CHECK_ADDR: {
|
||||||
//Update the pipe and device's address, and fill the address into the device object
|
// Update the pipe and device's address, and fill the address into the device object
|
||||||
ESP_ERROR_CHECK(hcd_pipe_update_dev_addr(enum_ctrl->pipe, ENUM_DEV_ADDR));
|
ESP_ERROR_CHECK(hcd_pipe_update_dev_addr(enum_ctrl->pipe, ENUM_DEV_ADDR));
|
||||||
ESP_ERROR_CHECK(usbh_hub_enum_fill_dev_addr(enum_ctrl->dev_hdl, ENUM_DEV_ADDR));
|
ESP_ERROR_CHECK(usbh_hub_enum_fill_dev_addr(enum_ctrl->dev_hdl, ENUM_DEV_ADDR));
|
||||||
ret = true;
|
ret = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ENUM_STAGE_CHECK_FULL_DEV_DESC: {
|
case ENUM_STAGE_CHECK_FULL_DEV_DESC: {
|
||||||
//Fill device descriptor into the device object
|
// Fill device descriptor into the device object
|
||||||
const usb_device_desc_t *device_desc = (const usb_device_desc_t *)(transfer->data_buffer + sizeof(usb_setup_packet_t));
|
const usb_device_desc_t *device_desc = (const usb_device_desc_t *)(transfer->data_buffer + sizeof(usb_setup_packet_t));
|
||||||
ESP_ERROR_CHECK(usbh_hub_enum_fill_dev_desc(enum_ctrl->dev_hdl, device_desc));
|
ESP_ERROR_CHECK(usbh_hub_enum_fill_dev_desc(enum_ctrl->dev_hdl, device_desc));
|
||||||
enum_ctrl->iManufacturer = device_desc->iManufacturer;
|
enum_ctrl->iManufacturer = device_desc->iManufacturer;
|
||||||
@@ -495,27 +495,27 @@ static bool enum_stage_transfer_check(enum_ctrl_t *enum_ctrl)
|
|||||||
}
|
}
|
||||||
case ENUM_STAGE_CHECK_SHORT_CONFIG_DESC: {
|
case ENUM_STAGE_CHECK_SHORT_CONFIG_DESC: {
|
||||||
const usb_config_desc_t *config_desc = (usb_config_desc_t *)(transfer->data_buffer + sizeof(usb_setup_packet_t));
|
const usb_config_desc_t *config_desc = (usb_config_desc_t *)(transfer->data_buffer + sizeof(usb_setup_packet_t));
|
||||||
//Check if the returned descriptor is corrupted
|
// Check if the returned descriptor is corrupted
|
||||||
if (config_desc->bDescriptorType != USB_B_DESCRIPTOR_TYPE_CONFIGURATION) {
|
if (config_desc->bDescriptorType != USB_B_DESCRIPTOR_TYPE_CONFIGURATION) {
|
||||||
ESP_LOGE(HUB_DRIVER_TAG, "Short config desc corrupt");
|
ESP_LOGE(HUB_DRIVER_TAG, "Short config desc corrupt");
|
||||||
ret = false;
|
ret = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if (ENUM_CTRL_TRANSFER_MAX_DATA_LEN < UINT16_MAX) //Suppress -Wtype-limits warning due to uint16_t wTotalLength
|
#if (ENUM_CTRL_TRANSFER_MAX_DATA_LEN < UINT16_MAX) // Suppress -Wtype-limits warning due to uint16_t wTotalLength
|
||||||
//Check if the descriptor is too long to be supported
|
// Check if the descriptor is too long to be supported
|
||||||
if (config_desc->wTotalLength > ENUM_CTRL_TRANSFER_MAX_DATA_LEN) {
|
if (config_desc->wTotalLength > ENUM_CTRL_TRANSFER_MAX_DATA_LEN) {
|
||||||
ESP_LOGE(HUB_DRIVER_TAG, "Configuration descriptor larger than control transfer max length");
|
ESP_LOGE(HUB_DRIVER_TAG, "Configuration descriptor larger than control transfer max length");
|
||||||
ret = false;
|
ret = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
//Save the configuration descriptors full length
|
// Save the configuration descriptors full length
|
||||||
enum_ctrl->wTotalLength = config_desc->wTotalLength;
|
enum_ctrl->wTotalLength = config_desc->wTotalLength;
|
||||||
ret = true;
|
ret = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ENUM_STAGE_CHECK_FULL_CONFIG_DESC: {
|
case ENUM_STAGE_CHECK_FULL_CONFIG_DESC: {
|
||||||
//Fill configuration descriptor into the device object
|
// Fill configuration descriptor into the device object
|
||||||
const usb_config_desc_t *config_desc = (usb_config_desc_t *)(transfer->data_buffer + sizeof(usb_setup_packet_t));
|
const usb_config_desc_t *config_desc = (usb_config_desc_t *)(transfer->data_buffer + sizeof(usb_setup_packet_t));
|
||||||
enum_ctrl->bConfigurationValue = config_desc->bConfigurationValue;
|
enum_ctrl->bConfigurationValue = config_desc->bConfigurationValue;
|
||||||
ESP_ERROR_CHECK(usbh_hub_enum_fill_config_desc(enum_ctrl->dev_hdl, config_desc));
|
ESP_ERROR_CHECK(usbh_hub_enum_fill_config_desc(enum_ctrl->dev_hdl, config_desc));
|
||||||
@@ -524,7 +524,7 @@ static bool enum_stage_transfer_check(enum_ctrl_t *enum_ctrl)
|
|||||||
}
|
}
|
||||||
case ENUM_STAGE_CHECK_CONFIG: {
|
case ENUM_STAGE_CHECK_CONFIG: {
|
||||||
ret = true;
|
ret = true;
|
||||||
//Nothing to do
|
// Nothing to do
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ENUM_STAGE_CHECK_SHORT_LANGID_TABLE:
|
case ENUM_STAGE_CHECK_SHORT_LANGID_TABLE:
|
||||||
@@ -532,7 +532,7 @@ static bool enum_stage_transfer_check(enum_ctrl_t *enum_ctrl)
|
|||||||
case ENUM_STAGE_CHECK_SHORT_PROD_STR_DESC:
|
case ENUM_STAGE_CHECK_SHORT_PROD_STR_DESC:
|
||||||
case ENUM_STAGE_CHECK_SHORT_SER_STR_DESC: {
|
case ENUM_STAGE_CHECK_SHORT_SER_STR_DESC: {
|
||||||
const usb_str_desc_t *str_desc = (usb_str_desc_t *)(transfer->data_buffer + sizeof(usb_setup_packet_t));
|
const usb_str_desc_t *str_desc = (usb_str_desc_t *)(transfer->data_buffer + sizeof(usb_setup_packet_t));
|
||||||
//Check if the returned descriptor is supported or corrupted
|
// Check if the returned descriptor is supported or corrupted
|
||||||
if (str_desc->bDescriptorType == 0) {
|
if (str_desc->bDescriptorType == 0) {
|
||||||
ESP_LOGW(HUB_DRIVER_TAG, "String desc not supported");
|
ESP_LOGW(HUB_DRIVER_TAG, "String desc not supported");
|
||||||
ret = false;
|
ret = false;
|
||||||
@@ -542,15 +542,15 @@ static bool enum_stage_transfer_check(enum_ctrl_t *enum_ctrl)
|
|||||||
ret = false;
|
ret = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#if (ENUM_CTRL_TRANSFER_MAX_DATA_LEN < UINT8_MAX) //Suppress -Wtype-limits warning due to uint8_t bLength
|
#if (ENUM_CTRL_TRANSFER_MAX_DATA_LEN < UINT8_MAX) // Suppress -Wtype-limits warning due to uint8_t bLength
|
||||||
//Check if the descriptor is too long to be supported
|
// Check if the descriptor is too long to be supported
|
||||||
if (str_desc->bLength > (uint32_t)ENUM_CTRL_TRANSFER_MAX_DATA_LEN) {
|
if (str_desc->bLength > (uint32_t)ENUM_CTRL_TRANSFER_MAX_DATA_LEN) {
|
||||||
ESP_LOGE(HUB_DRIVER_TAG, "String descriptor larger than control transfer max length");
|
ESP_LOGE(HUB_DRIVER_TAG, "String descriptor larger than control transfer max length");
|
||||||
ret = false;
|
ret = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
//Save the descriptors full length
|
// Save the descriptors full length
|
||||||
enum_ctrl->str_desc_bLength = str_desc->bLength;
|
enum_ctrl->str_desc_bLength = str_desc->bLength;
|
||||||
ret = true;
|
ret = true;
|
||||||
break;
|
break;
|
||||||
@@ -560,7 +560,7 @@ static bool enum_stage_transfer_check(enum_ctrl_t *enum_ctrl)
|
|||||||
case ENUM_STAGE_CHECK_FULL_PROD_STR_DESC:
|
case ENUM_STAGE_CHECK_FULL_PROD_STR_DESC:
|
||||||
case ENUM_STAGE_CHECK_FULL_SER_STR_DESC: {
|
case ENUM_STAGE_CHECK_FULL_SER_STR_DESC: {
|
||||||
const usb_str_desc_t *str_desc = (usb_str_desc_t *)(transfer->data_buffer + sizeof(usb_setup_packet_t));
|
const usb_str_desc_t *str_desc = (usb_str_desc_t *)(transfer->data_buffer + sizeof(usb_setup_packet_t));
|
||||||
//Check if the returned descriptor is supported or corrupted
|
// Check if the returned descriptor is supported or corrupted
|
||||||
if (str_desc->bDescriptorType == 0) {
|
if (str_desc->bDescriptorType == 0) {
|
||||||
ESP_LOGW(HUB_DRIVER_TAG, "String desc not supported");
|
ESP_LOGW(HUB_DRIVER_TAG, "String desc not supported");
|
||||||
ret = false;
|
ret = false;
|
||||||
@@ -571,10 +571,10 @@ static bool enum_stage_transfer_check(enum_ctrl_t *enum_ctrl)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (enum_ctrl->stage == ENUM_STAGE_CHECK_FULL_LANGID_TABLE) {
|
if (enum_ctrl->stage == ENUM_STAGE_CHECK_FULL_LANGID_TABLE) {
|
||||||
//Scan the LANGID table for our target LANGID
|
// Scan the LANGID table for our target LANGID
|
||||||
bool target_langid_found = false;
|
bool target_langid_found = false;
|
||||||
int langid_table_num_entries = (str_desc->bLength - sizeof(usb_str_desc_t))/2; //Each LANGID is 2 bytes
|
int langid_table_num_entries = (str_desc->bLength - sizeof(usb_str_desc_t)) / 2; // Each LANGID is 2 bytes
|
||||||
for (int i = 0; i < langid_table_num_entries; i++) { //Each LANGID is 2 bytes
|
for (int i = 0; i < langid_table_num_entries; i++) { // Each LANGID is 2 bytes
|
||||||
if (str_desc->wData[i] == ENUM_LANGID) {
|
if (str_desc->wData[i] == ENUM_LANGID) {
|
||||||
target_langid_found = true;
|
target_langid_found = true;
|
||||||
break;
|
break;
|
||||||
@@ -586,13 +586,13 @@ static bool enum_stage_transfer_check(enum_ctrl_t *enum_ctrl)
|
|||||||
ret = target_langid_found;
|
ret = target_langid_found;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
//Fill the string descriptor into the device object
|
// Fill the string descriptor into the device object
|
||||||
int select;
|
int select;
|
||||||
if (enum_ctrl->stage == ENUM_STAGE_CHECK_FULL_MANU_STR_DESC) {
|
if (enum_ctrl->stage == ENUM_STAGE_CHECK_FULL_MANU_STR_DESC) {
|
||||||
select = 0;
|
select = 0;
|
||||||
} else if (enum_ctrl->stage == ENUM_STAGE_CHECK_FULL_PROD_STR_DESC) {
|
} else if (enum_ctrl->stage == ENUM_STAGE_CHECK_FULL_PROD_STR_DESC) {
|
||||||
select = 1;
|
select = 1;
|
||||||
} else { //ENUM_STAGE_CHECK_FULL_PROD_STR_DESC
|
} else { // ENUM_STAGE_CHECK_FULL_PROD_STR_DESC
|
||||||
select = 2;
|
select = 2;
|
||||||
}
|
}
|
||||||
ESP_ERROR_CHECK(usbh_hub_enum_fill_str_desc(enum_ctrl->dev_hdl, str_desc, select));
|
ESP_ERROR_CHECK(usbh_hub_enum_fill_str_desc(enum_ctrl->dev_hdl, str_desc, select));
|
||||||
@@ -600,7 +600,7 @@ static bool enum_stage_transfer_check(enum_ctrl_t *enum_ctrl)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default: //Should never occur
|
default: // Should never occur
|
||||||
ret = false;
|
ret = false;
|
||||||
abort();
|
abort();
|
||||||
break;
|
break;
|
||||||
@@ -610,39 +610,39 @@ static bool enum_stage_transfer_check(enum_ctrl_t *enum_ctrl)
|
|||||||
|
|
||||||
static void enum_stage_cleanup(enum_ctrl_t *enum_ctrl)
|
static void enum_stage_cleanup(enum_ctrl_t *enum_ctrl)
|
||||||
{
|
{
|
||||||
//We currently only support a single device connected to the root port. Move the device handle from enum to root
|
// We currently only support a single device connected to the root port. Move the device handle from enum to root
|
||||||
HUB_DRIVER_ENTER_CRITICAL();
|
HUB_DRIVER_ENTER_CRITICAL();
|
||||||
p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_ACTIVE;
|
p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_ACTIVE;
|
||||||
HUB_DRIVER_EXIT_CRITICAL();
|
HUB_DRIVER_EXIT_CRITICAL();
|
||||||
p_hub_driver_obj->single_thread.root_dev_hdl = enum_ctrl->dev_hdl;
|
p_hub_driver_obj->single_thread.root_dev_hdl = enum_ctrl->dev_hdl;
|
||||||
usb_device_handle_t dev_hdl = enum_ctrl->dev_hdl;
|
usb_device_handle_t dev_hdl = enum_ctrl->dev_hdl;
|
||||||
//Clear values in enum_ctrl
|
// Clear values in enum_ctrl
|
||||||
enum_ctrl->dev_hdl = NULL;
|
enum_ctrl->dev_hdl = NULL;
|
||||||
enum_ctrl->pipe = NULL;
|
enum_ctrl->pipe = NULL;
|
||||||
//Update device object after enumeration is done
|
// Update device object after enumeration is done
|
||||||
ESP_ERROR_CHECK(usbh_hub_enum_done(dev_hdl));
|
ESP_ERROR_CHECK(usbh_hub_enum_done(dev_hdl));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void enum_stage_cleanup_failed(enum_ctrl_t *enum_ctrl)
|
static void enum_stage_cleanup_failed(enum_ctrl_t *enum_ctrl)
|
||||||
{
|
{
|
||||||
//Enumeration failed. Clear the enum device handle and pipe
|
// Enumeration failed. Clear the enum device handle and pipe
|
||||||
if (enum_ctrl->dev_hdl) {
|
if (enum_ctrl->dev_hdl) {
|
||||||
//If enumeration failed due to a port event, we need to Halt, flush, and dequeue enum default pipe in case there
|
// If enumeration failed due to a port event, we need to Halt, flush, and dequeue enum default pipe in case there
|
||||||
//was an in-flight URB.
|
// was an in-flight URB.
|
||||||
ESP_ERROR_CHECK(hcd_pipe_command(enum_ctrl->pipe, HCD_PIPE_CMD_HALT));
|
ESP_ERROR_CHECK(hcd_pipe_command(enum_ctrl->pipe, HCD_PIPE_CMD_HALT));
|
||||||
ESP_ERROR_CHECK(hcd_pipe_command(enum_ctrl->pipe, HCD_PIPE_CMD_FLUSH));
|
ESP_ERROR_CHECK(hcd_pipe_command(enum_ctrl->pipe, HCD_PIPE_CMD_FLUSH));
|
||||||
hcd_urb_dequeue(enum_ctrl->pipe); //This could return NULL if there
|
hcd_urb_dequeue(enum_ctrl->pipe); // This could return NULL if there
|
||||||
ESP_ERROR_CHECK(usbh_hub_enum_failed(enum_ctrl->dev_hdl)); //Free the underlying device object first before recovering the port
|
ESP_ERROR_CHECK(usbh_hub_enum_failed(enum_ctrl->dev_hdl)); // Free the underlying device object first before recovering the port
|
||||||
}
|
}
|
||||||
//Clear values in enum_ctrl
|
// Clear values in enum_ctrl
|
||||||
enum_ctrl->dev_hdl = NULL;
|
enum_ctrl->dev_hdl = NULL;
|
||||||
enum_ctrl->pipe = NULL;
|
enum_ctrl->pipe = NULL;
|
||||||
HUB_DRIVER_ENTER_CRITICAL();
|
HUB_DRIVER_ENTER_CRITICAL();
|
||||||
//Enum could have failed due to a port error. If so, we need to trigger a port recovery
|
// Enum could have failed due to a port error. If so, we need to trigger a port recovery
|
||||||
if (p_hub_driver_obj->dynamic.driver_state == HUB_DRIVER_STATE_ROOT_RECOVERY) {
|
if (p_hub_driver_obj->dynamic.driver_state == HUB_DRIVER_STATE_ROOT_RECOVERY) {
|
||||||
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_PORT_RECOVER;
|
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_PORT_RECOVER;
|
||||||
} else {
|
} else {
|
||||||
//Otherwise, we move to the enum failed state and wait for the device to disconnect
|
// Otherwise, we move to the enum failed state and wait for the device to disconnect
|
||||||
p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_ENUM_FAILED;
|
p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_ENUM_FAILED;
|
||||||
}
|
}
|
||||||
HUB_DRIVER_EXIT_CRITICAL();
|
HUB_DRIVER_EXIT_CRITICAL();
|
||||||
@@ -651,8 +651,8 @@ static void enum_stage_cleanup_failed(enum_ctrl_t *enum_ctrl)
|
|||||||
static enum_stage_t get_next_stage(enum_stage_t old_stage, enum_ctrl_t *enum_ctrl)
|
static enum_stage_t get_next_stage(enum_stage_t old_stage, enum_ctrl_t *enum_ctrl)
|
||||||
{
|
{
|
||||||
enum_stage_t new_stage = old_stage + 1;
|
enum_stage_t new_stage = old_stage + 1;
|
||||||
//Skip the GET_DESCRIPTOR string type corresponding stages if a particular index is 0.
|
// Skip the GET_DESCRIPTOR string type corresponding stages if a particular index is 0.
|
||||||
while(((new_stage == ENUM_STAGE_GET_SHORT_MANU_STR_DESC ||
|
while (((new_stage == ENUM_STAGE_GET_SHORT_MANU_STR_DESC ||
|
||||||
new_stage == ENUM_STAGE_CHECK_SHORT_MANU_STR_DESC ||
|
new_stage == ENUM_STAGE_CHECK_SHORT_MANU_STR_DESC ||
|
||||||
new_stage == ENUM_STAGE_GET_FULL_MANU_STR_DESC ||
|
new_stage == ENUM_STAGE_GET_FULL_MANU_STR_DESC ||
|
||||||
new_stage == ENUM_STAGE_CHECK_FULL_MANU_STR_DESC) && enum_ctrl->iManufacturer == 0) ||
|
new_stage == ENUM_STAGE_CHECK_FULL_MANU_STR_DESC) && enum_ctrl->iManufacturer == 0) ||
|
||||||
@@ -671,7 +671,7 @@ static enum_stage_t get_next_stage(enum_stage_t old_stage, enum_ctrl_t *enum_ctr
|
|||||||
|
|
||||||
static void enum_set_next_stage(enum_ctrl_t *enum_ctrl, bool last_stage_pass)
|
static void enum_set_next_stage(enum_ctrl_t *enum_ctrl, bool last_stage_pass)
|
||||||
{
|
{
|
||||||
//Set next stage
|
// Set next stage
|
||||||
if (last_stage_pass) {
|
if (last_stage_pass) {
|
||||||
if (enum_ctrl->stage != ENUM_STAGE_NONE &&
|
if (enum_ctrl->stage != ENUM_STAGE_NONE &&
|
||||||
enum_ctrl->stage != ENUM_STAGE_CLEANUP &&
|
enum_ctrl->stage != ENUM_STAGE_CLEANUP &&
|
||||||
@@ -683,7 +683,7 @@ static void enum_set_next_stage(enum_ctrl_t *enum_ctrl, bool last_stage_pass)
|
|||||||
} else {
|
} else {
|
||||||
switch (enum_ctrl->stage) {
|
switch (enum_ctrl->stage) {
|
||||||
case ENUM_STAGE_START:
|
case ENUM_STAGE_START:
|
||||||
//Stage failed but clean up not required
|
// Stage failed but clean up not required
|
||||||
enum_ctrl->stage = ENUM_STAGE_NONE;
|
enum_ctrl->stage = ENUM_STAGE_NONE;
|
||||||
break;
|
break;
|
||||||
case ENUM_STAGE_GET_SHORT_LANGID_TABLE:
|
case ENUM_STAGE_GET_SHORT_LANGID_TABLE:
|
||||||
@@ -702,17 +702,17 @@ static void enum_set_next_stage(enum_ctrl_t *enum_ctrl, bool last_stage_pass)
|
|||||||
case ENUM_STAGE_CHECK_SHORT_SER_STR_DESC:
|
case ENUM_STAGE_CHECK_SHORT_SER_STR_DESC:
|
||||||
case ENUM_STAGE_GET_FULL_SER_STR_DESC:
|
case ENUM_STAGE_GET_FULL_SER_STR_DESC:
|
||||||
case ENUM_STAGE_CHECK_FULL_SER_STR_DESC:
|
case ENUM_STAGE_CHECK_FULL_SER_STR_DESC:
|
||||||
//String descriptor stages are allow to fail. We just don't fetch them and treat enumeration as successful
|
// String descriptor stages are allow to fail. We just don't fetch them and treat enumeration as successful
|
||||||
enum_ctrl->stage = ENUM_STAGE_CLEANUP;
|
enum_ctrl->stage = ENUM_STAGE_CLEANUP;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
//Enumeration failed. Go to failure clean up
|
// Enumeration failed. Go to failure clean up
|
||||||
enum_ctrl->stage = ENUM_STAGE_CLEANUP_FAILED;
|
enum_ctrl->stage = ENUM_STAGE_CLEANUP_FAILED;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//These stages are not waiting for a callback, so we need to re-trigger the enum event
|
// These stages are not waiting for a callback, so we need to re-trigger the enum event
|
||||||
bool re_trigger;
|
bool re_trigger;
|
||||||
switch (enum_ctrl->stage) {
|
switch (enum_ctrl->stage) {
|
||||||
case ENUM_STAGE_GET_SHORT_DEV_DESC:
|
case ENUM_STAGE_GET_SHORT_DEV_DESC:
|
||||||
@@ -755,22 +755,22 @@ static bool root_port_callback(hcd_port_handle_t port_hdl, hcd_port_event_t port
|
|||||||
HUB_DRIVER_ENTER_CRITICAL_SAFE();
|
HUB_DRIVER_ENTER_CRITICAL_SAFE();
|
||||||
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ROOT_EVENT;
|
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ROOT_EVENT;
|
||||||
HUB_DRIVER_EXIT_CRITICAL_SAFE();
|
HUB_DRIVER_EXIT_CRITICAL_SAFE();
|
||||||
assert(in_isr); //Currently, this callback should only ever be called from an ISR context
|
assert(in_isr); // Currently, this callback should only ever be called from an ISR context
|
||||||
return p_hub_driver_obj->constant.notif_cb(USB_NOTIF_SOURCE_HUB, in_isr, p_hub_driver_obj->constant.notif_cb_arg);;
|
return p_hub_driver_obj->constant.proc_req_cb(USB_PROC_REQ_SOURCE_HUB, in_isr, p_hub_driver_obj->constant.proc_req_cb_arg);;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool enum_dflt_pipe_callback(hcd_pipe_handle_t pipe_hdl, hcd_pipe_event_t pipe_event, void *user_arg, bool in_isr)
|
static bool enum_dflt_pipe_callback(hcd_pipe_handle_t pipe_hdl, hcd_pipe_event_t pipe_event, void *user_arg, bool in_isr)
|
||||||
{
|
{
|
||||||
//Note: This callback may have triggered when a failed enumeration is already cleaned up (e.g., due to a failed port reset)
|
// Note: This callback may have triggered when a failed enumeration is already cleaned up (e.g., due to a failed port reset)
|
||||||
HUB_DRIVER_ENTER_CRITICAL_SAFE();
|
HUB_DRIVER_ENTER_CRITICAL_SAFE();
|
||||||
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ENUM_EVENT;
|
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ENUM_EVENT;
|
||||||
HUB_DRIVER_EXIT_CRITICAL_SAFE();
|
HUB_DRIVER_EXIT_CRITICAL_SAFE();
|
||||||
return p_hub_driver_obj->constant.notif_cb(USB_NOTIF_SOURCE_HUB, in_isr, p_hub_driver_obj->constant.notif_cb_arg);
|
return p_hub_driver_obj->constant.proc_req_cb(USB_PROC_REQ_SOURCE_HUB, in_isr, p_hub_driver_obj->constant.proc_req_cb_arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usbh_hub_req_callback(hcd_port_handle_t port_hdl, usbh_hub_req_t hub_req, void *arg)
|
static void usbh_hub_req_callback(hcd_port_handle_t port_hdl, usbh_hub_req_t hub_req, void *arg)
|
||||||
{
|
{
|
||||||
//We currently only support the root port, so the port_hdl should match the root port
|
// We currently only support the root port, so the port_hdl should match the root port
|
||||||
assert(port_hdl == p_hub_driver_obj->constant.root_port_hdl);
|
assert(port_hdl == p_hub_driver_obj->constant.root_port_hdl);
|
||||||
|
|
||||||
HUB_DRIVER_ENTER_CRITICAL();
|
HUB_DRIVER_ENTER_CRITICAL();
|
||||||
@@ -782,13 +782,13 @@ static void usbh_hub_req_callback(hcd_port_handle_t port_hdl, usbh_hub_req_t hub
|
|||||||
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_PORT_RECOVER;
|
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_PORT_RECOVER;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
//Should never occur
|
// Should never occur
|
||||||
abort();
|
abort();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
HUB_DRIVER_EXIT_CRITICAL();
|
HUB_DRIVER_EXIT_CRITICAL();
|
||||||
|
|
||||||
p_hub_driver_obj->constant.notif_cb(USB_NOTIF_SOURCE_HUB, false, p_hub_driver_obj->constant.notif_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);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------- Handlers -------------------------
|
// ---------------------- Handlers -------------------------
|
||||||
@@ -798,12 +798,12 @@ static void root_port_handle_events(hcd_port_handle_t root_port_hdl)
|
|||||||
hcd_port_event_t port_event = hcd_port_handle_event(root_port_hdl);
|
hcd_port_event_t port_event = hcd_port_handle_event(root_port_hdl);
|
||||||
switch (port_event) {
|
switch (port_event) {
|
||||||
case HCD_PORT_EVENT_NONE:
|
case HCD_PORT_EVENT_NONE:
|
||||||
//Nothing to do
|
// Nothing to do
|
||||||
break;
|
break;
|
||||||
case HCD_PORT_EVENT_CONNECTION: {
|
case HCD_PORT_EVENT_CONNECTION: {
|
||||||
if (hcd_port_command(root_port_hdl, HCD_PORT_CMD_RESET) == ESP_OK) {
|
if (hcd_port_command(root_port_hdl, HCD_PORT_CMD_RESET) == ESP_OK) {
|
||||||
ESP_LOGD(HUB_DRIVER_TAG, "Root port reset");
|
ESP_LOGD(HUB_DRIVER_TAG, "Root port reset");
|
||||||
//Start enumeration
|
// Start enumeration
|
||||||
HUB_DRIVER_ENTER_CRITICAL();
|
HUB_DRIVER_ENTER_CRITICAL();
|
||||||
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ENUM_EVENT;
|
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ENUM_EVENT;
|
||||||
p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_ENUM;
|
p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_ENUM;
|
||||||
@@ -820,22 +820,22 @@ static void root_port_handle_events(hcd_port_handle_t root_port_hdl)
|
|||||||
bool pass_event_to_usbh = false;
|
bool pass_event_to_usbh = false;
|
||||||
HUB_DRIVER_ENTER_CRITICAL();
|
HUB_DRIVER_ENTER_CRITICAL();
|
||||||
switch (p_hub_driver_obj->dynamic.driver_state) {
|
switch (p_hub_driver_obj->dynamic.driver_state) {
|
||||||
case HUB_DRIVER_STATE_ROOT_POWERED: //This occurred before enumeration
|
case HUB_DRIVER_STATE_ROOT_POWERED: // This occurred before enumeration
|
||||||
case HUB_DRIVER_STATE_ROOT_ENUM_FAILED: //This occurred after a failed enumeration.
|
case HUB_DRIVER_STATE_ROOT_ENUM_FAILED: // This occurred after a failed enumeration.
|
||||||
//Therefore, there's no device and we can go straight to port recovery
|
// Therefore, there's no device and we can go straight to port recovery
|
||||||
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_PORT_RECOVER;
|
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_PORT_RECOVER;
|
||||||
break;
|
break;
|
||||||
case HUB_DRIVER_STATE_ROOT_ENUM:
|
case HUB_DRIVER_STATE_ROOT_ENUM:
|
||||||
//This occurred during enumeration. Therefore, we need to recover the failed enumeration
|
// This occurred during enumeration. Therefore, we need to recover the failed enumeration
|
||||||
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ENUM_EVENT;
|
p_hub_driver_obj->dynamic.flags.actions |= HUB_DRIVER_FLAG_ACTION_ENUM_EVENT;
|
||||||
p_hub_driver_obj->single_thread.enum_ctrl.stage = ENUM_STAGE_CLEANUP_FAILED;
|
p_hub_driver_obj->single_thread.enum_ctrl.stage = ENUM_STAGE_CLEANUP_FAILED;
|
||||||
break;
|
break;
|
||||||
case HUB_DRIVER_STATE_ROOT_ACTIVE:
|
case HUB_DRIVER_STATE_ROOT_ACTIVE:
|
||||||
//There was an enumerated device. We need to indicate to USBH that the device is gone
|
// There was an enumerated device. We need to indicate to USBH that the device is gone
|
||||||
pass_event_to_usbh = true;
|
pass_event_to_usbh = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
abort(); //Should never occur
|
abort(); // Should never occur
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_RECOVERY;
|
p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_RECOVERY;
|
||||||
@@ -847,7 +847,7 @@ static void root_port_handle_events(hcd_port_handle_t root_port_hdl)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
abort(); //Should never occur
|
abort(); // Should never occur
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -863,7 +863,7 @@ static void enum_handle_events(void)
|
|||||||
case ENUM_STAGE_SECOND_RESET:
|
case ENUM_STAGE_SECOND_RESET:
|
||||||
stage_pass = enum_stage_second_reset(enum_ctrl);
|
stage_pass = enum_stage_second_reset(enum_ctrl);
|
||||||
break;
|
break;
|
||||||
//Transfer submission stages
|
// Transfer submission stages
|
||||||
case ENUM_STAGE_GET_SHORT_DEV_DESC:
|
case ENUM_STAGE_GET_SHORT_DEV_DESC:
|
||||||
case ENUM_STAGE_SET_ADDR:
|
case ENUM_STAGE_SET_ADDR:
|
||||||
case ENUM_STAGE_GET_FULL_DEV_DESC:
|
case ENUM_STAGE_GET_FULL_DEV_DESC:
|
||||||
@@ -880,11 +880,11 @@ static void enum_handle_events(void)
|
|||||||
case ENUM_STAGE_GET_FULL_SER_STR_DESC:
|
case ENUM_STAGE_GET_FULL_SER_STR_DESC:
|
||||||
stage_pass = enum_stage_transfer(enum_ctrl);
|
stage_pass = enum_stage_transfer(enum_ctrl);
|
||||||
break;
|
break;
|
||||||
//Recovery interval
|
// Recovery interval
|
||||||
case ENUM_STAGE_SET_ADDR_RECOVERY:
|
case ENUM_STAGE_SET_ADDR_RECOVERY:
|
||||||
stage_pass = enum_stage_wait(enum_ctrl);
|
stage_pass = enum_stage_wait(enum_ctrl);
|
||||||
break;
|
break;
|
||||||
//Transfer check stages
|
// Transfer check stages
|
||||||
case ENUM_STAGE_CHECK_SHORT_DEV_DESC:
|
case ENUM_STAGE_CHECK_SHORT_DEV_DESC:
|
||||||
case ENUM_STAGE_CHECK_ADDR:
|
case ENUM_STAGE_CHECK_ADDR:
|
||||||
case ENUM_STAGE_CHECK_FULL_DEV_DESC:
|
case ENUM_STAGE_CHECK_FULL_DEV_DESC:
|
||||||
@@ -910,7 +910,7 @@ static void enum_handle_events(void)
|
|||||||
stage_pass = true;
|
stage_pass = true;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
//Note: Don't abort here. The enum_dflt_pipe_callback() can trigger a HUB_DRIVER_FLAG_ACTION_ENUM_EVENT after a cleanup.
|
// Note: Don't abort here. The enum_dflt_pipe_callback() can trigger a HUB_DRIVER_FLAG_ACTION_ENUM_EVENT after a cleanup.
|
||||||
stage_pass = true;
|
stage_pass = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -929,14 +929,14 @@ esp_err_t hub_install(hub_config_t *hub_config)
|
|||||||
HUB_DRIVER_ENTER_CRITICAL();
|
HUB_DRIVER_ENTER_CRITICAL();
|
||||||
HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj == NULL, ESP_ERR_INVALID_STATE);
|
HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj == NULL, ESP_ERR_INVALID_STATE);
|
||||||
HUB_DRIVER_EXIT_CRITICAL();
|
HUB_DRIVER_EXIT_CRITICAL();
|
||||||
//Allocate Hub driver object
|
// Allocate Hub driver object
|
||||||
hub_driver_t *hub_driver_obj = heap_caps_calloc(1, sizeof(hub_driver_t), MALLOC_CAP_DEFAULT);
|
hub_driver_t *hub_driver_obj = heap_caps_calloc(1, sizeof(hub_driver_t), MALLOC_CAP_DEFAULT);
|
||||||
urb_t *enum_urb = urb_alloc(sizeof(usb_setup_packet_t) + ENUM_CTRL_TRANSFER_MAX_DATA_LEN, 0, 0);
|
urb_t *enum_urb = urb_alloc(sizeof(usb_setup_packet_t) + ENUM_CTRL_TRANSFER_MAX_DATA_LEN, 0, 0);
|
||||||
if (hub_driver_obj == NULL || enum_urb == NULL) {
|
if (hub_driver_obj == NULL || enum_urb == NULL) {
|
||||||
return ESP_ERR_NO_MEM;
|
return ESP_ERR_NO_MEM;
|
||||||
}
|
}
|
||||||
esp_err_t ret;
|
esp_err_t ret;
|
||||||
//Install HCD port
|
// Install HCD port
|
||||||
hcd_port_config_t port_config = {
|
hcd_port_config_t port_config = {
|
||||||
.fifo_bias = HUB_ROOT_HCD_PORT_FIFO_BIAS,
|
.fifo_bias = HUB_ROOT_HCD_PORT_FIFO_BIAS,
|
||||||
.callback = root_port_callback,
|
.callback = root_port_callback,
|
||||||
@@ -948,13 +948,13 @@ esp_err_t hub_install(hub_config_t *hub_config)
|
|||||||
if (ret != ESP_OK) {
|
if (ret != ESP_OK) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
//Initialize Hub driver object
|
// Initialize Hub driver object
|
||||||
hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_INSTALLED;
|
hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_INSTALLED;
|
||||||
hub_driver_obj->single_thread.enum_ctrl.stage = ENUM_STAGE_NONE;
|
hub_driver_obj->single_thread.enum_ctrl.stage = ENUM_STAGE_NONE;
|
||||||
hub_driver_obj->single_thread.enum_ctrl.urb = enum_urb;
|
hub_driver_obj->single_thread.enum_ctrl.urb = enum_urb;
|
||||||
hub_driver_obj->constant.root_port_hdl = port_hdl;
|
hub_driver_obj->constant.root_port_hdl = port_hdl;
|
||||||
hub_driver_obj->constant.notif_cb = hub_config->notif_cb;
|
hub_driver_obj->constant.proc_req_cb = hub_config->proc_req_cb;
|
||||||
hub_driver_obj->constant.notif_cb_arg = hub_config->notif_cb_arg;
|
hub_driver_obj->constant.proc_req_cb_arg = hub_config->proc_req_cb_arg;
|
||||||
HUB_DRIVER_ENTER_CRITICAL();
|
HUB_DRIVER_ENTER_CRITICAL();
|
||||||
if (p_hub_driver_obj != NULL) {
|
if (p_hub_driver_obj != NULL) {
|
||||||
HUB_DRIVER_EXIT_CRITICAL();
|
HUB_DRIVER_EXIT_CRITICAL();
|
||||||
@@ -963,7 +963,7 @@ esp_err_t hub_install(hub_config_t *hub_config)
|
|||||||
}
|
}
|
||||||
p_hub_driver_obj = hub_driver_obj;
|
p_hub_driver_obj = hub_driver_obj;
|
||||||
HUB_DRIVER_EXIT_CRITICAL();
|
HUB_DRIVER_EXIT_CRITICAL();
|
||||||
//Indicate to USBH that the hub is installed
|
// Indicate to USBH that the hub is installed
|
||||||
ESP_ERROR_CHECK(usbh_hub_is_installed(usbh_hub_req_callback, NULL));
|
ESP_ERROR_CHECK(usbh_hub_is_installed(usbh_hub_req_callback, NULL));
|
||||||
ret = ESP_OK;
|
ret = ESP_OK;
|
||||||
return ret;
|
return ret;
|
||||||
@@ -986,7 +986,7 @@ esp_err_t hub_uninstall(void)
|
|||||||
HUB_DRIVER_EXIT_CRITICAL();
|
HUB_DRIVER_EXIT_CRITICAL();
|
||||||
|
|
||||||
ESP_ERROR_CHECK(hcd_port_deinit(hub_driver_obj->constant.root_port_hdl));
|
ESP_ERROR_CHECK(hcd_port_deinit(hub_driver_obj->constant.root_port_hdl));
|
||||||
//Free Hub driver resources
|
// Free Hub driver resources
|
||||||
urb_free(hub_driver_obj->single_thread.enum_ctrl.urb);
|
urb_free(hub_driver_obj->single_thread.enum_ctrl.urb);
|
||||||
heap_caps_free(hub_driver_obj);
|
heap_caps_free(hub_driver_obj);
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
@@ -998,7 +998,7 @@ esp_err_t hub_root_start(void)
|
|||||||
HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj != NULL, ESP_ERR_INVALID_STATE);
|
HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj != NULL, ESP_ERR_INVALID_STATE);
|
||||||
HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj->dynamic.driver_state == HUB_DRIVER_STATE_INSTALLED, ESP_ERR_INVALID_STATE);
|
HUB_DRIVER_CHECK_FROM_CRIT(p_hub_driver_obj->dynamic.driver_state == HUB_DRIVER_STATE_INSTALLED, ESP_ERR_INVALID_STATE);
|
||||||
HUB_DRIVER_EXIT_CRITICAL();
|
HUB_DRIVER_EXIT_CRITICAL();
|
||||||
//Power ON the root port
|
// Power ON the root port
|
||||||
esp_err_t ret;
|
esp_err_t ret;
|
||||||
ret = hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_POWER_ON);
|
ret = hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_POWER_ON);
|
||||||
if (ret == ESP_OK) {
|
if (ret == ESP_OK) {
|
||||||
@@ -1045,7 +1045,7 @@ esp_err_t hub_process(void)
|
|||||||
ESP_LOGD(HUB_DRIVER_TAG, "Disabling root port");
|
ESP_LOGD(HUB_DRIVER_TAG, "Disabling root port");
|
||||||
hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_DISABLE);
|
hcd_port_command(p_hub_driver_obj->constant.root_port_hdl, HCD_PORT_CMD_DISABLE);
|
||||||
ESP_ERROR_CHECK(usbh_hub_pass_event(p_hub_driver_obj->single_thread.root_dev_hdl, USBH_HUB_EVENT_PORT_DISABLED));
|
ESP_ERROR_CHECK(usbh_hub_pass_event(p_hub_driver_obj->single_thread.root_dev_hdl, USBH_HUB_EVENT_PORT_DISABLED));
|
||||||
//The root port has been disabled, so the root_dev_hdl is no longer valid
|
// The root port has been disabled, so the root_dev_hdl is no longer valid
|
||||||
p_hub_driver_obj->single_thread.root_dev_hdl = NULL;
|
p_hub_driver_obj->single_thread.root_dev_hdl = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1056,7 +1056,7 @@ esp_err_t hub_process(void)
|
|||||||
HUB_DRIVER_ENTER_CRITICAL();
|
HUB_DRIVER_ENTER_CRITICAL();
|
||||||
p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_POWERED;
|
p_hub_driver_obj->dynamic.driver_state = HUB_DRIVER_STATE_ROOT_POWERED;
|
||||||
HUB_DRIVER_EXIT_CRITICAL();
|
HUB_DRIVER_EXIT_CRITICAL();
|
||||||
//USBH requesting a port recovery means the device has already been freed. Clear root_dev_hdl
|
// USBH requesting a port recovery means the device has already been freed. Clear root_dev_hdl
|
||||||
p_hub_driver_obj->single_thread.root_dev_hdl = NULL;
|
p_hub_driver_obj->single_thread.root_dev_hdl = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,7 +14,7 @@ Warning: The USB Host Library API is still a beta version and may be subject to
|
|||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "esp_err.h"
|
#include "esp_err.h"
|
||||||
#include "esp_intr_alloc.h"
|
#include "esp_intr_alloc.h"
|
||||||
//Include the other USB Host Library headers as well
|
// Include the other USB Host Library headers as well
|
||||||
#include "usb/usb_helpers.h"
|
#include "usb/usb_helpers.h"
|
||||||
#include "usb/usb_types_ch9.h"
|
#include "usb/usb_types_ch9.h"
|
||||||
#include "usb/usb_types_stack.h"
|
#include "usb/usb_types_stack.h"
|
||||||
@@ -34,7 +34,7 @@ extern "C" {
|
|||||||
*
|
*
|
||||||
* @note Asynchronous API
|
* @note Asynchronous API
|
||||||
*/
|
*/
|
||||||
typedef struct usb_host_client_handle_s * usb_host_client_handle_t;
|
typedef struct usb_host_client_handle_s *usb_host_client_handle_t;
|
||||||
|
|
||||||
// ----------------------- Events --------------------------
|
// ----------------------- Events --------------------------
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
bool is_synchronous; /**< Whether the client is asynchronous or synchronous or not. Set to false for now. */
|
bool is_synchronous; /**< Whether the client is asynchronous or synchronous or not. Set to false for now. */
|
||||||
int max_num_event_msg; /**< Maximum number of event messages that can be stored (e.g., 3) */
|
int max_num_event_msg; /**< Maximum number of event messages that can be stored (e.g., 3) */
|
||||||
union { //Note: Made into union or future expansion
|
union { // Note: Made into union or future expansion
|
||||||
struct {
|
struct {
|
||||||
usb_host_client_event_cb_t client_event_callback; /**< Client's event callback function */
|
usb_host_client_event_cb_t client_event_callback; /**< Client's event callback function */
|
||||||
void *callback_arg; /**< Event callback function argument */
|
void *callback_arg; /**< Event callback function argument */
|
||||||
|
@@ -346,10 +346,10 @@ ESP_STATIC_ASSERT(sizeof(usb_config_desc_t) == USB_CONFIG_DESC_SIZE, "Size of us
|
|||||||
/**
|
/**
|
||||||
* @brief Bit masks belonging to the bmAttributes field of a configuration descriptor
|
* @brief Bit masks belonging to the bmAttributes field of a configuration descriptor
|
||||||
*/
|
*/
|
||||||
#define USB_BM_ATTRIBUTES_ONE (1 << 7) //Must be set
|
#define USB_BM_ATTRIBUTES_ONE (1 << 7) /**< Must be set */
|
||||||
#define USB_BM_ATTRIBUTES_SELFPOWER (1 << 6) //Self powered
|
#define USB_BM_ATTRIBUTES_SELFPOWER (1 << 6) /**< Self powered */
|
||||||
#define USB_BM_ATTRIBUTES_WAKEUP (1 << 5) //Can wake-up
|
#define USB_BM_ATTRIBUTES_WAKEUP (1 << 5) /**< Can wake-up */
|
||||||
#define USB_BM_ATTRIBUTES_BATTERY (1 << 4) //Battery powered
|
#define USB_BM_ATTRIBUTES_BATTERY (1 << 4) /**< Battery powered */
|
||||||
|
|
||||||
// ---------- Interface Association Descriptor -------------
|
// ---------- Interface Association Descriptor -------------
|
||||||
|
|
||||||
|
@@ -43,7 +43,7 @@ typedef enum {
|
|||||||
/**
|
/**
|
||||||
* @brief Handle of a USB Device connected to a USB Host
|
* @brief Handle of a USB Device connected to a USB Host
|
||||||
*/
|
*/
|
||||||
typedef struct usb_device_handle_s * usb_device_handle_t;
|
typedef struct usb_device_handle_s *usb_device_handle_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Basic information of an enumerated device
|
* @brief Basic information of an enumerated device
|
||||||
@@ -126,7 +126,7 @@ typedef void (*usb_transfer_cb_t)(usb_transfer_t *transfer);
|
|||||||
* @brief USB transfer structure
|
* @brief USB transfer structure
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
struct usb_transfer_s{
|
struct usb_transfer_s {
|
||||||
uint8_t *const data_buffer; /**< Pointer to data buffer */
|
uint8_t *const data_buffer; /**< Pointer to data buffer */
|
||||||
const size_t data_buffer_size; /**< Size of the data buffer in bytes */
|
const size_t data_buffer_size; /**< Size of the data buffer in bytes */
|
||||||
int num_bytes; /**< Number of bytes to transfer.
|
int num_bytes; /**< Number of bytes to transfer.
|
||||||
|
@@ -116,12 +116,12 @@ typedef enum {
|
|||||||
/**
|
/**
|
||||||
* @brief Port handle type
|
* @brief Port handle type
|
||||||
*/
|
*/
|
||||||
typedef void * hcd_port_handle_t;
|
typedef void *hcd_port_handle_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Pipe handle type
|
* @brief Pipe handle type
|
||||||
*/
|
*/
|
||||||
typedef void * hcd_pipe_handle_t;
|
typedef void *hcd_pipe_handle_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Port event callback type
|
* @brief Port event callback type
|
||||||
@@ -448,13 +448,24 @@ esp_err_t hcd_pipe_set_persist_reset(hcd_pipe_handle_t pipe_hdl);
|
|||||||
void *hcd_pipe_get_context(hcd_pipe_handle_t pipe_hdl);
|
void *hcd_pipe_get_context(hcd_pipe_handle_t pipe_hdl);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the current sate of the pipe
|
* @brief Get the current state of the pipe
|
||||||
*
|
*
|
||||||
* @param pipe_hdl Pipe handle
|
* @param pipe_hdl Pipe handle
|
||||||
* @return hcd_pipe_state_t Current state of the pipe
|
* @return hcd_pipe_state_t Current state of the pipe
|
||||||
*/
|
*/
|
||||||
hcd_pipe_state_t hcd_pipe_get_state(hcd_pipe_handle_t pipe_hdl);
|
hcd_pipe_state_t hcd_pipe_get_state(hcd_pipe_handle_t pipe_hdl);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the number of in-flight URBs in the pipe
|
||||||
|
*
|
||||||
|
* Returns the current number of URBs that have been enqueued (via hcd_urb_enqueue()) and have yet to be dequeued (via
|
||||||
|
* hcd_urb_dequeue()).
|
||||||
|
*
|
||||||
|
* @param pipe_hdl Pipe handle
|
||||||
|
* @return Number of in-flight URBs
|
||||||
|
*/
|
||||||
|
unsigned int hcd_pipe_get_num_urbs(hcd_pipe_handle_t pipe_hdl);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Execute a command on a particular pipe
|
* @brief Execute a command on a particular pipe
|
||||||
*
|
*
|
||||||
|
@@ -22,8 +22,8 @@ extern "C" {
|
|||||||
* @brief Hub driver configuration
|
* @brief Hub driver configuration
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
usb_notif_cb_t notif_cb; /**< Notification callback */
|
usb_proc_req_cb_t proc_req_cb; /**< Processing request callback */
|
||||||
void *notif_cb_arg; /**< Notification callback argument */
|
void *proc_req_cb_arg; /**< Processing request callback argument */
|
||||||
} hub_config_t;
|
} hub_config_t;
|
||||||
|
|
||||||
// ---------------------------------------------- Hub Driver Functions -------------------------------------------------
|
// ---------------------------------------------- Hub Driver Functions -------------------------------------------------
|
||||||
@@ -77,7 +77,7 @@ esp_err_t hub_root_stop(void);
|
|||||||
* @brief Hub driver's processing function
|
* @brief Hub driver's processing function
|
||||||
*
|
*
|
||||||
* Hub driver handling function that must be called repeatdly to process the Hub driver's events. If blocking, the
|
* Hub driver handling function that must be called repeatdly to process the Hub driver's events. If blocking, the
|
||||||
* caller can block on the notification callback of source USB_NOTIF_SOURCE_HUB to run this function.
|
* caller can block on the notification callback of source USB_PROC_REQ_SOURCE_HUB to run this function.
|
||||||
*
|
*
|
||||||
* @return esp_err_t
|
* @return esp_err_t
|
||||||
*/
|
*/
|
||||||
|
@@ -36,26 +36,38 @@ typedef struct {
|
|||||||
} usb_transfer_dummy_t;
|
} usb_transfer_dummy_t;
|
||||||
_Static_assert(sizeof(usb_transfer_dummy_t) == sizeof(usb_transfer_t), "usb_transfer_dummy_t does not match usb_transfer_t");
|
_Static_assert(sizeof(usb_transfer_dummy_t) == sizeof(usb_transfer_t), "usb_transfer_dummy_t does not match usb_transfer_t");
|
||||||
|
|
||||||
struct urb_s{
|
struct urb_s {
|
||||||
TAILQ_ENTRY(urb_s) tailq_entry;
|
TAILQ_ENTRY(urb_s) tailq_entry;
|
||||||
//HCD Layer: Handler pointer and variables. Must be initialized to NULL and 0 respectively
|
// HCD Layer: Handler pointer and variables. Must be initialized to NULL and 0 respectively
|
||||||
void *hcd_ptr;
|
void *hcd_ptr;
|
||||||
uint32_t hcd_var;
|
uint32_t hcd_var;
|
||||||
//Host Lib Layer:
|
// Host Lib Layer:
|
||||||
void *usb_host_client; //Currently only used when submitted to shared pipes (i.e., Device default pipes)
|
void *usb_host_client; // Currently only used when submitted to shared pipes (i.e., Device default pipes)
|
||||||
size_t usb_host_header_size; //USB Host may need the data buffer to have a transparent header
|
size_t usb_host_header_size; // USB Host may need the data buffer to have a transparent header
|
||||||
bool usb_host_inflight; //Debugging variable, used to prevent re-submitting URBs already inflight
|
bool usb_host_inflight; // Debugging variable, used to prevent re-submitting URBs already inflight
|
||||||
//Public transfer structure. Must be last due to variable length array
|
// Public transfer structure. Must be last due to variable length array
|
||||||
usb_transfer_t transfer;
|
usb_transfer_t transfer;
|
||||||
};
|
};
|
||||||
typedef struct urb_s urb_t;
|
typedef struct urb_s urb_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Processing request source
|
||||||
|
*
|
||||||
|
* Enum to indicate which layer of the USB Host stack requires processing. The main handling loop should then call that
|
||||||
|
* layer's processing function (i.e., xxx_process()).
|
||||||
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
USB_NOTIF_SOURCE_USBH = 0x01,
|
USB_PROC_REQ_SOURCE_USBH = 0x01,
|
||||||
USB_NOTIF_SOURCE_HUB = 0x02,
|
USB_PROC_REQ_SOURCE_HUB = 0x02,
|
||||||
} usb_notif_source_t;
|
} usb_proc_req_source_t;
|
||||||
|
|
||||||
typedef bool (*usb_notif_cb_t)(usb_notif_source_t source, bool in_isr, void *context);
|
/**
|
||||||
|
* @brief Processing request callback
|
||||||
|
*
|
||||||
|
* Callback function provided to each layer of the USB Host stack so that each layer can request calls to their
|
||||||
|
* processing function.
|
||||||
|
*/
|
||||||
|
typedef bool (*usb_proc_req_cb_t)(usb_proc_req_source_t source, bool in_isr, void *context);
|
||||||
|
|
||||||
// --------------------------------------------------- Allocation ------------------------------------------------------
|
// --------------------------------------------------- Allocation ------------------------------------------------------
|
||||||
|
|
||||||
|
@@ -20,6 +20,13 @@ extern "C" {
|
|||||||
|
|
||||||
// ------------------------------------------------------ Types --------------------------------------------------------
|
// ------------------------------------------------------ Types --------------------------------------------------------
|
||||||
|
|
||||||
|
// ----------------------- Handles -------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Handle of a allocated endpoint
|
||||||
|
*/
|
||||||
|
typedef struct usbh_ep_handle_s *usbh_ep_handle_t;
|
||||||
|
|
||||||
// ----------------------- Events --------------------------
|
// ----------------------- Events --------------------------
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -29,16 +36,18 @@ typedef enum {
|
|||||||
} usbh_event_t;
|
} usbh_event_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Hub driver requests
|
* @brief Endpoint events
|
||||||
*
|
*
|
||||||
* Various requests of the Hub driver that the USBH can make.
|
* @note Optimization: Keep this identical to hcd_pipe_event_t
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
USBH_HUB_REQ_PORT_DISABLE, /**< Request that the Hub driver disable a particular port (occurs after a device
|
USBH_EP_EVENT_NONE, /**< The EP has no events (used to indicate no events when polling) */
|
||||||
has been freed). Hub driver should respond with a USBH_HUB_EVENT_PORT_DISABLED */
|
USBH_EP_EVENT_URB_DONE, /**< The EP has completed a URB. The URB can be dequeued */
|
||||||
USBH_HUB_REQ_PORT_RECOVER, /**< Request that the Hub driver recovers a particular port (occurs after a gone
|
USBH_EP_EVENT_ERROR_XFER, /**< The EP encountered excessive errors when transferring a URB i.e., three three consecutive transaction errors (e.g., no ACK, bad CRC etc) */
|
||||||
device has been freed). */
|
USBH_EP_EVENT_ERROR_URB_NOT_AVAIL, /**< The EP tried to execute a transfer but no URB was available */
|
||||||
} usbh_hub_req_t;
|
USBH_EP_EVENT_ERROR_OVERFLOW, /**< The EP received more data than requested. Usually a Packet babble error (i.e., an IN packet has exceeded the EP's MPS) */
|
||||||
|
USBH_EP_EVENT_ERROR_STALL, /**< EP received a STALL response */
|
||||||
|
} usbh_ep_event_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Hub driver events for the USBH
|
* @brief Hub driver events for the USBH
|
||||||
@@ -63,6 +72,31 @@ typedef enum {
|
|||||||
USBH_HUB_EVENT_PORT_DISABLED, /**< Previous USBH_HUB_REQ_PORT_DISABLE request completed */
|
USBH_HUB_EVENT_PORT_DISABLED, /**< Previous USBH_HUB_REQ_PORT_DISABLE request completed */
|
||||||
} usbh_hub_event_t;
|
} usbh_hub_event_t;
|
||||||
|
|
||||||
|
// ------------------ Requests/Commands --------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Hub driver requests
|
||||||
|
*
|
||||||
|
* Various requests of the Hub driver that the USBH can make.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
USBH_HUB_REQ_PORT_DISABLE, /**< Request that the Hub driver disable a particular port (occurs after a device
|
||||||
|
has been freed). Hub driver should respond with a USBH_HUB_EVENT_PORT_DISABLED */
|
||||||
|
USBH_HUB_REQ_PORT_RECOVER, /**< Request that the Hub driver recovers a particular port (occurs after a gone
|
||||||
|
device has been freed). */
|
||||||
|
} usbh_hub_req_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Endpoint commands
|
||||||
|
*
|
||||||
|
* @note Optimization: Keep this identical to hcd_pipe_cmd_t
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
USBH_EP_CMD_HALT, /**< Halt an active endpoint. Any currently executing URB will be canceled. Enqueued URBs are left untouched */
|
||||||
|
USBH_EP_CMD_FLUSH, /**< Can only be called when halted. Will cause all enqueued URBs to be canceled */
|
||||||
|
USBH_EP_CMD_CLEAR, /**< Causes a halted endpoint to become active again. Any enqueued URBs will being executing.*/
|
||||||
|
} usbh_ep_cmd_t;
|
||||||
|
|
||||||
// ---------------------- Callbacks ------------------------
|
// ---------------------- Callbacks ------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -87,29 +121,37 @@ typedef void (*usbh_event_cb_t)(usb_device_handle_t dev_hdl, usbh_event_t usbh_e
|
|||||||
*/
|
*/
|
||||||
typedef void (*usbh_hub_req_cb_t)(hcd_port_handle_t port_hdl, usbh_hub_req_t hub_req, void *arg);
|
typedef void (*usbh_hub_req_cb_t)(hcd_port_handle_t port_hdl, usbh_hub_req_t hub_req, void *arg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Callback used to indicate an event on an endpoint
|
||||||
|
*
|
||||||
|
* Return whether to yield or not if called from an ISR. Always return false if not called from an ISR
|
||||||
|
*/
|
||||||
|
typedef bool (*usbh_ep_cb_t)(usbh_ep_handle_t ep_hdl, usbh_ep_event_t ep_event, void *arg, bool in_isr);
|
||||||
|
|
||||||
// ----------------------- Objects -------------------------
|
// ----------------------- Objects -------------------------
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Configuration for an endpoint being allocated using usbh_ep_alloc()
|
* @brief Configuration for an endpoint being allocated using usbh_ep_alloc()
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const usb_ep_desc_t *ep_desc; /**< Endpoint descriptor */
|
uint8_t bInterfaceNumber; /**< Interface number */
|
||||||
hcd_pipe_callback_t pipe_cb; /**< Endpoint's pipe callback */
|
uint8_t bAlternateSetting; /**< Alternate setting number of the interface */
|
||||||
void *pipe_cb_arg; /**< Pipe callback argument */
|
uint8_t bEndpointAddress; /**< Endpoint address */
|
||||||
void *context; /**< Pipe context */
|
usbh_ep_cb_t ep_cb; /**< Endpoint event callback */
|
||||||
|
void *ep_cb_arg; /**< Endpoint callback argument */
|
||||||
|
void *context; /**< Endpoint context */
|
||||||
} usbh_ep_config_t;
|
} usbh_ep_config_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief USBH configuration used in usbh_install()
|
* @brief USBH configuration used in usbh_install()
|
||||||
*/
|
*/
|
||||||
typedef struct {
|
typedef struct {
|
||||||
usb_notif_cb_t notif_cb; /**< Notification callback */
|
usb_proc_req_cb_t proc_req_cb; /**< Processing request callback */
|
||||||
void *notif_cb_arg; /**< Notification callback argument */
|
void *proc_req_cb_arg; /**< Processing request callback argument */
|
||||||
usbh_ctrl_xfer_cb_t ctrl_xfer_cb; /**< Control transfer callback */
|
usbh_ctrl_xfer_cb_t ctrl_xfer_cb; /**< Control transfer callback */
|
||||||
void *ctrl_xfer_cb_arg; /**< Control transfer callback argument */
|
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 */
|
||||||
hcd_config_t hcd_config; /**< HCD configuration */
|
|
||||||
} usbh_config_t;
|
} usbh_config_t;
|
||||||
|
|
||||||
// ------------------------------------------------- USBH Functions ----------------------------------------------------
|
// ------------------------------------------------- USBH Functions ----------------------------------------------------
|
||||||
@@ -143,8 +185,8 @@ esp_err_t usbh_uninstall(void);
|
|||||||
* @brief USBH processing function
|
* @brief USBH processing function
|
||||||
*
|
*
|
||||||
* - USBH processing function that must be called repeatedly to process USBH events
|
* - USBH processing function that must be called repeatedly to process USBH events
|
||||||
* - If blocking, the caller can block until a USB_NOTIF_SOURCE_USBH notification is received before running this
|
* - If blocking, the caller can block until the proc_req_cb() is called with USB_PROC_REQ_SOURCE_USBH as the request
|
||||||
* function
|
* source. The USB_PROC_REQ_SOURCE_USBH source indicates that this function should be called.
|
||||||
*
|
*
|
||||||
* @note This function can block
|
* @note This function can block
|
||||||
* @return esp_err_t
|
* @return esp_err_t
|
||||||
@@ -271,31 +313,84 @@ esp_err_t usbh_dev_submit_ctrl_urb(usb_device_handle_t dev_hdl, urb_t *urb);
|
|||||||
/**
|
/**
|
||||||
* @brief Allocate an endpoint on a device
|
* @brief Allocate an endpoint on a device
|
||||||
*
|
*
|
||||||
* Clients that have opened a device must call this function to allocate all endpoints in an interface that is claimed.
|
* This function allows clients to allocate a non-default endpoint (i.e., not EP0) on a connected device
|
||||||
* The pipe handle of the endpoint is returned so that clients can use and control the pipe directly.
|
*
|
||||||
|
* - A client must have opened the device using usbh_dev_open() before attempting to allocate an endpoint on the device
|
||||||
|
* - A client should call this function to allocate all endpoints in an interface that the client has claimed.
|
||||||
|
* - A client must allocate an endpoint using this function before attempting to communicate with it
|
||||||
|
* - Once the client allocates an endpoint, the client is now owns/manages the endpoint. No other client should use or
|
||||||
|
* deallocate the endpoint.
|
||||||
*
|
*
|
||||||
* @note This function can block
|
* @note This function can block
|
||||||
* @note Default pipes are owned by the USBH. For control transfers, use usbh_dev_submit_ctrl_urb() instead
|
* @note Default endpoints (EP0) are owned by the USBH. For control transfers, use usbh_dev_submit_ctrl_urb() instead
|
||||||
* @note Device must be opened by the client first
|
|
||||||
*
|
*
|
||||||
* @param[in] dev_hdl Device handle
|
* @param[in] dev_hdl Device handle
|
||||||
* @param[in] ep_config
|
* @param[in] ep_config Endpoint configuration
|
||||||
* @param[out] pipe_hdl_ret Pipe handle
|
* @param[out] ep_hdl_ret Endpoint handle
|
||||||
* @return esp_err_t
|
* @return esp_err_t
|
||||||
*/
|
*/
|
||||||
esp_err_t usbh_ep_alloc(usb_device_handle_t dev_hdl, usbh_ep_config_t *ep_config, hcd_pipe_handle_t *pipe_hdl_ret);
|
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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Free and endpoint on a device
|
* @brief Free and endpoint on a device
|
||||||
*
|
*
|
||||||
* Free an endpoint previously opened by usbh_ep_alloc()
|
* This function frees an endpoint previously allocated by the client using usbh_ep_alloc()
|
||||||
|
*
|
||||||
|
* - Only the client that allocated the endpoint should free it
|
||||||
|
* - The client must have halted and flushed the endpoint using usbh_ep_command() before attempting to free it
|
||||||
|
* - The client must ensure that there are no more function calls to the endpoint before freeing it
|
||||||
*
|
*
|
||||||
* @note This function can block
|
* @note This function can block
|
||||||
* @param[in] dev_hdl Device handle
|
* @param[in] ep_hdl Endpoint handle
|
||||||
* @param[in] bEndpointAddress Endpoint's address
|
|
||||||
* @return esp_err_t
|
* @return esp_err_t
|
||||||
*/
|
*/
|
||||||
esp_err_t usbh_ep_free(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress);
|
esp_err_t usbh_ep_free(usbh_ep_handle_t ep_hdl);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the handle of an endpoint using its address
|
||||||
|
*
|
||||||
|
* The endpoint must have been previously allocated using usbh_ep_alloc()
|
||||||
|
*
|
||||||
|
* @param[in] dev_hdl Device handle
|
||||||
|
* @param[in] bEndpointAddress Endpoint address
|
||||||
|
* @param[out] ep_hdl_ret Endpoint handle
|
||||||
|
* @return esp_err_t
|
||||||
|
*/
|
||||||
|
esp_err_t usbh_ep_get_handle(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress, usbh_ep_handle_t *ep_hdl_ret);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enqueue a URB to an endpoint
|
||||||
|
*
|
||||||
|
* The URB will remain enqueued until it completes (successfully or errors out). Use usbh_ep_dequeue_urb() to dequeue
|
||||||
|
* a completed URB.
|
||||||
|
*
|
||||||
|
* @param[in] ep_hdl Endpoint handle
|
||||||
|
* @param[in] urb URB to enqueue
|
||||||
|
* @return esp_err_t
|
||||||
|
*/
|
||||||
|
esp_err_t usbh_ep_enqueue_urb(usbh_ep_handle_t ep_hdl, urb_t *urb);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Dequeue a URB from an endpoint
|
||||||
|
*
|
||||||
|
* Dequeue a completed URB from an endpoint. The USBH_EP_EVENT_URB_DONE indicates that URBs can be dequeued
|
||||||
|
*
|
||||||
|
* @param[in] ep_hdl Endpoint handle
|
||||||
|
* @param[out] urb_ret Dequeued URB, or NULL if no more URBs to dequeue
|
||||||
|
* @return esp_err_t
|
||||||
|
*/
|
||||||
|
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
|
* @brief Get the context of an endpoint
|
||||||
@@ -303,12 +398,10 @@ esp_err_t usbh_ep_free(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress);
|
|||||||
* Get the context variable assigned to and endpoint on allocation.
|
* Get the context variable assigned to and endpoint on allocation.
|
||||||
*
|
*
|
||||||
* @note This function can block
|
* @note This function can block
|
||||||
* @param[in] dev_hdl Device handle
|
* @param[in] ep_hdl Endpoint handle
|
||||||
* @param[in] bEndpointAddress Endpoint's address
|
* @return Endpoint context
|
||||||
* @param[out] context_ret Context variable
|
|
||||||
* @return esp_err_t
|
|
||||||
*/
|
*/
|
||||||
esp_err_t usbh_ep_get_context(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress, void **context_ret);
|
void *usbh_ep_get_context(usbh_ep_handle_t ep_hdl);
|
||||||
|
|
||||||
// -------------------------------------------------- Hub Functions ----------------------------------------------------
|
// -------------------------------------------------- Hub Functions ----------------------------------------------------
|
||||||
|
|
||||||
@@ -396,7 +489,7 @@ esp_err_t usbh_hub_enum_fill_config_desc(usb_device_handle_t dev_hdl, const usb_
|
|||||||
* @note Must call in sequence
|
* @note Must call in sequence
|
||||||
* @param dev_hdl Device handle
|
* @param dev_hdl Device handle
|
||||||
* @param str_desc Pointer to string descriptor
|
* @param str_desc Pointer to string descriptor
|
||||||
* @param select Select which string descriptor. 0/1/2 for Manufacturer/Product/Serial Number string descriptors respecitvely
|
* @param select Select which string descriptor. 0/1/2 for Manufacturer/Product/Serial Number string descriptors respectively
|
||||||
* @return esp_err_t
|
* @return esp_err_t
|
||||||
*/
|
*/
|
||||||
esp_err_t usbh_hub_enum_fill_str_desc(usb_device_handle_t dev_hdl, const usb_str_desc_t *str_desc, int select);
|
esp_err_t usbh_hub_enum_fill_str_desc(usb_device_handle_t dev_hdl, const usb_str_desc_t *str_desc, int select);
|
||||||
|
@@ -21,12 +21,12 @@ const usb_standard_desc_t *usb_parse_next_descriptor(const usb_standard_desc_t *
|
|||||||
{
|
{
|
||||||
assert(cur_desc != NULL && offset != NULL);
|
assert(cur_desc != NULL && offset != NULL);
|
||||||
if (*offset >= wTotalLength) {
|
if (*offset >= wTotalLength) {
|
||||||
return NULL; //We have traversed the entire configuration descriptor
|
return NULL; // We have traversed the entire configuration descriptor
|
||||||
}
|
}
|
||||||
if (*offset + cur_desc->bLength >= wTotalLength) {
|
if (*offset + cur_desc->bLength >= wTotalLength) {
|
||||||
return NULL; //Next descriptor is out of bounds
|
return NULL; // Next descriptor is out of bounds
|
||||||
}
|
}
|
||||||
//Return the next descriptor, update offset
|
// Return the next descriptor, update offset
|
||||||
const usb_standard_desc_t *ret_desc = (const usb_standard_desc_t *)(((uint32_t)cur_desc) + cur_desc->bLength);
|
const usb_standard_desc_t *ret_desc = (const usb_standard_desc_t *)(((uint32_t)cur_desc) + cur_desc->bLength);
|
||||||
*offset += cur_desc->bLength;
|
*offset += cur_desc->bLength;
|
||||||
return ret_desc;
|
return ret_desc;
|
||||||
@@ -35,8 +35,8 @@ const usb_standard_desc_t *usb_parse_next_descriptor(const usb_standard_desc_t *
|
|||||||
const usb_standard_desc_t *usb_parse_next_descriptor_of_type(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, uint8_t bDescriptorType, int *offset)
|
const usb_standard_desc_t *usb_parse_next_descriptor_of_type(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, uint8_t bDescriptorType, int *offset)
|
||||||
{
|
{
|
||||||
assert(cur_desc != NULL && offset != NULL);
|
assert(cur_desc != NULL && offset != NULL);
|
||||||
int offset_temp = *offset; //We only want to update offset if we've actually found a descriptor
|
int offset_temp = *offset; // We only want to update offset if we've actually found a descriptor
|
||||||
//Keep stepping over descriptors until we find one of bDescriptorType or until we go out of bounds
|
// Keep stepping over descriptors until we find one of bDescriptorType or until we go out of bounds
|
||||||
const usb_standard_desc_t *ret_desc = usb_parse_next_descriptor(cur_desc, wTotalLength, &offset_temp);
|
const usb_standard_desc_t *ret_desc = usb_parse_next_descriptor(cur_desc, wTotalLength, &offset_temp);
|
||||||
while (ret_desc != NULL) {
|
while (ret_desc != NULL) {
|
||||||
if (ret_desc->bDescriptorType == bDescriptorType) {
|
if (ret_desc->bDescriptorType == bDescriptorType) {
|
||||||
@@ -45,7 +45,7 @@ const usb_standard_desc_t *usb_parse_next_descriptor_of_type(const usb_standard_
|
|||||||
ret_desc = usb_parse_next_descriptor(ret_desc, wTotalLength, &offset_temp);
|
ret_desc = usb_parse_next_descriptor(ret_desc, wTotalLength, &offset_temp);
|
||||||
}
|
}
|
||||||
if (ret_desc != NULL) {
|
if (ret_desc != NULL) {
|
||||||
//We've found a descriptor. Update the offset
|
// We've found a descriptor. Update the offset
|
||||||
*offset = offset_temp;
|
*offset = offset_temp;
|
||||||
}
|
}
|
||||||
return ret_desc;
|
return ret_desc;
|
||||||
@@ -55,10 +55,10 @@ int usb_parse_interface_number_of_alternate(const usb_config_desc_t *config_desc
|
|||||||
{
|
{
|
||||||
assert(config_desc != NULL);
|
assert(config_desc != NULL);
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
//Find the first interface descriptor of bInterfaceNumber
|
// Find the first interface descriptor of bInterfaceNumber
|
||||||
const usb_intf_desc_t *first_intf_desc = usb_parse_interface_descriptor(config_desc, bInterfaceNumber, 0, &offset);
|
const usb_intf_desc_t *first_intf_desc = usb_parse_interface_descriptor(config_desc, bInterfaceNumber, 0, &offset);
|
||||||
if (first_intf_desc == NULL) {
|
if (first_intf_desc == NULL) {
|
||||||
return -1; //bInterfaceNumber not found
|
return -1; // bInterfaceNumber not found
|
||||||
}
|
}
|
||||||
|
|
||||||
int num_alt_setting = 0;
|
int num_alt_setting = 0;
|
||||||
@@ -77,31 +77,31 @@ const usb_intf_desc_t *usb_parse_interface_descriptor(const usb_config_desc_t *c
|
|||||||
{
|
{
|
||||||
assert(config_desc != NULL);
|
assert(config_desc != NULL);
|
||||||
|
|
||||||
//Walk to first interface descriptor of bInterfaceNumber
|
// Walk to first interface descriptor of bInterfaceNumber
|
||||||
int offset_temp = 0;
|
int offset_temp = 0;
|
||||||
const usb_intf_desc_t *next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)config_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp);
|
const usb_intf_desc_t *next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)config_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp);
|
||||||
while (next_intf_desc != NULL) {
|
while (next_intf_desc != NULL) {
|
||||||
if (next_intf_desc->bInterfaceNumber == bInterfaceNumber) {
|
if (next_intf_desc->bInterfaceNumber == bInterfaceNumber) {
|
||||||
break; //We found the first interface descriptor with matching bInterfaceNumber
|
break; // We found the first interface descriptor with matching bInterfaceNumber
|
||||||
}
|
}
|
||||||
next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp);
|
next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp);
|
||||||
}
|
}
|
||||||
if (next_intf_desc == NULL) {
|
if (next_intf_desc == NULL) {
|
||||||
return NULL; //Couldn't find a interface with bInterfaceNumber
|
return NULL; // Couldn't find a interface with bInterfaceNumber
|
||||||
}
|
}
|
||||||
|
|
||||||
//Keep walking until an interface descriptor matching bInterfaceNumber and bAlternateSetting is found
|
// Keep walking until an interface descriptor matching bInterfaceNumber and bAlternateSetting is found
|
||||||
while (next_intf_desc != NULL) {
|
while (next_intf_desc != NULL) {
|
||||||
if (next_intf_desc->bInterfaceNumber == bInterfaceNumber + 1) {
|
if (next_intf_desc->bInterfaceNumber == bInterfaceNumber + 1) {
|
||||||
//We've walked past our target bInterfaceNumber
|
// We've walked past our target bInterfaceNumber
|
||||||
next_intf_desc = NULL;
|
next_intf_desc = NULL;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (next_intf_desc->bAlternateSetting == bAlternateSetting) {
|
if (next_intf_desc->bAlternateSetting == bAlternateSetting) {
|
||||||
//We've found our target interface descriptor
|
// We've found our target interface descriptor
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//Get the next interface descriptor
|
// Get the next interface descriptor
|
||||||
next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp);
|
next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp);
|
||||||
}
|
}
|
||||||
if (next_intf_desc != NULL && offset != NULL) {
|
if (next_intf_desc != NULL && offset != NULL) {
|
||||||
@@ -114,9 +114,9 @@ const usb_ep_desc_t *usb_parse_endpoint_descriptor_by_index(const usb_intf_desc_
|
|||||||
{
|
{
|
||||||
assert(intf_desc != NULL && offset != NULL);
|
assert(intf_desc != NULL && offset != NULL);
|
||||||
if (index >= intf_desc->bNumEndpoints) {
|
if (index >= intf_desc->bNumEndpoints) {
|
||||||
return NULL; //Index is out of range
|
return NULL; // Index is out of range
|
||||||
}
|
}
|
||||||
//Walk to the Nth endpoint descriptor we find
|
// Walk to the Nth endpoint descriptor we find
|
||||||
int offset_temp = *offset;
|
int offset_temp = *offset;
|
||||||
bool ep_found = true;
|
bool ep_found = true;
|
||||||
const usb_standard_desc_t *next_desc = (const usb_standard_desc_t *)intf_desc;
|
const usb_standard_desc_t *next_desc = (const usb_standard_desc_t *)intf_desc;
|
||||||
@@ -138,14 +138,14 @@ const usb_ep_desc_t *usb_parse_endpoint_descriptor_by_address(const usb_config_d
|
|||||||
{
|
{
|
||||||
assert(config_desc != NULL);
|
assert(config_desc != NULL);
|
||||||
|
|
||||||
//Find the interface descriptor
|
// Find the interface descriptor
|
||||||
int offset_intf;
|
int offset_intf;
|
||||||
const usb_intf_desc_t *intf_desc = usb_parse_interface_descriptor(config_desc, bInterfaceNumber, bAlternateSetting, &offset_intf);
|
const usb_intf_desc_t *intf_desc = usb_parse_interface_descriptor(config_desc, bInterfaceNumber, bAlternateSetting, &offset_intf);
|
||||||
if (intf_desc == NULL) {
|
if (intf_desc == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Walk endpoint descriptors until one matching bEndpointAddress is found
|
// Walk endpoint descriptors until one matching bEndpointAddress is found
|
||||||
int offset_ep;
|
int offset_ep;
|
||||||
bool ep_found = false;
|
bool ep_found = false;
|
||||||
const usb_ep_desc_t *ep_desc = NULL;
|
const usb_ep_desc_t *ep_desc = NULL;
|
||||||
@@ -287,10 +287,10 @@ void usb_print_config_descriptor(const usb_config_desc_t *cfg_desc, print_class_
|
|||||||
print_ep_desc((const usb_ep_desc_t *)next_desc);
|
print_ep_desc((const usb_ep_desc_t *)next_desc);
|
||||||
break;
|
break;
|
||||||
case USB_B_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION:
|
case USB_B_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION:
|
||||||
print_iad_desc((const usb_iad_desc_t*)next_desc);
|
print_iad_desc((const usb_iad_desc_t *)next_desc);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if(class_specific_cb) {
|
if (class_specific_cb) {
|
||||||
class_specific_cb(next_desc);
|
class_specific_cb(next_desc);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -307,7 +307,7 @@ void usb_print_string_descriptor(const usb_str_desc_t *str_desc)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < str_desc->bLength/2; i++) {
|
for (int i = 0; i < str_desc->bLength / 2; i++) {
|
||||||
/*
|
/*
|
||||||
USB String descriptors of UTF-16.
|
USB String descriptors of UTF-16.
|
||||||
Right now We just skip any character larger than 0xFF to stay in BMP Basic Latin and Latin-1 Supplement range.
|
Right now We just skip any character larger than 0xFF to stay in BMP Basic Latin and Latin-1 Supplement range.
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -85,7 +85,7 @@ static esp_err_t phy_external_iopins_configure(const usb_phy_ext_io_conf_t *ext_
|
|||||||
{ext_io_conf->vmo_io_num, usb_otg_periph_signal.extphy_vmo_out, true},
|
{ext_io_conf->vmo_io_num, usb_otg_periph_signal.extphy_vmo_out, true},
|
||||||
};
|
};
|
||||||
|
|
||||||
return phy_iopins_configure(usb_periph_iopins, sizeof(usb_periph_iopins)/sizeof(usb_iopin_dsc_t));
|
return phy_iopins_configure(usb_periph_iopins, sizeof(usb_periph_iopins) / sizeof(usb_iopin_dsc_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t phy_otg_iopins_configure(const usb_phy_otg_io_conf_t *otg_io_conf)
|
static esp_err_t phy_otg_iopins_configure(const usb_phy_otg_io_conf_t *otg_io_conf)
|
||||||
@@ -103,7 +103,7 @@ static esp_err_t phy_otg_iopins_configure(const usb_phy_otg_io_conf_t *otg_io_co
|
|||||||
{otg_io_conf->chrgvbus_io_num, usb_otg_periph_signal.srp_chrgvbus_out, true},
|
{otg_io_conf->chrgvbus_io_num, usb_otg_periph_signal.srp_chrgvbus_out, true},
|
||||||
{otg_io_conf->dischrgvbus_io_num, usb_otg_periph_signal.srp_dischrgvbus_out, true},
|
{otg_io_conf->dischrgvbus_io_num, usb_otg_periph_signal.srp_dischrgvbus_out, true},
|
||||||
};
|
};
|
||||||
return phy_iopins_configure(usb_periph_iopins, sizeof(usb_periph_iopins)/sizeof(usb_iopin_dsc_t));
|
return phy_iopins_configure(usb_periph_iopins, sizeof(usb_periph_iopins) / sizeof(usb_iopin_dsc_t));
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t usb_phy_otg_set_mode(usb_phy_handle_t handle, usb_otg_mode_t mode)
|
esp_err_t usb_phy_otg_set_mode(usb_phy_handle_t handle, usb_otg_mode_t mode)
|
||||||
@@ -114,17 +114,17 @@ esp_err_t usb_phy_otg_set_mode(usb_phy_handle_t handle, usb_otg_mode_t mode)
|
|||||||
|
|
||||||
handle->otg_mode = mode;
|
handle->otg_mode = mode;
|
||||||
if (mode == USB_OTG_MODE_HOST) {
|
if (mode == USB_OTG_MODE_HOST) {
|
||||||
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_OTG_IDDIG_IN_IDX, false); //connected connector is A side
|
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_OTG_IDDIG_IN_IDX, false); // connected connector is A side
|
||||||
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_SRP_BVALID_IN_IDX, false);
|
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_SRP_BVALID_IN_IDX, false);
|
||||||
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_VBUSVALID_IN_IDX, false); //receiving a valid Vbus from host
|
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_VBUSVALID_IN_IDX, false); // receiving a valid Vbus from host
|
||||||
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_AVALID_IN_IDX, false); //HIGH to force USB host mode
|
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_AVALID_IN_IDX, false); // HIGH to force USB host mode
|
||||||
if (handle->target == USB_PHY_TARGET_INT) {
|
if (handle->target == USB_PHY_TARGET_INT) {
|
||||||
usb_phy_hal_int_load_conf_host(&(handle->hal_context));
|
usb_phy_hal_int_load_conf_host(&(handle->hal_context));
|
||||||
}
|
}
|
||||||
} else if (mode == USB_OTG_MODE_DEVICE) {
|
} else if (mode == USB_OTG_MODE_DEVICE) {
|
||||||
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_IDDIG_IN_IDX, false); //connected connector is mini-B side
|
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_IDDIG_IN_IDX, false); // connected connector is mini-B side
|
||||||
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_SRP_BVALID_IN_IDX, false); //HIGH to force USB device mode
|
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_SRP_BVALID_IN_IDX, false); // HIGH to force USB device mode
|
||||||
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_VBUSVALID_IN_IDX, false); //receiving a valid Vbus from device
|
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_OTG_VBUSVALID_IN_IDX, false); // receiving a valid Vbus from device
|
||||||
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_OTG_AVALID_IN_IDX, false);
|
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_OTG_AVALID_IN_IDX, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -15,8 +15,8 @@ urb_t *urb_alloc(size_t data_buffer_size, size_t header_size, int num_isoc_packe
|
|||||||
if (urb == NULL || data_buffer == NULL) {
|
if (urb == NULL || data_buffer == NULL) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
urb->usb_host_header_size = header_size; //Indicate that this URB's data_buffer has a header in front of it.
|
urb->usb_host_header_size = header_size; // Indicate that this URB's data_buffer has a header in front of it.
|
||||||
//Case as dummy transfer to write to initialize const fields
|
// Case as dummy transfer to write to initialize const fields
|
||||||
usb_transfer_dummy_t *dummy_transfer = (usb_transfer_dummy_t *)&urb->transfer;
|
usb_transfer_dummy_t *dummy_transfer = (usb_transfer_dummy_t *)&urb->transfer;
|
||||||
dummy_transfer->data_buffer = (uint8_t *)(data_buffer + header_size);
|
dummy_transfer->data_buffer = (uint8_t *)(data_buffer + header_size);
|
||||||
dummy_transfer->data_buffer_size = data_buffer_size;
|
dummy_transfer->data_buffer_size = data_buffer_size;
|
||||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user