diff --git a/cores/esp32/esp32-hal-tinyusb.c b/cores/esp32/esp32-hal-tinyusb.c index b7aa3ece..e47fed96 100644 --- a/cores/esp32/esp32-hal-tinyusb.c +++ b/cores/esp32/esp32-hal-tinyusb.c @@ -168,6 +168,8 @@ static tinyusb_desc_webusb_url_t tinyusb_url_descriptor = { /* * Configuration Descriptor * */ + +static tinyusb_descriptor_cb_t tinyusb_loaded_interfaces_callbacks[USB_INTERFACE_MAX]; static uint32_t tinyusb_loaded_interfaces_mask = 0; static uint8_t tinyusb_loaded_interfaces_num = 0; static uint16_t tinyusb_config_descriptor_len = 0; @@ -308,47 +310,6 @@ __attribute__ ((weak)) int32_t tud_msc_scsi_cb (uint8_t lun, uint8_t const scsi_ * Private API * */ -__attribute__ ((weak)) uint16_t tusb_cdc_load_descriptor(uint8_t * dst, uint8_t * itf) { return 0; } -__attribute__ ((weak)) uint16_t tusb_dfu_load_descriptor(uint8_t * dst, uint8_t * itf) { return 0; } -__attribute__ ((weak)) uint16_t tusb_hid_load_descriptor(uint8_t * dst, uint8_t * itf) { return 0; } -__attribute__ ((weak)) uint16_t tusb_msc_load_descriptor(uint8_t * dst, uint8_t * itf) { return 0; } -__attribute__ ((weak)) uint16_t tusb_midi_load_descriptor(uint8_t * dst, uint8_t * itf) { return 0; } -__attribute__ ((weak)) uint16_t tusb_vendor_load_descriptor(uint8_t * dst, uint8_t * itf) { return 0; } - -__attribute__ ((weak)) uint16_t tusb_custom_get_descriptor_len() { return 0; } -__attribute__ ((weak)) uint16_t tusb_custom_load_descriptor(uint8_t * dst, uint8_t * itf) { return 0; } - -static uint16_t tinyusb_load_descriptor(tinyusb_interface_t interface, uint8_t * dst, uint8_t * itf) -{ - switch (interface) { - case USB_INTERFACE_CDC: - return tusb_cdc_load_descriptor(dst, itf); - break; - case USB_INTERFACE_DFU: - return tusb_dfu_load_descriptor(dst, itf); - break; - case USB_INTERFACE_HID: - return tusb_hid_load_descriptor(dst, itf); - break; - case USB_INTERFACE_VENDOR: - return tusb_vendor_load_descriptor(dst, itf); - break; - case USB_INTERFACE_MSC: - return tusb_msc_load_descriptor(dst, itf); - break; - case USB_INTERFACE_MIDI: - return tusb_midi_load_descriptor(dst, itf); - break; - case USB_INTERFACE_CUSTOM: - return tusb_custom_load_descriptor(dst, itf); - break; - default: - - break; - } - return 0; -} - static bool tinyusb_reserve_in_endpoint(uint8_t endpoint){ if(endpoint > 6 || (tinyusb_endpoints.in & BIT(endpoint)) != 0){ return false; @@ -379,6 +340,14 @@ static bool tinyusb_has_available_fifos(void){ return active_endpoints < max_endpoints; } +static uint16_t tinyusb_load_descriptor(tinyusb_interface_t interface, uint8_t * dst, uint8_t * itf) +{ + if(tinyusb_loaded_interfaces_callbacks[interface]){ + return tinyusb_loaded_interfaces_callbacks[interface](dst, itf); + } + return 0; +} + static bool tinyusb_load_enabled_interfaces(){ tinyusb_config_descriptor_len += TUD_CONFIG_DESC_LEN; tinyusb_config_descriptor = (uint8_t *)malloc(tinyusb_config_descriptor_len); @@ -411,7 +380,7 @@ static bool tinyusb_load_enabled_interfaces(){ TUD_CONFIG_DESCRIPTOR(1, tinyusb_loaded_interfaces_num, str_index, tinyusb_config_descriptor_len, USB_DEVICE_ATTRIBUTES, USB_DEVICE_POWER) }; memcpy(tinyusb_config_descriptor, descriptor, TUD_CONFIG_DESC_LEN); - if ((tinyusb_loaded_interfaces_mask & ~(BIT(USB_INTERFACE_CDC) | BIT(USB_INTERFACE_DFU))) == 0) { + if ((tinyusb_loaded_interfaces_mask == (BIT(USB_INTERFACE_CDC) | BIT(USB_INTERFACE_DFU))) || (tinyusb_loaded_interfaces_mask == BIT(USB_INTERFACE_CDC))) { tinyusb_persist_set_enable(true); log_d("USB Persist enabled"); } @@ -493,6 +462,19 @@ static void usb_device_task(void *param) { * PUBLIC API * */ +esp_err_t tinyusb_enable_interface(tinyusb_interface_t interface, uint16_t descriptor_len, tinyusb_descriptor_cb_t cb) +{ + if((interface >= USB_INTERFACE_MAX) || (tinyusb_loaded_interfaces_mask & (1U << interface))){ + log_e("Interface %u not enabled", interface); + return ESP_FAIL; + } + tinyusb_loaded_interfaces_mask |= (1U << interface); + tinyusb_config_descriptor_len += descriptor_len; + tinyusb_loaded_interfaces_callbacks[interface] = cb; + log_d("Interface %u enabled", interface); + return ESP_OK; +} + esp_err_t tinyusb_init(tinyusb_device_config_t *config) { static bool initialized = false; if(initialized){ @@ -518,45 +500,6 @@ esp_err_t tinyusb_init(tinyusb_device_config_t *config) { return err; } -esp_err_t tinyusb_enable_interface(tinyusb_interface_t interface) -{ - uint16_t descriptor_len = 0; - switch (interface) { - case USB_INTERFACE_CDC: - descriptor_len = CFG_TUD_CDC * TUD_CDC_DESC_LEN; - break; - case USB_INTERFACE_DFU: - descriptor_len = CFG_TUD_DFU_RT * TUD_DFU_RT_DESC_LEN; - break; - case USB_INTERFACE_HID: - descriptor_len = CFG_TUD_HID * TUD_HID_INOUT_DESC_LEN; - break; - case USB_INTERFACE_MSC: - descriptor_len = CFG_TUD_MSC * TUD_MSC_DESC_LEN; - break; - case USB_INTERFACE_MIDI: - descriptor_len = CFG_TUD_MIDI * TUD_MIDI_DESC_LEN; - break; - case USB_INTERFACE_VENDOR: - descriptor_len = CFG_TUD_VENDOR * TUD_VENDOR_DESC_LEN; - break; - case USB_INTERFACE_CUSTOM: - descriptor_len = tusb_custom_get_descriptor_len(); - break; - default: - - break; - } - if (descriptor_len) { - tinyusb_config_descriptor_len += descriptor_len; - tinyusb_loaded_interfaces_mask |= (1U << interface); - log_d("Driver %u enabled", interface); - return ESP_OK; - } - log_e("Driver %u not enabled", interface); - return ESP_FAIL; -} - uint8_t tinyusb_add_string_descriptor(const char * str){ if(str == NULL || tinyusb_string_descriptor_len >= MAX_STRING_DESCRIPTORS){ return 0; diff --git a/cores/esp32/esp32-hal-tinyusb.h b/cores/esp32/esp32-hal-tinyusb.h index f75dabd3..1067a940 100644 --- a/cores/esp32/esp32-hal-tinyusb.h +++ b/cores/esp32/esp32-hal-tinyusb.h @@ -73,7 +73,9 @@ typedef enum { USB_INTERFACE_MAX } tinyusb_interface_t; -esp_err_t tinyusb_enable_interface(tinyusb_interface_t interface); +typedef uint16_t (*tinyusb_descriptor_cb_t)(uint8_t * dst, uint8_t * itf); + +esp_err_t tinyusb_enable_interface(tinyusb_interface_t interface, uint16_t descriptor_len, tinyusb_descriptor_cb_t cb); uint8_t tinyusb_add_string_descriptor(const char * str); uint8_t tinyusb_get_free_duplex_endpoint(void); uint8_t tinyusb_get_free_in_endpoint(void); diff --git a/libraries/USB/src/USB.cpp b/libraries/USB/src/USB.cpp index 736ab60a..87726ba5 100644 --- a/libraries/USB/src/USB.cpp +++ b/libraries/USB/src/USB.cpp @@ -15,11 +15,38 @@ #include "esp32-hal-tinyusb.h" #include "USB.h" #if CONFIG_USB_ENABLED +#include "usb_persist.h" extern "C" { #include "tinyusb.h" } +#if CFG_TUD_DFU_RT +static uint16_t load_dfu_descriptor(uint8_t * dst, uint8_t * itf) +{ +#define DFU_ATTR_CAN_DOWNLOAD 1 +#define DFU_ATTR_CAN_UPLOAD 2 +#define DFU_ATTR_MANIFESTATION_TOLERANT 4 +#define DFU_ATTR_WILL_DETACH 8 +#define DFU_ATTRS (DFU_ATTR_CAN_DOWNLOAD | DFU_ATTR_CAN_UPLOAD | DFU_ATTR_MANIFESTATION_TOLERANT) + + uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB DFU_RT"); + uint8_t descriptor[TUD_DFU_RT_DESC_LEN] = { + // Interface number, string index, attributes, detach timeout, transfer size */ + TUD_DFU_RT_DESCRIPTOR(*itf, str_index, DFU_ATTRS, 700, 64) + }; + *itf+=1; + memcpy(dst, descriptor, TUD_DFU_RT_DESC_LEN); + return TUD_DFU_RT_DESC_LEN; +} +// Invoked on DFU_DETACH request to reboot to the bootloader +void tud_dfu_rt_reboot_to_dfu(void) +{ + tinyusb_persist_set_mode(REBOOT_BOOTLOADER_DFU); + esp_restart(); +} +#endif /* CFG_TUD_DFU_RT */ + ESP_EVENT_DEFINE_BASE(ARDUINO_USB_EVENTS); static esp_event_loop_handle_t arduino_usb_event_loop_handle = NULL; @@ -141,6 +168,12 @@ ESPUSB::operator bool() const return _started && tinyusb_device_mounted; } +bool ESPUSB::enableDFU(){ +#if CFG_TUD_DFU_RT + return tinyusb_enable_interface(USB_INTERFACE_DFU, TUD_DFU_RT_DESC_LEN, load_dfu_descriptor) == ESP_OK; +#endif /* CFG_TUD_DFU_RT */ + return false; +} bool ESPUSB::VID(uint16_t v){ if(!_started){ diff --git a/libraries/USB/src/USB.h b/libraries/USB/src/USB.h index 5dfac3e6..ede52791 100644 --- a/libraries/USB/src/USB.h +++ b/libraries/USB/src/USB.h @@ -88,6 +88,7 @@ class ESPUSB { bool webUSBURL(const char * name); const char * webUSBURL(void); + bool enableDFU(); bool begin(); operator bool() const; diff --git a/libraries/USB/src/USBCDC.cpp b/libraries/USB/src/USBCDC.cpp index ee97d738..7bf46a21 100644 --- a/libraries/USB/src/USBCDC.cpp +++ b/libraries/USB/src/USBCDC.cpp @@ -24,29 +24,13 @@ esp_err_t arduino_usb_event_handler_register_with(esp_event_base_t event_base, i extern "C" { #include "tinyusb.h" - -#if CFG_TUD_DFU_RT -uint16_t tusb_dfu_load_descriptor(uint8_t * dst, uint8_t * itf) -{ -#define DFU_ATTR_CAN_DOWNLOAD 1 -#define DFU_ATTR_CAN_UPLOAD 2 -#define DFU_ATTR_MANIFESTATION_TOLERANT 4 -#define DFU_ATTR_WILL_DETACH 8 -#define DFU_ATTRS (DFU_ATTR_CAN_DOWNLOAD | DFU_ATTR_CAN_UPLOAD | DFU_ATTR_MANIFESTATION_TOLERANT) - - uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB DFU_RT"); - uint8_t descriptor[TUD_DFU_RT_DESC_LEN] = { - // Interface number, string index, attributes, detach timeout, transfer size */ - TUD_DFU_RT_DESCRIPTOR(*itf, str_index, DFU_ATTRS, 700, 64) - }; - *itf+=1; - memcpy(dst, descriptor, TUD_DFU_RT_DESC_LEN); - return TUD_DFU_RT_DESC_LEN; } -#endif /* CFG_TUD_DFU_RT */ #if CFG_TUD_CDC -uint16_t tusb_cdc_load_descriptor(uint8_t * dst, uint8_t * itf) +#define MAX_USB_CDC_DEVICES 2 +USBCDC * devices[MAX_USB_CDC_DEVICES] = {NULL, NULL}; + +static uint16_t load_cdc_descriptor(uint8_t * dst, uint8_t * itf) { uint8_t str_index = tinyusb_add_string_descriptor("TinyUSB CDC"); // Interface number, string index, attributes, detach timeout, transfer size */ @@ -58,22 +42,6 @@ uint16_t tusb_cdc_load_descriptor(uint8_t * dst, uint8_t * itf) memcpy(dst, descriptor, TUD_CDC_DESC_LEN); return TUD_CDC_DESC_LEN; } -#endif /* CFG_TUD_CDC */ -} - -#if CFG_TUD_CDC -#define MAX_USB_CDC_DEVICES 2 -USBCDC * devices[MAX_USB_CDC_DEVICES] = {NULL, NULL}; - -#if CFG_TUD_DFU_RT -// Invoked on DFU_DETACH request to reboot to the bootloader -void tud_dfu_rt_reboot_to_dfu(void) -{ - if(devices[0] != NULL){ - devices[0]->_onDFU(); - } -} -#endif /* CFG_TUD_DFU_RT */ void tud_cdc_line_state_cb(uint8_t itf, bool dtr, bool rts) { @@ -103,8 +71,7 @@ static void usb_unplugged_cb(void* arg, esp_event_base_t event_base, int32_t eve } USBCDC::USBCDC(uint8_t itfn) : itf(itfn), bit_rate(0), stop_bits(0), parity(0), data_bits(0), dtr(false), rts(false), connected(false), reboot_enable(true), rx_queue(NULL) { - tinyusb_enable_interface(USB_INTERFACE_CDC); - tinyusb_enable_interface(USB_INTERFACE_DFU); + tinyusb_enable_interface(USB_INTERFACE_CDC, TUD_CDC_DESC_LEN, load_cdc_descriptor); if(itf < MAX_USB_CDC_DEVICES){ devices[itf] = this; arduino_usb_event_handler_register_with(ARDUINO_USB_EVENTS, ARDUINO_USB_STOPPED_EVENT, usb_unplugged_cb, this); @@ -127,12 +94,10 @@ void USBCDC::begin(size_t rx_queue_len) if(!rx_queue){ return; } - tinyusb_persist_set_mode(REBOOT_PERSIST); } void USBCDC::end() { - tinyusb_persist_set_mode(REBOOT_NO_PERSIST); } void USBCDC::_onUnplugged(void){ @@ -145,13 +110,6 @@ void USBCDC::_onUnplugged(void){ } } -void USBCDC::_onDFU(void){ - if(reboot_enable){ - tinyusb_persist_set_mode(REBOOT_BOOTLOADER_DFU); - esp_restart(); - } -} - enum { CDC_LINE_IDLE, CDC_LINE_1, CDC_LINE_2, CDC_LINE_3 }; void USBCDC::_onLineState(bool _dtr, bool _rts){ static uint8_t lineState = CDC_LINE_IDLE; @@ -202,10 +160,6 @@ void USBCDC::_onLineState(bool _dtr, bool _rts){ l.line_state.rts = rts; arduino_usb_event_post(ARDUINO_USB_CDC_EVENTS, ARDUINO_USB_CDC_LINE_STATE_EVENT, &l, sizeof(arduino_usb_cdc_event_data_t), portMAX_DELAY); } else { - //[I][USBSerial.cpp:76] _onLineState(): dtr: 0, rts: 1 - //[I][USBSerial.cpp:76] _onLineState(): dtr: 1, rts: 1 - //[I][USBSerial.cpp:76] _onLineState(): dtr: 1, rts: 0 - //[I][USBSerial.cpp:76] _onLineState(): dtr: 0, rts: 0 log_d("CDC RESET: itf: %u, dtr: %u, rts: %u, state: %u", itf, dtr, rts, lineState); } diff --git a/tools/sdk/esp32s2/lib/libtinyusb.a b/tools/sdk/esp32s2/lib/libtinyusb.a index 4704da61..1d9ca88e 100644 Binary files a/tools/sdk/esp32s2/lib/libtinyusb.a and b/tools/sdk/esp32s2/lib/libtinyusb.a differ