USB Device Driver
Overview
The driver allows users to use ESP32-S2 chips to develop USB devices on top the TinyUSB stack. TinyUSB is integrating with ESP-IDF to provide USB features of the framework. Using this driver the chip works as a composite device supporting to represent several USB devices simultaneously. Currently, only the communications device class (CDC) type of the device with the ACM (Abstract Control Model) subclass is supported.
Features
Configuration of device and string USB descriptors
USB Serial Device (CDC-ACM)
Input and output through USB Serial Device
Hardware USB Connection
Any board with the ESP32-S2 chip with USB connectors or with exposed USB’s D+ and D- (DATA+/DATA-) pins.
If the board has no USB connector but has the pins, connect pins directly to the host (e.g. with do-it-yourself cable from any USB connection cable).
On ESP32-S2, connect GPIO 20 and 19 to D+/D- respectively:
Driver Structure
As the basis is used the TinyUSB stack.
On top of it the driver implements:
Customization of USB descriptors
Serial device support
Redirecting of standard streams through the Serial device
Encapsulated driver’s task servicing the TinyuSB
Configuration
Via Menuconfig options you can specify:
Several of descriptor’s parameters (see: Descriptors Configuration bellow)
USB Serial low-level Configuration
The verbosity of the TinyUSB’s log
Disable the TinyUSB main task (for the custom implementation)
Descriptors Configuration
The driver’s descriptors are provided by the tinyusb_config_t
structure’s descriptor
and string_descriptor
members. Therefore, users should initialize tinyusb_config_t
to their desired descriptor before calling tinyusb_driver_install()
to install driver.
However, the driver also provides a default descriptor. The driver can be installed with the default descriptor by setting the descriptor
and string_descriptor
members of tinyusb_config_t
to NULL before calling tinyusb_driver_install()
. The driver’s default descriptor is specified using Menuconfig, where the following fields should be configured:
PID
VID
bcdDevice
Manufacturer
Product name
Name of CDC device if it is On
Serial number
If you want to use own descriptors with extended modification, you can define them during the driver installation process
Install Driver
To initialize the driver, users should call tinyusb_driver_install()
. The driver’s configuration is specified in a tinyusb_config_t
structure that is passed as an argument to tinyusb_driver_install()
.
Note that the
tinyusb_config_t
structure can be zero initialized (e.g.tinyusb_config_t tusb_cfg = { 0 }
) or partially (as shown below). For any member that is initialized to 0 or NULL, the driver will use its default configuration values for that member (see example below)
tinyusb_config_t partial_init = {
.descriptor = NULL; //Uses default descriptor specified in Menuconfig
.string_descriptor = NULL; //Uses default string specified in Menuconfig
.external_phy = false;
}
USB Serial Device (CDC-ACM)
If the CDC option is enabled in Menuconfig, the USB Serial Device could be initialized with tusb_cdc_acm_init()
according to the settings from tinyusb_config_cdcacm_t
(see example below).
tinyusb_config_cdcacm_t acm_cfg = {
.usb_dev = TINYUSB_USBDEV_0,
.cdc_port = TINYUSB_CDC_ACM_0,
.rx_unread_buf_sz = 64,
.callback_rx = NULL,
.callback_rx_wanted_char = NULL,
.callback_line_state_changed = NULL,
.callback_line_coding_changed = NULL
};
tusb_cdc_acm_init(&acm_cfg);
To specify callbacks you can either set the pointer to your tusb_cdcacm_callback_t
function in the configuration structure or call tinyusb_cdcacm_register_callback()
after initialization.
USB Serial Console
The driver allows to redirect all standard application strings (stdin/out/err) to the USB Serial Device and return them to UART using esp_tusb_init_console()
/esp_tusb_deinit_console()
functions.
Application Examples
The table below describes the code examples available in the directory peripherals/usb/.
Code Example |
Description |
---|---|
How to set up ESP32-S2 chip to get log output via Serial Device connection |
|
How to set up ESP32-S2 chip to work as a Generic USB Device with a user-defined descriptor |
|
How to set up ESP32-S2 chip to work as a USB Serial Device |
API Reference
Header File
Functions
-
esp_err_t tinyusb_driver_install(const tinyusb_config_t *config)
This is an all-in-one helper function, including:
USB device driver initialization
Descriptors preparation
TinyUSB stack initialization
Creates and start a task to handle usb events
Note
Don’t change Custom descriptor, but if it has to be done, Suggest to define as follows in order to match the Interface Association Descriptor (IAD): bDeviceClass = TUSB_CLASS_MISC, bDeviceSubClass = MISC_SUBCLASS_COMMON,
- Parameters
config – tinyusb stack specific configuration
- Return values
ESP_ERR_INVALID_ARG – Install driver and tinyusb stack failed because of invalid argument
ESP_FAIL – Install driver and tinyusb stack failed because of internal error
ESP_OK – Install driver and tinyusb stack successfully
Functions
-
esp_err_t tusb_cdc_acm_init(const tinyusb_config_cdcacm_t *cfg)
Initialize CDC ACM. Initialization will be finished with the
tud_cdc_line_state_cb
callback.- Parameters
cfg – - init configuration structure
- Returns
esp_err_t
-
esp_err_t tinyusb_cdcacm_register_callback(tinyusb_cdcacm_itf_t itf, cdcacm_event_type_t event_type, tusb_cdcacm_callback_t callback)
Register a callback invoking on CDC event. If the callback had been already registered, it will be overwritten.
- Parameters
itf – - number of a CDC object
event_type – - type of registered event for a callback
callback – - callback function
- Returns
esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG
-
esp_err_t tinyusb_cdcacm_unregister_callback(tinyusb_cdcacm_itf_t itf, cdcacm_event_type_t event_type)
Unregister a callback invoking on CDC event.
- Parameters
itf – - number of a CDC object
event_type – - type of registered event for a callback
- Returns
esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG
-
size_t tinyusb_cdcacm_write_queue_char(tinyusb_cdcacm_itf_t itf, char ch)
Sent one character to a write buffer.
- Parameters
itf – - number of a CDC object
ch – - character to send
- Returns
size_t - amount of queued bytes
-
size_t tinyusb_cdcacm_write_queue(tinyusb_cdcacm_itf_t itf, const uint8_t *in_buf, size_t in_size)
Write data to write buffer from a byte array.
- Parameters
itf – - number of a CDC object
in_buf – - a source array
in_size – - size to write from arr_src
- Returns
size_t - amount of queued bytes
-
esp_err_t tinyusb_cdcacm_write_flush(tinyusb_cdcacm_itf_t itf, uint32_t timeout_ticks)
Send all data from a write buffer. Use
tinyusb_cdcacm_write_queue
to add data to the buffer.WARNING! TinyUSB can block output Endpoint for several RX callbacks, after will do additional flush after the each trasfer. That can leads to the situation when you requested a flush, but it will fail until ont of the next callbacks ends. SO USING OF THE FLUSH WITH TIMEOUTS IN CALLBACKS IS NOT RECOMENDED - YOU CAN GET A LOCK FOR THE TIMEOUT
- Parameters
itf – - number of a CDC object
timeout_ticks – - waiting until flush will be considered as failed
- Returns
esp_err_t - ESP_OK if (timeout_ticks > 0) and and flush was successful, ESP_ERR_TIMEOUT if timeout occurred3 or flush was successful with (timeout_ticks == 0) ESP_FAIL if flush was unsuccessful
-
esp_err_t tinyusb_cdcacm_read(tinyusb_cdcacm_itf_t itf, uint8_t *out_buf, size_t out_buf_sz, size_t *rx_data_size)
Read a content to the array, and defines it’s size to the sz_store.
- Parameters
itf – - number of a CDC object
out_buf – - to this array will be stored the object from a CDC buffer
out_buf_sz – - size of buffer for results
rx_data_size – - to this address will be stored the object’s size
- Returns
esp_err_t ESP_OK, ESP_FAIL or ESP_ERR_INVALID_STATE
-
bool tusb_cdc_acm_initialized(tinyusb_cdcacm_itf_t itf)
Check if the ACM initialized.
- Parameters
itf – - number of a CDC object
- Returns
true or false
Structures
-
struct cdcacm_event_rx_wanted_char_data_t
Data provided to the input of the
callback_rx_wanted_char
callback.Public Members
-
char wanted_char
Wanted character
-
char wanted_char
-
struct cdcacm_event_line_state_changed_data_t
Data provided to the input of the
callback_line_state_changed
callback.
-
struct cdcacm_event_line_coding_changed_data_t
Data provided to the input of the
line_coding_changed
callback.Public Members
-
cdc_line_coding_t const *p_line_coding
New line coding value
-
cdc_line_coding_t const *p_line_coding
-
struct cdcacm_event_t
Describes an event passing to the input of a callbacks.
Public Members
-
cdcacm_event_type_t type
Event type
-
cdcacm_event_rx_wanted_char_data_t rx_wanted_char_data
Data input of the
callback_rx_wanted_char
callback
-
cdcacm_event_line_state_changed_data_t line_state_changed_data
Data input of the
callback_line_state_changed
callback
-
cdcacm_event_line_coding_changed_data_t line_coding_changed_data
Data input of the
line_coding_changed
callback
-
cdcacm_event_type_t type
-
struct tinyusb_config_cdcacm_t
Configuration structure for CDC-ACM.
Public Members
-
tinyusb_usbdev_t usb_dev
Usb device to set up
-
tinyusb_cdcacm_itf_t cdc_port
CDC port
-
size_t rx_unread_buf_sz
Amount of data that can be passed to the ACM at once
-
tusb_cdcacm_callback_t callback_rx
Pointer to the function with the
tusb_cdcacm_callback_t
type that will be handled as a callback
-
tusb_cdcacm_callback_t callback_rx_wanted_char
Pointer to the function with the
tusb_cdcacm_callback_t
type that will be handled as a callback
-
tusb_cdcacm_callback_t callback_line_state_changed
Pointer to the function with the
tusb_cdcacm_callback_t
type that will be handled as a callback
-
tusb_cdcacm_callback_t callback_line_coding_changed
Pointer to the function with the
tusb_cdcacm_callback_t
type that will be handled as a callback
-
tinyusb_usbdev_t usb_dev
Type Definitions
-
typedef void (*tusb_cdcacm_callback_t)(int itf, cdcacm_event_t *event)
CDC-ACM callback type.
Enumerations
Functions
Functions
-
esp_err_t tusb_run_task(void)
This helper function creates and starts a task which wraps
tud_task()
.The wrapper function basically wraps tud_task and some log. Default parameters: stack size and priority as configured, argument = NULL, not pinned to any core. If you have more requirements for this task, you can create your own task which calls tud_task as the last step.
- Return values
ESP_OK – run tinyusb main task successfully
ESP_FAIL – run tinyusb main task failed of internal error
ESP_ERR_INVALID_STATE – tinyusb main task has been created before