diff --git a/device/esp_tinyusb/CHANGELOG.md b/device/esp_tinyusb/CHANGELOG.md index 1ace2e86..8f407a3d 100644 --- a/device/esp_tinyusb/CHANGELOG.md +++ b/device/esp_tinyusb/CHANGELOG.md @@ -1,14 +1,9 @@ -## 1.4.5 (Unreleased) +## 1.4.4 (Unreleased) - esp_tinyusb: Configuration descriptor for HS/FS Hosts - -## 1.4.4 - -- esp_tinyusb: Add BValid signal test - CDC-ACM: Remove MIN() definition if already defined - MSC: Set EP size in configuration descriptor based on speed - ## 1.4.3 - esp_tinyusb: ESP32P4 HS only support diff --git a/device/esp_tinyusb/descriptors_control.c b/device/esp_tinyusb/descriptors_control.c index bff7fc23..2076620e 100644 --- a/device/esp_tinyusb/descriptors_control.c +++ b/device/esp_tinyusb/descriptors_control.c @@ -6,7 +6,10 @@ #include #include "esp_log.h" +#include "esp_check.h" +#include "esp_err.h" #include "descriptors_control.h" +#include "usb_descriptors.h" #define USB_STRING_DESCRIPTOR_ARRAY_SIZE 8 // Max 8 string descriptors for a device. LANGID, Manufacturer, Product, Serial number + 4 user defined #define MAX_DESC_BUF_SIZE 32 // Max length of string descriptor (can be extended, USB supports lengths up to 255 bytes) @@ -89,11 +92,72 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) // ============================================================================= // Driver functions // ============================================================================= +esp_err_t tinyusb_prepare_descriptors_config(const tinyusb_config_t *config, tinyusb_descriptor_config_t *desc_cfg) +{ + assert(config); + assert(desc_cfg); + // Parse configuration and save descriptors's pointer + // Select Device Descriptor + if (NULL == config->device_descriptor) { + ESP_LOGW(TAG, "The device's device descriptor is not provided by user, using default."); + } + desc_cfg->dev = config->device_descriptor + ? config->device_descriptor + : &descriptor_dev_kconfig; + + // Select Configuration Descriptor +#if (TUD_OPT_HIGH_SPEED) + // High Speed + if (NULL == config->hs_cfg_desc) { + // Default configuration descriptor is provided only for CDC, MSC and NCM classes +#if (CFG_TUD_HID > 0 || CFG_TUD_MIDI > 0 || CFG_TUD_CUSTOM_CLASS > 0 || CFG_TUD_ECM_RNDIS > 0 || CFG_TUD_DFU > 0 || CFG_TUD_DFU_RUNTIME > 0 || CFG_TUD_BTH > 0) + ESP_RETURN_ON_FALSE(config->configuration_descriptor, ESP_ERR_INVALID_ARG, TAG, "Configuration descriptor must be provided for this device"); +#else + ESP_LOGW(TAG, "The device's configuration descriptor is not provided by user, using default."); +#endif + } + desc_cfg->cfg = config->hs_cfg_desc + ? config->hs_cfg_desc + : descriptor_cfg_kconfig; + + // Full Speed + // TODO: +#else + if (NULL == config->configuration_descriptor) { + // Default configuration descriptor is provided only for CDC, MSC and NCM classes +#if (CFG_TUD_HID > 0 || CFG_TUD_MIDI > 0 || CFG_TUD_CUSTOM_CLASS > 0 || CFG_TUD_ECM_RNDIS > 0 || CFG_TUD_DFU > 0 || CFG_TUD_DFU_RUNTIME > 0 || CFG_TUD_BTH > 0) + ESP_RETURN_ON_FALSE(config->configuration_descriptor, ESP_ERR_INVALID_ARG, TAG, "Configuration descriptor must be provided for this device"); +#else + ESP_LOGW(TAG, "The device's configuration descriptor is not provided by user, using default."); +#endif + } + desc_cfg->cfg = config->configuration_descriptor + ? config->configuration_descriptor + : descriptor_cfg_kconfig; +#endif // TUD_OPT_HIGH_SPEED + + // Select String Descriptors and count them + if (config->string_descriptor) { + desc_cfg->str = config->string_descriptor; + desc_cfg->str_count = (config->string_descriptor_count != 0) + ? config->string_descriptor_count + : 8; // '8' is for backward compatibility with esp_tinyusb v1.0.0. Do NOT remove! + } else { + desc_cfg->str = descriptor_str_kconfig; + while (descriptor_str_kconfig[++desc_cfg->str_count] != NULL); + ESP_LOGW(TAG, "The device's string descriptor is not provided by user, using default."); + } + + return ESP_OK; +} -void tinyusb_set_descriptor(const tusb_desc_device_t *dev_desc, const char **str_desc, int str_desc_count, const uint8_t *cfg_desc) +void tinyusb_set_descriptors(const tinyusb_descriptor_config_t *desc_cfg) { - assert(dev_desc && str_desc && cfg_desc); - assert(str_desc_count <= USB_STRING_DESCRIPTOR_ARRAY_SIZE); + assert(desc_cfg); + assert(desc_cfg->dev); + assert(desc_cfg->cfg); + assert(desc_cfg->str); + assert(desc_cfg->str_count <= USB_STRING_DESCRIPTOR_ARRAY_SIZE); ESP_LOGI(TAG, "\n" "┌─────────────────────────────────┐\n" @@ -121,16 +185,16 @@ void tinyusb_set_descriptor(const tusb_desc_device_t *dev_desc, const char **str "├───────────────────┼─────────────┤\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); - - // Save passed descriptors - s_device_descriptor = dev_desc; - s_configuration_descriptor = cfg_desc; - memcpy(s_str_descriptor, str_desc, str_desc_count * sizeof(str_desc[0])); + desc_cfg->dev->bDeviceClass, desc_cfg->dev->bDeviceSubClass, + desc_cfg->dev->bDeviceProtocol, desc_cfg->dev->bMaxPacketSize0, + desc_cfg->dev->idVendor, desc_cfg->dev->idProduct, desc_cfg->dev->bcdDevice, + desc_cfg->dev->iManufacturer, desc_cfg->dev->iProduct, desc_cfg->dev->iSerialNumber, + desc_cfg->dev->bNumConfigurations); + + // Save passed descriptors pointers(!) + s_device_descriptor = desc_cfg->dev; + s_configuration_descriptor = desc_cfg->cfg; + memcpy(s_str_descriptor, desc_cfg->str, desc_cfg->str_count * sizeof(desc_cfg->str[0])); } void tinyusb_set_str_descriptor(const char *str, int str_idx) diff --git a/device/esp_tinyusb/idf_component.yml b/device/esp_tinyusb/idf_component.yml index 13a37f48..24229aaa 100644 --- a/device/esp_tinyusb/idf_component.yml +++ b/device/esp_tinyusb/idf_component.yml @@ -1,7 +1,7 @@ ## IDF Component Manager Manifest File description: Espressif's additions to TinyUSB documentation: "https://docs.espressif.com/projects/esp-idf/en/latest/esp32s2/api-reference/peripherals/usb_device.html" -version: "1.4.4" +version: "1.4.3" url: https://github.com/espressif/esp-usb/tree/master/device/esp_tinyusb dependencies: idf: '>=5.0' # IDF 4.x contains TinyUSB as submodule diff --git a/device/esp_tinyusb/include/tinyusb.h b/device/esp_tinyusb/include/tinyusb.h index 37523719..01f19516 100644 --- a/device/esp_tinyusb/include/tinyusb.h +++ b/device/esp_tinyusb/include/tinyusb.h @@ -31,7 +31,18 @@ typedef struct { const char **string_descriptor; /*!< Pointer to array of string descriptors. If set to NULL, TinyUSB device will use a default string descriptors whose values are set in Kconfig */ int string_descriptor_count; /*!< Number of descriptors in above array */ 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 */ + union { + struct { + 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 */ + const uint8_t *reserved; /*!< For backward compatibility */ + }; +#if (TUD_OPT_HIGH_SPEED) + struct { + const uint8_t *hs_cfg_desc; /*!< Pointer to a HS configuration descriptor. If set to NULL, TinyUSB device will use a default configuration descriptor whose values are set in Kconfig */ + const uint8_t *fs_cfg_desc; /*!< Pointer to a FS configuration descriptor. If set to NULL, TinyUSB device will use a default configuration descriptor whose values are set in Kconfig */ + }; +#endif // TUD_OPT_HIGH_SPEED + }; 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; diff --git a/device/esp_tinyusb/include_private/descriptors_control.h b/device/esp_tinyusb/include_private/descriptors_control.h index 03d0dd56..dd0f9257 100644 --- a/device/esp_tinyusb/include_private/descriptors_control.h +++ b/device/esp_tinyusb/include_private/descriptors_control.h @@ -6,23 +6,42 @@ #pragma once -#include "tusb.h" +// #include "tusb.h" +#include "tinyusb.h" #ifdef __cplusplus extern "C" { #endif +/** + * @brief USB Device descriptor pointers for tinyusb configuration + * + */ +typedef struct { + const tusb_desc_device_t *dev; /*!< Pointer to device descriptor */ + const uint8_t *cfg; /*!< Pointer to configuration descriptor */ + const char **str; /*!< Pointer to array of UTF-8 strings */ + int str_count; /*!< Number of descriptors in str */ +} tinyusb_descriptor_config_t; + +/** + * @brief Parse tinyusb configuration and prepare the device configuration pointer list to configure tinyusb driver + * + * @attention All descriptors passed to this function must exist for the duration of USB device lifetime + * + * @param[in] config tinyusb stack specific configuration + * @param[out] desc_cfg Descriptor configuration for tinyusb + */ +esp_err_t tinyusb_prepare_descriptors_config(const tinyusb_config_t *config, tinyusb_descriptor_config_t *desc_cfg); + /** * @brief Set descriptors for this driver * * @attention All descriptors passed to this function must exist for the duration of USB device lifetime * - * @param[in] dev_desc Device descriptor - * @param[in] str_desc Pointer to array of UTF-8 strings - * @param[in] str_desc_count Number of descriptors in str_desc - * @param[in] cfg_desc Configuration descriptor + * @param[in] desc_cfg Descriptor configuration for tinyusb */ -void tinyusb_set_descriptor(const tusb_desc_device_t *dev_desc, const char **str_desc, int str_desc_count, const uint8_t *cfg_desc); +void tinyusb_set_descriptors(const tinyusb_descriptor_config_t *desc_cfg); /** * @brief Set specific string descriptor diff --git a/device/esp_tinyusb/test/CMakeLists.txt b/device/esp_tinyusb/test/CMakeLists.txt index 00435e85..fc89d7e0 100644 --- a/device/esp_tinyusb/test/CMakeLists.txt +++ b/device/esp_tinyusb/test/CMakeLists.txt @@ -1,4 +1,4 @@ -idf_component_register(SRCS "test_esp_tinyusb.c" "test_bvalid_sig.c" +idf_component_register(SRCS "test_esp_tinyusb.c" INCLUDE_DIRS "." REQUIRES unity esp_tinyusb ) diff --git a/device/esp_tinyusb/test/test_bvalid_sig.c b/device/esp_tinyusb/test/test_bvalid_sig.c deleted file mode 100644 index ecd19b66..00000000 --- a/device/esp_tinyusb/test/test_bvalid_sig.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD - * - * SPDX-License-Identifier: CC0-1.0 - */ - -#include "soc/soc_caps.h" - -#if SOC_USB_OTG_SUPPORTED - -#include -#include -#include "esp_system.h" -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "esp_log.h" -#include "esp_err.h" -#include "driver/gpio.h" -#include "esp_rom_gpio.h" -#include "soc/gpio_sig_map.h" -#include "unity.h" -#include "tinyusb.h" -#include "class/msc/msc_device.h" - -#define DEVICE_DETACH_TEST_ROUNDS 10 -#define DEVICE_DETACH_ROUND_DELAY_MS 1000 - -/* TinyUSB descriptors - ********************************************************************* */ -#define TUSB_DESC_TOTAL_LEN (TUD_CONFIG_DESC_LEN) - -static unsigned int dev_mounted = 0; -static unsigned int dev_umounted = 0; - -static uint8_t const test_configuration_descriptor[] = { - // Config number, interface count, string index, total length, attribute, power in mA - TUD_CONFIG_DESCRIPTOR(1, 0, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_SELF_POWERED | TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), -}; - -static tusb_desc_device_t test_device_descriptor = { - .bLength = sizeof(test_device_descriptor), - .bDescriptorType = TUSB_DESC_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = TUSB_CLASS_MISC, - .bDeviceSubClass = MISC_SUBCLASS_COMMON, - .bDeviceProtocol = MISC_PROTOCOL_IAD, - .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, - .idVendor = 0x303A, // This is Espressif VID. This needs to be changed according to Users / Customers - .idProduct = 0x4002, - .bcdDevice = 0x100, - .iManufacturer = 0x01, - .iProduct = 0x02, - .iSerialNumber = 0x03, - .bNumConfigurations = 0x01 -}; - -// Invoked when device is mounted -void tud_mount_cb(void) -{ - dev_mounted++; -} - -// Invoked when device is unmounted -void tud_umount_cb(void) -{ - dev_umounted++; -} - -TEST_CASE("bvalid_signal", "[esp_tinyusb]") -{ - unsigned int rounds = DEVICE_DETACH_TEST_ROUNDS; - - // Install TinyUSB driver - const tinyusb_config_t tusb_cfg = { - .external_phy = false, - .device_descriptor = &test_device_descriptor, - .configuration_descriptor = test_configuration_descriptor, - }; - TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); - - while (rounds--) { - // LOW to emulate disconnect USB device - esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, USB_SRP_BVALID_IN_IDX, false); - vTaskDelay(pdMS_TO_TICKS(DEVICE_DETACH_ROUND_DELAY_MS)); - // HIGH to emulate connect USB device - esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, USB_SRP_BVALID_IN_IDX, false); - vTaskDelay(pdMS_TO_TICKS(DEVICE_DETACH_ROUND_DELAY_MS)); - } - - // Verify - TEST_ASSERT_EQUAL(dev_mounted, dev_umounted); - TEST_ASSERT_EQUAL(dev_mounted, DEVICE_DETACH_TEST_ROUNDS); - - tinyusb_driver_uninstall(); -} -#endif // SOC_USB_OTG_SUPPORTED diff --git a/device/esp_tinyusb/tinyusb.c b/device/esp_tinyusb/tinyusb.c index a43a304c..590da0f7 100644 --- a/device/esp_tinyusb/tinyusb.c +++ b/device/esp_tinyusb/tinyusb.c @@ -13,7 +13,6 @@ #include "soc/usb_pins.h" #include "tinyusb.h" #include "descriptors_control.h" -#include "usb_descriptors.h" #include "tusb.h" #include "tusb_tasks.h" @@ -22,10 +21,6 @@ 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; - int string_descriptor_count = 0; - const uint8_t *cfg_descriptor; ESP_RETURN_ON_FALSE(config, ESP_ERR_INVALID_ARG, TAG, "Config can't be NULL"); // Configure USB PHY @@ -57,40 +52,12 @@ esp_err_t tinyusb_driver_install(const tinyusb_config_t *config) } ESP_RETURN_ON_ERROR(usb_new_phy(&phy_conf, &phy_hdl), TAG, "Install USB PHY failed"); - if (config->configuration_descriptor) { - cfg_descriptor = config->configuration_descriptor; - } else { - // Default configuration descriptor is provided only for CDC, MSC and NCM classes -#if (CFG_TUD_HID > 0 || CFG_TUD_MIDI > 0 || CFG_TUD_CUSTOM_CLASS > 0 || CFG_TUD_ECM_RNDIS > 0 || CFG_TUD_DFU > 0 || CFG_TUD_DFU_RUNTIME > 0 || CFG_TUD_BTH > 0) - ESP_RETURN_ON_FALSE(config->configuration_descriptor, ESP_ERR_INVALID_ARG, TAG, "Configuration descriptor must be provided for this device"); -#else - cfg_descriptor = descriptor_cfg_kconfig; - ESP_LOGW(TAG, "The device's configuration descriptor is not provided by user, using default."); -#endif - - } - - if (config->string_descriptor) { - string_descriptor = config->string_descriptor; - if (config->string_descriptor_count != 0) { - string_descriptor_count = config->string_descriptor_count; - } else { - string_descriptor_count = 8; // Backward compatibility with esp_tinyusb v1.0.0. Do NOT remove! - } - } else { - string_descriptor = descriptor_str_kconfig; - while (descriptor_str_kconfig[++string_descriptor_count] != NULL); - ESP_LOGW(TAG, "The device's string descriptor is not provided by user, using default."); - } - - if (config->device_descriptor) { - dev_descriptor = config->device_descriptor; - } else { - dev_descriptor = &descriptor_dev_kconfig; - ESP_LOGW(TAG, "The device's device descriptor is not provided by user, using default."); - } + // Descriptors config + tinyusb_descriptor_config_t tinyusb_desc_cfg = { 0 }; + ESP_RETURN_ON_ERROR(tinyusb_prepare_descriptors_config(config, &tinyusb_desc_cfg), TAG, "Prepare descriptors configuration failed"); + tinyusb_set_descriptors(&tinyusb_desc_cfg); - tinyusb_set_descriptor(dev_descriptor, string_descriptor, string_descriptor_count, cfg_descriptor); + // Init #if !CONFIG_TINYUSB_INIT_IN_DEFAULT_TASK ESP_RETURN_ON_FALSE(tusb_init(), ESP_FAIL, TAG, "Init TinyUSB stack failed"); #endif