mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
tinyusb: Use TinyUSB from component registry
This commit is contained in:
parent
0179edb71d
commit
61191a5ce5
1
.flake8
1
.flake8
@ -146,7 +146,6 @@ exclude =
|
||||
components/json/cJSON,
|
||||
components/mbedtls/mbedtls,
|
||||
components/openthread/openthread,
|
||||
components/tinyusb,
|
||||
components/unity/unity,
|
||||
components/spiffs/spiffs,
|
||||
# autogenerated scripts
|
||||
|
@ -170,7 +170,6 @@
|
||||
- "components/openthread/openthread"
|
||||
- "components/protobuf-c/protobuf-c"
|
||||
- "components/spiffs/spiffs"
|
||||
- "components/tinyusb/tinyusb"
|
||||
- "components/unity/unity"
|
||||
- "components/heap/tlsf"
|
||||
- ".gitmodules"
|
||||
|
4
.gitmodules
vendored
4
.gitmodules
vendored
@ -47,10 +47,6 @@
|
||||
path = components/esp_wifi/lib
|
||||
url = ../../espressif/esp32-wifi-lib.git
|
||||
|
||||
[submodule "components/tinyusb/tinyusb"]
|
||||
path = components/tinyusb/tinyusb
|
||||
url = ../../espressif/tinyusb.git
|
||||
|
||||
[submodule "components/cmock/CMock"]
|
||||
path = components/cmock/CMock
|
||||
url = ../../ThrowTheSwitch/CMock.git
|
||||
|
@ -1,84 +0,0 @@
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
|
||||
set(srcs)
|
||||
set(includes_public)
|
||||
set(includes_private)
|
||||
set(compile_options)
|
||||
|
||||
if(CONFIG_TINYUSB)
|
||||
if(target STREQUAL "esp32s3")
|
||||
set(tusb_mcu "OPT_MCU_ESP32S3")
|
||||
set(tusb_family "esp32sx")
|
||||
elseif(target STREQUAL "esp32s2")
|
||||
set(tusb_mcu "OPT_MCU_ESP32S2")
|
||||
set(tusb_family "esp32sx")
|
||||
else()
|
||||
# CONFIG_TINYUSB dependency has been garanteed by Kconfig logic,
|
||||
# So it's not possible that cmake goes here
|
||||
message(FATAL_ERROR "TinyUSB is not support on ${target}.")
|
||||
return()
|
||||
endif()
|
||||
|
||||
list(APPEND compile_options
|
||||
"-DCFG_TUSB_MCU=${tusb_mcu}"
|
||||
"-DCFG_TUSB_DEBUG=${CONFIG_TINYUSB_DEBUG_LEVEL}"
|
||||
)
|
||||
|
||||
idf_component_get_property(freertos_component_dir freertos COMPONENT_DIR)
|
||||
|
||||
list(APPEND includes_private
|
||||
"tinyusb/hw/bsp/"
|
||||
"tinyusb/src/"
|
||||
"tinyusb/src/device"
|
||||
"additions/include_private"
|
||||
)
|
||||
|
||||
list(APPEND includes_public
|
||||
"tinyusb/src/"
|
||||
"additions/include"
|
||||
# The FreeRTOS API include convention in tinyusb is different from esp-idf
|
||||
"${freertos_component_dir}/FreeRTOS-Kernel/include/freertos"
|
||||
)
|
||||
|
||||
list(APPEND srcs
|
||||
"tinyusb/src/portable/espressif/${tusb_family}/dcd_${tusb_family}.c"
|
||||
"tinyusb/src/class/cdc/cdc_device.c"
|
||||
"tinyusb/src/class/hid/hid_device.c"
|
||||
"tinyusb/src/class/midi/midi_device.c"
|
||||
"tinyusb/src/class/msc/msc_device.c"
|
||||
"tinyusb/src/class/vendor/vendor_device.c"
|
||||
"tinyusb/src/common/tusb_fifo.c"
|
||||
"tinyusb/src/device/usbd_control.c"
|
||||
"tinyusb/src/device/usbd.c"
|
||||
"tinyusb/src/tusb.c"
|
||||
"additions/src/descriptors_control.c"
|
||||
"additions/src/tinyusb.c"
|
||||
"additions/src/usb_descriptors.c"
|
||||
)
|
||||
|
||||
if(NOT CONFIG_TINYUSB_NO_DEFAULT_TASK)
|
||||
list(APPEND srcs "additions/src/tusb_tasks.c")
|
||||
endif()
|
||||
|
||||
# when no builtin class driver is enabled, an uint8_t data compared with `BUILTIN_DRIVER_COUNT` will always be false
|
||||
set_source_files_properties("tinyusb/src/device/usbd.c" PROPERTIES COMPILE_FLAGS "-Wno-type-limits")
|
||||
|
||||
if(CONFIG_TINYUSB_CDC_ENABLED)
|
||||
list(APPEND srcs
|
||||
"additions/src/cdc.c"
|
||||
"additions/src/tusb_cdc_acm.c"
|
||||
"additions/src/tusb_console.c"
|
||||
"additions/src/vfs_tinyusb.c"
|
||||
)
|
||||
endif() # CONFIG_TINYUSB_CDC_ENABLED
|
||||
endif() # CONFIG_TINYUSB
|
||||
|
||||
idf_component_register(SRCS ${srcs}
|
||||
INCLUDE_DIRS ${includes_public}
|
||||
PRIV_INCLUDE_DIRS ${includes_private}
|
||||
PRIV_REQUIRES "vfs" "usb" "driver"
|
||||
)
|
||||
|
||||
if(CONFIG_TINYUSB)
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE ${compile_options})
|
||||
endif()
|
@ -1,188 +0,0 @@
|
||||
menu "TinyUSB Stack"
|
||||
visible if USB_OTG_SUPPORTED
|
||||
|
||||
config TINYUSB
|
||||
bool "Use TinyUSB Stack"
|
||||
depends on USB_OTG_SUPPORTED
|
||||
default n
|
||||
help
|
||||
Enable TinyUSB stack support.
|
||||
Note that, esp-idf only uses the device stack provided by TinyUSB.
|
||||
|
||||
if TINYUSB
|
||||
config TINYUSB_DEBUG_LEVEL
|
||||
int "TinyUSB log level (0-3)"
|
||||
default 0
|
||||
range 0 3
|
||||
help
|
||||
Specify verbosity of TinyUSB log output.
|
||||
|
||||
menu "TinyUSB task configuration"
|
||||
config TINYUSB_NO_DEFAULT_TASK
|
||||
bool "Do not create a TinyUSB task"
|
||||
default n
|
||||
help
|
||||
This option allows to not create the FreeRTOS task during the driver initialization.
|
||||
User will have to handle TinyUSB events manually.
|
||||
|
||||
config TINYUSB_TASK_PRIORITY
|
||||
int "TinyUSB task priority"
|
||||
default 5
|
||||
depends on !TINYUSB_NO_DEFAULT_TASK
|
||||
help
|
||||
Set the priority of the default TinyUSB main task.
|
||||
|
||||
config TINYUSB_TASK_STACK_SIZE
|
||||
int "TinyUSB task stack size (bytes)"
|
||||
default 4096
|
||||
depends on !TINYUSB_NO_DEFAULT_TASK
|
||||
help
|
||||
Set the stack size of the default TinyUSB main task.
|
||||
endmenu
|
||||
|
||||
menu "Descriptor configuration"
|
||||
config TINYUSB_DESC_USE_ESPRESSIF_VID
|
||||
bool "VID: Use Espressif's vendor ID"
|
||||
default y
|
||||
help
|
||||
Enable this option, USB device will use Espressif's vendor ID as its VID.
|
||||
This is helpful at product develop stage.
|
||||
|
||||
config TINYUSB_DESC_CUSTOM_VID
|
||||
hex "VID: Custom vendor ID"
|
||||
default 0x1234
|
||||
depends on !TINYUSB_DESC_USE_ESPRESSIF_VID
|
||||
help
|
||||
Custom Vendor ID.
|
||||
|
||||
config TINYUSB_DESC_USE_DEFAULT_PID
|
||||
bool "PID: Use a default PID assigned to TinyUSB"
|
||||
default y
|
||||
help
|
||||
Default TinyUSB PID assigning uses values 0x4000...0x4007.
|
||||
|
||||
config TINYUSB_DESC_CUSTOM_PID
|
||||
hex "PID: Custom product ID"
|
||||
default 0x5678
|
||||
depends on !TINYUSB_DESC_USE_DEFAULT_PID
|
||||
help
|
||||
Custom Product ID.
|
||||
|
||||
config TINYUSB_DESC_BCD_DEVICE
|
||||
hex "bcdDevice"
|
||||
default 0x0100
|
||||
help
|
||||
Version of the firmware of the USB device.
|
||||
|
||||
config TINYUSB_DESC_MANUFACTURER_STRING
|
||||
string "Manufacturer name"
|
||||
default "Espressif Systems"
|
||||
help
|
||||
Name of the manufacturer of the USB device.
|
||||
|
||||
config TINYUSB_DESC_PRODUCT_STRING
|
||||
string "Product name"
|
||||
default "Espressif Device"
|
||||
help
|
||||
Name of the USB device.
|
||||
|
||||
config TINYUSB_DESC_SERIAL_STRING
|
||||
string "Serial string"
|
||||
default "123456"
|
||||
help
|
||||
Serial number of the USB device.
|
||||
|
||||
config TINYUSB_DESC_CDC_STRING
|
||||
depends on TINYUSB_CDC_ENABLED
|
||||
string "CDC Device String"
|
||||
default "Espressif CDC Device"
|
||||
help
|
||||
Name of the CDC device.
|
||||
|
||||
config TINYUSB_DESC_MSC_STRING
|
||||
depends on TINYUSB_MSC_ENABLED
|
||||
string "MSC Device String"
|
||||
default "Espressif MSC Device"
|
||||
help
|
||||
Name of the MSC device.
|
||||
|
||||
config TINYUSB_DESC_HID_STRING
|
||||
depends on TINYUSB_HID_COUNT > 0
|
||||
string "HID Device String"
|
||||
default "Espressif HID Device"
|
||||
help
|
||||
Name of the HID device
|
||||
|
||||
config TINYUSB_DESC_MIDI_STRING
|
||||
depends on TINYUSB_MIDI_ENABLED
|
||||
string "MIDI Device String"
|
||||
default "Espressif MIDI Device"
|
||||
help
|
||||
Name of the MIDI device
|
||||
endmenu # "Descriptor configuration"
|
||||
|
||||
menu "Massive Storage Class (MSC)"
|
||||
config TINYUSB_MSC_ENABLED
|
||||
bool "Enable TinyUSB MSC feature"
|
||||
default n
|
||||
help
|
||||
Enable TinyUSB MSC feature.
|
||||
|
||||
config TINYUSB_MSC_BUFSIZE
|
||||
depends on TINYUSB_MSC_ENABLED
|
||||
int "MSC FIFO size"
|
||||
default 512
|
||||
range 64 10000
|
||||
help
|
||||
MSC FIFO size, in bytes.
|
||||
endmenu # "Massive Storage Class"
|
||||
|
||||
menu "Communication Device Class (CDC)"
|
||||
config TINYUSB_CDC_ENABLED
|
||||
bool "Enable TinyUSB CDC feature"
|
||||
default n
|
||||
help
|
||||
Enable TinyUSB CDC feature.
|
||||
|
||||
config TINYUSB_CDC_COUNT
|
||||
int "CDC Channel Count"
|
||||
default 1
|
||||
range 1 2
|
||||
depends on TINYUSB_CDC_ENABLED
|
||||
help
|
||||
Number of independent serial ports.
|
||||
|
||||
config TINYUSB_CDC_RX_BUFSIZE
|
||||
depends on TINYUSB_CDC_ENABLED
|
||||
int "CDC FIFO size of RX channel"
|
||||
default 64
|
||||
range 64 10000
|
||||
help
|
||||
CDC FIFO size of RX channel.
|
||||
|
||||
config TINYUSB_CDC_TX_BUFSIZE
|
||||
depends on TINYUSB_CDC_ENABLED
|
||||
int "CDC FIFO size of TX channel"
|
||||
default 64
|
||||
help
|
||||
CDC FIFO size of TX channel.
|
||||
endmenu # "Communication Device Class"
|
||||
|
||||
menu "MIDI"
|
||||
config TINYUSB_MIDI_ENABLED
|
||||
bool "Enable TinyUSB MIDI feature"
|
||||
default n
|
||||
help
|
||||
Enable TinyUSB MIDI feature.
|
||||
endmenu # "MIDI"
|
||||
|
||||
menu "Human Interface Device Class (HID)"
|
||||
config TINYUSB_HID_COUNT
|
||||
int "TinyUSB HID interfaces count"
|
||||
default 0
|
||||
range 0 4
|
||||
help
|
||||
Setting value greater than 0 will enable TinyUSB HID feature.
|
||||
endmenu # "HID Device Class (HID)"
|
||||
endif # TINYUSB
|
||||
endmenu # "TinyUSB Stack"
|
@ -1,64 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
#include "tusb.h"
|
||||
#include "tusb_option.h"
|
||||
#include "tusb_config.h"
|
||||
#include "tinyusb_types.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Configuration structure of the TinyUSB core
|
||||
*
|
||||
* USB specification mandates self-powered devices to monitor USB VBUS to detect connection/disconnection events.
|
||||
* If you want to use this feature, connected VBUS to any free GPIO through a voltage divider or voltage comparator.
|
||||
* The voltage divider output should be (0.75 * Vdd) if VBUS is 4.4V (lowest valid voltage at device port).
|
||||
* The comparator thresholds should be set with hysteresis: 4.35V (falling edge) and 4.75V (raising edge).
|
||||
*/
|
||||
typedef struct {
|
||||
union {
|
||||
const tusb_desc_device_t *device_descriptor; /*!< Pointer to a device descriptor. If set to NULL, the TinyUSB device will use a default device descriptor whose values are set in Kconfig */
|
||||
const tusb_desc_device_t *descriptor __attribute__((deprecated)); /*!< Alias to `device_descriptor` for backward compatibility */
|
||||
};
|
||||
const char **string_descriptor; /*!< Pointer to an array of string descriptors */
|
||||
bool external_phy; /*!< Should USB use an external PHY */
|
||||
const uint8_t *configuration_descriptor; /*!< Pointer to a configuration descriptor. If set to NULL, TinyUSB device will use a default configuration descriptor whose values are set in Kconfig */
|
||||
bool self_powered; /*!< This is a self-powered USB device. USB VBUS must be monitored. */
|
||||
int vbus_monitor_io; /*!< GPIO for VBUS monitoring. Ignored if not self_powered. */
|
||||
} tinyusb_config_t;
|
||||
|
||||
/**
|
||||
* @brief This is an all-in-one helper function, including:
|
||||
* 1. USB device driver initialization
|
||||
* 2. Descriptors preparation
|
||||
* 3. TinyUSB stack initialization
|
||||
* 4. 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,
|
||||
*
|
||||
* @param config tinyusb stack specific configuration
|
||||
* @retval ESP_ERR_INVALID_ARG Install driver and tinyusb stack failed because of invalid argument
|
||||
* @retval ESP_FAIL Install driver and tinyusb stack failed because of internal error
|
||||
* @retval ESP_OK Install driver and tinyusb stack successfully
|
||||
*/
|
||||
esp_err_t tinyusb_driver_install(const tinyusb_config_t *config);
|
||||
|
||||
// TODO esp_err_t tinyusb_driver_uninstall(void); (IDF-1474)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,24 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define USB_ESPRESSIF_VID 0x303A
|
||||
#define USB_STRING_DESCRIPTOR_ARRAY_SIZE 7
|
||||
|
||||
typedef enum{
|
||||
TINYUSB_USBDEV_0,
|
||||
} tinyusb_usbdev_t;
|
||||
|
||||
typedef const char *tusb_desc_strarray_device_t[USB_STRING_DESCRIPTOR_ARRAY_SIZE];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,195 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "tusb.h"
|
||||
#include "tinyusb.h"
|
||||
|
||||
/**
|
||||
* @brief CDC ports available to setup
|
||||
*/
|
||||
typedef enum {
|
||||
TINYUSB_CDC_ACM_0 = 0x0,
|
||||
TINYUSB_CDC_ACM_1,
|
||||
TINYUSB_CDC_ACM_MAX
|
||||
} tinyusb_cdcacm_itf_t;
|
||||
|
||||
/* Callbacks and events
|
||||
********************************************************************* */
|
||||
|
||||
/**
|
||||
* @brief Data provided to the input of the `callback_rx_wanted_char` callback
|
||||
*/
|
||||
typedef struct {
|
||||
char wanted_char; /*!< Wanted character */
|
||||
} cdcacm_event_rx_wanted_char_data_t;
|
||||
|
||||
/**
|
||||
* @brief Data provided to the input of the `callback_line_state_changed` callback
|
||||
*/
|
||||
typedef struct {
|
||||
bool dtr; /*!< Data Terminal Ready (DTR) line state */
|
||||
bool rts; /*!< Request To Send (RTS) line state */
|
||||
} cdcacm_event_line_state_changed_data_t;
|
||||
|
||||
/**
|
||||
* @brief Data provided to the input of the `line_coding_changed` callback
|
||||
*/
|
||||
typedef struct {
|
||||
cdc_line_coding_t const *p_line_coding; /*!< New line coding value */
|
||||
} cdcacm_event_line_coding_changed_data_t;
|
||||
|
||||
/**
|
||||
* @brief Types of CDC ACM events
|
||||
*/
|
||||
typedef enum {
|
||||
CDC_EVENT_RX,
|
||||
CDC_EVENT_RX_WANTED_CHAR,
|
||||
CDC_EVENT_LINE_STATE_CHANGED,
|
||||
CDC_EVENT_LINE_CODING_CHANGED
|
||||
} cdcacm_event_type_t;
|
||||
|
||||
/**
|
||||
* @brief Describes an event passing to the input of a callbacks
|
||||
*/
|
||||
typedef struct {
|
||||
cdcacm_event_type_t type; /*!< Event type */
|
||||
union {
|
||||
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_t;
|
||||
|
||||
/**
|
||||
* @brief CDC-ACM callback type
|
||||
*/
|
||||
typedef void(*tusb_cdcacm_callback_t)(int itf, cdcacm_event_t *event);
|
||||
|
||||
/*********************************************************************** Callbacks and events*/
|
||||
/* Other structs
|
||||
********************************************************************* */
|
||||
|
||||
/**
|
||||
* @brief Configuration structure for CDC-ACM
|
||||
*/
|
||||
typedef struct {
|
||||
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_config_cdcacm_t;
|
||||
|
||||
/*********************************************************************** Other structs*/
|
||||
/* Public functions
|
||||
********************************************************************* */
|
||||
/**
|
||||
* @brief Initialize CDC ACM. Initialization will be finished with
|
||||
* the `tud_cdc_line_state_cb` callback
|
||||
*
|
||||
* @param cfg - init configuration structure
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t tusb_cdc_acm_init(const tinyusb_config_cdcacm_t *cfg);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Register a callback invoking on CDC event. If the callback had been
|
||||
* already registered, it will be overwritten
|
||||
*
|
||||
* @param itf - number of a CDC object
|
||||
* @param event_type - type of registered event for a callback
|
||||
* @param callback - callback function
|
||||
* @return esp_err_t - ESP_OK or ESP_ERR_INVALID_ARG
|
||||
*/
|
||||
esp_err_t tinyusb_cdcacm_register_callback(tinyusb_cdcacm_itf_t itf,
|
||||
cdcacm_event_type_t event_type,
|
||||
tusb_cdcacm_callback_t callback);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Unregister a callback invoking on CDC event.
|
||||
*
|
||||
* @param itf - number of a CDC object
|
||||
* @param event_type - type of registered event for a callback
|
||||
* @return 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);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sent one character to a write buffer
|
||||
*
|
||||
* @param itf - number of a CDC object
|
||||
* @param ch - character to send
|
||||
* @return size_t - amount of queued bytes
|
||||
*/
|
||||
size_t tinyusb_cdcacm_write_queue_char(tinyusb_cdcacm_itf_t itf, char ch);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write data to write buffer from a byte array
|
||||
*
|
||||
* @param itf - number of a CDC object
|
||||
* @param in_buf - a source array
|
||||
* @param in_size - size to write from arr_src
|
||||
* @return 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);
|
||||
|
||||
/**
|
||||
* @brief 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
|
||||
*
|
||||
* @param itf - number of a CDC object
|
||||
* @param timeout_ticks - waiting until flush will be considered as failed
|
||||
* @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
|
||||
*/
|
||||
esp_err_t tinyusb_cdcacm_write_flush(tinyusb_cdcacm_itf_t itf, uint32_t timeout_ticks);
|
||||
|
||||
/**
|
||||
* @brief Read a content to the array, and defines it's size to the sz_store
|
||||
*
|
||||
* @param itf - number of a CDC object
|
||||
* @param out_buf - to this array will be stored the object from a CDC buffer
|
||||
* @param out_buf_sz - size of buffer for results
|
||||
* @param rx_data_size - to this address will be stored the object's size
|
||||
* @return esp_err_t ESP_OK, ESP_FAIL or ESP_ERR_INVALID_STATE
|
||||
*/
|
||||
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);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Check if the ACM initialized
|
||||
*
|
||||
* @param itf - number of a CDC object
|
||||
* @return true or false
|
||||
*/
|
||||
bool tusb_cdc_acm_initialized(tinyusb_cdcacm_itf_t itf);
|
||||
|
||||
/*********************************************************************** Public functions*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,103 +0,0 @@
|
||||
/*
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2019 Ha Thach (tinyusb.org),
|
||||
* Additions Copyright (c) 2020, Espressif Systems (Shanghai) PTE LTD
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tusb_option.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_TINYUSB_CDC_ENABLED
|
||||
# define CONFIG_TINYUSB_CDC_ENABLED 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_TINYUSB_MSC_ENABLED
|
||||
# define CONFIG_TINYUSB_MSC_ENABLED 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_TINYUSB_HID_COUNT
|
||||
# define CONFIG_TINYUSB_HID_COUNT 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_TINYUSB_MIDI_ENABLED
|
||||
# define CONFIG_TINYUSB_MIDI_ENABLED 0
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED
|
||||
# define CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED 0
|
||||
#endif
|
||||
|
||||
#define CFG_TUSB_RHPORT0_MODE OPT_MODE_DEVICE | OPT_MODE_FULL_SPEED
|
||||
#define CFG_TUSB_OS OPT_OS_FREERTOS
|
||||
|
||||
/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
|
||||
* Tinyusb use follows macros to declare transferring memory so that they can be put
|
||||
* into those specific section.
|
||||
* e.g
|
||||
* - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
|
||||
* - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
|
||||
*/
|
||||
#ifndef CFG_TUSB_MEM_SECTION
|
||||
# define CFG_TUSB_MEM_SECTION
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUSB_MEM_ALIGN
|
||||
# define CFG_TUSB_MEM_ALIGN TU_ATTR_ALIGNED(4)
|
||||
#endif
|
||||
|
||||
#ifndef CFG_TUD_ENDPOINT0_SIZE
|
||||
#define CFG_TUD_ENDPOINT0_SIZE 64
|
||||
#endif
|
||||
|
||||
// CDC FIFO size of TX and RX
|
||||
#define CFG_TUD_CDC_RX_BUFSIZE CONFIG_TINYUSB_CDC_RX_BUFSIZE
|
||||
#define CFG_TUD_CDC_TX_BUFSIZE CONFIG_TINYUSB_CDC_TX_BUFSIZE
|
||||
|
||||
// MSC Buffer size of Device Mass storage
|
||||
#define CFG_TUD_MSC_BUFSIZE CONFIG_TINYUSB_MSC_BUFSIZE
|
||||
|
||||
#define CFG_TUD_MIDI_EP_BUFSIZE 64
|
||||
#define CFG_TUD_MIDI_EPSIZE CFG_TUD_MIDI_EP_BUFSIZE
|
||||
#define CFG_TUD_MIDI_RX_BUFSIZE 64
|
||||
#define CFG_TUD_MIDI_TX_BUFSIZE 64
|
||||
|
||||
// Enabled device class driver
|
||||
#if defined(CONFIG_TINYUSB_CDC_COUNT)
|
||||
#define CFG_TUD_CDC CONFIG_TINYUSB_CDC_COUNT
|
||||
#else
|
||||
#define CFG_TUD_CDC 0
|
||||
#endif
|
||||
#define CFG_TUD_MSC CONFIG_TINYUSB_MSC_ENABLED
|
||||
#define CFG_TUD_HID CONFIG_TINYUSB_HID_COUNT
|
||||
#define CFG_TUD_MIDI CONFIG_TINYUSB_MIDI_ENABLED
|
||||
#define CFG_TUD_CUSTOM_CLASS CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,33 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
/**
|
||||
* @brief Redirect output to the USB serial
|
||||
* @param cdc_intf - interface number of TinyUSB's CDC
|
||||
*
|
||||
* @return esp_err_t - ESP_OK, ESP_FAIL or an error code
|
||||
*/
|
||||
esp_err_t esp_tusb_init_console(int cdc_intf);
|
||||
|
||||
/**
|
||||
* @brief Switch log to the default output
|
||||
* @param cdc_intf - interface number of TinyUSB's CDC
|
||||
*
|
||||
* @return esp_err_t
|
||||
*/
|
||||
esp_err_t esp_tusb_deinit_console(int cdc_intf);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,38 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief 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.
|
||||
*
|
||||
* @retval ESP_OK run tinyusb main task successfully
|
||||
* @retval ESP_FAIL run tinyusb main task failed of internal error
|
||||
* @retval ESP_ERR_INVALID_STATE tinyusb main task has been created before
|
||||
*/
|
||||
esp_err_t tusb_run_task(void);
|
||||
|
||||
/**
|
||||
* @brief This helper function stops and destroys the task created by `tusb_run_task()`
|
||||
*
|
||||
* @retval ESP_OK stop and destory tinyusb main task successfully
|
||||
* @retval ESP_ERR_INVALID_STATE tinyusb main task hasn't been created yet
|
||||
*/
|
||||
esp_err_t tusb_stop_task(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,34 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Register TinyUSB CDC at VFS with path
|
||||
* @param cdc_intf - interface number of TinyUSB's CDC
|
||||
* @param path - path where the CDC will be registered, `/dev/tusb_cdc` will be used if left NULL.
|
||||
*
|
||||
* @return esp_err_t ESP_OK or ESP_FAIL
|
||||
*/
|
||||
esp_err_t esp_vfs_tusb_cdc_register(int cdc_intf, char const *path);
|
||||
|
||||
/**
|
||||
* @brief Unregister TinyUSB CDC from VFS
|
||||
* @param path - path where the CDC will be unregistered if NULL will be used `/dev/tusb_cdc`
|
||||
*
|
||||
* @return esp_err_t ESP_OK or ESP_FAIL
|
||||
*/
|
||||
esp_err_t esp_vfs_tusb_cdc_unregister(char const *path);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,82 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "tusb.h"
|
||||
#include "tinyusb_types.h"
|
||||
|
||||
/* CDC classification
|
||||
********************************************************************* */
|
||||
typedef enum {
|
||||
TINYUSB_CDC_DATA = 0x00,
|
||||
} cdc_data_sublcass_type_t; // CDC120 specification
|
||||
|
||||
/* Note:other classification is represented in the file components\tinyusb\tinyusb\src\class\cdc\cdc.h */
|
||||
|
||||
/*********************************************************************** CDC classification*/
|
||||
/* Structs
|
||||
********************************************************************* */
|
||||
typedef struct {
|
||||
tinyusb_usbdev_t usb_dev; /*!< USB device to set up */
|
||||
tusb_class_code_t cdc_class; /*!< CDC device class : Communications or Data device */
|
||||
union {
|
||||
cdc_comm_sublcass_type_t comm_subclass; /*!< Communications device subclasses: ACM, ECM, etc. */
|
||||
cdc_data_sublcass_type_t data_subclass; /*!< Data device has only one subclass.*/
|
||||
} cdc_subclass; /*!< CDC device subclass according to Class Definitions for Communications Devices the CDC v.1.20 */
|
||||
} tinyusb_config_cdc_t; /*!< Main configuration structure of a CDC device */
|
||||
|
||||
typedef struct {
|
||||
tinyusb_usbdev_t usb_dev; /*!< USB device used for the instance */
|
||||
tusb_class_code_t type;
|
||||
union {
|
||||
cdc_comm_sublcass_type_t comm_subclass; /*!< Communications device subclasses: ACM, ECM, etc. */
|
||||
cdc_data_sublcass_type_t data_subclass; /*!< Data device has only one subclass.*/
|
||||
} cdc_subclass; /*!< CDC device subclass according to Class Definitions for Communications Devices the CDC v.1.20 */
|
||||
void *subclass_obj; /*!< Dynamically allocated subclass specific object */
|
||||
} esp_tusb_cdc_t;
|
||||
/*********************************************************************** Structs*/
|
||||
/* Functions
|
||||
********************************************************************* */
|
||||
/**
|
||||
* @brief Initializing CDC basic object
|
||||
* @param itf - number of a CDC object
|
||||
* @param cfg - CDC configuration structure
|
||||
*
|
||||
* @return esp_err_t ESP_OK or ESP_FAIL
|
||||
*/
|
||||
esp_err_t tinyusb_cdc_init(int itf, const tinyusb_config_cdc_t *cfg);
|
||||
|
||||
|
||||
/**
|
||||
* @brief De-initializing CDC. Clean its objects
|
||||
* @param itf - number of a CDC object
|
||||
* @return esp_err_t ESP_OK, ESP_ERR_INVALID_ARG, ESP_ERR_INVALID_STATE
|
||||
*
|
||||
*/
|
||||
esp_err_t tinyusb_cdc_deinit(int itf);
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return interface of a CDC device
|
||||
*
|
||||
* @param itf_num
|
||||
* @return esp_tusb_cdc_t* pointer to the interface or (NULL) on error
|
||||
*/
|
||||
esp_tusb_cdc_t *tinyusb_cdc_get_intf(int itf_num);
|
||||
/*********************************************************************** Functions*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,23 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tusb.h"
|
||||
#include "tinyusb_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void tusb_set_descriptor(const tusb_desc_device_t *dev_desc, const char **str_desc, const uint8_t *cfg_desc);
|
||||
tusb_desc_device_t *tusb_get_active_desc(void);
|
||||
char **tusb_get_active_str_desc(void);
|
||||
void tusb_clear_descriptor(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,27 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tusb.h"
|
||||
#include "tinyusb_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n))
|
||||
|
||||
extern tusb_desc_device_t descriptor_tinyusb;
|
||||
extern tusb_desc_strarray_device_t descriptor_str_tinyusb;
|
||||
|
||||
extern const tusb_desc_device_t descriptor_dev_kconfig;
|
||||
extern tusb_desc_strarray_device_t descriptor_str_kconfig;
|
||||
extern const uint8_t descriptor_cfg_kconfig[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -1,109 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_check.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "tusb.h"
|
||||
#include "cdc.h"
|
||||
|
||||
#define CDC_INTF_NUM CFG_TUD_CDC // number of cdc blocks
|
||||
static esp_tusb_cdc_t *cdc_obj[CDC_INTF_NUM] = {};
|
||||
static const char *TAG = "tusb_cdc";
|
||||
|
||||
esp_tusb_cdc_t *tinyusb_cdc_get_intf(int itf_num)
|
||||
{
|
||||
if (itf_num >= CDC_INTF_NUM || itf_num < 0) {
|
||||
return NULL;
|
||||
}
|
||||
return cdc_obj[itf_num];
|
||||
}
|
||||
|
||||
static esp_err_t cdc_obj_check(int itf, bool expected_inited, tusb_class_code_t expected_type)
|
||||
{
|
||||
esp_tusb_cdc_t *this_itf = tinyusb_cdc_get_intf(itf);
|
||||
|
||||
bool inited = (this_itf != NULL);
|
||||
ESP_RETURN_ON_FALSE(expected_inited == inited, ESP_ERR_INVALID_STATE, TAG, "Wrong state of the interface. Expected state: %s", expected_inited ? "initialized" : "not initialized");
|
||||
ESP_RETURN_ON_FALSE(!(inited && (expected_type != -1) && !(this_itf->type == expected_type)), ESP_ERR_INVALID_STATE, TAG, "Wrong type of the interface. Should be : 0x%x (tusb_class_code_t)", expected_type);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t tusb_cdc_comm_init(int itf)
|
||||
{
|
||||
ESP_RETURN_ON_ERROR(cdc_obj_check(itf, false, -1), TAG, "cdc_obj_check failed");
|
||||
cdc_obj[itf] = calloc(1, sizeof(esp_tusb_cdc_t));
|
||||
if (cdc_obj[itf] != NULL) {
|
||||
cdc_obj[itf]->type = TUSB_CLASS_CDC;
|
||||
ESP_LOGD(TAG, "CDC Comm class initialized");
|
||||
return ESP_OK;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "CDC Comm initialization error");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t tusb_cdc_deinit_comm(int itf)
|
||||
{
|
||||
ESP_RETURN_ON_ERROR(cdc_obj_check(itf, true, TUSB_CLASS_CDC), TAG, "cdc_obj_check failed");
|
||||
free(cdc_obj[itf]);
|
||||
cdc_obj[itf] = NULL;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t tusb_cdc_data_init(int itf)
|
||||
{
|
||||
ESP_RETURN_ON_ERROR(cdc_obj_check(itf, false, TUSB_CLASS_CDC_DATA), TAG, "cdc_obj_check failed");
|
||||
cdc_obj[itf] = calloc(1, sizeof(esp_tusb_cdc_t));
|
||||
if (cdc_obj[itf] != NULL) {
|
||||
cdc_obj[itf]->type = TUSB_CLASS_CDC_DATA;
|
||||
ESP_LOGD(TAG, "CDC Data class initialized");
|
||||
return ESP_OK;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "CDC Data initialization error");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t tusb_cdc_deinit_data(int itf)
|
||||
{
|
||||
ESP_RETURN_ON_ERROR(cdc_obj_check(itf, true, TUSB_CLASS_CDC_DATA), TAG, "cdc_obj_check failed");
|
||||
free(cdc_obj[itf]);
|
||||
cdc_obj[itf] = NULL;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t tinyusb_cdc_init(int itf, const tinyusb_config_cdc_t *cfg)
|
||||
{
|
||||
ESP_RETURN_ON_ERROR(cdc_obj_check(itf, false, -1), TAG, "cdc_obj_check failed");
|
||||
|
||||
ESP_LOGD(TAG, "Init CDC %d", itf);
|
||||
if (cfg->cdc_class == TUSB_CLASS_CDC) {
|
||||
ESP_RETURN_ON_ERROR(tusb_cdc_comm_init(itf), TAG, "tusb_cdc_comm_init failed");
|
||||
cdc_obj[itf]->cdc_subclass.comm_subclass = cfg->cdc_subclass.comm_subclass;
|
||||
} else {
|
||||
ESP_RETURN_ON_ERROR(tusb_cdc_data_init(itf), TAG, "tusb_cdc_data_init failed");
|
||||
cdc_obj[itf]->cdc_subclass.data_subclass = cfg->cdc_subclass.data_subclass;
|
||||
}
|
||||
cdc_obj[itf]->usb_dev = cfg->usb_dev;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t tinyusb_cdc_deinit(int itf)
|
||||
{
|
||||
ESP_RETURN_ON_ERROR(cdc_obj_check(itf, true, -1), TAG, "cdc_obj_check failed");
|
||||
|
||||
ESP_LOGD(TAG, "Deinit CDC %d", itf);
|
||||
if (cdc_obj[itf]->type == TUSB_CLASS_CDC) {
|
||||
ESP_RETURN_ON_ERROR(tusb_cdc_deinit_comm(itf), TAG, "tusb_cdc_deinit_comm failed");
|
||||
} else if (cdc_obj[itf]->type == TUSB_CLASS_CDC_DATA) {
|
||||
ESP_RETURN_ON_ERROR(tusb_cdc_deinit_data(itf), TAG, "tusb_cdc_deinit_data failed");
|
||||
} else {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
@ -1,144 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "esp_log.h"
|
||||
#include "descriptors_control.h"
|
||||
|
||||
static const char *TAG = "tusb_desc";
|
||||
static tusb_desc_device_t s_device_descriptor;
|
||||
static const uint8_t *s_configuration_descriptor;
|
||||
static char *s_str_descriptor[USB_STRING_DESCRIPTOR_ARRAY_SIZE];
|
||||
#define MAX_DESC_BUF_SIZE 32
|
||||
|
||||
// =============================================================================
|
||||
// CALLBACKS
|
||||
// =============================================================================
|
||||
|
||||
/**
|
||||
* @brief Invoked when received GET DEVICE DESCRIPTOR.
|
||||
* Application returns pointer to descriptor
|
||||
*
|
||||
* @return uint8_t const*
|
||||
*/
|
||||
uint8_t const *tud_descriptor_device_cb(void)
|
||||
{
|
||||
return (uint8_t const *)&s_device_descriptor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Invoked when received GET CONFIGURATION DESCRIPTOR.
|
||||
* Descriptor contents must exist long enough for transfer to complete
|
||||
*
|
||||
* @param index
|
||||
* @return uint8_t const* Application return pointer to descriptor
|
||||
*/
|
||||
uint8_t const *tud_descriptor_configuration_cb(uint8_t index)
|
||||
{
|
||||
(void)index; // for multiple configurations
|
||||
return s_configuration_descriptor;
|
||||
}
|
||||
|
||||
static uint16_t _desc_str[MAX_DESC_BUF_SIZE];
|
||||
|
||||
// Invoked when received GET STRING DESCRIPTOR request
|
||||
// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
|
||||
uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid)
|
||||
{
|
||||
(void) langid;
|
||||
|
||||
uint8_t chr_count;
|
||||
|
||||
if ( index == 0) {
|
||||
memcpy(&_desc_str[1], s_str_descriptor[0], 2);
|
||||
chr_count = 1;
|
||||
} else {
|
||||
// Convert ASCII string into UTF-16
|
||||
|
||||
if ( index >= sizeof(s_str_descriptor) / sizeof(s_str_descriptor[0]) ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *str = s_str_descriptor[index];
|
||||
|
||||
// Cap at max char
|
||||
chr_count = strlen(str);
|
||||
if ( chr_count > MAX_DESC_BUF_SIZE - 1 ) {
|
||||
chr_count = MAX_DESC_BUF_SIZE - 1;
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < chr_count; i++) {
|
||||
_desc_str[1 + i] = str[i];
|
||||
}
|
||||
}
|
||||
|
||||
// first byte is length (including header), second byte is string type
|
||||
_desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2 * chr_count + 2);
|
||||
|
||||
return _desc_str;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Driver functions
|
||||
// =============================================================================
|
||||
|
||||
void tusb_set_descriptor(const tusb_desc_device_t *dev_desc, const char **str_desc, const uint8_t *cfg_desc)
|
||||
{
|
||||
ESP_LOGI(TAG, "\n"
|
||||
"┌─────────────────────────────────┐\n"
|
||||
"│ USB Device Descriptor Summary │\n"
|
||||
"├───────────────────┬─────────────┤\n"
|
||||
"│bDeviceClass │ %-4u │\n"
|
||||
"├───────────────────┼─────────────┤\n"
|
||||
"│bDeviceSubClass │ %-4u │\n"
|
||||
"├───────────────────┼─────────────┤\n"
|
||||
"│bDeviceProtocol │ %-4u │\n"
|
||||
"├───────────────────┼─────────────┤\n"
|
||||
"│bMaxPacketSize0 │ %-4u │\n"
|
||||
"├───────────────────┼─────────────┤\n"
|
||||
"│idVendor │ %-#10x │\n"
|
||||
"├───────────────────┼─────────────┤\n"
|
||||
"│idProduct │ %-#10x │\n"
|
||||
"├───────────────────┼─────────────┤\n"
|
||||
"│bcdDevice │ %-#10x │\n"
|
||||
"├───────────────────┼─────────────┤\n"
|
||||
"│iManufacturer │ %-#10x │\n"
|
||||
"├───────────────────┼─────────────┤\n"
|
||||
"│iProduct │ %-#10x │\n"
|
||||
"├───────────────────┼─────────────┤\n"
|
||||
"│iSerialNumber │ %-#10x │\n"
|
||||
"├───────────────────┼─────────────┤\n"
|
||||
"│bNumConfigurations │ %-#10x │\n"
|
||||
"└───────────────────┴─────────────┘",
|
||||
dev_desc->bDeviceClass, dev_desc->bDeviceSubClass,
|
||||
dev_desc->bDeviceProtocol, dev_desc->bMaxPacketSize0,
|
||||
dev_desc->idVendor, dev_desc->idProduct, dev_desc->bcdDevice,
|
||||
dev_desc->iManufacturer, dev_desc->iProduct, dev_desc->iSerialNumber,
|
||||
dev_desc->bNumConfigurations);
|
||||
s_device_descriptor = *dev_desc;
|
||||
s_configuration_descriptor = cfg_desc;
|
||||
|
||||
if (str_desc != NULL) {
|
||||
memcpy(s_str_descriptor, str_desc,
|
||||
sizeof(s_str_descriptor[0])*USB_STRING_DESCRIPTOR_ARRAY_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
tusb_desc_device_t *tusb_get_active_desc(void)
|
||||
{
|
||||
return &s_device_descriptor;
|
||||
}
|
||||
|
||||
char **tusb_get_active_str_desc(void)
|
||||
{
|
||||
return s_str_descriptor;
|
||||
}
|
||||
|
||||
void tusb_clear_descriptor(void)
|
||||
{
|
||||
memset(&s_device_descriptor, 0, sizeof(s_device_descriptor));
|
||||
memset(&s_str_descriptor, 0, sizeof(s_str_descriptor));
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "esp_private/usb_phy.h"
|
||||
#include "soc/usb_pins.h"
|
||||
#include "tinyusb.h"
|
||||
#include "descriptors_control.h"
|
||||
#include "usb_descriptors.h"
|
||||
#include "tusb.h"
|
||||
#include "tusb_tasks.h"
|
||||
|
||||
const static char *TAG = "TinyUSB";
|
||||
static usb_phy_handle_t phy_hdl;
|
||||
|
||||
esp_err_t tinyusb_driver_install(const tinyusb_config_t *config)
|
||||
{
|
||||
const tusb_desc_device_t *dev_descriptor;
|
||||
const char **string_descriptor;
|
||||
const uint8_t *cfg_descriptor;
|
||||
ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
|
||||
// Configure USB PHY
|
||||
usb_phy_config_t phy_conf = {
|
||||
.controller = USB_PHY_CTRL_OTG,
|
||||
.otg_mode = USB_OTG_MODE_DEVICE,
|
||||
};
|
||||
|
||||
// External PHY IOs config
|
||||
usb_phy_ext_io_conf_t ext_io_conf = {
|
||||
.vp_io_num = USBPHY_VP_NUM,
|
||||
.vm_io_num = USBPHY_VM_NUM,
|
||||
.rcv_io_num = USBPHY_RCV_NUM,
|
||||
.oen_io_num = USBPHY_OEN_NUM,
|
||||
.vpo_io_num = USBPHY_VPO_NUM,
|
||||
.vmo_io_num = USBPHY_VMO_NUM,
|
||||
};
|
||||
if (config->external_phy) {
|
||||
phy_conf.target = USB_PHY_TARGET_EXT;
|
||||
phy_conf.ext_io_conf = &ext_io_conf;
|
||||
} else {
|
||||
phy_conf.target = USB_PHY_TARGET_INT;
|
||||
}
|
||||
|
||||
// OTG IOs config
|
||||
const usb_phy_otg_io_conf_t otg_io_conf = USB_PHY_SELF_POWERED_DEVICE(config->vbus_monitor_io);
|
||||
if (config->self_powered) {
|
||||
phy_conf.otg_io_conf = &otg_io_conf;
|
||||
}
|
||||
ESP_RETURN_ON_ERROR(usb_new_phy(&phy_conf, &phy_hdl), TAG, "Install USB PHY failed");
|
||||
|
||||
#if (CONFIG_TINYUSB_HID_COUNT > 0)
|
||||
// For HID device, configuration descriptor must be provided
|
||||
ESP_RETURN_ON_FALSE(config->configuration_descriptor, ESP_ERR_INVALID_ARG, TAG, "Configuration descriptor must be provided for HID device");
|
||||
#endif
|
||||
dev_descriptor = config->device_descriptor ? config->device_descriptor : &descriptor_dev_kconfig;
|
||||
string_descriptor = config->string_descriptor ? config->string_descriptor : descriptor_str_kconfig;
|
||||
cfg_descriptor = config->configuration_descriptor ? config->configuration_descriptor : descriptor_cfg_kconfig;
|
||||
|
||||
tusb_set_descriptor(dev_descriptor, string_descriptor, cfg_descriptor);
|
||||
|
||||
ESP_RETURN_ON_FALSE(tusb_init(), ESP_FAIL, TAG, "Init TinyUSB stack failed");
|
||||
#if !CONFIG_TINYUSB_NO_DEFAULT_TASK
|
||||
ESP_RETURN_ON_ERROR(tusb_run_task(), TAG, "Run TinyUSB task failed");
|
||||
#endif
|
||||
ESP_LOGI(TAG, "TinyUSB Driver installed");
|
||||
return ESP_OK;
|
||||
}
|
@ -1,415 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_check.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/ringbuf.h"
|
||||
#include "tusb.h"
|
||||
#include "tusb_cdc_acm.h"
|
||||
#include "cdc.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#define RX_UNREADBUF_SZ_DEFAULT 64 // buffer storing all unread RX data
|
||||
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||
|
||||
|
||||
typedef struct {
|
||||
bool initialized;
|
||||
size_t rx_unread_buf_sz;
|
||||
RingbufHandle_t rx_unread_buf;
|
||||
SemaphoreHandle_t ringbuf_read_mux;
|
||||
uint8_t *rx_tfbuf;
|
||||
tusb_cdcacm_callback_t callback_rx;
|
||||
tusb_cdcacm_callback_t callback_rx_wanted_char;
|
||||
tusb_cdcacm_callback_t callback_line_state_changed;
|
||||
tusb_cdcacm_callback_t callback_line_coding_changed;
|
||||
} esp_tusb_cdcacm_t; /*!< CDC_ACM object */
|
||||
|
||||
static const char *TAG = "tusb_cdc_acm";
|
||||
|
||||
static inline esp_tusb_cdcacm_t *get_acm(tinyusb_cdcacm_itf_t itf)
|
||||
{
|
||||
esp_tusb_cdc_t *cdc_inst = tinyusb_cdc_get_intf(itf);
|
||||
if (cdc_inst == NULL) {
|
||||
return (esp_tusb_cdcacm_t *)NULL;
|
||||
}
|
||||
return (esp_tusb_cdcacm_t *)(cdc_inst->subclass_obj);
|
||||
}
|
||||
|
||||
|
||||
/* TinyUSB callbacks
|
||||
********************************************************************* */
|
||||
|
||||
/* Invoked by cdc interface when line state changed e.g connected/disconnected */
|
||||
void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts)
|
||||
{
|
||||
esp_tusb_cdcacm_t *acm = get_acm(itf);
|
||||
if (dtr && rts) { // connected
|
||||
if (acm != NULL) {
|
||||
ESP_LOGV(TAG, "Host connected to CDC no.%d.", itf);
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Host is connected to CDC no.%d, but it is not initialized. Initialize it using `tinyusb_cdc_init`.", itf);
|
||||
return;
|
||||
}
|
||||
} else { // disconnected
|
||||
if (acm != NULL) {
|
||||
ESP_LOGV(TAG, "Serial device is ready to connect to CDC no.%d", itf);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (acm) {
|
||||
tusb_cdcacm_callback_t cb = acm->callback_line_state_changed;
|
||||
if (cb) {
|
||||
cdcacm_event_t event = {
|
||||
.type = CDC_EVENT_LINE_STATE_CHANGED,
|
||||
.line_state_changed_data = {
|
||||
.dtr = dtr,
|
||||
.rts = rts
|
||||
}
|
||||
};
|
||||
cb(itf, &event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Invoked when CDC interface received data from host */
|
||||
void tud_cdc_rx_cb(uint8_t itf)
|
||||
{
|
||||
esp_tusb_cdcacm_t *acm = get_acm(itf);
|
||||
if (acm) {
|
||||
if (!acm->rx_unread_buf) {
|
||||
ESP_LOGE(TAG, "There is no RX buffer created");
|
||||
abort();
|
||||
}
|
||||
} else {
|
||||
tud_cdc_n_read_flush(itf); // we have no place to store data, so just drop it
|
||||
return;
|
||||
}
|
||||
while (tud_cdc_n_available(itf)) {
|
||||
int read_res = tud_cdc_n_read( itf,
|
||||
acm->rx_tfbuf,
|
||||
CONFIG_TINYUSB_CDC_RX_BUFSIZE );
|
||||
int res = xRingbufferSend(acm->rx_unread_buf,
|
||||
acm->rx_tfbuf,
|
||||
read_res, 0);
|
||||
if (res != pdTRUE) {
|
||||
ESP_LOGW(TAG, "The unread buffer is too small, the data has been lost");
|
||||
} else {
|
||||
ESP_LOGV(TAG, "Sent %d bytes to the buffer", read_res);
|
||||
}
|
||||
}
|
||||
if (acm) {
|
||||
tusb_cdcacm_callback_t cb = acm->callback_rx;
|
||||
if (cb) {
|
||||
cdcacm_event_t event = {
|
||||
.type = CDC_EVENT_RX
|
||||
};
|
||||
cb(itf, &event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Invoked when line coding is change via SET_LINE_CODING
|
||||
void tud_cdc_line_coding_cb(uint8_t itf, cdc_line_coding_t const *p_line_coding)
|
||||
{
|
||||
esp_tusb_cdcacm_t *acm = get_acm(itf);
|
||||
if (acm) {
|
||||
tusb_cdcacm_callback_t cb = acm->callback_line_coding_changed;
|
||||
if (cb) {
|
||||
cdcacm_event_t event = {
|
||||
.type = CDC_EVENT_LINE_CODING_CHANGED,
|
||||
.line_coding_changed_data = {
|
||||
.p_line_coding = p_line_coding,
|
||||
}
|
||||
};
|
||||
cb(itf, &event);
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Invoked when received `wanted_char`
|
||||
void tud_cdc_rx_wanted_cb(uint8_t itf, char wanted_char)
|
||||
{
|
||||
esp_tusb_cdcacm_t *acm = get_acm(itf);
|
||||
if (acm) {
|
||||
tusb_cdcacm_callback_t cb = acm->callback_rx_wanted_char;
|
||||
if (cb) {
|
||||
cdcacm_event_t event = {
|
||||
.type = CDC_EVENT_RX_WANTED_CHAR,
|
||||
.rx_wanted_char_data = {
|
||||
.wanted_char = wanted_char,
|
||||
}
|
||||
};
|
||||
cb(itf, &event);
|
||||
}
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t tinyusb_cdcacm_register_callback(tinyusb_cdcacm_itf_t itf,
|
||||
cdcacm_event_type_t event_type,
|
||||
tusb_cdcacm_callback_t callback)
|
||||
{
|
||||
esp_tusb_cdcacm_t *acm = get_acm(itf);
|
||||
if (acm) {
|
||||
switch (event_type) {
|
||||
case CDC_EVENT_RX:
|
||||
acm->callback_rx = callback;
|
||||
return ESP_OK;
|
||||
case CDC_EVENT_RX_WANTED_CHAR:
|
||||
acm->callback_rx_wanted_char = callback;
|
||||
return ESP_OK;
|
||||
case CDC_EVENT_LINE_STATE_CHANGED:
|
||||
acm->callback_line_state_changed = callback;
|
||||
return ESP_OK;
|
||||
case CDC_EVENT_LINE_CODING_CHANGED:
|
||||
acm->callback_line_coding_changed = callback;
|
||||
return ESP_OK;
|
||||
default:
|
||||
ESP_LOGE(TAG, "Wrong event type");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "CDC-ACM is not initialized");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t tinyusb_cdcacm_unregister_callback(tinyusb_cdcacm_itf_t itf,
|
||||
cdcacm_event_type_t event_type)
|
||||
{
|
||||
esp_tusb_cdcacm_t *acm = get_acm(itf);
|
||||
if (!acm) {
|
||||
ESP_LOGE(TAG, "Interface is not initialized. Use `tinyusb_cdc_init` for initialization");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
switch (event_type) {
|
||||
case CDC_EVENT_RX:
|
||||
acm->callback_rx = NULL;
|
||||
return ESP_OK;
|
||||
case CDC_EVENT_RX_WANTED_CHAR:
|
||||
acm->callback_rx_wanted_char = NULL;
|
||||
return ESP_OK;
|
||||
case CDC_EVENT_LINE_STATE_CHANGED:
|
||||
acm->callback_line_state_changed = NULL;
|
||||
return ESP_OK;
|
||||
case CDC_EVENT_LINE_CODING_CHANGED:
|
||||
acm->callback_line_coding_changed = NULL;
|
||||
return ESP_OK;
|
||||
default:
|
||||
ESP_LOGE(TAG, "Wrong event type");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
|
||||
/*********************************************************************** TinyUSB callbacks*/
|
||||
/* CDC-ACM
|
||||
********************************************************************* */
|
||||
|
||||
static esp_err_t read_from_rx_unread_to_buffer(esp_tusb_cdcacm_t *acm, uint8_t *out_buf, size_t req_bytes, size_t *read_bytes)
|
||||
{
|
||||
uint8_t *buf = xRingbufferReceiveUpTo(acm->rx_unread_buf, read_bytes, 0, req_bytes);
|
||||
if (buf) {
|
||||
memcpy(out_buf, buf, *read_bytes);
|
||||
vRingbufferReturnItem(acm->rx_unread_buf, (void *)(buf));
|
||||
return ESP_OK;
|
||||
} else {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t ringbuf_mux_take(esp_tusb_cdcacm_t *acm)
|
||||
{
|
||||
if (xSemaphoreTake(acm->ringbuf_read_mux, 0) != pdTRUE) {
|
||||
ESP_LOGW(TAG, "Read error: ACM is busy");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t ringbuf_mux_give(esp_tusb_cdcacm_t *acm)
|
||||
{
|
||||
BaseType_t ret = xSemaphoreGive(acm->ringbuf_read_mux);
|
||||
assert(ret == pdTRUE);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
esp_tusb_cdcacm_t *acm = get_acm(itf);
|
||||
ESP_RETURN_ON_FALSE(acm, ESP_ERR_INVALID_STATE, TAG, "Interface is not initialized. Use `tinyusb_cdc_init` for initialization");
|
||||
size_t read_sz;
|
||||
|
||||
/* Take a mutex to proceed two uninterrupted read operations */
|
||||
ESP_RETURN_ON_ERROR(ringbuf_mux_take(acm), TAG, "ringbuf_mux_take failed");
|
||||
|
||||
esp_err_t res = read_from_rx_unread_to_buffer(acm, out_buf, out_buf_sz, &read_sz);
|
||||
if (res != ESP_OK) {
|
||||
ESP_RETURN_ON_ERROR(ringbuf_mux_give(acm), TAG, "ringbuf_mux_give failed");
|
||||
return res;
|
||||
}
|
||||
|
||||
*rx_data_size = read_sz;
|
||||
/* Buffer's data can be wrapped, at that situations we should make another retrievement */
|
||||
if (read_from_rx_unread_to_buffer(acm, out_buf + read_sz, out_buf_sz - read_sz, &read_sz) == ESP_OK) {
|
||||
*rx_data_size += read_sz;
|
||||
}
|
||||
|
||||
ESP_RETURN_ON_ERROR(ringbuf_mux_give(acm), TAG, "ringbuf_mux_give failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
size_t tinyusb_cdcacm_write_queue_char(tinyusb_cdcacm_itf_t itf, char ch)
|
||||
{
|
||||
if (!get_acm(itf)) { // non-initialized
|
||||
return 0;
|
||||
}
|
||||
return tud_cdc_n_write_char(itf, ch);
|
||||
}
|
||||
|
||||
size_t tinyusb_cdcacm_write_queue(tinyusb_cdcacm_itf_t itf, const uint8_t *in_buf, size_t in_size)
|
||||
{
|
||||
if (!get_acm(itf)) { // non-initialized
|
||||
return 0;
|
||||
}
|
||||
const uint32_t size_available = tud_cdc_n_write_available(itf);
|
||||
return tud_cdc_n_write(itf, in_buf, MIN(in_size, size_available));
|
||||
}
|
||||
|
||||
static uint32_t tud_cdc_n_write_occupied(tinyusb_cdcacm_itf_t itf)
|
||||
{
|
||||
return CFG_TUD_CDC_TX_BUFSIZE - tud_cdc_n_write_available(itf);
|
||||
}
|
||||
|
||||
esp_err_t tinyusb_cdcacm_write_flush(tinyusb_cdcacm_itf_t itf, uint32_t timeout_ticks)
|
||||
{
|
||||
if (!get_acm(itf)) { // non-initialized
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (!timeout_ticks) { // if no timeout - nonblocking mode
|
||||
int res = tud_cdc_n_write_flush(itf);
|
||||
if (!res) {
|
||||
ESP_LOGW(TAG, "flush failed (res: %d)", res);
|
||||
return ESP_FAIL;
|
||||
} else {
|
||||
if (tud_cdc_n_write_occupied(itf)) {
|
||||
ESP_LOGW(TAG, "remained data to flush!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
return ESP_ERR_TIMEOUT;
|
||||
} else { // trying during the timeout
|
||||
uint32_t ticks_start = xTaskGetTickCount();
|
||||
uint32_t ticks_now = ticks_start;
|
||||
while (1) { // loop until success or until the time runs out
|
||||
ticks_now = xTaskGetTickCount();
|
||||
if (!tud_cdc_n_write_occupied(itf)) { // if nothing to write - nothing to flush
|
||||
break;
|
||||
}
|
||||
if (tud_cdc_n_write_flush(itf)) { // Success
|
||||
break;
|
||||
}
|
||||
if ( (ticks_now - ticks_start) > timeout_ticks ) { // Time is up
|
||||
ESP_LOGW(TAG, "Flush failed");
|
||||
return ESP_ERR_TIMEOUT;
|
||||
}
|
||||
vTaskDelay(1);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t alloc_obj(tinyusb_cdcacm_itf_t itf)
|
||||
{
|
||||
esp_tusb_cdc_t *cdc_inst = tinyusb_cdc_get_intf(itf);
|
||||
cdc_inst->subclass_obj = calloc(1, sizeof(esp_tusb_cdcacm_t));
|
||||
if (!cdc_inst->subclass_obj) {
|
||||
return ESP_FAIL;
|
||||
} else {
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
|
||||
static void free_obj(tinyusb_cdcacm_itf_t itf)
|
||||
{
|
||||
esp_tusb_cdc_t *cdc_inst = tinyusb_cdc_get_intf(itf);
|
||||
free(cdc_inst->subclass_obj);
|
||||
cdc_inst->subclass_obj = NULL;
|
||||
}
|
||||
|
||||
esp_err_t tusb_cdc_acm_init(const tinyusb_config_cdcacm_t *cfg)
|
||||
{
|
||||
int itf = (int)cfg->cdc_port;
|
||||
/* Creating a CDC object */
|
||||
const tinyusb_config_cdc_t cdc_cfg = {
|
||||
.usb_dev = cfg->usb_dev,
|
||||
.cdc_class = TUSB_CLASS_CDC,
|
||||
.cdc_subclass.comm_subclass = CDC_COMM_SUBCLASS_ABSTRACT_CONTROL_MODEL
|
||||
};
|
||||
ESP_RETURN_ON_ERROR(tinyusb_cdc_init(itf, &cdc_cfg), TAG, "tinyusb_cdc_init failed");
|
||||
ESP_RETURN_ON_ERROR(alloc_obj(itf), TAG, "alloc_obj failed");
|
||||
|
||||
esp_tusb_cdcacm_t *acm = get_acm(itf);
|
||||
/* Callbacks setting up*/
|
||||
if (cfg->callback_rx) {
|
||||
tinyusb_cdcacm_register_callback(itf, CDC_EVENT_RX, cfg->callback_rx);
|
||||
}
|
||||
if (cfg->callback_rx_wanted_char) {
|
||||
tinyusb_cdcacm_register_callback(itf, CDC_EVENT_RX_WANTED_CHAR, cfg->callback_rx_wanted_char);
|
||||
}
|
||||
if (cfg->callback_line_state_changed) {
|
||||
tinyusb_cdcacm_register_callback(itf, CDC_EVENT_LINE_STATE_CHANGED, cfg->callback_line_state_changed);
|
||||
}
|
||||
if (cfg->callback_line_coding_changed) {
|
||||
tinyusb_cdcacm_register_callback( itf, CDC_EVENT_LINE_CODING_CHANGED, cfg->callback_line_coding_changed);
|
||||
}
|
||||
|
||||
/* Buffers */
|
||||
|
||||
acm->ringbuf_read_mux = xSemaphoreCreateMutex();
|
||||
if (acm->ringbuf_read_mux == NULL) {
|
||||
ESP_LOGE(TAG, "Creation of a ringbuf mutex failed");
|
||||
free_obj(itf);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
acm->rx_tfbuf = malloc(CONFIG_TINYUSB_CDC_RX_BUFSIZE);
|
||||
if (!acm->rx_tfbuf) {
|
||||
ESP_LOGE(TAG, "Creation buffer error");
|
||||
free_obj(itf);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
acm->rx_unread_buf_sz = cfg->rx_unread_buf_sz == 0 ? RX_UNREADBUF_SZ_DEFAULT : cfg->rx_unread_buf_sz;
|
||||
acm->rx_unread_buf = xRingbufferCreate(acm->rx_unread_buf_sz, RINGBUF_TYPE_BYTEBUF);
|
||||
if (acm->rx_unread_buf == NULL) {
|
||||
ESP_LOGE(TAG, "Creation buffer error");
|
||||
free_obj(itf);
|
||||
return ESP_ERR_NO_MEM;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Comm Initialized buff:%d bytes", cfg->rx_unread_buf_sz);
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
|
||||
bool tusb_cdc_acm_initialized(tinyusb_cdcacm_itf_t itf)
|
||||
{
|
||||
esp_tusb_cdcacm_t *acm = get_acm(itf);
|
||||
if (acm) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
/*********************************************************************** CDC-ACM*/
|
@ -1,115 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdio_ext.h>
|
||||
#include "esp_log.h"
|
||||
#include "cdc.h"
|
||||
#include "tusb_console.h"
|
||||
#include "tinyusb.h"
|
||||
#include "vfs_tinyusb.h"
|
||||
#include "esp_check.h"
|
||||
|
||||
#define STRINGIFY(s) STRINGIFY2(s)
|
||||
#define STRINGIFY2(s) #s
|
||||
|
||||
static const char *TAG = "tusb_console";
|
||||
|
||||
typedef struct {
|
||||
FILE *in;
|
||||
FILE *out;
|
||||
FILE *err;
|
||||
} console_handle_t;
|
||||
|
||||
static console_handle_t con;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Reopen standard streams using a new path
|
||||
*
|
||||
* @param f_in - pointer to a pointer holding a file for in or NULL to don't change stdin
|
||||
* @param f_out - pointer to a pointer holding a file for out or NULL to don't change stdout
|
||||
* @param f_err - pointer to a pointer holding a file for err or NULL to don't change stderr
|
||||
* @param path - mount point
|
||||
* @return esp_err_t ESP_FAIL or ESP_OK
|
||||
*/
|
||||
static esp_err_t redirect_std_streams_to(FILE **f_in, FILE **f_out, FILE **f_err, const char *path)
|
||||
{
|
||||
if (f_in) {
|
||||
*f_in = freopen(path, "r", stdin);
|
||||
if (*f_in == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to reopen in!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
if (f_out) {
|
||||
*f_out = freopen(path, "w", stdout);
|
||||
if (*f_out == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to reopen out!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
if (f_err) {
|
||||
*f_err = freopen(path, "w", stderr);
|
||||
if (*f_err == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to reopen err!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Restore output to default
|
||||
*
|
||||
* @param f_in - pointer to a pointer of an in file updated with `redirect_std_streams_to` or NULL to don't change stdin
|
||||
* @param f_out - pointer to a pointer of an out file updated with `redirect_std_streams_to` or NULL to don't change stdout
|
||||
* @param f_err - pointer to a pointer of an err file updated with `redirect_std_streams_to` or NULL to don't change stderr
|
||||
* @return esp_err_t ESP_FAIL or ESP_OK
|
||||
*/
|
||||
static esp_err_t restore_std_streams(FILE **f_in, FILE **f_out, FILE **f_err)
|
||||
{
|
||||
const char *default_uart_dev = "/dev/uart/" STRINGIFY(CONFIG_ESP_CONSOLE_UART_NUM);
|
||||
if (f_in) {
|
||||
stdin = freopen(default_uart_dev, "r", *f_in);
|
||||
if (stdin == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to reopen stdin!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
if (f_out) {
|
||||
stdout = freopen(default_uart_dev, "w", *f_out);
|
||||
if (stdout == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to reopen stdout!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
if (f_err) {
|
||||
stderr = freopen(default_uart_dev, "w", *f_err);
|
||||
if (stderr == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to reopen stderr!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_tusb_init_console(int cdc_intf)
|
||||
{
|
||||
/* Registering TUSB at VFS */
|
||||
ESP_RETURN_ON_ERROR(esp_vfs_tusb_cdc_register(cdc_intf, NULL), TAG, "");
|
||||
ESP_RETURN_ON_ERROR(redirect_std_streams_to(&con.in, &con.out, &con.err, "/dev/tusb_cdc"), TAG, "Failed to redirect STD streams");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_tusb_deinit_console(int cdc_intf)
|
||||
{
|
||||
ESP_RETURN_ON_ERROR(restore_std_streams(&con.in, &con.out, &con.err), TAG, "Failed to restore STD streams");
|
||||
esp_vfs_tusb_cdc_unregister(NULL);
|
||||
return ESP_OK;
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_check.h"
|
||||
#include "tinyusb.h"
|
||||
#include "tusb_tasks.h"
|
||||
|
||||
const static char *TAG = "tusb_tsk";
|
||||
static TaskHandle_t s_tusb_tskh;
|
||||
|
||||
/**
|
||||
* @brief This top level thread processes all usb events and invokes callbacks
|
||||
*/
|
||||
static void tusb_device_task(void *arg)
|
||||
{
|
||||
ESP_LOGD(TAG, "tinyusb task started");
|
||||
while (1) { // RTOS forever loop
|
||||
tud_task();
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t tusb_run_task(void)
|
||||
{
|
||||
// This function is not garanteed to be thread safe, if invoked multiple times without calling `tusb_stop_task`, will cause memory leak
|
||||
// doing a sanity check anyway
|
||||
ESP_RETURN_ON_FALSE(!s_tusb_tskh, ESP_ERR_INVALID_STATE, TAG, "TinyUSB main task already started");
|
||||
// Create a task for tinyusb device stack:
|
||||
xTaskCreate(tusb_device_task, "TinyUSB", CONFIG_TINYUSB_TASK_STACK_SIZE, NULL, CONFIG_TINYUSB_TASK_PRIORITY, &s_tusb_tskh);
|
||||
ESP_RETURN_ON_FALSE(s_tusb_tskh, ESP_FAIL, TAG, "create TinyUSB main task failed");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t tusb_stop_task(void)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(s_tusb_tskh, ESP_ERR_INVALID_STATE, TAG, "TinyUSB main task not started yet");
|
||||
vTaskDelete(s_tusb_tskh);
|
||||
s_tusb_tskh = NULL;
|
||||
return ESP_OK;
|
||||
}
|
@ -1,210 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include "usb_descriptors.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/*
|
||||
* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
|
||||
* Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
|
||||
*
|
||||
* Auto ProductID layout's Bitmap:
|
||||
* [MSB] HID | MSC | CDC [LSB]
|
||||
*/
|
||||
#define USB_TUSB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
|
||||
_PID_MAP(MIDI, 3) ) //| _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) )
|
||||
|
||||
/**** TinyUSB default ****/
|
||||
tusb_desc_device_t descriptor_tinyusb = {
|
||||
.bLength = sizeof(descriptor_tinyusb),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
|
||||
#if CFG_TUD_CDC
|
||||
// Use Interface Association Descriptor (IAD) for CDC
|
||||
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
|
||||
.bDeviceClass = TUSB_CLASS_MISC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
#else
|
||||
.bDeviceClass = 0x00,
|
||||
.bDeviceSubClass = 0x00,
|
||||
.bDeviceProtocol = 0x00,
|
||||
#endif
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = 0xCafe,
|
||||
.idProduct = USB_TUSB_PID,
|
||||
.bcdDevice = 0x0100,
|
||||
|
||||
.iManufacturer = 0x01,
|
||||
.iProduct = 0x02,
|
||||
.iSerialNumber = 0x03,
|
||||
|
||||
.bNumConfigurations = 0x01
|
||||
};
|
||||
|
||||
tusb_desc_strarray_device_t descriptor_str_tinyusb = {
|
||||
// array of pointer to string descriptors
|
||||
(char[]){0x09, 0x04}, // 0: is supported language is English (0x0409)
|
||||
"TinyUSB", // 1: Manufacturer
|
||||
"TinyUSB Device", // 2: Product
|
||||
"123456", // 3: Serials, should use chip ID
|
||||
"TinyUSB CDC", // 4: CDC Interface
|
||||
"TinyUSB MSC", // 5: MSC Interface
|
||||
"TinyUSB MIDI" // 6: MIDI
|
||||
};
|
||||
/* End of TinyUSB default */
|
||||
|
||||
/**** Kconfig driven Descriptor ****/
|
||||
const tusb_desc_device_t descriptor_dev_kconfig = {
|
||||
.bLength = sizeof(descriptor_dev_kconfig),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200,
|
||||
|
||||
#if CFG_TUD_CDC
|
||||
// Use Interface Association Descriptor (IAD) for CDC
|
||||
// As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1)
|
||||
.bDeviceClass = TUSB_CLASS_MISC,
|
||||
.bDeviceSubClass = MISC_SUBCLASS_COMMON,
|
||||
.bDeviceProtocol = MISC_PROTOCOL_IAD,
|
||||
#else
|
||||
.bDeviceClass = 0x00,
|
||||
.bDeviceSubClass = 0x00,
|
||||
.bDeviceProtocol = 0x00,
|
||||
#endif
|
||||
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
#if CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID
|
||||
.idVendor = USB_ESPRESSIF_VID,
|
||||
#else
|
||||
.idVendor = CONFIG_TINYUSB_DESC_CUSTOM_VID,
|
||||
#endif
|
||||
|
||||
#if CONFIG_TINYUSB_DESC_USE_DEFAULT_PID
|
||||
.idProduct = USB_TUSB_PID,
|
||||
#else
|
||||
.idProduct = CONFIG_TINYUSB_DESC_CUSTOM_PID,
|
||||
#endif
|
||||
|
||||
.bcdDevice = CONFIG_TINYUSB_DESC_BCD_DEVICE,
|
||||
|
||||
.iManufacturer = 0x01,
|
||||
.iProduct = 0x02,
|
||||
.iSerialNumber = 0x03,
|
||||
|
||||
.bNumConfigurations = 0x01
|
||||
};
|
||||
|
||||
tusb_desc_strarray_device_t descriptor_str_kconfig = {
|
||||
// array of pointer to string descriptors
|
||||
(char[]){0x09, 0x04}, // 0: is supported language is English (0x0409)
|
||||
CONFIG_TINYUSB_DESC_MANUFACTURER_STRING, // 1: Manufacturer
|
||||
CONFIG_TINYUSB_DESC_PRODUCT_STRING, // 2: Product
|
||||
CONFIG_TINYUSB_DESC_SERIAL_STRING, // 3: Serials, should use chip ID
|
||||
|
||||
#if CONFIG_TINYUSB_CDC_ENABLED
|
||||
CONFIG_TINYUSB_DESC_CDC_STRING, // 4: CDC Interface
|
||||
#else
|
||||
"",
|
||||
#endif
|
||||
|
||||
#if CONFIG_TINYUSB_MSC_ENABLED
|
||||
CONFIG_TINYUSB_DESC_MSC_STRING, // 5: MSC Interface
|
||||
#else
|
||||
"",
|
||||
#endif
|
||||
|
||||
#if CONFIG_TINYUSB_MIDI_ENABLED
|
||||
CONFIG_TINYUSB_DESC_MIDI_STRING // 6: MIDI
|
||||
#else
|
||||
"",
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
//------------- Configuration Descriptor -------------//
|
||||
enum {
|
||||
#if CFG_TUD_CDC
|
||||
ITF_NUM_CDC = 0,
|
||||
ITF_NUM_CDC_DATA,
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_CDC > 1
|
||||
ITF_NUM_CDC1,
|
||||
ITF_NUM_CDC1_DATA,
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_MSC
|
||||
ITF_NUM_MSC,
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_MIDI
|
||||
ITF_NUM_MIDI,
|
||||
ITF_NUM_MIDI_STREAMING,
|
||||
#endif
|
||||
|
||||
ITF_NUM_TOTAL
|
||||
};
|
||||
|
||||
enum {
|
||||
TUSB_DESC_TOTAL_LEN = TUD_CONFIG_DESC_LEN +
|
||||
CFG_TUD_CDC * TUD_CDC_DESC_LEN +
|
||||
CFG_TUD_MSC * TUD_MSC_DESC_LEN +
|
||||
CFG_TUD_MIDI * TUD_MIDI_DESC_LEN
|
||||
};
|
||||
|
||||
//------------- USB Endpoint numbers -------------//
|
||||
enum {
|
||||
// Available USB Endpoints: 5 IN/OUT EPs and 1 IN EP
|
||||
EP_EMPTY = 0,
|
||||
#if CFG_TUD_CDC
|
||||
EPNUM_0_CDC_NOTIF,
|
||||
EPNUM_0_CDC,
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_CDC > 1
|
||||
EPNUM_1_CDC_NOTIF,
|
||||
EPNUM_1_CDC,
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_MSC
|
||||
EPNUM_MSC,
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_MIDI
|
||||
EPNUM_MIDI,
|
||||
#endif
|
||||
};
|
||||
|
||||
uint8_t const descriptor_cfg_kconfig[] = {
|
||||
// Configuration number, interface count, string index, total length, attribute, power in mA
|
||||
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
|
||||
|
||||
#if CFG_TUD_CDC
|
||||
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, 0x80 | EPNUM_0_CDC_NOTIF, 8, EPNUM_0_CDC, 0x80 | EPNUM_0_CDC, CFG_TUD_CDC_EP_BUFSIZE),
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_CDC > 1
|
||||
// Interface number, string index, EP notification address and size, EP data address (out, in) and size.
|
||||
TUD_CDC_DESCRIPTOR(ITF_NUM_CDC1, 4, 0x80 | EPNUM_1_CDC_NOTIF, 8, EPNUM_1_CDC, 0x80 | EPNUM_1_CDC, CFG_TUD_CDC_EP_BUFSIZE),
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_MSC
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC, 0x80 | EPNUM_MSC, 64), // highspeed 512
|
||||
#endif
|
||||
|
||||
#if CFG_TUD_MIDI
|
||||
// Interface number, string index, EP Out & EP In address, EP size
|
||||
TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 6, EPNUM_MIDI, 0x80 | EPNUM_MIDI, 64) // highspeed 512
|
||||
#endif
|
||||
};
|
||||
|
||||
/* End of Kconfig driven Descriptor */
|
@ -1,289 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <string.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/param.h>
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_vfs.h"
|
||||
#include "esp_vfs_dev.h"
|
||||
#include "tinyusb.h"
|
||||
#include "tusb_cdc_acm.h"
|
||||
#include "vfs_tinyusb.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
const static char *TAG = "tusb_vfs";
|
||||
#define VFS_TUSB_MAX_PATH 16
|
||||
#define VFS_TUSB_PATH_DEFAULT "/dev/tusb_cdc"
|
||||
|
||||
// Token signifying that no character is available
|
||||
#define NONE -1
|
||||
|
||||
#define FD_CHECK(fd, ret_val) do { \
|
||||
if ((fd) != 0) { \
|
||||
errno = EBADF; \
|
||||
return (ret_val); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
#if CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF
|
||||
# define DEFAULT_TX_MODE ESP_LINE_ENDINGS_CRLF
|
||||
#elif CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR
|
||||
# define DEFAULT_TX_MODE ESP_LINE_ENDINGS_CR
|
||||
#else
|
||||
# define DEFAULT_TX_MODE ESP_LINE_ENDINGS_LF
|
||||
#endif
|
||||
|
||||
#if CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF
|
||||
# define DEFAULT_RX_MODE ESP_LINE_ENDINGS_CRLF
|
||||
#elif CONFIG_NEWLIB_STDIN_LINE_ENDING_CR
|
||||
# define DEFAULT_RX_MODE ESP_LINE_ENDINGS_CR
|
||||
#else
|
||||
# define DEFAULT_RX_MODE ESP_LINE_ENDINGS_LF
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
_lock_t write_lock;
|
||||
_lock_t read_lock;
|
||||
esp_line_endings_t tx_mode; // Newline conversion mode when transmitting
|
||||
esp_line_endings_t rx_mode; // Newline conversion mode when receiving
|
||||
uint32_t flags;
|
||||
char vfs_path[VFS_TUSB_MAX_PATH];
|
||||
int cdc_intf;
|
||||
} vfs_tinyusb_t;
|
||||
|
||||
static vfs_tinyusb_t s_vfstusb;
|
||||
|
||||
|
||||
static esp_err_t apply_path(char const *path)
|
||||
{
|
||||
if (path != NULL) {
|
||||
size_t path_len = strlen(path) + 1;
|
||||
if (path_len > VFS_TUSB_MAX_PATH) {
|
||||
ESP_LOGE(TAG, "The path is too long; maximum is %d characters", VFS_TUSB_MAX_PATH);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
strncpy(s_vfstusb.vfs_path, path, (VFS_TUSB_MAX_PATH - 1));
|
||||
} else {
|
||||
strncpy(s_vfstusb.vfs_path,
|
||||
VFS_TUSB_PATH_DEFAULT,
|
||||
(VFS_TUSB_MAX_PATH - 1));
|
||||
}
|
||||
ESP_LOGV(TAG, "Path is set to `%s`", s_vfstusb.vfs_path);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Fill s_vfstusb
|
||||
*
|
||||
* @param cdc_intf - interface of tusb for registration
|
||||
* @param path - a path where the CDC will be registered
|
||||
* @return esp_err_t ESP_OK or ESP_ERR_INVALID_ARG
|
||||
*/
|
||||
static esp_err_t vfstusb_init(int cdc_intf, char const *path)
|
||||
{
|
||||
s_vfstusb.cdc_intf = cdc_intf;
|
||||
s_vfstusb.tx_mode = DEFAULT_TX_MODE;
|
||||
s_vfstusb.rx_mode = DEFAULT_RX_MODE;
|
||||
|
||||
return apply_path(path);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear s_vfstusb to default values
|
||||
*/
|
||||
static void vfstusb_deinit(void)
|
||||
{
|
||||
memset(&s_vfstusb, 0, sizeof(s_vfstusb));
|
||||
}
|
||||
|
||||
|
||||
static int tusb_open(const char *path, int flags, int mode)
|
||||
{
|
||||
(void) mode;
|
||||
(void) path;
|
||||
s_vfstusb.flags = flags | O_NONBLOCK; // for now only non-blocking mode is implemented
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t tusb_write(int fd, const void *data, size_t size)
|
||||
{
|
||||
FD_CHECK(fd, -1);
|
||||
size_t written_sz = 0;
|
||||
const char *data_c = (const char *)data;
|
||||
_lock_acquire(&(s_vfstusb.write_lock));
|
||||
for (size_t i = 0; i < size; i++) {
|
||||
int c = data_c[i];
|
||||
/* handling the EOL */
|
||||
if (c == '\n' && s_vfstusb.tx_mode != ESP_LINE_ENDINGS_LF) {
|
||||
if (tinyusb_cdcacm_write_queue_char(s_vfstusb.cdc_intf, '\r')) {
|
||||
written_sz++;
|
||||
} else {
|
||||
break; // can't write anymore
|
||||
}
|
||||
if (s_vfstusb.tx_mode == ESP_LINE_ENDINGS_CR) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
/* write a char */
|
||||
if (tinyusb_cdcacm_write_queue_char(s_vfstusb.cdc_intf, c)) {
|
||||
written_sz++;
|
||||
} else {
|
||||
break; // can't write anymore
|
||||
}
|
||||
|
||||
}
|
||||
tud_cdc_n_write_flush(s_vfstusb.cdc_intf);
|
||||
_lock_release(&(s_vfstusb.write_lock));
|
||||
return written_sz;
|
||||
}
|
||||
|
||||
static int tusb_close(int fd)
|
||||
{
|
||||
FD_CHECK(fd, -1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t tusb_read(int fd, void *data, size_t size)
|
||||
{
|
||||
FD_CHECK(fd, -1);
|
||||
char *data_c = (char *) data;
|
||||
size_t received = 0;
|
||||
_lock_acquire(&(s_vfstusb.read_lock));
|
||||
int cm1 = NONE;
|
||||
int c = NONE;
|
||||
|
||||
while (received < size) {
|
||||
cm1 = c; // store the old char
|
||||
int c = tud_cdc_n_read_char(0); // get a new one
|
||||
if (s_vfstusb.rx_mode == ESP_LINE_ENDINGS_CR) {
|
||||
if (c == '\r') {
|
||||
c = '\n';
|
||||
}
|
||||
} else if (s_vfstusb.rx_mode == ESP_LINE_ENDINGS_CR) {
|
||||
if ((c == '\n') & (cm1 == '\r')) {
|
||||
--received; // step back
|
||||
c = '\n';
|
||||
}
|
||||
}
|
||||
if ( c == NONE) { // if data ends
|
||||
break;
|
||||
}
|
||||
data_c[received] = (char) c;
|
||||
++received;
|
||||
if (c == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
_lock_release(&(s_vfstusb.read_lock));
|
||||
if (received > 0) {
|
||||
return received;
|
||||
}
|
||||
errno = EWOULDBLOCK;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static int tusb_fstat(int fd, struct stat *st)
|
||||
{
|
||||
FD_CHECK(fd, -1);
|
||||
memset(st, 0, sizeof(*st));
|
||||
st->st_mode = S_IFCHR;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tusb_fcntl(int fd, int cmd, int arg)
|
||||
{
|
||||
FD_CHECK(fd, -1);
|
||||
int result = 0;
|
||||
switch (cmd) {
|
||||
case F_GETFL:
|
||||
result = s_vfstusb.flags;
|
||||
break;
|
||||
case F_SETFL:
|
||||
s_vfstusb.flags = arg;
|
||||
break;
|
||||
default:
|
||||
result = -1;
|
||||
errno = ENOSYS;
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
esp_err_t esp_vfs_tusb_cdc_unregister(char const *path)
|
||||
{
|
||||
ESP_LOGD(TAG, "Unregistering TinyUSB driver");
|
||||
int res;
|
||||
|
||||
if (path == NULL) { // NULL means using the default path for unregistering: VFS_TUSB_PATH_DEFAULT
|
||||
res = strcmp(s_vfstusb.vfs_path, VFS_TUSB_PATH_DEFAULT);
|
||||
} else {
|
||||
res = strcmp(s_vfstusb.vfs_path, path);
|
||||
}
|
||||
|
||||
if (res) {
|
||||
res = ESP_ERR_INVALID_ARG;
|
||||
ESP_LOGE(TAG, "There is no TinyUSB driver registerred to the path '%s' (err: 0x%x)", s_vfstusb.vfs_path, res);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
res = esp_vfs_unregister(s_vfstusb.vfs_path);
|
||||
if (res != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Can't unregister TinyUSB driver from '%s' (err: 0x%x)", s_vfstusb.vfs_path, res);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Unregistered TinyUSB driver");
|
||||
vfstusb_deinit();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
esp_err_t esp_vfs_tusb_cdc_register(int cdc_intf, char const *path)
|
||||
{
|
||||
ESP_LOGD(TAG, "Registering TinyUSB CDC driver");
|
||||
int res;
|
||||
if (!tusb_cdc_acm_initialized(cdc_intf)) {
|
||||
ESP_LOGE(TAG, "TinyUSB CDC#%d is not initialized", cdc_intf);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
res = vfstusb_init(cdc_intf, path);
|
||||
if (res != ESP_OK) {
|
||||
return res;
|
||||
}
|
||||
|
||||
esp_vfs_t vfs = {
|
||||
.flags = ESP_VFS_FLAG_DEFAULT,
|
||||
.close = &tusb_close,
|
||||
.fcntl = &tusb_fcntl,
|
||||
.fstat = &tusb_fstat,
|
||||
.open = &tusb_open,
|
||||
.read = &tusb_read,
|
||||
.write = &tusb_write,
|
||||
};
|
||||
|
||||
res = esp_vfs_register(s_vfstusb.vfs_path, &vfs, NULL);
|
||||
if (res != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Can't register TinyUSB driver (err: %x)", res);
|
||||
} else {
|
||||
ESP_LOGD(TAG, "TinyUSB CDC registered (%s)", s_vfstusb.vfs_path);
|
||||
}
|
||||
return res;
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
# sdkconfig replacement configurations for deprecated options formatted as
|
||||
# CONFIG_DEPRECATED_OPTION CONFIG_NEW_OPTION
|
||||
CONFIG_USB_ENABLED CONFIG_TINYUSB
|
||||
CONFIG_USB_DO_NOT_CREATE_TASK CONFIG_TINYUSB_NO_DEFAULT_TASK
|
||||
CONFIG_USB_TASK_PRIORITY CONFIG_TINYUSB_TASK_PRIORITY
|
||||
CONFIG_USB_DESC_USE_ESPRESSIF_VID CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID
|
||||
CONFIG_USB_DESC_CUSTOM_VID CONFIG_TINYUSB_DESC_CUSTOM_VID
|
||||
CONFIG_USB_DESC_USE_DEFAULT_PID CONFIG_TINYUSB_DESC_USE_DEFAULT_PID
|
||||
CONFIG_USB_DESC_CUSTOM_PID CONFIG_TINYUSB_DESC_CUSTOM_PID
|
||||
CONFIG_USB_DESC_BCDDEVICE CONFIG_TINYUSB_DESC_BCD_DEVICE
|
||||
CONFIG_USB_DESC_MANUFACTURER_STRING CONFIG_TINYUSB_DESC_MANUFACTURER_STRING
|
||||
CONFIG_USB_DESC_PRODUCT_STRING CONFIG_TINYUSB_DESC_PRODUCT_STRING
|
||||
CONFIG_USB_DESC_SERIAL_STRING CONFIG_TINYUSB_DESC_SERIAL_STRING
|
||||
CONFIG_USB_DESC_CDC_STRING CONFIG_TINYUSB_DESC_CDC_STRING
|
||||
CONFIG_USB_DESC_MSC_STRING CONFIG_TINYUSB_DESC_MSC_STRING
|
||||
CONFIG_USB_DESC_HID_STRING CONFIG_TINYUSB_DESC_HID_STRING
|
||||
CONFIG_USB_MSC_ENABLED CONFIG_TINYUSB_MSC_ENABLED
|
||||
CONFIG_USB_MSC_BUFSIZE CONFIG_TINYUSB_MSC_BUFSIZE
|
||||
CONFIG_USB_CDC_ENABLED CONFIG_TINYUSB_CDC_ENABLED
|
||||
CONFIG_USB_CDC_RX_BUFSIZE CONFIG_TINYUSB_CDC_RX_BUFSIZE
|
||||
CONFIG_USB_CDC_TX_BUFSIZE CONFIG_TINYUSB_CDC_TX_BUFSIZE
|
||||
CONFIG_USB_DEBUG_LEVEL CONFIG_TINYUSB_DEBUG_LEVEL
|
@ -1 +0,0 @@
|
||||
Subproject commit c1986586098643edfa6b75a776299c576ad0ce8b
|
@ -210,13 +210,6 @@ INPUT = \
|
||||
$(PROJECT_PATH)/components/spi_flash/include/esp_partition.h \
|
||||
$(PROJECT_PATH)/components/spi_flash/include/spi_flash_mmap.h \
|
||||
$(PROJECT_PATH)/components/spiffs/include/esp_spiffs.h \
|
||||
$(PROJECT_PATH)/components/tinyusb/additions/include/tinyusb.h \
|
||||
$(PROJECT_PATH)/components/tinyusb/additions/include/tinyusb_types.h \
|
||||
$(PROJECT_PATH)/components/tinyusb/additions/include/tusb_cdc_acm.h \
|
||||
$(PROJECT_PATH)/components/tinyusb/additions/include/tusb_config.h \
|
||||
$(PROJECT_PATH)/components/tinyusb/additions/include/tusb_console.h \
|
||||
$(PROJECT_PATH)/components/tinyusb/additions/include/tusb_tasks.h \
|
||||
$(PROJECT_PATH)/components/tinyusb/additions/include/vfs_tinyusb.h \
|
||||
$(PROJECT_PATH)/components/ulp/ulp_common/include/ulp_common.h \
|
||||
$(PROJECT_PATH)/components/ulp/ulp_fsm/include/ulp_fsm_common.h \
|
||||
$(PROJECT_PATH)/components/ulp/ulp_riscv/include/ulp_riscv.h \
|
||||
|
@ -13,6 +13,8 @@ Overview
|
||||
|
||||
The driver allows users to use {IDF_TARGET_NAME} chips to develop USB devices on a top of the TinyUSB stack. TinyUSB is integrated with ESP-IDF to provide USB features of the framework. Using this driver the chip works as a composite device supporting several USB devices simultaneously. Currently, only the Communications Device Class (CDC) type of the device with the Abstract Control Model (ACM) subclass and the Musical Instrument Digital Interface (MIDI) are supported.
|
||||
|
||||
TinyUSB stack is distributed via `IDF Component Registry <https://components.espressif.com/components/espressif/esp_tinyusb>`_.
|
||||
|
||||
Our USB-OTG implementation is limited to {IDF_TARGET_USB_EP_NUM} USB endpoints ({IDF_TARGET_USB_EP_NUM_INOUT} IN/OUT endpoints and {IDF_TARGET_USB_EP_NUM_IN} IN endpoint) - find more information in `technical reference manual <{IDF_TARGET_TRM_EN_URL}>`_.
|
||||
|
||||
Features
|
||||
@ -151,21 +153,9 @@ The table below describes the code examples available in the directory :example:
|
||||
- Description
|
||||
* - :example:`peripherals/usb/device/tusb_console`
|
||||
- How to set up {IDF_TARGET_NAME} chip to get log output via Serial Device connection
|
||||
* - :example:`peripherals/usb/device/tusb_sample_descriptor`
|
||||
- How to set up {IDF_TARGET_NAME} chip to work as a Generic USB Device with a user-defined descriptor
|
||||
* - :example:`peripherals/usb/device/tusb_serial_device`
|
||||
- How to set up {IDF_TARGET_NAME} chip to work as a USB Serial Device
|
||||
* - :example:`peripherals/usb/device/tusb_midi`
|
||||
- How to set up {IDF_TARGET_NAME} chip to work as a USB MIDI Device
|
||||
* - :example:`peripherals/usb/device/tusb_hid`
|
||||
- How to set up {IDF_TARGET_NAME} chip to work as a USB Human Interface Device
|
||||
|
||||
API Reference
|
||||
-------------
|
||||
|
||||
.. include-build-file:: inc/tinyusb.inc
|
||||
.. include-build-file:: inc/tinyusb_types.inc
|
||||
.. include-build-file:: inc/tusb_cdc_acm.inc
|
||||
.. include-build-file:: inc/tusb_console.inc
|
||||
.. include-build-file:: inc/tusb_tasks.inc
|
||||
.. include-build-file:: inc/vfs_tinyusb.inc
|
||||
|
@ -22,6 +22,7 @@ Following components are removed from ESP-IDF and moved to `IDF Component Regist
|
||||
* `qrcode <https://components.espressif.com/component/espressif/qrcode>`_
|
||||
* `tjpgd <https://components.espressif.com/component/espressif/esp_jpeg>`_
|
||||
* `esp_serial_slave_link <https://components.espressif.com/components/espressif/esp_serial_slave_link>`_
|
||||
* `tinyusb <https://components.espressif.com/components/espressif/esp_tinyusb>`_
|
||||
|
||||
.. note::
|
||||
Please note that http parser functionality which was previously part of ``nghttp`` component is now part of :component:`http_parser <http_parser>` component.
|
||||
|
@ -19,6 +19,7 @@
|
||||
* `expat <https://components.espressif.com/component/espressif/expat>`_
|
||||
* `coap <https://components.espressif.com/component/espressif/coap>`_
|
||||
* `tjpgd <https://components.espressif.com/component/espressif/esp_jpeg>`_
|
||||
* `tinyusb <https://components.espressif.com/components/espressif/esp_tinyusb>`_
|
||||
|
||||
.. note::
|
||||
请注意,http 解析功能以前属于 ``nghttp`` 组件一部分,但现在属于 :component:`http_parser <http_parser>` 组件。
|
||||
|
@ -0,0 +1,4 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
espressif/esp_tinyusb: "0.0.1"
|
||||
idf: "^5.0"
|
@ -1,2 +1 @@
|
||||
CONFIG_TINYUSB=y
|
||||
CONFIG_TINYUSB_CDC_ENABLED=y
|
||||
|
@ -1,5 +1,5 @@
|
||||
idf_component_register(
|
||||
SRCS "tusb_hid_example_main.c"
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES driver tinyusb
|
||||
REQUIRES driver
|
||||
)
|
||||
|
@ -0,0 +1,4 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
espressif/esp_tinyusb: "0.0.1"
|
||||
idf: "^5.0"
|
@ -1,5 +1,4 @@
|
||||
# This file was generated using idf.py save-defconfig. It can be edited manually.
|
||||
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
|
||||
#
|
||||
CONFIG_TINYUSB=y
|
||||
CONFIG_TINYUSB_HID_COUNT=1
|
||||
|
@ -0,0 +1,4 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
espressif/esp_tinyusb: "0.0.1"
|
||||
idf: "^5.0"
|
@ -1,2 +1 @@
|
||||
CONFIG_TINYUSB=y
|
||||
CONFIG_TINYUSB_MIDI_ENABLED=y
|
||||
CONFIG_TINYUSB_MIDI_COUNT=1
|
||||
|
@ -1,6 +0,0 @@
|
||||
# The following five lines of boilerplate have to be in your project's
|
||||
# CMakeLists in this exact order for cmake to work correctly
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
project(tusb_sample_descriptor)
|
@ -1,123 +0,0 @@
|
||||
| Supported Targets | ESP32-S2 | ESP32-S3 |
|
||||
| ----------------- | -------- | -------- |
|
||||
|
||||
# TinyUSB Sample Descriptor
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
This example is demonstrating how to set up ESP chip to work as a Generic USB Device with a user-defined descriptor. You can specify a manufacturer, device's name, ID and other USB-devices parameters responsible for identification by host.
|
||||
|
||||
As a USB stack, a TinyUSB component is used.
|
||||
|
||||
## How to use example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
Any ESP boards that have USB-OTG supported.
|
||||
|
||||
#### Pin Assignment
|
||||
|
||||
See common pin assignments for USB Device examples from [upper level](../../README.md#common-pin-assignments).
|
||||
|
||||
### Configure the project
|
||||
|
||||
There are two ways to set up a descriptor - using Menuconfig tool and in-code
|
||||
|
||||
#### In-code setting up
|
||||
|
||||
For the manual descriptor configuration use the default example's settings and modify `my_descriptor` in [source code](main/tusb_sample_descriptor_main.c) according to your needs
|
||||
|
||||
#### Menuconfig
|
||||
|
||||
If you want to set up the descriptor using Menuconfig UI:
|
||||
|
||||
1. Execute in the terminal from the example's directory: `idf.py menuconfig`
|
||||
|
||||
2. Turn off `Set up a USB descriptor manually in code` parameter at `Example Configuration`
|
||||
|
||||
3. Follow `Component config -> TinyUSB -> Descriptor configuration` for all available configurations.
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||
|
||||
```bash
|
||||
idf.py -p PORT flash monitor
|
||||
```
|
||||
|
||||
(Replace PORT with the name of the serial port to use.)
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
## Example Output
|
||||
|
||||
After the flashing you should see the output:
|
||||
|
||||
```
|
||||
I (287) example: USB initialization
|
||||
I (287) tusb_desc:
|
||||
┌─────────────────────────────────┐
|
||||
│ USB Device Descriptor Summary │
|
||||
├───────────────────┬─────────────┤
|
||||
│bDeviceClass │ 0 │
|
||||
├───────────────────┼─────────────┤
|
||||
│bDeviceSubClass │ 0 │
|
||||
├───────────────────┼─────────────┤
|
||||
│bDeviceProtocol │ 0 │
|
||||
├───────────────────┼─────────────┤
|
||||
│bMaxPacketSize0 │ 64 │
|
||||
├───────────────────┼─────────────┤
|
||||
│idVendor │ 0x303a │
|
||||
├───────────────────┼─────────────┤
|
||||
│idProduct │ 0x3000 │
|
||||
├───────────────────┼─────────────┤
|
||||
│bcdDevice │ 0x101 │
|
||||
├───────────────────┼─────────────┤
|
||||
│iManufacturer │ 0x1 │
|
||||
├───────────────────┼─────────────┤
|
||||
│iProduct │ 0x2 │
|
||||
├───────────────────┼─────────────┤
|
||||
│iSerialNumber │ 0x3 │
|
||||
├───────────────────┼─────────────┤
|
||||
│bNumConfigurations │ 0x1 │
|
||||
└───────────────────┴─────────────┘
|
||||
I (457) TinyUSB: TinyUSB Driver installed
|
||||
I (467) example: USB initialization DONE
|
||||
```
|
||||
|
||||
From PC, running `lsusb -v`, you should find the device's descriptor like:
|
||||
```
|
||||
Bus 001 Device 007: ID 303a:3000 I My Custom Device
|
||||
Device Descriptor:
|
||||
bLength 18
|
||||
bDescriptorType 1
|
||||
bcdUSB 2.00
|
||||
bDeviceClass 0
|
||||
bDeviceSubClass 0
|
||||
bDeviceProtocol 0
|
||||
bMaxPacketSize0 64
|
||||
idVendor 0x303a
|
||||
idProduct 0x3000
|
||||
bcdDevice 1.01
|
||||
iManufacturer 1 I
|
||||
iProduct 2 My Custom Device
|
||||
iSerial 3 012-345
|
||||
bNumConfigurations 1
|
||||
Configuration Descriptor:
|
||||
bLength 9
|
||||
bDescriptorType 2
|
||||
wTotalLength 0x0009
|
||||
bNumInterfaces 0
|
||||
bConfigurationValue 1
|
||||
iConfiguration 0
|
||||
bmAttributes 0xa0
|
||||
(Bus Powered)
|
||||
Remote Wakeup
|
||||
MaxPower 100mA
|
||||
can't get device qualifier: Resource temporarily unavailable
|
||||
can't get debug descriptor: Resource temporarily unavailable
|
||||
Device Status: 0x0000
|
||||
(Bus Powered)
|
||||
```
|
@ -1,2 +0,0 @@
|
||||
idf_component_register(SRCS "tusb_sample_descriptor_main.c"
|
||||
INCLUDE_DIRS .)
|
@ -1,10 +0,0 @@
|
||||
menu "Example Configuration"
|
||||
|
||||
config EXAMPLE_MANUAL_DESC
|
||||
bool "Set up a USB descriptor manually in code"
|
||||
default y
|
||||
help
|
||||
You can set up a descriptor using Menuconfig or independently of
|
||||
your project configuration - manually in code
|
||||
|
||||
endmenu
|
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "tinyusb.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
static const char *TAG = "example";
|
||||
|
||||
void app_main(void)
|
||||
{
|
||||
ESP_LOGI(TAG, "USB initialization");
|
||||
|
||||
#if CONFIG_EXAMPLE_MANUAL_DESC
|
||||
// Setting of descriptor. You can use descriptor_tinyusb and
|
||||
// descriptor_str_tinyusb as a reference
|
||||
tusb_desc_device_t my_descriptor = {
|
||||
.bLength = sizeof(my_descriptor),
|
||||
.bDescriptorType = TUSB_DESC_DEVICE,
|
||||
.bcdUSB = 0x0200, // USB version. 0x0200 means version 2.0
|
||||
.bDeviceClass = TUSB_CLASS_UNSPECIFIED,
|
||||
.bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
|
||||
|
||||
.idVendor = 0x303A,
|
||||
.idProduct = 0x3000,
|
||||
.bcdDevice = 0x0101, // Device FW version
|
||||
|
||||
.iManufacturer = 0x01, // see string_descriptor[1] bellow
|
||||
.iProduct = 0x02, // see string_descriptor[2] bellow
|
||||
.iSerialNumber = 0x03, // see string_descriptor[3] bellow
|
||||
|
||||
.bNumConfigurations = 0x01
|
||||
};
|
||||
|
||||
tusb_desc_strarray_device_t my_string_descriptor = {
|
||||
// array of pointer to string descriptors
|
||||
(char[]){0x09, 0x04}, // 0: is supported language is English (0x0409)
|
||||
"I", // 1: Manufacturer
|
||||
"My Custom Device", // 2: Product
|
||||
"012-345", // 3: Serials, should use chip ID
|
||||
};
|
||||
|
||||
const tinyusb_config_t tusb_cfg = {
|
||||
.descriptor = &my_descriptor,
|
||||
.string_descriptor = my_string_descriptor,
|
||||
.external_phy = false,
|
||||
.configuration_descriptor = NULL,
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
const tinyusb_config_t tusb_cfg = {
|
||||
.device_descriptor = NULL,
|
||||
.string_descriptor = NULL,
|
||||
.external_phy = false,
|
||||
.configuration_descriptor = NULL,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));
|
||||
ESP_LOGI(TAG, "USB initialization DONE");
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
CONFIG_TINYUSB=y
|
||||
CONFIG_TINYUSB_DESC_USE_ESPRESSIF_VID=n
|
||||
CONFIG_TINYUSB_DESC_CUSTOM_VID=0x303A
|
||||
CONFIG_TINYUSB_DESC_USE_DEFAULT_PID=n
|
||||
CONFIG_TINYUSB_DESC_CUSTOM_PID=0x3000
|
@ -0,0 +1,4 @@
|
||||
## IDF Component Manager Manifest File
|
||||
dependencies:
|
||||
espressif/esp_tinyusb: "0.0.1"
|
||||
idf: "^5.0"
|
@ -1,2 +1 @@
|
||||
CONFIG_TINYUSB=y
|
||||
CONFIG_TINYUSB_CDC_ENABLED=y
|
||||
|
@ -1305,7 +1305,6 @@ components/tcp_transport/test/test_transport_basic.c
|
||||
components/tcp_transport/test/test_transport_connect.c
|
||||
components/tcp_transport/test/test_transport_fixtures.c
|
||||
components/tcp_transport/transport_utils.c
|
||||
components/tinyusb/additions/include/tusb_config.h
|
||||
components/touch_element/include/touch_element/touch_button.h
|
||||
components/touch_element/include/touch_element/touch_element_private.h
|
||||
components/touch_element/test/test_touch_button.c
|
||||
|
@ -27,7 +27,6 @@ skip:
|
||||
- "components/openthread/openthread"
|
||||
- "components/protobuf-c/protobuf-c"
|
||||
- "components/spiffs/spiffs"
|
||||
- "components/tinyusb/tinyusb"
|
||||
- "components/unity/unity"
|
||||
- "components/heap/tlsf"
|
||||
|
||||
|
@ -235,3 +235,8 @@
|
||||
re: "fatal error: (esp_rom_tjpgd.h): No such file or directory"
|
||||
hint: "{} was removed. Please use esp_jpeg component from IDF component manager instead.\nPlease look out for component in 'https://components.espressif.com' and add using 'idf.py add-dependency' command.\nRefer to the migration guide for more details."
|
||||
match_to_output: True
|
||||
|
||||
-
|
||||
re: "fatal error: (tinyusb.h): No such file or directory"
|
||||
hint: "{} was removed. Please use esp_tinyusb component from IDF component manager instead.\nYou can install `esp_tinyusb` using 'idf.py add-dependency espressif/esp_tinyusb' command.\nRefer to the migration guide for more details."
|
||||
match_to_output: True
|
||||
|
Loading…
Reference in New Issue
Block a user