mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
usb_host: Run formatting script
This commit is contained in:
parent
1ffbbf5aef
commit
cbed197e10
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -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 */
|
||||
|
@ -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 -------------
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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 --------------------------
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user