Esp32 s3 support (#6341)

Co-authored-by: Jason2866 <24528715+Jason2866@users.noreply.github.com>
Co-authored-by: Unexpected Maker <seon@unexpectedmaker.com>
Co-authored-by: Rodrigo Garcia <rodrigo.garcia@espressif.com>
Co-authored-by: Tomáš Pilný <34927466+PilnyTomas@users.noreply.github.com>
Co-authored-by: Pedro Minatel <pedro.minatel@espressif.com>
Co-authored-by: Ivan Grokhotkov <ivan@espressif.com>
Co-authored-by: Jan Procházka <90197375+P-R-O-C-H-Y@users.noreply.github.com>
Co-authored-by: Limor "Ladyada" Fried <limor@ladyada.net>
This commit is contained in:
Me No Dev
2022-03-28 12:09:41 +03:00
committed by GitHub
parent 3f79097d5f
commit 8ee5f0a11e
3774 changed files with 685773 additions and 19284 deletions

View File

@ -0,0 +1,144 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "soc/soc_caps.h"
#include "hal/usb_phy_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief USB PHY status
*/
typedef enum {
USB_PHY_STATUS_FREE, /**< PHY is not being used */
USB_PHY_STATUS_IN_USE, /**< PHY is in use */
} usb_phy_status_t;
/**
* @brief USB PHY available actions
*/
typedef enum {
USB_PHY_ACTION_HOST_ALLOW_CONN, /**< Enable physical connection when operating as an OTG Host */
USB_PHY_ACTION_HOST_FORCE_DISCONN, /**< Disable physical connection when operating as an OTG Host */
USB_PHY_ACTION_MAX,
} usb_phy_action_t;
/**
* @brief USB external PHY iopins configure struct
*/
typedef struct {
int vp_io_num; /**< GPIO pin to USB_EXTPHY_VP_IDX */
int vm_io_num; /**< GPIO pin to USB_EXTPHY_VM_IDX */
int rcv_io_num; /**< GPIO pin to USB_EXTPHY_RCV_IDX */
int oen_io_num; /**< GPIO pin to USB_EXTPHY_OEN_IDX */
int vpo_io_num; /**< GPIO pin to USB_EXTPHY_VPO_IDX */
int vmo_io_num; /**< GPIO pin to USB_EXTPHY_VMO_IDX */
} usb_phy_gpio_conf_t;
/**
* @brief USB PHY configure struct
*
* At minimum the PHY controller and PHY target must be initialized.
*/
typedef struct {
usb_phy_controller_t controller; /**< USB PHY controller */
usb_phy_target_t target; /**< USB PHY target INT/EXT */
usb_otg_mode_t otg_mode; /**< USB OTG mode */
usb_phy_speed_t otg_speed; /**< USB OTG speed */
usb_phy_gpio_conf_t *gpio_conf; /**< USB external PHY iopins configure */
} usb_phy_config_t;
typedef struct phy_context_t *usb_phy_handle_t; /**< USB PHY context handle */
/**
* @brief Initialize a new USB PHY
* Configure at least PHY source.
*
* This function will enable the OTG Controller
*
* @param[in] config USB PHY configurtion struct
* @param[out] handle_ret USB PHY context handle
*
* @return
* - ESP_OK Success
* - ESP_FAIL USB PHY init error.
* - ESP_ERR_INVALID_STATE USB PHY not installed.
* - ESP_ERR_NO_MEM USB_OTG installation failed due to no mem.
*/
esp_err_t usb_new_phy(const usb_phy_config_t *config, usb_phy_handle_t *handle_ret);
/**
* @brief Configure OTG mode for a USB PHY
*
* @param handle Pointer of USB PHY context handle
* @param mode USB OTG mode
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error.
* - ESP_FAIL OTG set mode fail.
*/
esp_err_t usb_phy_otg_set_mode(usb_phy_handle_t handle, usb_otg_mode_t mode);
/**
* @brief Configure USB speed for a USB PHY that is operating as an OTG Device
*
* @param handle Pointer of USB PHY context handle
* @param mode USB speed
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error.
* - ESP_FAIL OTG set speed fail.
*/
esp_err_t usb_phy_otg_dev_set_speed(usb_phy_handle_t handle, usb_phy_speed_t speed);
/**
* @brief Take a action for a USB PHY
*
* @param handle Pointer of USB PHY context handle
* @param action USB PHY action
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error.
* - ESP_FAIL Action cannot be performed.
*/
esp_err_t usb_phy_action(usb_phy_handle_t handle, usb_phy_action_t action);
/**
* @brief Delete a USB PHY
*
* @param handle Pointer of USB PHY context handle
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error.
*/
esp_err_t usb_del_phy(usb_phy_handle_t handle);
/**
* @brief Get status of a USB PHY
*
* @param[in] target The specific PHY target to check
* @param[out] status Status of the PHY
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Parameter error.
* - ESP_ERR_INVALID_STATE USB PHY not installed.
*/
esp_err_t usb_phy_get_phy_status(usb_phy_target_t target, usb_phy_status_t *status);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,176 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
Warning: The USB Host Library API is still a beta version and may be subject to change
*/
#pragma once
#include <stdint.h>
#include "esp_err.h"
#include "usb/usb_types_stack.h"
#include "usb/usb_types_ch9.h"
#ifdef __cplusplus
extern "C" {
#endif
// ---------------------------------------- Configuration Descriptor Parsing -------------------------------------------
/**
* @brief Get the next descriptor
*
* Given a particular descriptor within a full configuration descriptor, get the next descriptor within the
* configuration descriptor. This is a convenience function that can be used to walk each individual descriptor within
* a full configuration descriptor.
*
* @param[in] cur_desc Current descriptor
* @param[in] wTotalLength Total length of the configuration descriptor
* @param[inout] offset Byte offset relative to the start of the configuration descriptor. On input, it is the offset of
* the current descriptor. On output, it is the offset of the returned descriptor.
* @return usb_standard_desc_t* Next descriptor, NULL if end of configuration descriptor reached
*/
const usb_standard_desc_t *usb_parse_next_descriptor(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, int *offset);
/**
* @brief Get the next descriptor of a particular type
*
* Given a particular descriptor within a full configuration descriptor, get the next descriptor of a particular type
* (i.e., using the bDescriptorType value) within the configuration descriptor.
*
* @param[in] cur_desc Current descriptor
* @param[in] wTotalLength Total length of the configuration descriptor
* @param[in] bDescriptorType Type of the next descriptor to get
* @param[inout] offset Byte offset relative to the start of the configuration descriptor. On input, it is the offset of
* the current descriptor. On output, it is the offset of the returned descriptor.
* @return usb_standard_desc_t* Next descriptor, NULL if end descriptor is not found or configuration descriptor reached
*/
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);
/**
* @brief Get the number of alternate settings for a bInterfaceNumber
*
* Given a particular configuration descriptor, for a particular bInterfaceNumber, get the number of alternate settings
* available for that interface (i.e., the max possible value of bAlternateSetting for that bInterfaceNumber).
*
* @param[in] config_desc Pointer to the start of a full configuration descriptor
* @param[in] bInterfaceNumber Interface number
* @return int The number of alternate settings that the interface has, -1 if bInterfaceNumber not found
*/
int usb_parse_interface_number_of_alternate(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber);
/**
* @brief Get a particular interface descriptor (using bInterfaceNumber and bAlternateSetting)
*
* Given a full configuration descriptor, get a particular interface descriptor.
*
* @note To get the number of alternate settings for a particular bInterfaceNumber, call
* usb_parse_interface_number_of_alternate()
*
* @param[in] config_desc Pointer to the start of a full configuration descriptor
* @param[in] bInterfaceNumber Interface number
* @param[in] bAlternateSetting Alternate setting number
* @param[out] offset Byte offset of the interface descriptor relative to the start of the configuration descriptor. Can be NULL.
* @return const usb_intf_desc_t* Pointer to interface descriptor, NULL if not found.
*/
const usb_intf_desc_t *usb_parse_interface_descriptor(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, int *offset);
/**
* @brief Get an endpoint descriptor within an interface descriptor
*
* Given an interface descriptor, get the Nth endpoint descriptor of the interface. The number of endpoints in an
* interface is indicated by the bNumEndpoints field of the interface descriptor.
*
* @note If bNumEndpoints is 0, it means the interface uses the default endpoint only
*
* @param[in] intf_desc Pointer to thee start of an interface descriptor
* @param[in] index Endpoint index
* @param[in] wTotalLength Total length of the containing configuration descriptor
* @param[inout] offset Byte offset relative to the start of the configuration descriptor. On input, it is the offset
* of the interface descriptor. On output, it is the offset of the endpoint descriptor.
* @return const usb_ep_desc_t* Pointer to endpoint descriptor, NULL if not found.
*/
const usb_ep_desc_t *usb_parse_endpoint_descriptor_by_index(const usb_intf_desc_t *intf_desc, int index, uint16_t wTotalLength, int *offset);
/**
* @brief Get an endpoint descriptor based on an endpoint's address
*
* Given a configuration descriptor, get an endpoint descriptor based on it's bEndpointAddress, bAlternateSetting, and
* bInterfaceNumber.
*
* @param[in] config_desc Pointer to the start of a full configuration descriptor
* @param[in] bInterfaceNumber Interface number
* @param[in] bAlternateSetting Alternate setting number
* @param[in] bEndpointAddress Endpoint address
* @param[out] offset Byte offset of the endpoint descriptor relative to the start of the configuration descriptor. Can be NULL
* @return const usb_ep_desc_t* Pointer to endpoint descriptor, NULL if not found.
*/
const usb_ep_desc_t *usb_parse_endpoint_descriptor_by_address(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, uint8_t bEndpointAddress, int *offset);
// ----------------------------------------------- Descriptor Printing -------------------------------------------------
/**
* @brief Print class specific descriptor callback
*
* Optional callback to be provided to usb_print_config_descriptor() function.
* The callback is called when when a non-standard descriptor is encountered.
* The callback should decode the descriptor as print it.
*/
typedef void (*print_class_descriptor_cb)(const usb_standard_desc_t *);
/**
* @brief Print device descriptor
*
* @param devc_desc Device descriptor
*/
void usb_print_device_descriptor(const usb_device_desc_t *devc_desc);
/**
* @brief Print configuration descriptor
*
* - This function prints the full contents of a configuration descriptor (including interface and endpoint descriptors)
* - When a non-standard descriptor is encountered, this function will call the class_specific_cb if it is provided
*
* @param cfg_desc Configuration descriptor
* @param class_specific_cb Class specific descriptor callback. Can be NULL
*/
void usb_print_config_descriptor(const usb_config_desc_t *cfg_desc, print_class_descriptor_cb class_specific_cb);
/**
* @brief Print a string descriptor
*
* This funciton will only print ASCII characters of the UTF-16 encoded string
*
* @param str_desc String descriptor
*/
void usb_print_string_descriptor(const usb_str_desc_t *str_desc);
// ------------------------------------------------------ Misc ---------------------------------------------------------
/**
* @brief Round up to an integer multiple of endpoint's MPS
*
* This is a convenience function to round up a size/length to an endpoint's MPS (Maximum packet size). This is useful
* when calculating transfer or buffer lengths of IN endpoints.
* - If MPS <= 0, this function will return 0
* - If num_bytes <= 0, this function will return 0
*
* @param[in] num_bytes Number of bytes
* @param[in] mps MPS
* @return int Round up integer multiple of MPS
*/
static inline int usb_round_up_to_mps(int num_bytes, int mps)
{
if (num_bytes <= 0 || mps <= 0) { //MPS can never be zero
return 0;
}
return ((num_bytes + mps - 1) / mps) * mps;
}
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,479 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
Warning: The USB Host Library API is still a beta version and may be subject to change
*/
#pragma once
#include <stdint.h>
#include "freertos/FreeRTOS.h"
#include "esp_err.h"
#include "esp_intr_alloc.h"
//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"
#ifdef __cplusplus
extern "C" {
#endif
// ------------------------------------------------- Macros and Types --------------------------------------------------
// ----------------------- Handles -------------------------
/**
* @brief Handle to a USB Host Library asynchronous client
*
* An asynchronous client can be registered using usb_host_client_register()
*
* @note Asynchronous API
*/
typedef struct usb_host_client_handle_s * usb_host_client_handle_t;
// ----------------------- Events --------------------------
#define USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS 0x01 /**< All clients have been deregistered from the USB Host Library */
#define USB_HOST_LIB_EVENT_FLAGS_ALL_FREE 0x02 /**< The USB Host Library has freed all devices */
/**
* @brief The type event in a client event message
*/
typedef enum {
USB_HOST_CLIENT_EVENT_NEW_DEV, /**< A new device has been enumerated and added to the USB Host Library */
USB_HOST_CLIENT_EVENT_DEV_GONE, /**< A device opened by the client is now gone */
} usb_host_client_event_t;
/**
* @brief Client event message
*
* Client event messages are sent to each client of the USB Host Library in order to notify them of various
* USB Host Library events such as:
* - Addition of new devices
* - Removal of existing devices
*
* @note The event message structure has a union with members corresponding to each particular event. Based on the event
* type, only the relevant member field should be accessed.
*/
typedef struct {
usb_host_client_event_t event; /**< Type of event */
union {
struct {
uint8_t address; /**< New device's address */
} new_dev;
struct {
usb_device_handle_t dev_hdl; /**< The handle of the device that was gone */
} dev_gone;
};
} usb_host_client_event_msg_t;
// ------------------------ Info ---------------------------
/**
* @brief Current information about the USB Host Library obtained via usb_host_lib_info()
*/
typedef struct {
int num_devices; /**< Current number of connected (and enumerated) devices */
int num_clients; /**< Current number of registered clients */
} usb_host_lib_info_t;
// ---------------------- Callbacks ------------------------
/**
* @brief Client event callback
*
* - Each client of the USB Host Library must register an event callback to receive event messages from the USB Host
* Library.
* - The client event callback is run from the context of the clients usb_host_client_handle_events() function
*/
typedef void (*usb_host_client_event_cb_t)(const usb_host_client_event_msg_t *event_msg, void *arg);
// -------------------- Configurations ---------------------
/**
* @brief USB Host Library configuration
*
* Configuration structure of the USB Host Library. Provided in the usb_host_install() function
*/
typedef struct {
bool skip_phy_setup; /**< If set, the USB Host Library will not configure the USB PHY thus allowing the user
to manually configure the USB PHY before calling usb_host_install(). Users should
set this if they want to use an external USB PHY. Otherwise, the USB Host Library
will automatically configure the internal USB PHY */
int intr_flags; /**< Interrupt flags for the underlying ISR used by the USB Host stack */
} usb_host_config_t;
/**
* @brief USB Host Library Client configuration
*
* Configuration structure for a USB Host Library client. Provided in usb_host_client_register()
*/
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
struct {
usb_host_client_event_cb_t client_event_callback; /**< Client's event callback function */
void *callback_arg; /**< Event callback function argument */
} async;
};
} usb_host_client_config_t;
// ------------------------------------------------ Library Functions --------------------------------------------------
/**
* @brief Install the USB Host Library
*
* - This function should only once to install the USB Host Library
* - This function should be called before any other USB Host Library functions are called
*
* @note If skip_phy_setup is set in the install configuration, the user is responsible for ensuring that the underlying
* Host Controller is enabled and the USB PHY (internal or external) is already setup before this function is
* called.
* @param[in] config USB Host Library configuration
* @return esp_err_t
*/
esp_err_t usb_host_install(const usb_host_config_t *config);
/**
* @brief Uninstall the USB Host Library
*
* - This function should be called to uninstall the USB Host Library, thereby freeing its resources
* - All clients must have been deregistered before calling this function
* - All devices must have been freed by calling usb_host_device_free_all() and receiving the
* USB_HOST_LIB_EVENT_FLAGS_ALL_FREE event flag
*
* @note If skip_phy_setup was set when the Host Library was installed, the user is responsible for disabling the
* underlying Host Controller and USB PHY (internal or external).
* @return esp_err_t
*/
esp_err_t usb_host_uninstall(void);
/**
* @brief Handle USB Host Library events
*
* - This function handles all of the USB Host Library's processing and should be called repeatedly in a loop
* - Check event_flags_ret to see if an flags are set indicating particular USB Host Library events
* - This function should never be called by multiple threads simultaneously
*
* @note This function can block
* @param[in] timeout_ticks Timeout in ticks to wait for an event to occur
* @param[out] event_flags_ret Event flags that indicate what USB Host Library event occurred.
* @return esp_err_t
*/
esp_err_t usb_host_lib_handle_events(TickType_t timeout_ticks, uint32_t *event_flags_ret);
/**
* @brief Unblock the USB Host Library handler
*
* - This function simply unblocks the USB Host Library event handling function (usb_host_lib_handle_events())
*
* @return esp_err_t
*/
esp_err_t usb_host_lib_unblock(void);
/**
* @brief Get current information about the USB Host Library
*
* @param[out] info_ret USB Host Library Information
* @return esp_err_t
*/
esp_err_t usb_host_lib_info(usb_host_lib_info_t *info_ret);
// ------------------------------------------------ Client Functions ---------------------------------------------------
/**
* @brief Register a client of the USB Host Library
*
* - This function registers a client of the USB Host Library
* - Once a client is registered, its processing function usb_host_client_handle_events() should be called repeatedly
*
* @param[in] client_config Client configuration
* @param[out] client_hdl_ret Client handle
* @return esp_err_t
*/
esp_err_t usb_host_client_register(const usb_host_client_config_t *client_config, usb_host_client_handle_t *client_hdl_ret);
/**
* @brief Deregister a USB Host Library client
*
* - This function deregisters a client of the USB Host Library
* - The client must have closed all previously opened devices before attempting to deregister
*
* @param[in] client_hdl Client handle
* @return esp_err_t
*/
esp_err_t usb_host_client_deregister(usb_host_client_handle_t client_hdl);
/**
* @brief USB Host Library client processing function
*
* - This function handles all of a client's processing and should be called repeatedly in a loop
* - For a particular client, this function should never be called by multiple threads simultaneously
*
* @note This function can block
* @param[in] client_hdl Client handle
* @param[in] timeout_ticks Timeout in ticks to wait for an event to occur
* @return esp_err_t
*/
esp_err_t usb_host_client_handle_events(usb_host_client_handle_t client_hdl, TickType_t timeout_ticks);
/**
* @brief Unblock a client
*
* - This function simply unblocks a client if it is blocked on the usb_host_client_handle_events() function.
* - This function is useful when need to unblock a client in order to deregister it.
*
* @param[in] client_hdl Client handle
* @return esp_err_t
*/
esp_err_t usb_host_client_unblock(usb_host_client_handle_t client_hdl);
// ------------------------------------------------- Device Handling ---------------------------------------------------
/**
* @brief Open a device
*
* - This function allows a client to open a device
* - A client must open a device first before attempting to use it (e.g., sending transfers, device requests etc.)
*
* @param[in] client_hdl Client handle
* @param[in] dev_addr Device's address
* @param[out] dev_hdl_ret Device's handle
* @return esp_err_t
*/
esp_err_t usb_host_device_open(usb_host_client_handle_t client_hdl, uint8_t dev_addr, usb_device_handle_t *dev_hdl_ret);
/**
* @brief Close a device
*
* - This function allows a client to close a device
* - A client must close a device after it has finished using the device (claimed interfaces must also be released)
* - A client must close all devices it has opened before deregistering
*
* @note This function can block
* @param[in] client_hdl Client handle
* @param[in] dev_hdl Device handle
* @return esp_err_t
*/
esp_err_t usb_host_device_close(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl);
/**
* @brief Indicate that all devices can be freed when possible
*
* - This function marks all devices as waiting to be freed
* - If a device is not opened by any clients, it will be freed immediately
* - If a device is opened by at least one client, the device will be free when the last client closes that device.
* - Wait for the USB_HOST_LIB_EVENT_FLAGS_ALL_FREE flag to be set by usb_host_lib_handle_events() in order to know
* when all devices have been freed
* - This function is useful when cleaning up devices before uninstalling the USB Host Library
*
* @return
* - ESP_ERR_NOT_FINISHED: There are one or more devices that still need to be freed. Wait for USB_HOST_LIB_EVENT_FLAGS_ALL_FREE event
* - ESP_OK: All devices already freed (i.e., there were no devices)
* - Other: Error
*/
esp_err_t usb_host_device_free_all(void);
/**
* @brief Fill a list of device address
*
* - This function fills an empty list with the address of connected devices
* - The Device addresses can then used in usb_host_device_open()
* - If there are more devices than the list_len, this function will only fill up to list_len number of devices.
*
* @param[in] list_len Length of the empty list
* @param[inout] dev_addr_list Empty list to be filled
* @param[out] num_dev_ret Number of devices
* @return esp_err_t
*/
esp_err_t usb_host_device_addr_list_fill(int list_len, uint8_t *dev_addr_list, int *num_dev_ret);
// ------------------------------------------------- Device Requests ---------------------------------------------------
// ------------------- Cached Requests ---------------------
/**
* @brief Get device's information
*
* - This function gets some basic information of a device
* - The device must be opened first before attempting to get its information
*
* @note This function can block
* @param[in] dev_hdl Device handle
* @param[out] dev_info Device information
* @return esp_err_t
*/
esp_err_t usb_host_device_info(usb_device_handle_t dev_hdl, usb_device_info_t *dev_info);
// ----------------------------------------------- Descriptor Requests -------------------------------------------------
// ----------------- Cached Descriptors --------------------
/**
* @brief Get device's device descriptor
*
* - A client must call usb_host_device_open() first
* - No control transfer is sent. The device's descriptor is cached on enumeration
* - This function simple returns a pointer to the cached descriptor
*
* @note No control transfer is sent. The device's descriptor is cached on enumeration
* @param[in] dev_hdl Device handle
* @param[out] device_desc Device descriptor
* @return esp_err_t
*/
esp_err_t usb_host_get_device_descriptor(usb_device_handle_t dev_hdl, const usb_device_desc_t **device_desc);
/**
* @brief Get device's active configuration descriptor
*
* - A client must call usb_host_device_open() first
* - No control transfer is sent. The device's active configuration descriptor is cached on enumeration
* - This function simple returns a pointer to the cached descriptor
*
* @note This function can block
* @note No control transfer is sent. A device's active configuration descriptor is cached on enumeration
* @param[in] dev_hdl Device handle
* @param[out] config_desc Configuration descriptor
* @return esp_err_t
*/
esp_err_t usb_host_get_active_config_descriptor(usb_device_handle_t dev_hdl, const usb_config_desc_t **config_desc);
// ----------------------------------------------- Interface Functions -------------------------------------------------
/**
* @brief Function for a client to claim a device's interface
*
* - A client must claim a device's interface before attempting to communicate with any of its endpoints
* - Once an interface is claimed by a client, it cannot be claimed by any other client.
*
* @note This function can block
* @param[in] client_hdl Client handle
* @param[in] dev_hdl Device handle
* @param[in] bInterfaceNumber Interface number
* @param[in] bAlternateSetting Interface alternate setting number
* @return esp_err_t
*/
esp_err_t usb_host_interface_claim(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl, uint8_t bInterfaceNumber, uint8_t bAlternateSetting);
/**
* @brief Function for a client to release a previously claimed interface
*
* - A client should release a device's interface after it no longer needs to communicate with the interface
* - A client must release all of its interfaces of a device it has claimed before being able to close the device
*
* @note This function can block
* @param[in] client_hdl Client handle
* @param[in] dev_hdl Device handle
* @param[in] bInterfaceNumber Interface number
* @return esp_err_t
*/
esp_err_t usb_host_interface_release(usb_host_client_handle_t client_hdl, usb_device_handle_t dev_hdl, uint8_t bInterfaceNumber);
/**
* @brief Halt a particular endpoint
*
* - The device must have been opened by a client
* - The endpoint must be part of an interface claimed by a client
* - Once halted, the endpoint must be cleared using usb_host_endpoint_clear() before it can communicate again
*
* @note This function can block
* @param dev_hdl Device handle
* @param bEndpointAddress Endpoint address
* @return esp_err_t
*/
esp_err_t usb_host_endpoint_halt(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress);
/**
* @brief Flush a particular endpoint
*
* - The device must have been opened by a client
* - The endpoint must be part of an interface claimed by a client
* - The endpoint must have been halted (either through a transfer error, or usb_host_endpoint_halt())
* - Flushing an endpoint will caused an queued up transfers to be canceled
*
* @note This function can block
* @param dev_hdl Device handle
* @param bEndpointAddress Endpoint address
* @return esp_err_t
*/
esp_err_t usb_host_endpoint_flush(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress);
/**
* @brief Clear a halt on a particular endpoint
*
* - The device must have been opened by a client
* - The endpoint must be part of an interface claimed by a client
* - The endpoint must have been halted (either through a transfer error, or usb_host_endpoint_halt())
* - If the endpoint has any queued up transfers, clearing a halt will resume their execution
*
* @note This function can block
* @param dev_hdl Device handle
* @param bEndpointAddress Endpoint address
* @return esp_err_t
*/
esp_err_t usb_host_endpoint_clear(usb_device_handle_t dev_hdl, uint8_t bEndpointAddress);
// ------------------------------------------------ Asynchronous I/O ---------------------------------------------------
/**
* @brief Allocate a transfer object
*
* - This function allocates a transfer object
* - Each transfer object has a fixed sized buffer specified on allocation
* - A transfer object can be re-used indefinitely
* - A transfer can be submitted using usb_host_transfer_submit() or usb_host_transfer_submit_control()
*
* @param[in] data_buffer_size Size of the transfer's data buffer
* @param[in] num_isoc_packets Number of isochronous packets in transfer (set to 0 for non-isochronous transfers)
* @param[out] transfer Transfer object
* @return esp_err_t
*/
esp_err_t usb_host_transfer_alloc(size_t data_buffer_size, int num_isoc_packets, usb_transfer_t **transfer);
/**
* @brief Free a transfer object
*
* - Free a transfer object previously allocated using usb_host_transfer_alloc()
* - The transfer must not be in-flight when attempting to free it
* - If a NULL pointer is passed, this function will simply return ESP_OK
*
* @param[in] transfer Transfer object
* @return esp_err_t
*/
esp_err_t usb_host_transfer_free(usb_transfer_t *transfer);
/**
* @brief Submit a non-control transfer
*
* - Submit a transfer to a particular endpoint. The device and endpoint number is specified inside the transfer
* - The transfer must be properly initialized before submitting
* - On completion, the transfer's callback will be called from the client's usb_host_client_handle_events() function.
*
* @param[in] transfer Initialized transfer object
* @return esp_err_t
*/
esp_err_t usb_host_transfer_submit(usb_transfer_t *transfer);
/**
* @brief Submit a control transfer
*
* - Submit a control transfer to a particular device. The client must have opened the device first
* - The transfer must be properly initialized before submitting. The first 8 bytes of the transfer's data buffer should
* contain the control transfer setup packet
* - On completion, the transfer's callback will be called from the client's usb_host_client_handle_events() function.
*
* @param[in] client_hdl Client handle
* @param[in] transfer Initialized transfer object
* @return esp_err_t
*/
esp_err_t usb_host_transfer_submit_control(usb_host_client_handle_t client_hdl, usb_transfer_t *transfer);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,485 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
Warning: The USB Host Library API is still a beta version and may be subject to change
*/
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C"
{
#endif
#define USB_DESC_ATTR __attribute__((packed))
// ---------------------------------------------------- Chapter 9 ------------------------------------------------------
/**
* @brief USB2.0 device states
*
* See Table 9-1 of USB2.0 specification for more details
*
* @note The USB_DEVICE_STATE_NOT_ATTACHED is not part of the USB2.0 specification, but is a catch all state for devices
* that need to be cleaned up after a sudden disconnection or port error.
*/
typedef enum {
USB_DEVICE_STATE_NOT_ATTACHED, /**< The device was previously configured or suspended, but is no longer attached (either suddenly disconnected or a port error) */
USB_DEVICE_STATE_ATTACHED, /**< Device is attached to the USB, but is not powered. */
USB_DEVICE_STATE_POWERED, /**< Device is attached to the USB and powered, but has not been reset. */
USB_DEVICE_STATE_DEFAULT, /**< Device is attached to the USB and powered and has been reset, but has not been assigned a unique address. Device responds at the default address. */
USB_DEVICE_STATE_ADDRESS, /**< Device is attached to the USB, powered, has been reset, and a unique device address has been assigned. Device is not configured. */
USB_DEVICE_STATE_CONFIGURED, /**< Device is attached to the USB, powered, has been reset, has a unique address, is configured, and is not suspended. The host may now use the function provided by the device. */
USB_DEVICE_STATE_SUSPENDED, /**< Device is, at minimum, attached to the USB and is powered and has not seen bus activity for 3 ms. It may also have a unique address and be configured for use. However, because the device is suspended, the host may not use the devices function. */
} usb_device_state_t;
/**
* @brief Descriptor types from USB2.0 specification table 9.5
*/
#define USB_B_DESCRIPTOR_TYPE_DEVICE 0x01
#define USB_B_DESCRIPTOR_TYPE_CONFIGURATION 0x02
#define USB_B_DESCRIPTOR_TYPE_STRING 0x03
#define USB_B_DESCRIPTOR_TYPE_INTERFACE 0x04
#define USB_B_DESCRIPTOR_TYPE_ENDPOINT 0x05
#define USB_B_DESCRIPTOR_TYPE_DEVICE_QUALIFIER 0x06
#define USB_B_DESCRIPTOR_TYPE_OTHER_SPEED_CONFIGURATION 0x07
#define USB_B_DESCRIPTOR_TYPE_INTERFACE_POWER 0x08
/**
* @brief Descriptor types from USB 2.0 ECN
*/
#define USB_B_DESCRIPTOR_TYPE_OTG 0x09
#define USB_B_DESCRIPTOR_TYPE_DEBUG 0x0a
#define USB_B_DESCRIPTOR_TYPE_INTERFACE_ASSOCIATION 0x0b
/**
* @brief Descriptor types from Wireless USB spec
*/
#define USB_B_DESCRIPTOR_TYPE_SECURITY 0x0c
#define USB_B_DESCRIPTOR_TYPE_KEY 0x0d
#define USB_B_DESCRIPTOR_TYPE_ENCRYPTION_TYPE 0x0e
#define USB_B_DESCRIPTOR_TYPE_BOS 0x0f
#define USB_B_DESCRIPTOR_TYPE_DEVICE_CAPABILITY 0x10
#define USB_B_DESCRIPTOR_TYPE_WIRELESS_ENDPOINT_COMP 0x11
#define USB_B_DESCRIPTOR_TYPE_WIRE_ADAPTER 0x21
#define USB_B_DESCRIPTOR_TYPE_RPIPE 0x22
#define USB_B_DESCRIPTOR_TYPE_CS_RADIO_CONTROL 0x23
/**
* @brief Descriptor types from UAS specification
*/
#define USB_B_DESCRIPTOR_TYPE_PIPE_USAGE 0x24
// -------------------- Setup Packet -----------------------
/**
* @brief Size of a USB control transfer setup packet in bytes
*/
#define USB_SETUP_PACKET_SIZE 8
/**
* @brief Structure representing a USB control transfer setup packet
*
* See Table 9-2 of USB2.0 specification for more details
*/
typedef union {
struct {
uint8_t bmRequestType; /**< Characteristics of request */
uint8_t bRequest; /**< Specific request */
uint16_t wValue; /**< Word-sized field that varies according to request */
uint16_t wIndex; /**< Word-sized field that varies according to request; typically used to pass an index or offset */
uint16_t wLength; /**< Number of bytes to transfer if there is a data stage */
} __attribute__((packed));
uint8_t val[USB_SETUP_PACKET_SIZE];
} usb_setup_packet_t;
_Static_assert(sizeof(usb_setup_packet_t) == USB_SETUP_PACKET_SIZE, "Size of usb_setup_packet_t incorrect");
/**
* @brief Bit masks belonging to the bmRequestType field of a setup packet
*/
#define USB_BM_REQUEST_TYPE_DIR_OUT (0X00 << 7)
#define USB_BM_REQUEST_TYPE_DIR_IN (0x01 << 7)
#define USB_BM_REQUEST_TYPE_TYPE_STANDARD (0x00 << 5)
#define USB_BM_REQUEST_TYPE_TYPE_CLASS (0x01 << 5)
#define USB_BM_REQUEST_TYPE_TYPE_VENDOR (0x02 << 5)
#define USB_BM_REQUEST_TYPE_TYPE_RESERVED (0x03 << 5)
#define USB_BM_REQUEST_TYPE_TYPE_MASK (0x03 << 5)
#define USB_BM_REQUEST_TYPE_RECIP_DEVICE (0x00 << 0)
#define USB_BM_REQUEST_TYPE_RECIP_INTERFACE (0x01 << 0)
#define USB_BM_REQUEST_TYPE_RECIP_ENDPOINT (0x02 << 0)
#define USB_BM_REQUEST_TYPE_RECIP_OTHER (0x03 << 0)
#define USB_BM_REQUEST_TYPE_RECIP_MASK (0x1f << 0)
/**
* @brief Bit masks belonging to the bRequest field of a setup packet
*/
#define USB_B_REQUEST_GET_STATUS 0x00
#define USB_B_REQUEST_CLEAR_FEATURE 0x01
#define USB_B_REQUEST_SET_FEATURE 0x03
#define USB_B_REQUEST_SET_ADDRESS 0x05
#define USB_B_REQUEST_GET_DESCRIPTOR 0x06
#define USB_B_REQUEST_SET_DESCRIPTOR 0x07
#define USB_B_REQUEST_GET_CONFIGURATION 0x08
#define USB_B_REQUEST_SET_CONFIGURATION 0x09
#define USB_B_REQUEST_GET_INTERFACE 0x0A
#define USB_B_REQUEST_SET_INTERFACE 0x0B
#define USB_B_REQUEST_SYNCH_FRAME 0x0C
/**
* @brief Bit masks belonging to the wValue field of a setup packet
*/
#define USB_W_VALUE_DT_DEVICE 0x01
#define USB_W_VALUE_DT_CONFIG 0x02
#define USB_W_VALUE_DT_STRING 0x03
#define USB_W_VALUE_DT_INTERFACE 0x04
#define USB_W_VALUE_DT_ENDPOINT 0x05
#define USB_W_VALUE_DT_DEVICE_QUALIFIER 0x06
#define USB_W_VALUE_DT_OTHER_SPEED_CONFIG 0x07
#define USB_W_VALUE_DT_INTERFACE_POWER 0x08
/**
* @brief Initializer for a SET_ADDRESS request
*
* Sets the address of a connected device
*/
#define USB_SETUP_PACKET_INIT_SET_ADDR(setup_pkt_ptr, addr) ({ \
(setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_OUT | USB_BM_REQUEST_TYPE_TYPE_STANDARD |USB_BM_REQUEST_TYPE_RECIP_DEVICE; \
(setup_pkt_ptr)->bRequest = USB_B_REQUEST_SET_ADDRESS; \
(setup_pkt_ptr)->wValue = (addr); \
(setup_pkt_ptr)->wIndex = 0; \
(setup_pkt_ptr)->wLength = 0; \
})
/**
* @brief Initializer for a request to get a device's device descriptor
*/
#define USB_SETUP_PACKET_INIT_GET_DEVICE_DESC(setup_pkt_ptr) ({ \
(setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_IN | USB_BM_REQUEST_TYPE_TYPE_STANDARD | USB_BM_REQUEST_TYPE_RECIP_DEVICE; \
(setup_pkt_ptr)->bRequest = USB_B_REQUEST_GET_DESCRIPTOR; \
(setup_pkt_ptr)->wValue = (USB_W_VALUE_DT_DEVICE << 8); \
(setup_pkt_ptr)->wIndex = 0; \
(setup_pkt_ptr)->wLength = 18; \
})
/**
* @brief Initializer for a request to get a device's current configuration number
*/
#define USB_SETUP_PACKET_INIT_GET_CONFIG(setup_pkt_ptr) ({ \
(setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_IN | USB_BM_REQUEST_TYPE_TYPE_STANDARD | USB_BM_REQUEST_TYPE_RECIP_DEVICE; \
(setup_pkt_ptr)->bRequest = USB_B_REQUEST_GET_CONFIGURATION; \
(setup_pkt_ptr)->wValue = 0; \
(setup_pkt_ptr)->wIndex = 0; \
(setup_pkt_ptr)->wLength = 1; \
})
/**
* @brief Initializer for a request to get one of the device's current configuration descriptor
*
* - desc_index indicates the configuration's index number
* - Number of bytes of the configuration descriptor to get
*/
#define USB_SETUP_PACKET_INIT_GET_CONFIG_DESC(setup_pkt_ptr, desc_index, desc_len) ({ \
(setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_IN | USB_BM_REQUEST_TYPE_TYPE_STANDARD | USB_BM_REQUEST_TYPE_RECIP_DEVICE; \
(setup_pkt_ptr)->bRequest = USB_B_REQUEST_GET_DESCRIPTOR; \
(setup_pkt_ptr)->wValue = (USB_W_VALUE_DT_CONFIG << 8) | ((desc_index) & 0xFF); \
(setup_pkt_ptr)->wIndex = 0; \
(setup_pkt_ptr)->wLength = (desc_len); \
})
/**
* @brief Initializer for a request to set a device's current configuration number
*/
#define USB_SETUP_PACKET_INIT_SET_CONFIG(setup_pkt_ptr, config_num) ({ \
(setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_OUT | USB_BM_REQUEST_TYPE_TYPE_STANDARD | USB_BM_REQUEST_TYPE_RECIP_DEVICE; \
(setup_pkt_ptr)->bRequest = USB_B_REQUEST_SET_CONFIGURATION; \
(setup_pkt_ptr)->wValue = (config_num); \
(setup_pkt_ptr)->wIndex = 0; \
(setup_pkt_ptr)->wLength = 0; \
})
/**
* @brief Initializer for a request to set an interface's alternate setting
*/
#define USB_SETUP_PACKET_INIT_SET_INTERFACE(setup_pkt_ptr, intf_num, alt_setting_num) ({ \
(setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_OUT | USB_BM_REQUEST_TYPE_TYPE_STANDARD | USB_BM_REQUEST_TYPE_RECIP_INTERFACE; \
(setup_pkt_ptr)->bRequest = USB_B_REQUEST_SET_INTERFACE; \
(setup_pkt_ptr)->wValue = (alt_setting_num); \
(setup_pkt_ptr)->wIndex = (intf_num); \
(setup_pkt_ptr)->wLength = 0; \
})
/**
* @brief Initializer for a request to get an string descriptor
*/
#define USB_SETUP_PACKET_INIT_GET_STR_DESC(setup_pkt_ptr, string_index, lang_id, desc_len) ({ \
(setup_pkt_ptr)->bmRequestType = USB_BM_REQUEST_TYPE_DIR_IN | USB_BM_REQUEST_TYPE_TYPE_STANDARD | USB_BM_REQUEST_TYPE_RECIP_DEVICE; \
(setup_pkt_ptr)->bRequest = USB_B_REQUEST_GET_DESCRIPTOR; \
(setup_pkt_ptr)->wValue = (USB_W_VALUE_DT_STRING << 8) | ((string_index) & 0xFF); \
(setup_pkt_ptr)->wIndex = (lang_id); \
(setup_pkt_ptr)->wLength = (desc_len); \
})
// ---------------- Standard Descriptor --------------------
/**
* @brief Size of dummy USB standard descriptor
*/
#define USB_STANDARD_DESC_SIZE 2
/**
* @brief USB standard descriptor
*
* All USB standard descriptors start with these two bytes. Use this type when traversing over configuration descriptors
*/
typedef union {
struct {
uint8_t bLength; /**< Size of the descriptor in bytes */
uint8_t bDescriptorType; /**< Descriptor Type */
} USB_DESC_ATTR;
uint8_t val[USB_STANDARD_DESC_SIZE];
} usb_standard_desc_t;
_Static_assert(sizeof(usb_standard_desc_t) == USB_STANDARD_DESC_SIZE, "Size of usb_standard_desc_t incorrect");
// ------------------ Device Descriptor --------------------
/**
* @brief Size of a USB device descriptor in bytes
*/
#define USB_DEVICE_DESC_SIZE 18
/**
* @brief Structure representing a USB device descriptor
*
* See Table 9-8 of USB2.0 specification for more details
*/
typedef union {
struct {
uint8_t bLength; /**< Size of the descriptor in bytes */
uint8_t bDescriptorType; /**< DEVICE Descriptor Type */
uint16_t bcdUSB; /**< USB Specification Release Number in Binary-Coded Decimal (i.e., 2.10 is 210H) */
uint8_t bDeviceClass; /**< Class code (assigned by the USB-IF) */
uint8_t bDeviceSubClass; /**< Subclass code (assigned by the USB-IF) */
uint8_t bDeviceProtocol; /**< Protocol code (assigned by the USB-IF) */
uint8_t bMaxPacketSize0; /**< Maximum packet size for endpoint zero (only 8, 16, 32, or 64 are valid) */
uint16_t idVendor; /**< Vendor ID (assigned by the USB-IF) */
uint16_t idProduct; /**< Product ID (assigned by the manufacturer) */
uint16_t bcdDevice; /**< Device release number in binary-coded decimal */
uint8_t iManufacturer; /**< Index of string descriptor describing manufacturer */
uint8_t iProduct; /**< Index of string descriptor describing product */
uint8_t iSerialNumber; /**< Index of string descriptor describing the devices serial number */
uint8_t bNumConfigurations; /**< Number of possible configurations */
} USB_DESC_ATTR;
uint8_t val[USB_DEVICE_DESC_SIZE];
} usb_device_desc_t;
_Static_assert(sizeof(usb_device_desc_t) == USB_DEVICE_DESC_SIZE, "Size of usb_device_desc_t incorrect");
/**
* @brief Possible base class values of the bDeviceClass field of a USB device descriptor
*/
#define USB_CLASS_PER_INTERFACE 0x00
#define USB_CLASS_AUDIO 0x01
#define USB_CLASS_COMM 0x02
#define USB_CLASS_HID 0x03
#define USB_CLASS_PHYSICAL 0x05
#define USB_CLASS_STILL_IMAGE 0x06
#define USB_CLASS_PRINTER 0x07
#define USB_CLASS_MASS_STORAGE 0x08
#define USB_CLASS_HUB 0x09
#define USB_CLASS_CDC_DATA 0x0a
#define USB_CLASS_CSCID 0x0b
#define USB_CLASS_CONTENT_SEC 0x0d
#define USB_CLASS_VIDEO 0x0e
#define USB_CLASS_WIRELESS_CONTROLLER 0xe0
#define USB_CLASS_PERSONAL_HEALTHCARE 0x0f
#define USB_CLASS_AUDIO_VIDEO 0x10
#define USB_CLASS_BILLBOARD 0x11
#define USB_CLASS_USB_TYPE_C_BRIDGE 0x12
#define USB_CLASS_MISC 0xef
#define USB_CLASS_APP_SPEC 0xfe
#define USB_CLASS_VENDOR_SPEC 0xff
/**
* @brief Vendor specific subclass code
*/
#define USB_SUBCLASS_VENDOR_SPEC 0xff
// -------------- Configuration Descriptor -----------------
/**
* @brief Size of a short USB configuration descriptor in bytes
*
* @note The size of a full USB configuration includes all the interface and endpoint
* descriptors of that configuration.
*/
#define USB_CONFIG_DESC_SIZE 9
/**
* @brief Structure representing a short USB configuration descriptor
*
* See Table 9-10 of USB2.0 specification for more details
*
* @note The full USB configuration includes all the interface and endpoint
* descriptors of that configuration.
*/
typedef union {
struct {
uint8_t bLength; /**< Size of the descriptor in bytes */
uint8_t bDescriptorType; /**< CONFIGURATION Descriptor Type */
uint16_t wTotalLength; /**< Total length of data returned for this configuration */
uint8_t bNumInterfaces; /**< Number of interfaces supported by this configuration */
uint8_t bConfigurationValue; /**< Value to use as an argument to the SetConfiguration() request to select this configuration */
uint8_t iConfiguration; /**< Index of string descriptor describing this configuration */
uint8_t bmAttributes; /**< Configuration characteristics */
uint8_t bMaxPower; /**< Maximum power consumption of the USB device from the bus in this specific configuration when the device is fully operational. */
} USB_DESC_ATTR;
uint8_t val[USB_CONFIG_DESC_SIZE];
} usb_config_desc_t;
_Static_assert(sizeof(usb_config_desc_t) == USB_CONFIG_DESC_SIZE, "Size of usb_config_desc_t incorrect");
/**
* @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
// ---------- Interface Association Descriptor -------------
/**
* @brief Size of a USB interface association descriptor in bytes
*/
#define USB_IAD_DESC_SIZE 9
/**
* @brief Structure representing a USB interface association descriptor
*/
typedef union {
struct {
uint8_t bLength; /**< Size of the descriptor in bytes */
uint8_t bDescriptorType; /**< INTERFACE ASSOCIATION Descriptor Type */
uint8_t bFirstInterface; /**< Interface number of the first interface that is associated with this function */
uint8_t bInterfaceCount; /**< Number of contiguous interfaces that are associated with this function */
uint8_t bFunctionClass; /**< Class code (assigned by USB-IF) */
uint8_t bFunctionSubClass; /**< Subclass code (assigned by USB-IF) */
uint8_t bFunctionProtocol; /**< Protocol code (assigned by USB-IF) */
uint8_t iFunction; /**< Index of string descriptor describing this function */
} USB_DESC_ATTR;
uint8_t val[USB_IAD_DESC_SIZE];
} usb_iad_desc_t;
_Static_assert(sizeof(usb_iad_desc_t) == USB_IAD_DESC_SIZE, "Size of usb_iad_desc_t incorrect");
// ---------------- Interface Descriptor -------------------
/**
* @brief Size of a USB interface descriptor in bytes
*/
#define USB_INTF_DESC_SIZE 9
/**
* @brief Structure representing a USB interface descriptor
*
* See Table 9-12 of USB2.0 specification for more details
*/
typedef union {
struct {
uint8_t bLength; /**< Size of the descriptor in bytes */
uint8_t bDescriptorType; /**< INTERFACE Descriptor Type */
uint8_t bInterfaceNumber; /**< Number of this interface. */
uint8_t bAlternateSetting; /**< Value used to select this alternate setting for the interface identified in the prior field */
uint8_t bNumEndpoints; /**< Number of endpoints used by this interface (excluding endpoint zero). */
uint8_t bInterfaceClass; /**< Class code (assigned by the USB-IF) */
uint8_t bInterfaceSubClass; /**< Subclass code (assigned by the USB-IF) */
uint8_t bInterfaceProtocol; /**< Protocol code (assigned by the USB) */
uint8_t iInterface; /**< Index of string descriptor describing this interface */
} USB_DESC_ATTR;
uint8_t val[USB_INTF_DESC_SIZE];
} usb_intf_desc_t;
_Static_assert(sizeof(usb_intf_desc_t) == USB_INTF_DESC_SIZE, "Size of usb_intf_desc_t incorrect");
// ----------------- Endpoint Descriptor -------------------
/**
* @brief Size of a USB endpoint descriptor in bytes
*/
#define USB_EP_DESC_SIZE 7
/**
* @brief Structure representing a USB endpoint descriptor
*
* See Table 9-13 of USB2.0 specification for more details
*/
typedef union {
struct {
uint8_t bLength; /**< Size of the descriptor in bytes */
uint8_t bDescriptorType; /**< ENDPOINT Descriptor Type */
uint8_t bEndpointAddress; /**< The address of the endpoint on the USB device described by this descriptor */
uint8_t bmAttributes; /**< This field describes the endpoints attributes when it is configured using the bConfigurationValue. */
uint16_t wMaxPacketSize; /**< Maximum packet size this endpoint is capable of sending or receiving when this configuration is selected. */
uint8_t bInterval; /**< Interval for polling Isochronous and Interrupt endpoints. Expressed in frames or microframes depending on the device operating speed (1 ms for Low-Speed and Full-Speed or 125 us for USB High-Speed and above). */
} USB_DESC_ATTR;
uint8_t val[USB_EP_DESC_SIZE];
} usb_ep_desc_t;
_Static_assert(sizeof(usb_ep_desc_t) == USB_EP_DESC_SIZE, "Size of usb_ep_desc_t incorrect");
/**
* @brief Bit masks belonging to the bEndpointAddress field of an endpoint descriptor
*/
#define USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK 0x0f
#define USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK 0x80
/**
* @brief Bit masks belonging to the bmAttributes field of an endpoint descriptor
*/
#define USB_BM_ATTRIBUTES_XFERTYPE_MASK 0x03
#define USB_BM_ATTRIBUTES_XFER_CONTROL (0 << 0)
#define USB_BM_ATTRIBUTES_XFER_ISOC (1 << 0)
#define USB_BM_ATTRIBUTES_XFER_BULK (2 << 0)
#define USB_BM_ATTRIBUTES_XFER_INT (3 << 0)
#define USB_BM_ATTRIBUTES_SYNCTYPE_MASK 0x0C /* in bmAttributes */
#define USB_BM_ATTRIBUTES_SYNC_NONE (0 << 2)
#define USB_BM_ATTRIBUTES_SYNC_ASYNC (1 << 2)
#define USB_BM_ATTRIBUTES_SYNC_ADAPTIVE (2 << 2)
#define USB_BM_ATTRIBUTES_SYNC_SYNC (3 << 2)
#define USB_BM_ATTRIBUTES_USAGETYPE_MASK 0x30
#define USB_BM_ATTRIBUTES_USAGE_DATA (0 << 4)
#define USB_BM_ATTRIBUTES_USAGE_FEEDBACK (1 << 4)
#define USB_BM_ATTRIBUTES_USAGE_IMPLICIT_FB (2 << 4)
/**
* @brief Macro helpers to get information about an endpoint from its descriptor
*/
#define USB_EP_DESC_GET_XFERTYPE(desc_ptr) ((usb_transfer_type_t) ((desc_ptr)->bmAttributes & USB_BM_ATTRIBUTES_XFERTYPE_MASK))
#define USB_EP_DESC_GET_EP_NUM(desc_ptr) ((desc_ptr)->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_NUM_MASK)
#define USB_EP_DESC_GET_EP_DIR(desc_ptr) (((desc_ptr)->bEndpointAddress & USB_B_ENDPOINT_ADDRESS_EP_DIR_MASK) ? 1 : 0)
#define USB_EP_DESC_GET_MPS(desc_ptr) ((desc_ptr)->wMaxPacketSize & 0x7FF)
// ------------------ String Descriptor --------------------
/**
* @brief Size of a short USB string descriptor in bytes
*/
#define USB_STR_DESC_SIZE 2
/**
* @brief Structure representing a USB string descriptor
*/
typedef union {
struct {
uint8_t bLength; /**< Size of the descriptor in bytes */
uint8_t bDescriptorType; /**< STRING Descriptor Type */
uint16_t wData[]; /**< UTF-16LE encoded */
} USB_DESC_ATTR;
uint8_t val[USB_STR_DESC_SIZE];
} usb_str_desc_t;
_Static_assert(sizeof(usb_str_desc_t) == USB_STR_DESC_SIZE, "Size of usb_str_desc_t incorrect");
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,171 @@
/*
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
Warning: The USB Host Library API is still a beta version and may be subject to change
*/
#pragma once
#include "usb/usb_types_ch9.h"
#ifdef __cplusplus
extern "C" {
#endif
// ------------------------------------------------ Protocol Standard --------------------------------------------------
/**
* @brief USB Standard Speeds
*/
typedef enum {
USB_SPEED_LOW = 0, /**< USB Low Speed (1.5 Mbit/s) */
USB_SPEED_FULL, /**< USB Full Speed (12 Mbit/s) */
} usb_speed_t;
/**
* @brief The type of USB transfer
*
* @note The enum values need to match the bmAttributes field of an EP descriptor
*/
typedef enum {
USB_TRANSFER_TYPE_CTRL = 0,
USB_TRANSFER_TYPE_ISOCHRONOUS,
USB_TRANSFER_TYPE_BULK,
USB_TRANSFER_TYPE_INTR,
} usb_transfer_type_t;
// ------------------------------------------------- Device Related ----------------------------------------------------
/**
* @brief Handle of a USB Device connected to a USB Host
*/
typedef struct usb_device_handle_s * usb_device_handle_t;
/**
* @brief Basic information of an enumerated device
*/
typedef struct {
usb_speed_t speed; /**< Device's speed */
uint8_t dev_addr; /**< Device's address */
uint8_t bMaxPacketSize0; /**< The maximum packet size of the device's default endpoint */
uint8_t bConfigurationValue; /**< Device's current configuration number */
const usb_str_desc_t *str_desc_manufacturer; /**< Pointer to Manufacturer string descriptor (can be NULL) */
const usb_str_desc_t *str_desc_product; /**< Pointer to Product string descriptor (can be NULL) */
const usb_str_desc_t *str_desc_serial_num; /**< Pointer to Serial Number string descriptor (can be NULL) */
} usb_device_info_t;
// ------------------------------------------------ Transfer Related ---------------------------------------------------
/**
* @brief The status of a particular transfer
*/
typedef enum {
USB_TRANSFER_STATUS_COMPLETED, /**< The transfer was successful (but may be short) */
USB_TRANSFER_STATUS_ERROR, /**< The transfer failed because due to excessive errors (e.g. no response or CRC error) */
USB_TRANSFER_STATUS_TIMED_OUT, /**< The transfer failed due to a time out */
USB_TRANSFER_STATUS_CANCELED, /**< The transfer was canceled */
USB_TRANSFER_STATUS_STALL, /**< The transfer was stalled */
USB_TRANSFER_STATUS_OVERFLOW, /**< The transfer as more data was sent than was requested */
USB_TRANSFER_STATUS_SKIPPED, /**< ISOC packets only. The packet was skipped due to system latency or bus overload */
USB_TRANSFER_STATUS_NO_DEVICE, /**< The transfer failed because the target device is gone */
} usb_transfer_status_t;
/**
* @brief Isochronous packet descriptor
*
* If the number of bytes in an Isochronous transfer is larger than the MPS of the endpoint, the transfer is split
* into multiple packets transmitted at the endpoint's specified interval. An array of Isochronous packet descriptors
* describes how an Isochronous transfer should be split into multiple packets.
*/
typedef struct {
int num_bytes; /**< Number of bytes to transmit/receive in the packet. IN packets should be integer multiple of MPS */
int actual_num_bytes; /**< Actual number of bytes transmitted/received in the packet */
usb_transfer_status_t status; /**< Status of the packet */
} usb_isoc_packet_desc_t;
/**
* @brief USB transfer structure
*
* This structure is used to represent a transfer from a software client to an endpoint over the USB bus. Some of the
* fields are made const on purpose as they are fixed on allocation. Users should call the appropriate USB Host Library
* function to allocate a USB transfer structure instead of allocating this structure themselves.
*
* The transfer type is inferred from the endpoint this transfer is sent to. Depending on the transfer type, users
* should note the following:
*
* - Bulk: This structure represents a single bulk transfer. If the number of bytes exceeds the endpoint's MPS, the
* transfer will be split into multiple MPS sized packets followed by a short packet.
* - Control: This structure represents a single control transfer. This first 8 bytes of the data_buffer must be filled
* with the setup packet (see usb_setup_packet_t). The num_bytes field should be the total size of the
* transfer (i.e., size of setup packet + wLength).
* - Interrupt: Represents an interrupt transfer. If num_bytes exceeds the MPS of the endpoint, the transfer will be
* split into multiple packets, and each packet is transferred at the endpoint's specified interval.
* - Isochronous: Represents a stream of bytes that should be transferred to an endpoint at a fixed rate. The transfer
* is split into packets according to the each isoc_packet_desc. A packet is transferred at each interval
* of the endpoint. If an entire ISOC URB was transferred without error (skipped packets do not count as
* errors), the URB's overall status and the status of each packet descriptor will be updated, and the
* actual_num_bytes reflects the total bytes transferred over all packets. If the ISOC URB encounters an
* error, the entire URB is considered erroneous so only the overall status will updated.
*
* @note For Bulk/Control/Interrupt IN transfers, the num_bytes must be a integer multiple of the endpoint's MPS
* @note This structure should be allocated via usb_host_transfer_alloc()
* @note Once the transfer has be submitted, users should not modify the structure until the transfer has completed
*/
typedef struct usb_transfer_s usb_transfer_t;
/**
* @brief USB transfer completion callback
*/
typedef void (*usb_transfer_cb_t)(usb_transfer_t *transfer);
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.
Control transfers should include the size of the setup packet.
Isochronous transfer should be the total transfer size of all packets.
For non-control IN transfers, num_bytes should be an integer multiple of MPS. */
int actual_num_bytes; /**< Actual number of bytes transferred */
uint32_t flags; /**< Transfer flags */
usb_device_handle_t device_handle; /**< Device handle */
uint8_t bEndpointAddress; /**< Endpoint Address */
usb_transfer_status_t status; /**< Status of the transfer */
uint32_t timeout_ms; /**< Timeout (in milliseconds) of the packet (currently not supported yet) */
usb_transfer_cb_t callback; /**< Transfer callback */
void *context; /**< Context variable for transfer to associate transfer with something */
const int num_isoc_packets; /**< Only relevant to Isochronous. Number of service periods (i.e., intervals) to transfer data buffer over. */
usb_isoc_packet_desc_t isoc_packet_desc[]; /**< Descriptors for each Isochronous packet */
};
/**
* @brief Terminate Bulk/Interrupt OUT transfer with a zero length packet
*
* OUT transfers normally terminate when the Host has transferred the exact amount of data it needs to the device.
* However, for bulk and interrupt OUT transfers, if the transfer size just happened to be a multiple of MPS, it will be
* impossible to know the boundary between two consecutive transfers to the same endpoint.
*
* Therefore, this flag will cause the transfer to automatically add a zero length packet (ZLP) at the end of the
* transfer if the following conditions are met:
* - The target endpoint is a Bulk/Interrupt OUT endpoint (Host to device)
* - The transfer's length (i.e., transfer.num_bytes) is a multiple of the endpoint's MPS
*
* Otherwise, this flag has no effect.
*
* Users should check whether their target device's class requires a ZLP, as not all Bulk/Interrupt OUT endpoints
* require them. For example:
* - For MSC Bulk Only Transport class, the Host MUST NEVER send a ZLP. Bulk transfer boundaries are determined by the CBW and CSW instead
* - For CDC Ethernet, the Host MUST ALWAYS send a ZLP if a segment (i.e., a transfer) is a multiple of MPS (See 3.3.1 Segment Delineation)
*
* @note See USB2.0 specification 5.7.3 and 5.8.3 for more details
* @note IN transfers normally terminate when the Host as receive the exact amount of data it needs (must be multiple of MPS)
* or the endpoint sends a short packet to the Host
*/
#define USB_TRANSFER_FLAG_ZERO_PACK 0x01 /**< (For bulk OUT only). Indicates that a bulk OUT transfers should always terminate with a short packet, even if it means adding an extra zero length packet */
#ifdef __cplusplus
}
#endif