usb_host: Run formatting script

This commit is contained in:
Darian Leung 2023-05-09 00:53:27 +08:00
parent 1ffbbf5aef
commit cbed197e10
13 changed files with 1604 additions and 1604 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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 "esp_err.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_types_ch9.h"
#include "usb/usb_types_stack.h"
@ -34,7 +34,7 @@ extern "C" {
*
* @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 --------------------------
@ -116,7 +116,7 @@ typedef struct {
typedef struct {
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) */
union { //Note: Made into union or future expansion
union { // Note: Made into union or future expansion
struct {
usb_host_client_event_cb_t client_event_callback; /**< Client's event callback function */
void *callback_arg; /**< Event callback function argument */

View File

@ -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
*/
#define USB_BM_ATTRIBUTES_ONE (1 << 7) //Must be set
#define USB_BM_ATTRIBUTES_SELFPOWER (1 << 6) //Self powered
#define USB_BM_ATTRIBUTES_WAKEUP (1 << 5) //Can wake-up
#define USB_BM_ATTRIBUTES_BATTERY (1 << 4) //Battery powered
#define USB_BM_ATTRIBUTES_ONE (1 << 7) /**< Must be set */
#define USB_BM_ATTRIBUTES_SELFPOWER (1 << 6) /**< Self powered */
#define USB_BM_ATTRIBUTES_WAKEUP (1 << 5) /**< Can wake-up */
#define USB_BM_ATTRIBUTES_BATTERY (1 << 4) /**< Battery powered */
// ---------- Interface Association Descriptor -------------

View File

@ -43,7 +43,7 @@ typedef enum {
/**
* @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
@ -126,7 +126,7 @@ typedef void (*usb_transfer_cb_t)(usb_transfer_t *transfer);
* @brief USB transfer structure
*
*/
struct usb_transfer_s{
struct usb_transfer_s {
uint8_t *const data_buffer; /**< Pointer to data buffer */
const size_t data_buffer_size; /**< Size of the data buffer in bytes */
int num_bytes; /**< Number of bytes to transfer.

View File

@ -116,12 +116,12 @@ typedef enum {
/**
* @brief Port handle type
*/
typedef void * hcd_port_handle_t;
typedef void *hcd_port_handle_t;
/**
* @brief Pipe handle type
*/
typedef void * hcd_pipe_handle_t;
typedef void *hcd_pipe_handle_t;
/**
* @brief Port event callback type

View File

@ -36,16 +36,16 @@ typedef struct {
} 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");
struct urb_s{
struct urb_s {
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;
uint32_t hcd_var;
//Host Lib Layer:
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
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
// Host Lib Layer:
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
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
usb_transfer_t transfer;
};
typedef struct urb_s urb_t;

View File

@ -25,7 +25,7 @@ extern "C" {
/**
* @brief Handle of a allocated endpoint
*/
typedef struct usbh_ep_handle_s * usbh_ep_handle_t;
typedef struct usbh_ep_handle_s *usbh_ep_handle_t;
// ----------------------- Events --------------------------

View File

@ -21,12 +21,12 @@ const usb_standard_desc_t *usb_parse_next_descriptor(const usb_standard_desc_t *
{
assert(cur_desc != NULL && offset != NULL);
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) {
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);
*offset += cur_desc->bLength;
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)
{
assert(cur_desc != NULL && offset != NULL);
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
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
const usb_standard_desc_t *ret_desc = usb_parse_next_descriptor(cur_desc, wTotalLength, &offset_temp);
while (ret_desc != NULL) {
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);
}
if (ret_desc != NULL) {
//We've found a descriptor. Update the offset
// We've found a descriptor. Update the offset
*offset = offset_temp;
}
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);
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);
if (first_intf_desc == NULL) {
return -1; //bInterfaceNumber not found
return -1; // bInterfaceNumber not found
}
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);
//Walk to first interface descriptor of bInterfaceNumber
// Walk to first interface descriptor of bInterfaceNumber
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);
while (next_intf_desc != NULL) {
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);
}
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) {
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;
break;
}
if (next_intf_desc->bAlternateSetting == bAlternateSetting) {
//We've found our target interface descriptor
// We've found our target interface descriptor
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);
}
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);
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;
bool ep_found = true;
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);
//Find the interface descriptor
// Find the interface descriptor
int offset_intf;
const usb_intf_desc_t *intf_desc = usb_parse_interface_descriptor(config_desc, bInterfaceNumber, bAlternateSetting, &offset_intf);
if (intf_desc == NULL) {
return NULL;
}
//Walk endpoint descriptors until one matching bEndpointAddress is found
// Walk endpoint descriptors until one matching bEndpointAddress is found
int offset_ep;
bool ep_found = false;
const usb_ep_desc_t *ep_desc = NULL;
@ -174,21 +174,21 @@ static void print_ep_desc(const usb_ep_desc_t *ep_desc)
int type = ep_desc->bmAttributes & USB_BM_ATTRIBUTES_XFERTYPE_MASK;
switch (type) {
case USB_BM_ATTRIBUTES_XFER_CONTROL:
ep_type_str = "CTRL";
break;
case USB_BM_ATTRIBUTES_XFER_ISOC:
ep_type_str = "ISOC";
break;
case USB_BM_ATTRIBUTES_XFER_BULK:
ep_type_str = "BULK";
break;
case USB_BM_ATTRIBUTES_XFER_INT:
ep_type_str = "INT";
break;
default:
ep_type_str = NULL;
break;
case USB_BM_ATTRIBUTES_XFER_CONTROL:
ep_type_str = "CTRL";
break;
case USB_BM_ATTRIBUTES_XFER_ISOC:
ep_type_str = "ISOC";
break;
case USB_BM_ATTRIBUTES_XFER_BULK:
ep_type_str = "BULK";
break;
case USB_BM_ATTRIBUTES_XFER_INT:
ep_type_str = "INT";
break;
default:
ep_type_str = NULL;
break;
}
printf("\t\t*** Endpoint descriptor ***\n");
@ -277,23 +277,23 @@ void usb_print_config_descriptor(const usb_config_desc_t *cfg_desc, print_class_
do {
switch (next_desc->bDescriptorType) {
case USB_B_DESCRIPTOR_TYPE_CONFIGURATION:
usbh_print_cfg_desc((const usb_config_desc_t *)next_desc);
break;
case USB_B_DESCRIPTOR_TYPE_INTERFACE:
usbh_print_intf_desc((const usb_intf_desc_t *)next_desc);
break;
case USB_B_DESCRIPTOR_TYPE_ENDPOINT:
print_ep_desc((const usb_ep_desc_t *)next_desc);
break;
case USB_B_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION:
print_iad_desc((const usb_iad_desc_t*)next_desc);
break;
default:
if(class_specific_cb) {
class_specific_cb(next_desc);
}
break;
case USB_B_DESCRIPTOR_TYPE_CONFIGURATION:
usbh_print_cfg_desc((const usb_config_desc_t *)next_desc);
break;
case USB_B_DESCRIPTOR_TYPE_INTERFACE:
usbh_print_intf_desc((const usb_intf_desc_t *)next_desc);
break;
case USB_B_DESCRIPTOR_TYPE_ENDPOINT:
print_ep_desc((const usb_ep_desc_t *)next_desc);
break;
case USB_B_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION:
print_iad_desc((const usb_iad_desc_t *)next_desc);
break;
default:
if (class_specific_cb) {
class_specific_cb(next_desc);
}
break;
}
next_desc = usb_parse_next_descriptor(next_desc, wTotalLength, &offset);
@ -307,7 +307,7 @@ void usb_print_string_descriptor(const usb_str_desc_t *str_desc)
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.
Right now We just skip any character larger than 0xFF to stay in BMP Basic Latin and Latin-1 Supplement range.

View File

@ -52,19 +52,19 @@ typedef struct interface_s interface_t;
typedef struct client_s client_t;
struct ep_wrapper_s {
//Dynamic members require a critical section
// Dynamic members require a critical section
struct {
TAILQ_ENTRY(ep_wrapper_s) tailq_entry;
union {
struct {
uint32_t pending: 1;
uint32_t reserved31:31;
uint32_t reserved31: 31;
};
} flags;
uint32_t num_urb_inflight;
usbh_ep_event_t last_event;
} dynamic;
//Constant members do no change after claiming the interface thus do not require a critical section
// Constant members do no change after claiming the interface thus do not require a critical section
struct {
usbh_ep_handle_t ep_hdl;
interface_t *intf_obj;
@ -72,11 +72,11 @@ struct ep_wrapper_s {
};
struct interface_s {
//Dynamic members require a critical section
// Dynamic members require a critical section
struct {
TAILQ_ENTRY(interface_s) tailq_entry;
} mux_protected;
//Constant members do no change after claiming the interface thus do not require a critical section
// Constant members do no change after claiming the interface thus do not require a critical section
struct {
const usb_intf_desc_t *intf_desc;
usb_device_handle_t dev_hdl;
@ -86,7 +86,7 @@ struct interface_s {
};
struct client_s {
//Dynamic members require a critical section
// Dynamic members require a critical section
struct {
TAILQ_ENTRY(client_s) tailq_entry;
TAILQ_HEAD(tailhead_pending_ep, ep_wrapper_s) pending_ep_tailq;
@ -107,11 +107,11 @@ struct client_s {
uint32_t num_done_ctrl_xfer;
uint32_t opened_dev_addr_map;
} dynamic;
//Mux protected members must be protected by host library the mux_lock when accessed
// Mux protected members must be protected by host library the mux_lock when accessed
struct {
TAILQ_HEAD(tailhead_interfaces, interface_s) interface_tailq;
} mux_protected;
//Constant members do no change after registration thus do not require a critical section
// Constant members do no change after registration thus do not require a critical section
struct {
SemaphoreHandle_t event_sem;
usb_host_client_event_cb_t event_callback;
@ -121,9 +121,9 @@ struct client_s {
};
typedef struct {
//Dynamic members require a critical section
// Dynamic members require a critical section
struct {
//Access to these should be done in a critical section
// Access to these should be done in a critical section
uint32_t process_pending_flags;
uint32_t lib_event_flags;
union {
@ -138,15 +138,15 @@ typedef struct {
uint32_t val;
} flags;
} dynamic;
//Mux protected members must be protected by host library the mux_lock when accessed
// Mux protected members must be protected by host library the mux_lock when accessed
struct {
TAILQ_HEAD(tailhead_clients, client_s) client_tailq; //List of all clients registered
TAILQ_HEAD(tailhead_clients, client_s) client_tailq; // List of all clients registered
} mux_protected;
//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 {
SemaphoreHandle_t event_sem;
SemaphoreHandle_t mux_lock;
usb_phy_handle_t phy_handle; //Will be NULL if host library is installed with skip_phy_setup
usb_phy_handle_t phy_handle; // Will be NULL if host library is installed with skip_phy_setup
} constant;
} host_lib_t;
@ -228,13 +228,13 @@ static bool _unblock_lib(bool in_isr)
static void send_event_msg_to_clients(const usb_host_client_event_msg_t *event_msg, bool send_to_all, uint8_t opened_dev_addr)
{
//Lock client list
// Lock client list
xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY);
//Send event message to relevant or all clients
// Send event message to relevant or all clients
client_t *client_obj;
TAILQ_FOREACH(client_obj, &p_host_lib_obj->mux_protected.client_tailq, dynamic.tailq_entry) {
if (!send_to_all) {
//Check if client opened the device
// Check if client opened the device
HOST_ENTER_CRITICAL();
bool send = _check_client_opened_device(client_obj, opened_dev_addr);
HOST_EXIT_CRITICAL();
@ -242,7 +242,7 @@ static void send_event_msg_to_clients(const usb_host_client_event_msg_t *event_m
continue;
}
}
//Send the event message
// Send the event message
if (xQueueSend(client_obj->constant.event_msg_queue, event_msg, 0) == pdTRUE) {
HOST_ENTER_CRITICAL();
_unblock_client(client_obj, false);
@ -251,7 +251,7 @@ static void send_event_msg_to_clients(const usb_host_client_event_msg_t *event_m
ESP_LOGE(USB_HOST_TAG, "Client event message queue full");
}
}
//Unlock client list
// Unlock client list
xSemaphoreGive(p_host_lib_obj->constant.mux_lock);
}
@ -262,14 +262,14 @@ static void send_event_msg_to_clients(const usb_host_client_event_msg_t *event_m
static bool proc_req_callback(usb_proc_req_source_t source, bool in_isr, void *arg)
{
HOST_ENTER_CRITICAL_SAFE();
//Store the processing request source
// Store the processing request source
switch (source) {
case USB_PROC_REQ_SOURCE_USBH:
p_host_lib_obj->dynamic.process_pending_flags |= PROCESS_REQUEST_PENDING_FLAG_USBH;
break;
case USB_PROC_REQ_SOURCE_HUB:
p_host_lib_obj->dynamic.process_pending_flags |= PROCESS_REQUEST_PENDING_FLAG_HUB;
break;
case USB_PROC_REQ_SOURCE_USBH:
p_host_lib_obj->dynamic.process_pending_flags |= PROCESS_REQUEST_PENDING_FLAG_USBH;
break;
case USB_PROC_REQ_SOURCE_HUB:
p_host_lib_obj->dynamic.process_pending_flags |= PROCESS_REQUEST_PENDING_FLAG_HUB;
break;
}
bool yield = _unblock_lib(in_isr);
HOST_EXIT_CRITICAL_SAFE();
@ -280,7 +280,7 @@ static bool proc_req_callback(usb_proc_req_source_t source, bool in_isr, void *a
static void ctrl_xfer_callback(usb_device_handle_t dev_hdl, urb_t *urb, void *arg)
{
assert(urb->usb_host_client != NULL);
//Redistribute done control transfer to the clients that submitted them
// Redistribute done control transfer to the clients that submitted them
client_t *client_obj = (client_t *)urb->usb_host_client;
HOST_ENTER_CRITICAL();
@ -292,41 +292,41 @@ static void ctrl_xfer_callback(usb_device_handle_t dev_hdl, urb_t *urb, void *ar
static void dev_event_callback(usb_device_handle_t dev_hdl, usbh_event_t usbh_event, void *arg)
{
//Check usbh_event. The data type of event_arg depends on the type of event
// Check usbh_event. The data type of event_arg depends on the type of event
switch (usbh_event) {
case USBH_EVENT_DEV_NEW: {
//Prepare a NEW_DEV client event message, the send it to all clients
uint8_t dev_addr;
ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr));
usb_host_client_event_msg_t event_msg = {
.event = USB_HOST_CLIENT_EVENT_NEW_DEV,
.new_dev.address = dev_addr,
};
send_event_msg_to_clients(&event_msg, true, 0);
break;
}
case USBH_EVENT_DEV_GONE: {
//Prepare event msg, send only to clients that have opened the device
uint8_t dev_addr;
ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr));
usb_host_client_event_msg_t event_msg = {
.event = USB_HOST_CLIENT_EVENT_DEV_GONE,
.dev_gone.dev_hdl = dev_hdl,
};
send_event_msg_to_clients(&event_msg, false, dev_addr);
break;
}
case USBH_EVENT_DEV_ALL_FREE: {
//Notify the lib handler that all devices are free
HOST_ENTER_CRITICAL();
p_host_lib_obj->dynamic.lib_event_flags |= USB_HOST_LIB_EVENT_FLAGS_ALL_FREE;
_unblock_lib(false);
HOST_EXIT_CRITICAL();
break;
}
default:
abort(); //Should never occur
break;
case USBH_EVENT_DEV_NEW: {
// Prepare a NEW_DEV client event message, the send it to all clients
uint8_t dev_addr;
ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr));
usb_host_client_event_msg_t event_msg = {
.event = USB_HOST_CLIENT_EVENT_NEW_DEV,
.new_dev.address = dev_addr,
};
send_event_msg_to_clients(&event_msg, true, 0);
break;
}
case USBH_EVENT_DEV_GONE: {
// Prepare event msg, send only to clients that have opened the device
uint8_t dev_addr;
ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr));
usb_host_client_event_msg_t event_msg = {
.event = USB_HOST_CLIENT_EVENT_DEV_GONE,
.dev_gone.dev_hdl = dev_hdl,
};
send_event_msg_to_clients(&event_msg, false, dev_addr);
break;
}
case USBH_EVENT_DEV_ALL_FREE: {
// Notify the lib handler that all devices are free
HOST_ENTER_CRITICAL();
p_host_lib_obj->dynamic.lib_event_flags |= USB_HOST_LIB_EVENT_FLAGS_ALL_FREE;
_unblock_lib(false);
HOST_EXIT_CRITICAL();
break;
}
default:
abort(); // Should never occur
break;
}
}
@ -338,9 +338,9 @@ static bool endpoint_callback(usbh_ep_handle_t ep_hdl, usbh_ep_event_t ep_event,
client_t *client_obj = (client_t *)ep_wrap->constant.intf_obj->constant.client_obj;
HOST_ENTER_CRITICAL_SAFE();
//Store the event to be handled later. Note that we allow overwriting of events because more severe will halt the pipe prevent any further events.
// Store the event to be handled later. Note that we allow overwriting of events because more severe will halt the pipe prevent any further events.
ep_wrap->dynamic.last_event = ep_event;
//Add the EP to the client's pending list if it's not in the list already
// Add the EP to the client's pending list if it's not in the list already
if (!ep_wrap->dynamic.flags.pending) {
ep_wrap->dynamic.flags.pending = 1;
TAILQ_REMOVE(&client_obj->dynamic.idle_ep_tailq, ep_wrap, dynamic.tailq_entry);
@ -371,7 +371,7 @@ esp_err_t usb_host_install(const usb_host_config_t *config)
ret = ESP_ERR_NO_MEM;
goto alloc_err;
}
//Initialize host library object
// Initialize host library object
TAILQ_INIT(&host_lib_obj->mux_protected.client_tailq);
host_lib_obj->constant.event_sem = event_sem;
host_lib_obj->constant.mux_lock = mux_lock;
@ -384,24 +384,24 @@ esp_err_t usb_host_install(const usb_host_config_t *config)
- Hub
*/
//Install USB PHY (if necessary). USB PHY driver will also enable the underlying Host Controller
// Install USB PHY (if necessary). USB PHY driver will also enable the underlying Host Controller
if (!config->skip_phy_setup) {
//Host Library defaults to internal PHY
// Host Library defaults to internal PHY
usb_phy_config_t phy_config = {
.controller = USB_PHY_CTRL_OTG,
.target = USB_PHY_TARGET_INT,
.otg_mode = USB_OTG_MODE_HOST,
.otg_speed = USB_PHY_SPEED_UNDEFINED, //In Host mode, the speed is determined by the connected device
.otg_speed = USB_PHY_SPEED_UNDEFINED, // In Host mode, the speed is determined by the connected device
.ext_io_conf = NULL,
.otg_io_conf = NULL,
};
ret = usb_new_phy(&phy_config, &host_lib_obj->constant.phy_handle);
if (ret != ESP_OK) {
goto phy_err;
}
if (ret != ESP_OK) {
goto phy_err;
}
}
//Install HCD
// Install HCD
hcd_config_t hcd_config = {
.intr_flags = config->intr_flags
};
@ -410,7 +410,7 @@ esp_err_t usb_host_install(const usb_host_config_t *config)
goto hcd_err;
}
//Install USBH
// Install USBH
usbh_config_t usbh_config = {
.proc_req_cb = proc_req_callback,
.proc_req_cb_arg = NULL,
@ -424,7 +424,7 @@ esp_err_t usb_host_install(const usb_host_config_t *config)
goto usbh_err;
}
//Install Hub
// Install Hub
hub_config_t hub_config = {
.proc_req_cb = proc_req_callback,
.proc_req_cb_arg = NULL,
@ -434,7 +434,7 @@ esp_err_t usb_host_install(const usb_host_config_t *config)
goto hub_err;
}
//Assign host library object
// Assign host library object
HOST_ENTER_CRITICAL();
if (p_host_lib_obj != NULL) {
HOST_EXIT_CRITICAL();
@ -444,7 +444,7 @@ esp_err_t usb_host_install(const usb_host_config_t *config)
p_host_lib_obj = host_lib_obj;
HOST_EXIT_CRITICAL();
//Start the root hub
// Start the root hub
ESP_ERROR_CHECK(hub_root_start());
ret = ESP_OK;
return ret;
@ -473,7 +473,7 @@ alloc_err:
esp_err_t usb_host_uninstall(void)
{
//All devices must have been freed at this point
// All devices must have been freed at this point
HOST_ENTER_CRITICAL();
HOST_CHECK_FROM_CRIT(p_host_lib_obj != NULL, ESP_ERR_INVALID_STATE);
HOST_CHECK_FROM_CRIT(p_host_lib_obj->dynamic.process_pending_flags == 0 &&
@ -482,10 +482,10 @@ esp_err_t usb_host_uninstall(void)
ESP_ERR_INVALID_STATE);
HOST_EXIT_CRITICAL();
//Stop the root hub
// Stop the root hub
ESP_ERROR_CHECK(hub_root_stop());
//Unassign the host library object
// Unassign the host library object
HOST_ENTER_CRITICAL();
host_lib_t *host_lib_obj = p_host_lib_obj;
p_host_lib_obj = NULL;
@ -501,12 +501,12 @@ esp_err_t usb_host_uninstall(void)
ESP_ERROR_CHECK(hub_uninstall());
ESP_ERROR_CHECK(usbh_uninstall());
ESP_ERROR_CHECK(hcd_uninstall());
//If the USB PHY was setup, then delete it
// If the USB PHY was setup, then delete it
if (host_lib_obj->constant.phy_handle) {
ESP_ERROR_CHECK(usb_del_phy(host_lib_obj->constant.phy_handle));
}
//Free memory objects
// Free memory objects
vSemaphoreDelete(host_lib_obj->constant.mux_lock);
vSemaphoreDelete(host_lib_obj->constant.event_sem);
heap_caps_free(host_lib_obj);
@ -520,7 +520,7 @@ esp_err_t usb_host_lib_handle_events(TickType_t timeout_ticks, uint32_t *event_f
HOST_ENTER_CRITICAL();
if (!p_host_lib_obj->dynamic.flags.process_pending) {
//There is currently processing that needs to be done. Wait for some processing
// There is currently processing that needs to be done. Wait for some processing
HOST_EXIT_CRITICAL();
BaseType_t sem_ret = xSemaphoreTake(p_host_lib_obj->constant.event_sem, timeout_ticks);
if (sem_ret == pdFALSE) {
@ -529,7 +529,7 @@ esp_err_t usb_host_lib_handle_events(TickType_t timeout_ticks, uint32_t *event_f
}
HOST_ENTER_CRITICAL();
}
//Read and clear process pending flags
// Read and clear process pending flags
uint32_t process_pending_flags = p_host_lib_obj->dynamic.process_pending_flags;
p_host_lib_obj->dynamic.process_pending_flags = 0;
p_host_lib_obj->dynamic.flags.handling_events = 1;
@ -542,7 +542,7 @@ esp_err_t usb_host_lib_handle_events(TickType_t timeout_ticks, uint32_t *event_f
ESP_ERROR_CHECK(hub_process());
}
HOST_ENTER_CRITICAL();
//Read and clear process pending flags again, and loop back if there is more to process
// Read and clear process pending flags again, and loop back if there is more to process
process_pending_flags = p_host_lib_obj->dynamic.process_pending_flags;
p_host_lib_obj->dynamic.process_pending_flags = 0;
}
@ -562,7 +562,7 @@ exit:
esp_err_t usb_host_lib_unblock(void)
{
//All devices must have been freed at this point
// All devices must have been freed at this point
HOST_ENTER_CRITICAL();
HOST_CHECK_FROM_CRIT(p_host_lib_obj != NULL, ESP_ERR_INVALID_STATE);
_unblock_lib(false);
@ -581,7 +581,7 @@ esp_err_t usb_host_lib_info(usb_host_lib_info_t *info_ret)
HOST_EXIT_CRITICAL();
usbh_num_devs(&num_devs_temp);
//Write back return values
// Write back return values
info_ret->num_devices = num_devs_temp;
info_ret->num_clients = num_clients_temp;
return ESP_OK;
@ -593,9 +593,9 @@ esp_err_t usb_host_lib_info(usb_host_lib_info_t *info_ret)
static void _handle_pending_ep(client_t *client_obj)
{
//Handle each EP on the pending list
// Handle each EP on the pending list
while (!TAILQ_EMPTY(&client_obj->dynamic.pending_ep_tailq)) {
//Get the next pending EP.
// Get the next pending EP.
ep_wrapper_t *ep_wrap = TAILQ_FIRST(&client_obj->dynamic.pending_ep_tailq);
TAILQ_REMOVE(&client_obj->dynamic.pending_ep_tailq, ep_wrap, dynamic.tailq_entry);
TAILQ_INSERT_TAIL(&client_obj->dynamic.idle_ep_tailq, ep_wrap, dynamic.tailq_entry);
@ -604,36 +604,36 @@ static void _handle_pending_ep(client_t *client_obj)
uint32_t num_urb_dequeued = 0;
HOST_EXIT_CRITICAL();
//Handle pipe event
// Handle pipe event
switch (last_event) {
case USBH_EP_EVENT_ERROR_XFER:
case USBH_EP_EVENT_ERROR_URB_NOT_AVAIL:
case USBH_EP_EVENT_ERROR_OVERFLOW:
case USBH_EP_EVENT_ERROR_STALL:
//The endpoint is now stalled. Flush all pending URBs
ESP_ERROR_CHECK(usbh_ep_command(ep_wrap->constant.ep_hdl, USBH_EP_CMD_FLUSH));
//All URBs in this pipe are now retired waiting to be dequeued. Fall through to dequeue them
__attribute__((fallthrough));
case USBH_EP_EVENT_URB_DONE: {
//Dequeue all URBs and run their transfer callback
urb_t *urb;
case USBH_EP_EVENT_ERROR_XFER:
case USBH_EP_EVENT_ERROR_URB_NOT_AVAIL:
case USBH_EP_EVENT_ERROR_OVERFLOW:
case USBH_EP_EVENT_ERROR_STALL:
// The endpoint is now stalled. Flush all pending URBs
ESP_ERROR_CHECK(usbh_ep_command(ep_wrap->constant.ep_hdl, USBH_EP_CMD_FLUSH));
// All URBs in this pipe are now retired waiting to be dequeued. Fall through to dequeue them
__attribute__((fallthrough));
case USBH_EP_EVENT_URB_DONE: {
// Dequeue all URBs and run their transfer callback
urb_t *urb;
usbh_ep_dequeue_urb(ep_wrap->constant.ep_hdl, &urb);
while (urb != NULL) {
// Clear the transfer's in-flight flag to indicate the transfer is no longer in-flight
urb->usb_host_inflight = false;
urb->transfer.callback(&urb->transfer);
num_urb_dequeued++;
usbh_ep_dequeue_urb(ep_wrap->constant.ep_hdl, &urb);
while (urb != NULL) {
//Clear the transfer's in-flight flag to indicate the transfer is no longer in-flight
urb->usb_host_inflight = false;
urb->transfer.callback(&urb->transfer);
num_urb_dequeued++;
usbh_ep_dequeue_urb(ep_wrap->constant.ep_hdl, &urb);
}
break;
}
default:
abort(); //Should never occur
break;
break;
}
default:
abort(); // Should never occur
break;
}
HOST_ENTER_CRITICAL();
//Update the endpoint's number of URB's in-flight
// Update the endpoint's number of URB's in-flight
assert(num_urb_dequeued <= ep_wrap->dynamic.num_urb_inflight);
ep_wrap->dynamic.num_urb_inflight -= num_urb_dequeued;
}
@ -647,12 +647,12 @@ esp_err_t usb_host_client_register(const usb_host_client_config_t *client_config
HOST_CHECK(client_config != NULL && client_hdl_ret != NULL, ESP_ERR_INVALID_ARG);
HOST_CHECK(client_config->max_num_event_msg > 0, ESP_ERR_INVALID_ARG);
if (!client_config->is_synchronous) {
//Asynchronous clients must provide a
// Asynchronous clients must provide a
HOST_CHECK(client_config->async.client_event_callback != NULL, ESP_ERR_INVALID_ARG);
}
esp_err_t ret;
//Create client object
// Create client object
client_t *client_obj = heap_caps_calloc(1, sizeof(client_t), MALLOC_CAP_DEFAULT);
SemaphoreHandle_t event_sem = xSemaphoreCreateBinary();
QueueHandle_t event_msg_queue = xQueueCreate(client_config->max_num_event_msg, sizeof(usb_host_client_event_msg_t));
@ -660,7 +660,7 @@ esp_err_t usb_host_client_register(const usb_host_client_config_t *client_config
ret = ESP_ERR_NO_MEM;
goto alloc_err;
}
//Initialize client object
// Initialize client object
TAILQ_INIT(&client_obj->dynamic.pending_ep_tailq);
TAILQ_INIT(&client_obj->dynamic.idle_ep_tailq);
TAILQ_INIT(&client_obj->mux_protected.interface_tailq);
@ -670,7 +670,7 @@ esp_err_t usb_host_client_register(const usb_host_client_config_t *client_config
client_obj->constant.callback_arg = client_config->async.callback_arg;
client_obj->constant.event_msg_queue = event_msg_queue;
//Add client to the host library's list of clients
// Add client to the host library's list of clients
xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY);
HOST_ENTER_CRITICAL();
p_host_lib_obj->dynamic.flags.num_clients++;
@ -678,7 +678,7 @@ esp_err_t usb_host_client_register(const usb_host_client_config_t *client_config
TAILQ_INSERT_TAIL(&p_host_lib_obj->mux_protected.client_tailq, client_obj, dynamic.tailq_entry);
xSemaphoreGive(p_host_lib_obj->constant.mux_lock);
//Write back client handle
// Write back client handle
*client_hdl_ret = (usb_host_client_handle_t)client_obj;
ret = ESP_OK;
return ret;
@ -700,41 +700,41 @@ esp_err_t usb_host_client_deregister(usb_host_client_handle_t client_hdl)
client_t *client_obj = (client_t *)client_hdl;
esp_err_t ret;
//We take the mux_lock because we need to access the host library's client_tailq
// We take the mux_lock because we need to access the host library's client_tailq
xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY);
HOST_ENTER_CRITICAL();
//Check that client can currently deregistered
// Check that client can currently deregistered
bool can_deregister;
if (!TAILQ_EMPTY(&client_obj->dynamic.pending_ep_tailq) ||
!TAILQ_EMPTY(&client_obj->dynamic.idle_ep_tailq) ||
!TAILQ_EMPTY(&client_obj->dynamic.done_ctrl_xfer_tailq) ||
client_obj->dynamic.flags.handling_events ||
client_obj->dynamic.flags.blocked ||
client_obj->dynamic.flags.taking_mux ||
client_obj->dynamic.flags.num_intf_claimed != 0 ||
client_obj->dynamic.num_done_ctrl_xfer != 0 ||
client_obj->dynamic.opened_dev_addr_map != 0) {
can_deregister = false;
} else {
can_deregister = true;
}
!TAILQ_EMPTY(&client_obj->dynamic.idle_ep_tailq) ||
!TAILQ_EMPTY(&client_obj->dynamic.done_ctrl_xfer_tailq) ||
client_obj->dynamic.flags.handling_events ||
client_obj->dynamic.flags.blocked ||
client_obj->dynamic.flags.taking_mux ||
client_obj->dynamic.flags.num_intf_claimed != 0 ||
client_obj->dynamic.num_done_ctrl_xfer != 0 ||
client_obj->dynamic.opened_dev_addr_map != 0) {
can_deregister = false;
} else {
can_deregister = true;
}
HOST_EXIT_CRITICAL();
if (!can_deregister) {
ret = ESP_ERR_INVALID_STATE;
goto exit;
}
//Remove client object from the library's list of clients
// Remove client object from the library's list of clients
TAILQ_REMOVE(&p_host_lib_obj->mux_protected.client_tailq, client_obj, dynamic.tailq_entry);
HOST_ENTER_CRITICAL();
p_host_lib_obj->dynamic.flags.num_clients--;
if (p_host_lib_obj->dynamic.flags.num_clients == 0) {
//This is the last client being deregistered. Notify the lib handler
// This is the last client being deregistered. Notify the lib handler
p_host_lib_obj->dynamic.lib_event_flags |= USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS;
_unblock_lib(false);
}
HOST_EXIT_CRITICAL();
//Free client object
// Free client object
vQueueDelete(client_obj->constant.event_msg_queue);
vSemaphoreDelete(client_obj->constant.event_sem);
heap_caps_free(client_obj);
@ -752,7 +752,7 @@ esp_err_t usb_host_client_handle_events(usb_host_client_handle_t client_hdl, Tic
HOST_ENTER_CRITICAL();
if (!client_obj->dynamic.flags.events_pending) {
//There are currently no events, wait for one to occur
// There are currently no events, wait for one to occur
client_obj->dynamic.flags.blocked = 1;
HOST_EXIT_CRITICAL();
BaseType_t sem_ret = xSemaphoreTake(client_obj->constant.event_sem, timeout_ticks);
@ -760,45 +760,45 @@ esp_err_t usb_host_client_handle_events(usb_host_client_handle_t client_hdl, Tic
client_obj->dynamic.flags.blocked = 0;
if (sem_ret == pdFALSE) {
HOST_EXIT_CRITICAL();
//Timed out waiting for semaphore
// Timed out waiting for semaphore
ret = ESP_ERR_TIMEOUT;
goto exit;
}
}
//Mark that we're processing events
// Mark that we're processing events
client_obj->dynamic.flags.handling_events = 1;
while (client_obj->dynamic.flags.handling_events) {
//Handle pending endpoints
// Handle pending endpoints
if (!TAILQ_EMPTY(&client_obj->dynamic.pending_ep_tailq)) {
_handle_pending_ep(client_obj);
}
//Handle any done control transfers
// Handle any done control transfers
while (client_obj->dynamic.num_done_ctrl_xfer > 0) {
urb_t *urb = TAILQ_FIRST(&client_obj->dynamic.done_ctrl_xfer_tailq);
TAILQ_REMOVE(&client_obj->dynamic.done_ctrl_xfer_tailq, urb, tailq_entry);
client_obj->dynamic.num_done_ctrl_xfer--;
HOST_EXIT_CRITICAL();
//Clear the transfer's in-flight flag to indicate the transfer is no longer in-flight
// Clear the transfer's in-flight flag to indicate the transfer is no longer in-flight
urb->usb_host_inflight = false;
//Call the transfer's callback
// Call the transfer's callback
urb->transfer.callback(&urb->transfer);
HOST_ENTER_CRITICAL();
}
//Handle event messages
// Handle event messages
while (uxQueueMessagesWaiting(client_obj->constant.event_msg_queue) > 0) {
HOST_EXIT_CRITICAL();
//Dequeue the event message and call the client event callback
// Dequeue the event message and call the client event callback
usb_host_client_event_msg_t event_msg;
BaseType_t queue_ret = xQueueReceive(client_obj->constant.event_msg_queue, &event_msg, 0);
assert(queue_ret == pdTRUE);
client_obj->constant.event_callback(&event_msg, client_obj->constant.callback_arg);
HOST_ENTER_CRITICAL();
}
//Check each event again to see any new events occurred
// Check each event again to see any new events occurred
if (TAILQ_EMPTY(&client_obj->dynamic.pending_ep_tailq) &&
client_obj->dynamic.num_done_ctrl_xfer == 0 &&
uxQueueMessagesWaiting(client_obj->constant.event_msg_queue) == 0) {
//All pending endpoints and event messages handled
client_obj->dynamic.num_done_ctrl_xfer == 0 &&
uxQueueMessagesWaiting(client_obj->constant.event_msg_queue) == 0) {
// All pending endpoints and event messages handled
client_obj->dynamic.flags.events_pending = 0;
client_obj->dynamic.flags.handling_events = 0;
}
@ -838,12 +838,12 @@ esp_err_t usb_host_device_open(usb_host_client_handle_t client_hdl, uint8_t dev_
HOST_ENTER_CRITICAL();
if (_check_client_opened_device(client_obj, dev_addr)) {
//Client has already opened the device. Close it and return an error
// Client has already opened the device. Close it and return an error
ret = ESP_ERR_INVALID_STATE;
HOST_EXIT_CRITICAL();
goto already_opened;
}
//Record in client object that we have opened the device of this address
// Record in client object that we have opened the device of this address
_record_client_opened_device(client_obj, dev_addr);
HOST_EXIT_CRITICAL();
@ -862,10 +862,10 @@ esp_err_t usb_host_device_close(usb_host_client_handle_t client_hdl, usb_device_
HOST_CHECK(dev_hdl != NULL && client_hdl != NULL, ESP_ERR_INVALID_ARG);
client_t *client_obj = (client_t *)client_hdl;
//We take the lock because we need to walk the interface list
// We take the lock because we need to walk the interface list
xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY);
esp_err_t ret;
//Check that all interfaces claimed by this client do not belong to this device
// Check that all interfaces claimed by this client do not belong to this device
bool all_released = true;
interface_t *intf_obj;
TAILQ_FOREACH(intf_obj, &client_obj->mux_protected.interface_tailq, mux_protected.tailq_entry) {
@ -879,18 +879,18 @@ esp_err_t usb_host_device_close(usb_host_client_handle_t client_hdl, usb_device_
goto exit;
}
//Check that client actually opened the device in the first place
// Check that client actually opened the device in the first place
HOST_ENTER_CRITICAL();
uint8_t dev_addr;
ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr));
HOST_CHECK_FROM_CRIT(_check_client_opened_device(client_obj, dev_addr), ESP_ERR_NOT_FOUND);
if (!_check_client_opened_device(client_obj, dev_addr)) {
//Client never opened this device
// Client never opened this device
ret = ESP_ERR_INVALID_STATE;
HOST_EXIT_CRITICAL();
goto exit;
}
//Proceed to clear the record of the device form the client
// Proceed to clear the record of the device form the client
_clear_client_opened_device(client_obj, dev_addr);
HOST_EXIT_CRITICAL();
@ -904,11 +904,11 @@ exit:
esp_err_t usb_host_device_free_all(void)
{
HOST_ENTER_CRITICAL();
HOST_CHECK_FROM_CRIT(p_host_lib_obj->dynamic.flags.num_clients == 0, ESP_ERR_INVALID_STATE); //All clients must have been deregistered
HOST_CHECK_FROM_CRIT(p_host_lib_obj->dynamic.flags.num_clients == 0, ESP_ERR_INVALID_STATE); // All clients must have been deregistered
HOST_EXIT_CRITICAL();
esp_err_t ret;
ret = usbh_dev_mark_all_free();
//If ESP_ERR_NOT_FINISHED is returned, caller must wait for USB_HOST_LIB_EVENT_FLAGS_ALL_FREE to confirm all devices are free
// If ESP_ERR_NOT_FINISHED is returned, caller must wait for USB_HOST_LIB_EVENT_FLAGS_ALL_FREE to confirm all devices are free
return ret;
}
@ -968,10 +968,10 @@ static esp_err_t ep_wrapper_alloc(usb_device_handle_t dev_hdl, const usb_ep_desc
if (ret != ESP_OK) {
goto alloc_err;
}
//Initialize endpoint wrapper item
// Initialize endpoint wrapper item
ep_wrap->constant.ep_hdl = ep_hdl;
ep_wrap->constant.intf_obj = intf_obj;
//Write back result
// Write back result
*ep_wrap_ret = ep_wrap;
ret = ESP_OK;
return ret;
@ -986,9 +986,9 @@ static void ep_wrapper_free(usb_device_handle_t dev_hdl, ep_wrapper_t *ep_wrap)
if (ep_wrap == NULL) {
return;
}
//Free the underlying endpoint
// Free the underlying endpoint
ESP_ERROR_CHECK(usbh_ep_free(ep_wrap->constant.ep_hdl));
//Free the endpoint wrapper item
// Free the endpoint wrapper item
heap_caps_free(ep_wrap);
}
@ -1018,21 +1018,21 @@ static void interface_free(interface_t *intf_obj)
static esp_err_t interface_claim(client_t *client_obj, usb_device_handle_t dev_hdl, const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, interface_t **intf_obj_ret)
{
esp_err_t ret;
//We need to walk to configuration descriptor to find the correct interface descriptor, and each of its constituent endpoint descriptors
//Find the interface descriptor and allocate the interface object
// We need to walk to configuration descriptor to find the correct interface descriptor, and each of its constituent endpoint descriptors
// Find the interface descriptor and allocate the interface object
int offset_intf;
const usb_intf_desc_t *intf_desc = usb_parse_interface_descriptor(config_desc, bInterfaceNumber, bAlternateSetting, &offset_intf);
if (intf_desc == NULL) {
ret = ESP_ERR_NOT_FOUND;
goto exit;
}
//Allocate interface object
// Allocate interface object
interface_t *intf_obj = interface_alloc(client_obj, dev_hdl, intf_desc);
if (intf_obj == NULL) {
ret = ESP_ERR_NO_MEM;
goto exit;
}
//Find each endpoint descriptor in the interface by index, and allocate those endpoints
// Find each endpoint descriptor in the interface by index, and allocate those endpoints
for (int i = 0; i < intf_desc->bNumEndpoints; i++) {
int offset_ep = offset_intf;
const usb_ep_desc_t *ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, i, config_desc->wTotalLength, &offset_ep);
@ -1040,24 +1040,24 @@ static esp_err_t interface_claim(client_t *client_obj, usb_device_handle_t dev_h
ret = ESP_ERR_NOT_FOUND;
goto ep_alloc_err;
}
//Allocate the endpoint wrapper item
// Allocate the endpoint wrapper item
ep_wrapper_t *ep_wrap;
ret = ep_wrapper_alloc(dev_hdl, ep_desc, intf_obj, &ep_wrap);
if (ret != ESP_OK) {
goto ep_alloc_err;
}
//Fill the interface object with the allocated endpoints
// Fill the interface object with the allocated endpoints
intf_obj->constant.endpoints[i] = ep_wrap;
}
//Add interface object to client (safe because we have already taken the mutex)
// Add interface object to client (safe because we have already taken the mutex)
TAILQ_INSERT_TAIL(&client_obj->mux_protected.interface_tailq, intf_obj, mux_protected.tailq_entry);
//Add each endpoint wrapper item to the client's endpoint list
// Add each endpoint wrapper item to the client's endpoint list
HOST_ENTER_CRITICAL();
for (int i = 0; i < intf_desc->bNumEndpoints; i++) {
TAILQ_INSERT_TAIL(&client_obj->dynamic.idle_ep_tailq, intf_obj->constant.endpoints[i], dynamic.tailq_entry);
}
HOST_EXIT_CRITICAL();
//Write back result
// Write back result
*intf_obj_ret = intf_obj;
ret = ESP_OK;
return ret;
@ -1075,7 +1075,7 @@ exit:
static esp_err_t interface_release(client_t *client_obj, usb_device_handle_t dev_hdl, uint8_t bInterfaceNumber)
{
esp_err_t ret;
//Find the interface object
// Find the interface object
interface_t *intf_obj_iter;
interface_t *intf_obj = NULL;
TAILQ_FOREACH(intf_obj_iter, &client_obj->mux_protected.interface_tailq, mux_protected.tailq_entry) {
@ -1089,13 +1089,13 @@ static esp_err_t interface_release(client_t *client_obj, usb_device_handle_t dev
goto exit;
}
//Check that all endpoints in the interface are in a state to be freed
//Todo: Check that each EP is halted before allowing them to be freed (IDF-7273)
// Check that all endpoints in the interface are in a state to be freed
// Todo: Check that each EP is halted before allowing them to be freed (IDF-7273)
HOST_ENTER_CRITICAL();
bool can_free = true;
for (int i = 0; i < intf_obj->constant.intf_desc->bNumEndpoints; i++) {
ep_wrapper_t *ep_wrap = intf_obj->constant.endpoints[i];
//Endpoint must not be on the pending list and must not have in-flight URBs
// Endpoint must not be on the pending list and must not have in-flight URBs
if (ep_wrap->dynamic.num_urb_inflight != 0 || ep_wrap->dynamic.flags.pending) {
can_free = false;
break;
@ -1106,21 +1106,21 @@ static esp_err_t interface_release(client_t *client_obj, usb_device_handle_t dev
ret = ESP_ERR_INVALID_STATE;
goto exit;
}
//Proceed to remove all endpoint wrapper items from the list
// Proceed to remove all endpoint wrapper items from the list
for (int i = 0; i < intf_obj->constant.intf_desc->bNumEndpoints; i++) {
TAILQ_REMOVE(&client_obj->dynamic.idle_ep_tailq, intf_obj->constant.endpoints[i], dynamic.tailq_entry);
}
HOST_EXIT_CRITICAL();
//Remove the interface object from the list (safe because we have already taken the mutex)
// Remove the interface object from the list (safe because we have already taken the mutex)
TAILQ_REMOVE(&client_obj->mux_protected.interface_tailq, intf_obj, mux_protected.tailq_entry);
//Free each endpoint in the interface
for (int i = 0; i < intf_obj->constant.intf_desc->bNumEndpoints; i++) {
// Free each endpoint in the interface
for (int i = 0; i < intf_obj->constant.intf_desc->bNumEndpoints; i++) {
ep_wrapper_free(dev_hdl, intf_obj->constant.endpoints[i]);
intf_obj->constant.endpoints[i] = NULL;
}
//Free the interface object itself
// Free the interface object itself
interface_free(intf_obj);
ret = ESP_OK;
exit:
@ -1137,18 +1137,18 @@ esp_err_t usb_host_interface_claim(usb_host_client_handle_t client_hdl, usb_devi
HOST_ENTER_CRITICAL();
uint8_t dev_addr;
ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr));
//Check if client actually opened device
// Check if client actually opened device
HOST_CHECK_FROM_CRIT(_check_client_opened_device(client_obj, dev_addr), ESP_ERR_INVALID_STATE);
client_obj->dynamic.flags.taking_mux = 1;
HOST_EXIT_CRITICAL();
//Take mux lock. This protects the client being released or other clients from claiming interfaces
// Take mux lock. This protects the client being released or other clients from claiming interfaces
xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY);
esp_err_t ret;
const usb_config_desc_t *config_desc;
ESP_ERROR_CHECK(usbh_dev_get_config_desc(dev_hdl, &config_desc));
interface_t *intf_obj;
//Claim interface
// Claim interface
ret = interface_claim(client_obj, dev_hdl, config_desc, bInterfaceNumber, bAlternateSetting, &intf_obj);
if (ret != ESP_OK) {
goto exit;
@ -1174,12 +1174,12 @@ esp_err_t usb_host_interface_release(usb_host_client_handle_t client_hdl, usb_de
HOST_ENTER_CRITICAL();
uint8_t dev_addr;
ESP_ERROR_CHECK(usbh_dev_get_addr(dev_hdl, &dev_addr));
//Check if client actually opened device
// Check if client actually opened device
HOST_CHECK_FROM_CRIT(_check_client_opened_device(client_obj, dev_addr), ESP_ERR_INVALID_STATE);
client_obj->dynamic.flags.taking_mux = 1;
HOST_EXIT_CRITICAL();
//Take mux lock. This protects the client being released or other clients from claiming interfaces
// Take mux lock. This protects the client being released or other clients from claiming interfaces
xSemaphoreTake(p_host_lib_obj->constant.mux_lock, portMAX_DELAY);
esp_err_t ret = interface_release(client_obj, dev_hdl, bInterfaceNumber);
xSemaphoreGive(p_host_lib_obj->constant.mux_lock);
@ -1266,8 +1266,8 @@ esp_err_t usb_host_transfer_free(usb_transfer_t *transfer)
esp_err_t usb_host_transfer_submit(usb_transfer_t *transfer)
{
HOST_CHECK(transfer != NULL, ESP_ERR_INVALID_ARG);
//Check that transfer and target endpoint are valid
HOST_CHECK(transfer->device_handle != NULL, ESP_ERR_INVALID_ARG); //Target device must be set
// Check that transfer and target endpoint are valid
HOST_CHECK(transfer->device_handle != NULL, ESP_ERR_INVALID_ARG); // Target device must be set
HOST_CHECK((transfer->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK) != 0, ESP_ERR_INVALID_ARG);
usbh_ep_handle_t ep_hdl;
@ -1281,7 +1281,7 @@ esp_err_t usb_host_transfer_submit(usb_transfer_t *transfer)
}
ep_wrap = usbh_ep_get_context(ep_hdl);
assert(ep_wrap != NULL);
//Check that we are not submitting a transfer already in-flight
// Check that we are not submitting a transfer already in-flight
HOST_CHECK(!urb_obj->usb_host_inflight, ESP_ERR_NOT_FINISHED);
urb_obj->usb_host_inflight = true;
HOST_ENTER_CRITICAL();
@ -1306,17 +1306,17 @@ err:
esp_err_t usb_host_transfer_submit_control(usb_host_client_handle_t client_hdl, usb_transfer_t *transfer)
{
HOST_CHECK(client_hdl != NULL && transfer != NULL, ESP_ERR_INVALID_ARG);
//Check that control transfer is valid
HOST_CHECK(transfer->device_handle != NULL, ESP_ERR_INVALID_ARG); //Target device must be set
//Control transfers must be targeted at EP 0
// Check that control transfer is valid
HOST_CHECK(transfer->device_handle != NULL, ESP_ERR_INVALID_ARG); // Target device must be set
// Control transfers must be targeted at EP 0
HOST_CHECK((transfer->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK) == 0, ESP_ERR_INVALID_ARG);
usb_device_handle_t dev_hdl = transfer->device_handle;
urb_t *urb_obj = __containerof(transfer, urb_t, transfer);
//Check that we are not submitting a transfer already in-flight
// Check that we are not submitting a transfer already in-flight
HOST_CHECK(!urb_obj->usb_host_inflight, ESP_ERR_NOT_FINISHED);
urb_obj->usb_host_inflight = true;
//Save client handle into URB
// Save client handle into URB
urb_obj->usb_host_client = (void *)client_hdl;
esp_err_t ret;

View File

@ -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},
};
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)
@ -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->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)
@ -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;
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_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_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
if (handle->target == USB_PHY_TARGET_INT) {
usb_phy_hal_int_load_conf_host(&(handle->hal_context));
}
} 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_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_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_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);
}
@ -160,37 +160,37 @@ esp_err_t usb_phy_action(usb_phy_handle_t handle, usb_phy_action_t action)
esp_err_t ret = ESP_OK;
switch (action) {
case USB_PHY_ACTION_HOST_ALLOW_CONN:
if (handle->target == USB_PHY_TARGET_INT) {
usb_phy_hal_int_mimick_disconn(&(handle->hal_context), false);
} else {
if (!handle->iopins) {
ret = ESP_FAIL;
ESP_LOGE(USBPHY_TAG, "no I/O pins provided for connection");
break;
}
/*
Allow for connections on the external PHY by connecting the VP and VM signals to the external PHY.
*/
esp_rom_gpio_connect_in_signal(handle->iopins->vp_io_num, USB_EXTPHY_VP_IDX, false);
esp_rom_gpio_connect_in_signal(handle->iopins->vm_io_num, USB_EXTPHY_VM_IDX, false);
case USB_PHY_ACTION_HOST_ALLOW_CONN:
if (handle->target == USB_PHY_TARGET_INT) {
usb_phy_hal_int_mimick_disconn(&(handle->hal_context), false);
} else {
if (!handle->iopins) {
ret = ESP_FAIL;
ESP_LOGE(USBPHY_TAG, "no I/O pins provided for connection");
break;
}
break;
/*
Allow for connections on the external PHY by connecting the VP and VM signals to the external PHY.
*/
esp_rom_gpio_connect_in_signal(handle->iopins->vp_io_num, USB_EXTPHY_VP_IDX, false);
esp_rom_gpio_connect_in_signal(handle->iopins->vm_io_num, USB_EXTPHY_VM_IDX, false);
}
break;
case USB_PHY_ACTION_HOST_FORCE_DISCONN:
if (handle->target == USB_PHY_TARGET_INT) {
usb_phy_hal_int_mimick_disconn(&(handle->hal_context), true);
} else {
/*
Disable connections on the external PHY by connecting the VP and VM signals to the constant LOW signal.
*/
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_EXTPHY_VP_IDX, false);
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_EXTPHY_VM_IDX, false);
}
break;
case USB_PHY_ACTION_HOST_FORCE_DISCONN:
if (handle->target == USB_PHY_TARGET_INT) {
usb_phy_hal_int_mimick_disconn(&(handle->hal_context), true);
} else {
/*
Disable connections on the external PHY by connecting the VP and VM signals to the constant LOW signal.
*/
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_EXTPHY_VP_IDX, false);
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_EXTPHY_VM_IDX, false);
}
break;
default:
break;
default:
break;
}
return ret;

View File

@ -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) {
goto err;
}
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
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
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_size = data_buffer_size;

View File

@ -25,17 +25,17 @@
#define EP_NUM_MAX 16 // The largest possible non-default endpoint number
#define NUM_NON_DEFAULT_EP ((EP_NUM_MAX - 1) * 2) // The total number of non-default endpoints a device can have.
//Device action flags. LISTED IN THE ORDER THEY SHOULD BE HANDLED IN within usbh_process(). Some actions are mutually exclusive
// Device action flags. LISTED IN THE ORDER THEY SHOULD BE HANDLED IN within usbh_process(). Some actions are mutually exclusive
typedef enum {
DEV_ACTION_EPn_HALT_FLUSH = (1 << 0), //Halt all non-default endpoints then flush them (called after a device gone is gone)
DEV_ACTION_EP0_FLUSH = (1 << 1), //Retire all URBS submitted to EP0
DEV_ACTION_EP0_DEQUEUE = (1 << 2), //Dequeue all URBs from EP0
DEV_ACTION_EP0_CLEAR = (1 << 3), //Move EP0 to the the active state
DEV_ACTION_PROP_GONE_EVT = (1 << 4), //Propagate a USBH_EVENT_DEV_GONE event
DEV_ACTION_FREE_AND_RECOVER = (1 << 5), //Free the device object, but send a USBH_HUB_REQ_PORT_RECOVER request afterwards.
DEV_ACTION_FREE = (1 << 6), //Free the device object
DEV_ACTION_PORT_DISABLE = (1 << 7), //Request the hub driver to disable the port of the device
DEV_ACTION_PROP_NEW = (1 << 8), //Propagate a USBH_EVENT_DEV_NEW event
DEV_ACTION_EPn_HALT_FLUSH = (1 << 0), // Halt all non-default endpoints then flush them (called after a device gone is gone)
DEV_ACTION_EP0_FLUSH = (1 << 1), // Retire all URBS submitted to EP0
DEV_ACTION_EP0_DEQUEUE = (1 << 2), // Dequeue all URBs from EP0
DEV_ACTION_EP0_CLEAR = (1 << 3), // Move EP0 to the the active state
DEV_ACTION_PROP_GONE_EVT = (1 << 4), // Propagate a USBH_EVENT_DEV_GONE event
DEV_ACTION_FREE_AND_RECOVER = (1 << 5), // Free the device object, but send a USBH_HUB_REQ_PORT_RECOVER request afterwards.
DEV_ACTION_FREE = (1 << 6), // Free the device object
DEV_ACTION_PORT_DISABLE = (1 << 7), // Request the hub driver to disable the port of the device
DEV_ACTION_PROP_NEW = (1 << 8), // Propagate a USBH_EVENT_DEV_NEW event
} dev_action_t;
typedef struct device_s device_t;
@ -45,13 +45,13 @@ typedef struct {
usbh_ep_cb_t ep_cb;
void *ep_cb_arg;
hcd_pipe_handle_t pipe_hdl;
device_t *dev; //Pointer to the device object that this endpoint is contained in
const usb_ep_desc_t *ep_desc; //This just stores a pointer endpoint descriptor inside the device's "config_desc"
device_t *dev; // Pointer to the device object that this endpoint is contained in
const usb_ep_desc_t *ep_desc; // This just stores a pointer endpoint descriptor inside the device's "config_desc"
} constant;
} endpoint_t;
struct device_s {
//Dynamic members require a critical section
// Dynamic members require a critical section
struct {
TAILQ_ENTRY(device_s) tailq_entry;
union {
@ -70,7 +70,7 @@ struct device_s {
usb_device_state_t state;
uint32_t ref_count;
} dynamic;
//Mux protected members must be protected by the USBH mux_lock when accessed
// Mux protected members must be protected by the USBH mux_lock when accessed
struct {
/*
- Endpoint object pointers for each possible non-default endpoint
@ -78,7 +78,7 @@ struct device_s {
*/
endpoint_t *endpoints[NUM_NON_DEFAULT_EP];
} mux_protected;
//Constant members do not change after device allocation and enumeration thus do not require a critical section
// Constant members do not change after device allocation and enumeration thus do not require a critical section
struct {
hcd_pipe_handle_t default_pipe;
hcd_port_handle_t port_hdl;
@ -93,16 +93,16 @@ struct device_s {
};
typedef struct {
//Dynamic members require a critical section
// Dynamic members require a critical section
struct {
TAILQ_HEAD(tailhead_devs, device_s) devs_idle_tailq; //Tailq of all enum and configured devices
TAILQ_HEAD(tailhead_devs_cb, device_s) devs_pending_tailq; //Tailq of devices that need to have their cb called
TAILQ_HEAD(tailhead_devs, device_s) devs_idle_tailq; // Tailq of all enum and configured devices
TAILQ_HEAD(tailhead_devs_cb, device_s) devs_pending_tailq; // Tailq of devices that need to have their cb called
} dynamic;
//Mux protected members must be protected by the USBH mux_lock when accessed
// Mux protected members must be protected by the USBH mux_lock when accessed
struct {
uint8_t num_device; //Number of enumerated devices
uint8_t num_device; // Number of enumerated devices
} mux_protected;
//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 {
usb_proc_req_cb_t proc_req_cb;
void *proc_req_cb_arg;
@ -169,13 +169,13 @@ static endpoint_t *get_ep_from_addr(device_t *dev_obj, uint8_t bEndpointAddress)
CALLER IS RESPONSIBLE FOR TAKING THE mux_lock
*/
//Calculate index to the device's endpoint object list
// Calculate index to the device's endpoint object list
int index;
// EP_NUM_MIN should map to an index of 0
index = (bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK) - EP_NUM_MIN;
assert(index >= 0); // Endpoint address is not supported
if (bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK) {
//OUT EPs are listed before IN EPs, so add an offset
// OUT EPs are listed before IN EPs, so add an offset
index += (EP_NUM_MAX - EP_NUM_MIN);
}
return dev_obj->mux_protected.endpoints[index];
@ -187,13 +187,13 @@ static inline void set_ep_from_addr(device_t *dev_obj, uint8_t bEndpointAddress,
CALLER IS RESPONSIBLE FOR TAKING THE mux_lock
*/
//Calculate index to the device's endpoint object list
// Calculate index to the device's endpoint object list
int index;
// EP_NUM_MIN should map to an index of 0
// EP_NUM_MIN should map to an index of 0
index = (bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK) - EP_NUM_MIN;
assert(index >= 0); // Endpoint address is not supported
if (bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK) {
//OUT EPs are listed before IN EPs, so add an offset
// OUT EPs are listed before IN EPs, so add an offset
index += (EP_NUM_MAX - EP_NUM_MIN);
}
dev_obj->mux_protected.endpoints[index] = ep_obj;
@ -215,20 +215,20 @@ static bool urb_check_args(urb_t *urb)
static bool transfer_check_usb_compliance(usb_transfer_t *transfer, usb_transfer_type_t type, int mps, bool is_in)
{
if (type == USB_TRANSFER_TYPE_CTRL) {
//Check that num_bytes and wLength are set correctly
// Check that num_bytes and wLength are set correctly
usb_setup_packet_t *setup_pkt = (usb_setup_packet_t *)transfer->data_buffer;
if (transfer->num_bytes != sizeof(usb_setup_packet_t) + setup_pkt->wLength) {
ESP_LOGE(USBH_TAG, "usb_transfer_t num_bytes and usb_setup_packet_t wLength mismatch");
return false;
}
} else if (type == USB_TRANSFER_TYPE_ISOCHRONOUS) {
//Check that there is at least one isochronous packet descriptor
// Check that there is at least one isochronous packet descriptor
if (transfer->num_isoc_packets <= 0) {
ESP_LOGE(USBH_TAG, "usb_transfer_t num_isoc_packets is 0");
return false;
}
//Check that sum of all packet lengths add up to transfer length
//If IN, check that each packet length is integer multiple of MPS
// Check that sum of all packet lengths add up to transfer length
// If IN, check that each packet length is integer multiple of MPS
int total_num_bytes = 0;
bool mod_mps_all_zero = true;
for (int i = 0; i < transfer->num_isoc_packets; i++) {
@ -246,7 +246,7 @@ static bool transfer_check_usb_compliance(usb_transfer_t *transfer, usb_transfer
return false;
}
} else {
//Check that IN transfers are integer multiple of MPS
// Check that IN transfers are integer multiple of MPS
if (is_in && (transfer->num_bytes % mps != 0)) {
ESP_LOGE(USBH_TAG, "IN transfer num_bytes not integer multiple of MPS");
return false;
@ -267,7 +267,7 @@ static esp_err_t endpoint_alloc(device_t *dev_obj, const usb_ep_desc_t *ep_desc,
if (ep_obj == NULL) {
return ESP_ERR_NO_MEM;
}
//Allocate the EP's underlying pipe
// Allocate the EP's underlying pipe
hcd_pipe_config_t pipe_config = {
.callback = epN_pipe_callback,
.callback_arg = (void *)ep_obj,
@ -280,13 +280,13 @@ static esp_err_t endpoint_alloc(device_t *dev_obj, const usb_ep_desc_t *ep_desc,
if (ret != ESP_OK) {
goto pipe_err;
}
//Initialize the endpoint object
// Initialize the endpoint object
ep_obj->constant.pipe_hdl = pipe_hdl;
ep_obj->constant.ep_cb = ep_config->ep_cb;
ep_obj->constant.ep_cb_arg = ep_config->ep_cb_arg;
ep_obj->constant.dev = dev_obj;
ep_obj->constant.ep_desc = ep_desc;
//Return the endpoint object
// Return the endpoint object
*ep_obj_ret = ep_obj;
ret = ESP_OK;
@ -302,9 +302,9 @@ static void endpoint_free(endpoint_t *ep_obj)
if (ep_obj == NULL) {
return;
}
//Deallocate the EP's underlying pipe
// Deallocate the EP's underlying pipe
ESP_ERROR_CHECK(hcd_pipe_free(ep_obj->constant.pipe_hdl));
//Free the heap object
// Free the heap object
heap_caps_free(ep_obj);
}
@ -317,12 +317,12 @@ static esp_err_t device_alloc(hcd_port_handle_t port_hdl, usb_speed_t speed, dev
ret = ESP_ERR_NO_MEM;
goto err;
}
//Allocate a pipe for EP0. We set the pipe callback to NULL for now
// Allocate a pipe for EP0. We set the pipe callback to NULL for now
hcd_pipe_config_t pipe_config = {
.callback = NULL,
.callback_arg = NULL,
.context = (void *)dev_obj,
.ep_desc = NULL, //No endpoint descriptor means we're allocating a pipe for EP0
.ep_desc = NULL, // No endpoint descriptor means we're allocating a pipe for EP0
.dev_speed = speed,
.dev_addr = 0,
};
@ -331,11 +331,11 @@ static esp_err_t device_alloc(hcd_port_handle_t port_hdl, usb_speed_t speed, dev
if (ret != ESP_OK) {
goto err;
}
//Initialize device object
// Initialize device object
dev_obj->dynamic.state = USB_DEVICE_STATE_DEFAULT;
dev_obj->constant.default_pipe = default_pipe_hdl;
dev_obj->constant.port_hdl = port_hdl;
//Note: dev_obj->constant.address is assigned later during enumeration
// Note: dev_obj->constant.address is assigned later during enumeration
dev_obj->constant.speed = speed;
dev_obj->constant.desc = dev_desc;
*dev_obj_ret = dev_obj;
@ -353,11 +353,11 @@ static void device_free(device_t *dev_obj)
if (dev_obj == NULL) {
return;
}
//Configuration might not have been allocated (in case of early enumeration failure)
// Configuration might not have been allocated (in case of early enumeration failure)
if (dev_obj->constant.config_desc) {
heap_caps_free((usb_config_desc_t *)dev_obj->constant.config_desc);
}
//String descriptors might not have been allocated (in case of early enumeration failure)
// String descriptors might not have been allocated (in case of early enumeration failure)
if (dev_obj->constant.str_desc_manu) {
heap_caps_free((usb_str_desc_t *)dev_obj->constant.str_desc_manu);
}
@ -379,35 +379,35 @@ static bool ep0_pipe_callback(hcd_pipe_handle_t pipe_hdl, hcd_pipe_event_t pipe_
uint32_t action_flags;
device_t *dev_obj = (device_t *)user_arg;
switch (pipe_event) {
case HCD_PIPE_EVENT_URB_DONE:
//A control transfer completed on EP0's pipe . We need to dequeue it
action_flags = DEV_ACTION_EP0_DEQUEUE;
break;
case HCD_PIPE_EVENT_ERROR_XFER:
case HCD_PIPE_EVENT_ERROR_URB_NOT_AVAIL:
case HCD_PIPE_EVENT_ERROR_OVERFLOW:
//EP0's pipe has encountered an error. We need to retire all URBs, dequeue them, then make the pipe active again
action_flags = DEV_ACTION_EP0_FLUSH |
DEV_ACTION_EP0_DEQUEUE |
DEV_ACTION_EP0_CLEAR;
if (in_isr) {
ESP_EARLY_LOGE(USBH_TAG, "Dev %d EP 0 Error", dev_obj->constant.address);
} else {
ESP_LOGE(USBH_TAG, "Dev %d EP 0 Error", dev_obj->constant.address);
}
break;
case HCD_PIPE_EVENT_ERROR_STALL:
//EP0's pipe encountered a "protocol stall". We just need to dequeue URBs then make the pipe active again
action_flags = DEV_ACTION_EP0_DEQUEUE | DEV_ACTION_EP0_CLEAR;
if (in_isr) {
ESP_EARLY_LOGE(USBH_TAG, "Dev %d EP 0 STALL", dev_obj->constant.address);
} else {
ESP_LOGE(USBH_TAG, "Dev %d EP 0 STALL", dev_obj->constant.address);
}
break;
default:
action_flags = 0;
break;
case HCD_PIPE_EVENT_URB_DONE:
// A control transfer completed on EP0's pipe . We need to dequeue it
action_flags = DEV_ACTION_EP0_DEQUEUE;
break;
case HCD_PIPE_EVENT_ERROR_XFER:
case HCD_PIPE_EVENT_ERROR_URB_NOT_AVAIL:
case HCD_PIPE_EVENT_ERROR_OVERFLOW:
// EP0's pipe has encountered an error. We need to retire all URBs, dequeue them, then make the pipe active again
action_flags = DEV_ACTION_EP0_FLUSH |
DEV_ACTION_EP0_DEQUEUE |
DEV_ACTION_EP0_CLEAR;
if (in_isr) {
ESP_EARLY_LOGE(USBH_TAG, "Dev %d EP 0 Error", dev_obj->constant.address);
} else {
ESP_LOGE(USBH_TAG, "Dev %d EP 0 Error", dev_obj->constant.address);
}
break;
case HCD_PIPE_EVENT_ERROR_STALL:
// EP0's pipe encountered a "protocol stall". We just need to dequeue URBs then make the pipe active again
action_flags = DEV_ACTION_EP0_DEQUEUE | DEV_ACTION_EP0_CLEAR;
if (in_isr) {
ESP_EARLY_LOGE(USBH_TAG, "Dev %d EP 0 STALL", dev_obj->constant.address);
} else {
ESP_LOGE(USBH_TAG, "Dev %d EP 0 STALL", dev_obj->constant.address);
}
break;
default:
action_flags = 0;
break;
}
USBH_ENTER_CRITICAL_SAFE();
@ -438,9 +438,9 @@ static bool _dev_set_actions(device_t *dev_obj, uint32_t action_flags)
return false;
}
bool call_proc_req_cb;
//Check if device is already on the callback list
// Check if device is already on the callback list
if (!dev_obj->dynamic.flags.in_pending_list) {
//Move device form idle device list to callback device list
// Move device form idle device list to callback device list
TAILQ_REMOVE(&p_usbh_obj->dynamic.devs_idle_tailq, dev_obj, dynamic.tailq_entry);
TAILQ_INSERT_TAIL(&p_usbh_obj->dynamic.devs_pending_tailq, dev_obj, dynamic.tailq_entry);
dev_obj->dynamic.action_flags |= action_flags;
@ -454,9 +454,9 @@ static bool _dev_set_actions(device_t *dev_obj, uint32_t action_flags)
static inline void handle_epn_halt_flush(device_t *dev_obj)
{
//We need to take the mux_lock to access mux_protected members
// We need to take the mux_lock to access mux_protected members
xSemaphoreTake(p_usbh_obj->constant.mux_lock, portMAX_DELAY);
//Halt then flush all non-default EPs
// Halt then flush all non-default EPs
for (int i = 0; i < NUM_NON_DEFAULT_EP; i++) {
if (dev_obj->mux_protected.endpoints[i] != NULL) {
ESP_ERROR_CHECK(hcd_pipe_command(dev_obj->mux_protected.endpoints[i]->constant.pipe_hdl, HCD_PIPE_CMD_HALT));
@ -474,7 +474,7 @@ static inline void handle_ep0_flush(device_t *dev_obj)
static inline void handle_ep0_dequeue(device_t *dev_obj)
{
//Empty URBs from EP0's pipe and call the control transfer callback
// Empty URBs from EP0's pipe and call the control transfer callback
ESP_LOGD(USBH_TAG, "Default pipe device %d", dev_obj->constant.address);
int num_urbs = 0;
urb_t *urb = hcd_urb_dequeue(dev_obj->constant.default_pipe);
@ -490,28 +490,28 @@ static inline void handle_ep0_dequeue(device_t *dev_obj)
static inline void handle_ep0_clear(device_t *dev_obj)
{
//We allow the pipe command to fail just in case the pipe becomes invalid mid command
// We allow the pipe command to fail just in case the pipe becomes invalid mid command
hcd_pipe_command(dev_obj->constant.default_pipe, HCD_PIPE_CMD_CLEAR);
}
static inline void handle_prop_gone_evt(device_t *dev_obj)
{
//Flush EP0's pipe. Then propagate a USBH_EVENT_DEV_GONE event
// Flush EP0's pipe. Then propagate a USBH_EVENT_DEV_GONE event
ESP_LOGE(USBH_TAG, "Device %d gone", dev_obj->constant.address);
p_usbh_obj->constant.event_cb((usb_device_handle_t)dev_obj, USBH_EVENT_DEV_GONE, p_usbh_obj->constant.event_cb_arg);
}
static void handle_free_and_recover(device_t *dev_obj, bool recover_port)
{
//Cache a copy of the port handle as we are about to free the device object
// Cache a copy of the port handle as we are about to free the device object
bool all_free;
hcd_port_handle_t port_hdl = dev_obj->constant.port_hdl;
ESP_LOGD(USBH_TAG, "Freeing device %d", dev_obj->constant.address);
//We need to take the mux_lock to access mux_protected members
// We need to take the mux_lock to access mux_protected members
xSemaphoreTake(p_usbh_obj->constant.mux_lock, portMAX_DELAY);
USBH_ENTER_CRITICAL();
//Remove the device object for it's containing list
// Remove the device object for it's containing list
if (dev_obj->dynamic.flags.in_pending_list) {
dev_obj->dynamic.flags.in_pending_list = 0;
TAILQ_REMOVE(&p_usbh_obj->dynamic.devs_pending_tailq, dev_obj, dynamic.tailq_entry);
@ -524,12 +524,12 @@ static void handle_free_and_recover(device_t *dev_obj, bool recover_port)
xSemaphoreGive(p_usbh_obj->constant.mux_lock);
device_free(dev_obj);
//If all devices have been freed, propagate a USBH_EVENT_DEV_ALL_FREE event
// If all devices have been freed, propagate a USBH_EVENT_DEV_ALL_FREE event
if (all_free) {
ESP_LOGD(USBH_TAG, "Device all free");
p_usbh_obj->constant.event_cb((usb_device_handle_t)NULL, USBH_EVENT_DEV_ALL_FREE, p_usbh_obj->constant.event_cb_arg);
}
//Check if we need to recover the device's port
// Check if we need to recover the device's port
if (recover_port) {
p_usbh_obj->constant.hub_req_cb(port_hdl, USBH_HUB_REQ_PORT_RECOVER, p_usbh_obj->constant.hub_req_cb_arg);
}
@ -537,7 +537,7 @@ static void handle_free_and_recover(device_t *dev_obj, bool recover_port)
static inline void handle_port_disable(device_t *dev_obj)
{
//Request that the HUB disables this device's port
// Request that the HUB disables this device's port
ESP_LOGD(USBH_TAG, "Disable device port %d", dev_obj->constant.address);
p_usbh_obj->constant.hub_req_cb(dev_obj->constant.port_hdl, USBH_HUB_REQ_PORT_DISABLE, p_usbh_obj->constant.hub_req_cb_arg);
}
@ -564,7 +564,7 @@ esp_err_t usbh_install(const usbh_config_t *usbh_config)
ret = ESP_ERR_NO_MEM;
goto err;
}
//Initialize USBH object
// Initialize USBH object
TAILQ_INIT(&usbh_obj->dynamic.devs_idle_tailq);
TAILQ_INIT(&usbh_obj->dynamic.devs_pending_tailq);
usbh_obj->constant.proc_req_cb = usbh_config->proc_req_cb;
@ -575,7 +575,7 @@ esp_err_t usbh_install(const usbh_config_t *usbh_config)
usbh_obj->constant.ctrl_xfer_cb_arg = usbh_config->ctrl_xfer_cb_arg;
usbh_obj->constant.mux_lock = mux_lock;
//Assign USBH object pointer
// Assign USBH object pointer
USBH_ENTER_CRITICAL();
if (p_usbh_obj != NULL) {
USBH_EXIT_CRITICAL();
@ -598,28 +598,28 @@ err:
esp_err_t usbh_uninstall(void)
{
//Check that USBH is in a state to be uninstalled
// Check that USBH is in a state to be uninstalled
USBH_ENTER_CRITICAL();
USBH_CHECK_FROM_CRIT(p_usbh_obj != NULL, ESP_ERR_INVALID_STATE);
usbh_t *usbh_obj = p_usbh_obj;
USBH_EXIT_CRITICAL();
esp_err_t ret;
//We need to take the mux_lock to access mux_protected members
// We need to take the mux_lock to access mux_protected members
xSemaphoreTake(usbh_obj->constant.mux_lock, portMAX_DELAY);
if (p_usbh_obj->mux_protected.num_device > 0) {
//There are still devices allocated. Can't uninstall right now.
// There are still devices allocated. Can't uninstall right now.
ret = ESP_ERR_INVALID_STATE;
goto exit;
}
//Check again if we can uninstall
// Check again if we can uninstall
USBH_ENTER_CRITICAL();
assert(p_usbh_obj == usbh_obj);
p_usbh_obj = NULL;
USBH_EXIT_CRITICAL();
xSemaphoreGive(usbh_obj->constant.mux_lock);
//Free resources
// Free resources
vSemaphoreDelete(usbh_obj->constant.mux_lock);
heap_caps_free(usbh_obj);
ret = ESP_OK;
@ -634,13 +634,13 @@ esp_err_t usbh_process(void)
{
USBH_ENTER_CRITICAL();
USBH_CHECK_FROM_CRIT(p_usbh_obj != NULL, ESP_ERR_INVALID_STATE);
//Keep processing until all device's with pending events have been handled
while (!TAILQ_EMPTY(&p_usbh_obj->dynamic.devs_pending_tailq)){
//Move the device back into the idle device list,
// Keep processing until all device's with pending events have been handled
while (!TAILQ_EMPTY(&p_usbh_obj->dynamic.devs_pending_tailq)) {
// Move the device back into the idle device list,
device_t *dev_obj = TAILQ_FIRST(&p_usbh_obj->dynamic.devs_pending_tailq);
TAILQ_REMOVE(&p_usbh_obj->dynamic.devs_pending_tailq, dev_obj, dynamic.tailq_entry);
TAILQ_INSERT_TAIL(&p_usbh_obj->dynamic.devs_idle_tailq, dev_obj, dynamic.tailq_entry);
//Clear the device's flags
// Clear the device's flags
uint32_t action_flags = dev_obj->dynamic.action_flags;
dev_obj->dynamic.action_flags = 0;
dev_obj->dynamic.flags.in_pending_list = 0;
@ -650,7 +650,7 @@ esp_err_t usbh_process(void)
--------------------------------------------------------------------- */
USBH_EXIT_CRITICAL();
ESP_LOGD(USBH_TAG, "Processing actions 0x%"PRIx32"", action_flags);
//Sanity check. If the device is being freed, there must not be any other action flags set
// Sanity check. If the device is being freed, there must not be any other action flags set
assert(!(action_flags & DEV_ACTION_FREE) || action_flags == DEV_ACTION_FREE);
if (action_flags & DEV_ACTION_EPn_HALT_FLUSH) {
@ -713,7 +713,7 @@ esp_err_t usbh_dev_addr_list_fill(int list_len, uint8_t *dev_addr_list, int *num
USBH_ENTER_CRITICAL();
int num_filled = 0;
device_t *dev_obj;
//Fill list with devices from idle tailq
// Fill list with devices from idle tailq
TAILQ_FOREACH(dev_obj, &p_usbh_obj->dynamic.devs_idle_tailq, dynamic.tailq_entry) {
if (num_filled < list_len) {
dev_addr_list[num_filled] = dev_obj->constant.address;
@ -722,7 +722,7 @@ esp_err_t usbh_dev_addr_list_fill(int list_len, uint8_t *dev_addr_list, int *num
break;
}
}
//Fill list with devices from pending tailq
// Fill list with devices from pending tailq
TAILQ_FOREACH(dev_obj, &p_usbh_obj->dynamic.devs_pending_tailq, dynamic.tailq_entry) {
if (num_filled < list_len) {
dev_addr_list[num_filled] = dev_obj->constant.address;
@ -732,7 +732,7 @@ esp_err_t usbh_dev_addr_list_fill(int list_len, uint8_t *dev_addr_list, int *num
}
}
USBH_EXIT_CRITICAL();
//Write back number of devices filled
// Write back number of devices filled
*num_dev_ret = num_filled;
return ESP_OK;
}
@ -743,7 +743,7 @@ esp_err_t usbh_dev_open(uint8_t dev_addr, usb_device_handle_t *dev_hdl)
esp_err_t ret;
USBH_ENTER_CRITICAL();
//Go through the device lists to find the device with the specified address
// Go through the device lists to find the device with the specified address
device_t *found_dev_obj = NULL;
device_t *dev_obj;
TAILQ_FOREACH(dev_obj, &p_usbh_obj->dynamic.devs_idle_tailq, dynamic.tailq_entry) {
@ -760,7 +760,7 @@ esp_err_t usbh_dev_open(uint8_t dev_addr, usb_device_handle_t *dev_hdl)
}
exit:
if (found_dev_obj != NULL) {
//The device is not in a state to be referenced
// The device is not in a state to be referenced
if (dev_obj->dynamic.flags.is_gone || dev_obj->dynamic.flags.waiting_port_disable || dev_obj->dynamic.flags.waiting_free) {
ret = ESP_ERR_INVALID_STATE;
} else {
@ -785,19 +785,19 @@ esp_err_t usbh_dev_close(usb_device_handle_t dev_hdl)
dev_obj->dynamic.ref_count--;
bool call_proc_req_cb = false;
if (dev_obj->dynamic.ref_count == 0) {
//Sanity check.
assert(dev_obj->dynamic.num_ctrl_xfers_inflight == 0); //There cannot be any control transfer in-flight
assert(!dev_obj->dynamic.flags.waiting_free); //This can only be set when ref count reaches 0
// Sanity check.
assert(dev_obj->dynamic.num_ctrl_xfers_inflight == 0); // There cannot be any control transfer in-flight
assert(!dev_obj->dynamic.flags.waiting_free); // This can only be set when ref count reaches 0
if (dev_obj->dynamic.flags.is_gone) {
//Device is already gone so it's port is already disabled. Trigger the USBH process to free the device
// Device is already gone so it's port is already disabled. Trigger the USBH process to free the device
dev_obj->dynamic.flags.waiting_free = 1;
call_proc_req_cb = _dev_set_actions(dev_obj, DEV_ACTION_FREE_AND_RECOVER); //Port error occurred so we need to recover it
call_proc_req_cb = _dev_set_actions(dev_obj, DEV_ACTION_FREE_AND_RECOVER); // Port error occurred so we need to recover it
} else if (dev_obj->dynamic.flags.waiting_close) {
//Device is still connected but is no longer needed. Trigger the USBH process to request device's port be disabled
// Device is still connected but is no longer needed. Trigger the USBH process to request device's port be disabled
dev_obj->dynamic.flags.waiting_port_disable = 1;
call_proc_req_cb = _dev_set_actions(dev_obj, DEV_ACTION_PORT_DISABLE);
}
//Else, there's nothing to do. Leave the device allocated
// Else, there's nothing to do. Leave the device allocated
}
USBH_EXIT_CRITICAL();
@ -820,25 +820,25 @@ esp_err_t usbh_dev_mark_all_free(void)
for (int i = 0; i < 2; i++) {
device_t *dev_obj_cur;
device_t *dev_obj_next;
//Go through pending list first as it's more efficient
// Go through pending list first as it's more efficient
if (i == 0) {
dev_obj_cur = TAILQ_FIRST(&p_usbh_obj->dynamic.devs_pending_tailq);
} else {
dev_obj_cur = TAILQ_FIRST(&p_usbh_obj->dynamic.devs_idle_tailq);
}
while (dev_obj_cur != NULL) {
assert(!dev_obj_cur->dynamic.flags.waiting_close); //Sanity check
//Keep a copy of the next item first in case we remove the current item
assert(!dev_obj_cur->dynamic.flags.waiting_close); // Sanity check
// Keep a copy of the next item first in case we remove the current item
dev_obj_next = TAILQ_NEXT(dev_obj_cur, dynamic.tailq_entry);
if (dev_obj_cur->dynamic.ref_count == 0 && !dev_obj_cur->dynamic.flags.is_gone) {
//Device is not opened as is not gone, so we can disable it now
// Device is not opened as is not gone, so we can disable it now
dev_obj_cur->dynamic.flags.waiting_port_disable = 1;
call_proc_req_cb |= _dev_set_actions(dev_obj_cur, DEV_ACTION_PORT_DISABLE);
} else {
//Device is still opened. Just mark it as waiting to be closed
// Device is still opened. Just mark it as waiting to be closed
dev_obj_cur->dynamic.flags.waiting_close = 1;
}
wait_for_free = true; //As long as there is still a device, we need to wait for an event indicating it is freed
wait_for_free = true; // As long as there is still a device, we need to wait for an event indicating it is freed
dev_obj_cur = dev_obj_next;
}
}
@ -871,21 +871,21 @@ esp_err_t usbh_dev_get_info(usb_device_handle_t dev_hdl, usb_device_info_t *dev_
device_t *dev_obj = (device_t *)dev_hdl;
esp_err_t ret;
//Device must be configured, or not attached (if it suddenly disconnected)
// Device must be configured, or not attached (if it suddenly disconnected)
USBH_ENTER_CRITICAL();
if (!(dev_obj->dynamic.state == USB_DEVICE_STATE_CONFIGURED || dev_obj->dynamic.state == USB_DEVICE_STATE_NOT_ATTACHED)) {
USBH_EXIT_CRITICAL();
ret = ESP_ERR_INVALID_STATE;
goto exit;
}
//Critical section for the dynamic members
// Critical section for the dynamic members
dev_info->speed = dev_obj->constant.speed;
dev_info->dev_addr = dev_obj->constant.address;
dev_info->bMaxPacketSize0 = dev_obj->constant.desc->bMaxPacketSize0;
USBH_EXIT_CRITICAL();
assert(dev_obj->constant.config_desc);
dev_info->bConfigurationValue = dev_obj->constant.config_desc->bConfigurationValue;
//String descriptors are allowed to be NULL as not all devices support them
// String descriptors are allowed to be NULL as not all devices support them
dev_info->str_desc_manufacturer = dev_obj->constant.str_desc_manu;
dev_info->str_desc_product = dev_obj->constant.str_desc_product;
dev_info->str_desc_serial_num = dev_obj->constant.str_desc_ser_num;
@ -913,7 +913,7 @@ esp_err_t usbh_dev_get_config_desc(usb_device_handle_t dev_hdl, const usb_config
device_t *dev_obj = (device_t *)dev_hdl;
esp_err_t ret;
//Device must be in the configured state
// Device must be in the configured state
USBH_ENTER_CRITICAL();
if (dev_obj->dynamic.state != USB_DEVICE_STATE_CONFIGURED) {
USBH_EXIT_CRITICAL();
@ -938,7 +938,7 @@ esp_err_t usbh_dev_submit_ctrl_urb(usb_device_handle_t dev_hdl, urb_t *urb)
USBH_ENTER_CRITICAL();
USBH_CHECK_FROM_CRIT(dev_obj->dynamic.state == USB_DEVICE_STATE_CONFIGURED, ESP_ERR_INVALID_STATE);
//Increment the control transfer count first
// Increment the control transfer count first
dev_obj->dynamic.num_ctrl_xfers_inflight++;
USBH_EXIT_CRITICAL();
@ -973,41 +973,41 @@ esp_err_t usbh_ep_alloc(usb_device_handle_t dev_hdl, usbh_ep_config_t *ep_config
device_t *dev_obj = (device_t *)dev_hdl;
endpoint_t *ep_obj;
//Find the endpoint descriptor from the device's current configuration descriptor
// Find the endpoint descriptor from the device's current configuration descriptor
const usb_ep_desc_t *ep_desc = usb_parse_endpoint_descriptor_by_address(dev_obj->constant.config_desc, ep_config->bInterfaceNumber, ep_config->bAlternateSetting, ep_config->bEndpointAddress, NULL);
if (ep_desc == NULL) {
return ESP_ERR_NOT_FOUND;
}
//Allocate the endpoint object
// Allocate the endpoint object
ret = endpoint_alloc(dev_obj, ep_desc, ep_config, &ep_obj);
if (ret != ESP_OK) {
goto alloc_err;
}
//We need to take the mux_lock to access mux_protected members
// We need to take the mux_lock to access mux_protected members
xSemaphoreTake(p_usbh_obj->constant.mux_lock, portMAX_DELAY);
USBH_ENTER_CRITICAL();
//Check the device's state before we assign the a pipe to the allocated endpoint
// Check the device's state before we assign the a pipe to the allocated endpoint
if (dev_obj->dynamic.state != USB_DEVICE_STATE_CONFIGURED) {
USBH_EXIT_CRITICAL();
ret = ESP_ERR_INVALID_STATE;
goto dev_state_err;
}
USBH_EXIT_CRITICAL();
//Check if the endpoint has already been allocated
// Check if the endpoint has already been allocated
if (get_ep_from_addr(dev_obj, bEndpointAddress) == NULL) {
set_ep_from_addr(dev_obj, bEndpointAddress, ep_obj);
//Write back the endpoint handle
// Write back the endpoint handle
*ep_hdl_ret = (usbh_ep_handle_t)ep_obj;
ret = ESP_OK;
} else {
//Endpoint is already allocated
// Endpoint is already allocated
ret = ESP_ERR_INVALID_STATE;
}
dev_state_err:
xSemaphoreGive(p_usbh_obj->constant.mux_lock);
//If the endpoint was not assigned, free it
// If the endpoint was not assigned, free it
if (ret != ESP_OK) {
endpoint_free(ep_obj);
}
@ -1024,18 +1024,18 @@ esp_err_t usbh_ep_free(usbh_ep_handle_t ep_hdl)
device_t *dev_obj = (device_t *)ep_obj->constant.dev;
uint8_t bEndpointAddress = ep_obj->constant.ep_desc->bEndpointAddress;
//Todo: Check that the EP's underlying pipe is halted before allowing the EP to be freed (IDF-7273)
//Check that the the EP's underlying pipe has no more in-flight URBs
// Todo: Check that the EP's underlying pipe is halted before allowing the EP to be freed (IDF-7273)
// Check that the the EP's underlying pipe has no more in-flight URBs
if (hcd_pipe_get_num_urbs(ep_obj->constant.pipe_hdl) != 0) {
ret = ESP_ERR_INVALID_STATE;
goto exit;
}
//We need to take the mux_lock to access mux_protected members
// We need to take the mux_lock to access mux_protected members
xSemaphoreTake(p_usbh_obj->constant.mux_lock, portMAX_DELAY);
//Check if the endpoint was allocated on this device
// Check if the endpoint was allocated on this device
if (ep_obj == get_ep_from_addr(dev_obj, bEndpointAddress)) {
//Clear the endpoint from the device's endpoint object list
// Clear the endpoint from the device's endpoint object list
set_ep_from_addr(dev_obj, bEndpointAddress, NULL);
ret = ESP_OK;
} else {
@ -1043,7 +1043,7 @@ esp_err_t usbh_ep_free(usbh_ep_handle_t ep_hdl)
}
xSemaphoreGive(p_usbh_obj->constant.mux_lock);
//Finally, we free the endpoint object
// Finally, we free the endpoint object
if (ret == ESP_OK) {
endpoint_free(ep_obj);
}
@ -1060,7 +1060,7 @@ esp_err_t usbh_ep_get_handle(usb_device_handle_t dev_hdl, uint8_t bEndpointAddre
device_t *dev_obj = (device_t *)dev_hdl;
endpoint_t *ep_obj;
//We need to take the mux_lock to access mux_protected members
// We need to take the mux_lock to access mux_protected members
xSemaphoreTake(p_usbh_obj->constant.mux_lock, portMAX_DELAY);
ep_obj = get_ep_from_addr(dev_obj, bEndpointAddress);
xSemaphoreGive(p_usbh_obj->constant.mux_lock);
@ -1083,11 +1083,11 @@ esp_err_t usbh_ep_enqueue_urb(usbh_ep_handle_t ep_hdl, urb_t *urb)
*/
endpoint_t *ep_obj = (endpoint_t *)ep_hdl;
//Check that the EP's underlying pipe is in the active state before submitting the URB
// Check that the EP's underlying pipe is in the active state before submitting the URB
if (hcd_pipe_get_state(ep_obj->constant.pipe_hdl) != HCD_PIPE_STATE_ACTIVE) {
return ESP_ERR_INVALID_STATE;
}
//Enqueue the URB to the EP's underlying pipe
// Enqueue the URB to the EP's underlying pipe
return hcd_urb_enqueue(ep_obj->constant.pipe_hdl, urb);
}
@ -1096,7 +1096,7 @@ esp_err_t usbh_ep_dequeue_urb(usbh_ep_handle_t ep_hdl, urb_t **urb_ret)
USBH_CHECK(ep_hdl != NULL && urb_ret != NULL, ESP_ERR_INVALID_ARG);
endpoint_t *ep_obj = (endpoint_t *)ep_hdl;
//Enqueue the URB to the EP's underlying pipe
// Enqueue the URB to the EP's underlying pipe
*urb_ret = hcd_urb_dequeue(ep_obj->constant.pipe_hdl);
return ESP_OK;
}
@ -1106,7 +1106,7 @@ esp_err_t usbh_ep_command(usbh_ep_handle_t ep_hdl, usbh_ep_cmd_t command)
USBH_CHECK(ep_hdl != NULL, ESP_ERR_INVALID_ARG);
endpoint_t *ep_obj = (endpoint_t *)ep_hdl;
//Send the command to the EP's underlying pipe
// Send the command to the EP's underlying pipe
return hcd_pipe_command(ep_obj->constant.pipe_hdl, (hcd_pipe_cmd_t)command);
}
@ -1126,9 +1126,9 @@ esp_err_t usbh_hub_is_installed(usbh_hub_req_cb_t hub_req_callback, void *callba
USBH_CHECK(hub_req_callback != NULL, ESP_ERR_INVALID_ARG);
USBH_ENTER_CRITICAL();
//Check that USBH is already installed
// Check that USBH is already installed
USBH_CHECK_FROM_CRIT(p_usbh_obj != NULL, ESP_ERR_INVALID_STATE);
//Check that Hub has not be installed yet
// Check that Hub has not be installed yet
USBH_CHECK_FROM_CRIT(p_usbh_obj->constant.hub_req_cb == NULL, ESP_ERR_INVALID_STATE);
p_usbh_obj->constant.hub_req_cb = hub_req_callback;
p_usbh_obj->constant.hub_req_cb_arg = callback_arg;
@ -1139,7 +1139,7 @@ esp_err_t usbh_hub_is_installed(usbh_hub_req_cb_t hub_req_callback, void *callba
esp_err_t usbh_hub_add_dev(hcd_port_handle_t port_hdl, usb_speed_t dev_speed, usb_device_handle_t *new_dev_hdl, hcd_pipe_handle_t *default_pipe_hdl)
{
//Note: Parent device handle can be NULL if it's connected to the root hub
// Note: Parent device handle can be NULL if it's connected to the root hub
USBH_CHECK(new_dev_hdl != NULL, ESP_ERR_INVALID_ARG);
esp_err_t ret;
device_t *dev_obj;
@ -1147,7 +1147,7 @@ esp_err_t usbh_hub_add_dev(hcd_port_handle_t port_hdl, usb_speed_t dev_speed, us
if (ret != ESP_OK) {
return ret;
}
//Write-back device handle
// Write-back device handle
*new_dev_hdl = (usb_device_handle_t)dev_obj;
*default_pipe_hdl = dev_obj->constant.default_pipe;
ret = ESP_OK;
@ -1161,34 +1161,34 @@ esp_err_t usbh_hub_pass_event(usb_device_handle_t dev_hdl, usbh_hub_event_t hub_
bool call_proc_req_cb;
switch (hub_event) {
case USBH_HUB_EVENT_PORT_ERROR: {
USBH_ENTER_CRITICAL();
dev_obj->dynamic.flags.is_gone = 1;
//Check if the device can be freed now
if (dev_obj->dynamic.ref_count == 0) {
dev_obj->dynamic.flags.waiting_free = 1;
//Device is already waiting free so none of it's EP's will be in use. Can free immediately.
call_proc_req_cb = _dev_set_actions(dev_obj, DEV_ACTION_FREE_AND_RECOVER); //Port error occurred so we need to recover it
} else {
call_proc_req_cb = _dev_set_actions(dev_obj,
DEV_ACTION_EPn_HALT_FLUSH |
DEV_ACTION_EP0_FLUSH |
DEV_ACTION_EP0_DEQUEUE |
DEV_ACTION_PROP_GONE_EVT);
}
USBH_EXIT_CRITICAL();
break;
}
case USBH_HUB_EVENT_PORT_DISABLED: {
USBH_ENTER_CRITICAL();
assert(dev_obj->dynamic.ref_count == 0); //At this stage, the device should have been closed by all users
case USBH_HUB_EVENT_PORT_ERROR: {
USBH_ENTER_CRITICAL();
dev_obj->dynamic.flags.is_gone = 1;
// Check if the device can be freed now
if (dev_obj->dynamic.ref_count == 0) {
dev_obj->dynamic.flags.waiting_free = 1;
call_proc_req_cb = _dev_set_actions(dev_obj, DEV_ACTION_FREE);
USBH_EXIT_CRITICAL();
break;
// Device is already waiting free so none of it's EP's will be in use. Can free immediately.
call_proc_req_cb = _dev_set_actions(dev_obj, DEV_ACTION_FREE_AND_RECOVER); // Port error occurred so we need to recover it
} else {
call_proc_req_cb = _dev_set_actions(dev_obj,
DEV_ACTION_EPn_HALT_FLUSH |
DEV_ACTION_EP0_FLUSH |
DEV_ACTION_EP0_DEQUEUE |
DEV_ACTION_PROP_GONE_EVT);
}
default:
return ESP_ERR_INVALID_ARG;
USBH_EXIT_CRITICAL();
break;
}
case USBH_HUB_EVENT_PORT_DISABLED: {
USBH_ENTER_CRITICAL();
assert(dev_obj->dynamic.ref_count == 0); // At this stage, the device should have been closed by all users
dev_obj->dynamic.flags.waiting_free = 1;
call_proc_req_cb = _dev_set_actions(dev_obj, DEV_ACTION_FREE);
USBH_EXIT_CRITICAL();
break;
}
default:
return ESP_ERR_INVALID_ARG;
}
if (call_proc_req_cb) {
@ -1208,7 +1208,7 @@ esp_err_t usbh_hub_enum_fill_dev_addr(usb_device_handle_t dev_hdl, uint8_t dev_a
dev_obj->dynamic.state = USB_DEVICE_STATE_ADDRESS;
USBH_EXIT_CRITICAL();
//We can modify the info members outside the critical section
// We can modify the info members outside the critical section
dev_obj->constant.address = dev_addr;
return ESP_OK;
}
@ -1217,7 +1217,7 @@ esp_err_t usbh_hub_enum_fill_dev_desc(usb_device_handle_t dev_hdl, const usb_dev
{
USBH_CHECK(dev_hdl != NULL && device_desc != NULL, ESP_ERR_INVALID_ARG);
device_t *dev_obj = (device_t *)dev_hdl;
//We can modify the info members outside the critical section
// We can modify the info members outside the critical section
memcpy((usb_device_desc_t *)dev_obj->constant.desc, device_desc, sizeof(usb_device_desc_t));
return ESP_OK;
}
@ -1226,14 +1226,14 @@ esp_err_t usbh_hub_enum_fill_config_desc(usb_device_handle_t dev_hdl, const usb_
{
USBH_CHECK(dev_hdl != NULL && config_desc_full != NULL, ESP_ERR_INVALID_ARG);
device_t *dev_obj = (device_t *)dev_hdl;
//Allocate memory to store the configuration descriptor
usb_config_desc_t *config_desc = heap_caps_malloc(config_desc_full->wTotalLength, MALLOC_CAP_DEFAULT); //Buffer to copy over full configuration descriptor (wTotalLength)
// Allocate memory to store the configuration descriptor
usb_config_desc_t *config_desc = heap_caps_malloc(config_desc_full->wTotalLength, MALLOC_CAP_DEFAULT); // Buffer to copy over full configuration descriptor (wTotalLength)
if (config_desc == NULL) {
return ESP_ERR_NO_MEM;
}
//Copy the configuration descriptor
// Copy the configuration descriptor
memcpy(config_desc, config_desc_full, config_desc_full->wTotalLength);
//Assign the config desc to the device object
// Assign the config desc to the device object
assert(dev_obj->constant.config_desc == NULL);
dev_obj->constant.config_desc = config_desc;
return ESP_OK;
@ -1243,27 +1243,27 @@ esp_err_t usbh_hub_enum_fill_str_desc(usb_device_handle_t dev_hdl, const usb_str
{
USBH_CHECK(dev_hdl != NULL && str_desc != NULL && (select >= 0 && select < 3), ESP_ERR_INVALID_ARG);
device_t *dev_obj = (device_t *)dev_hdl;
//Allocate memory to store the manufacturer string descriptor
// Allocate memory to store the manufacturer string descriptor
usb_str_desc_t *str_desc_fill = heap_caps_malloc(str_desc->bLength, MALLOC_CAP_DEFAULT);
if (str_desc_fill == NULL) {
return ESP_ERR_NO_MEM;
}
//Copy the string descriptor
// Copy the string descriptor
memcpy(str_desc_fill, str_desc, str_desc->bLength);
//Assign filled string descriptor to the device object
// Assign filled string descriptor to the device object
switch (select) {
case 0:
assert(dev_obj->constant.str_desc_manu == NULL);
dev_obj->constant.str_desc_manu = str_desc_fill;
break;
case 1:
assert(dev_obj->constant.str_desc_product == NULL);
dev_obj->constant.str_desc_product = str_desc_fill;
break;
default: //2
assert(dev_obj->constant.str_desc_ser_num == NULL);
dev_obj->constant.str_desc_ser_num = str_desc_fill;
break;
case 0:
assert(dev_obj->constant.str_desc_manu == NULL);
dev_obj->constant.str_desc_manu = str_desc_fill;
break;
case 1:
assert(dev_obj->constant.str_desc_product == NULL);
dev_obj->constant.str_desc_product = str_desc_fill;
break;
default: // 2
assert(dev_obj->constant.str_desc_ser_num == NULL);
dev_obj->constant.str_desc_ser_num = str_desc_fill;
break;
}
return ESP_OK;
}
@ -1273,20 +1273,20 @@ esp_err_t usbh_hub_enum_done(usb_device_handle_t dev_hdl)
USBH_CHECK(dev_hdl != NULL, ESP_ERR_INVALID_ARG);
device_t *dev_obj = (device_t *)dev_hdl;
//We need to take the mux_lock to access mux_protected members
// We need to take the mux_lock to access mux_protected members
xSemaphoreTake(p_usbh_obj->constant.mux_lock, portMAX_DELAY);
USBH_ENTER_CRITICAL();
dev_obj->dynamic.state = USB_DEVICE_STATE_CONFIGURED;
//Add the device to list of devices, then trigger a device event
TAILQ_INSERT_TAIL(&p_usbh_obj->dynamic.devs_idle_tailq, dev_obj, dynamic.tailq_entry); //Add it to the idle device list first
// Add the device to list of devices, then trigger a device event
TAILQ_INSERT_TAIL(&p_usbh_obj->dynamic.devs_idle_tailq, dev_obj, dynamic.tailq_entry); // Add it to the idle device list first
bool call_proc_req_cb = _dev_set_actions(dev_obj, DEV_ACTION_PROP_NEW);
USBH_EXIT_CRITICAL();
p_usbh_obj->mux_protected.num_device++;
xSemaphoreGive(p_usbh_obj->constant.mux_lock);
//Update the EP0's underlying pipe's callback
// Update the EP0's underlying pipe's callback
ESP_ERROR_CHECK(hcd_pipe_update_callback(dev_obj->constant.default_pipe, ep0_pipe_callback, (void *)dev_obj));
//Call the processing request callback
// Call the processing request callback
if (call_proc_req_cb) {
p_usbh_obj->constant.proc_req_cb(USB_PROC_REQ_SOURCE_USBH, false, p_usbh_obj->constant.proc_req_cb_arg);
}