USB Device Driver¶
Overview¶
The driver allows users to use ESP32-S3 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-S3 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-S3, 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 amc_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(&amc_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-S3 chip to get log output via Serial Device connection |
|
How to set up ESP32-S3 chip to work as a Generic USB Device with a user-defined descriptor |
|
How to set up ESP32-S3 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 Value
ESP_ERR_INVALID_ARG
: Install driver and tinyusb stack failed because of invalid argumentESP_FAIL
: Install driver and tinyusb stack failed because of internal errorESP_OK
: Install driver and tinyusb stack successfully
Type Definitions¶
-
typedef const char *
tusb_desc_strarray_device_t
[USB_STRING_DESCRIPTOR_ARRAY_SIZE
]¶
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.- Return
esp_err_t
- Parameters
cfg
: - init configuration structure
-
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.
- Return
esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG
- Parameters
itf
: - number of a CDC objectevent_type
: - type of registered event for a callbackcallback
: - callback function
-
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.
- Return
esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG
- Parameters
itf
: - number of a CDC objectevent_type
: - type of registered event for a callback
-
size_t
tinyusb_cdcacm_write_queue_char
(tinyusb_cdcacm_itf_t itf, char ch)¶ Sent one character to a write buffer.
- Return
size_t - amount of queued bytes
- Parameters
itf
: - number of a CDC objectch
: - character to send
-
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.
- Return
size_t - amount of queued bytes
- Parameters
itf
: - number of a CDC objectin_buf
: - a source arrayin_size
: - size to write from arr_src
-
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
- Return
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
- Parameters
itf
: - number of a CDC objecttimeout_ticks
: - waiting until flush will be considered as failed
-
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.
- Return
esp_err_t ESP_OK, ESP_FAIL or ESP_ERR_INVALID_STATE
- Parameters
itf
: - number of a CDC objectout_buf
: - to this array will be stored the object from a CDC bufferout_buf_sz
: - size of buffer for resultsrx_data_size
: - to this address will be stored the object’s size
-
bool
tusb_cdc_acm_initialized
(tinyusb_cdcacm_itf_t itf)¶ Check if the ACM initialized.
- Return
true or false
- Parameters
itf
: - number of a CDC object
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
-
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 *
-
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
-
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 AMC 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
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 Value
ESP_OK
: run tinyusb main task successfullyESP_FAIL
: run tinyusb main task failed of internal errorESP_ERR_INVALID_STATE
: tinyusb main task has been created before