From 8ea55b6c48e35c93c99c6d98d61ec996c37a0414 Mon Sep 17 00:00:00 2001 From: Roman Leonov Date: Tue, 6 Feb 2024 13:39:11 +0100 Subject: [PATCH] feature(esp_tinyusb): Added FS configuration descriptor for HS device Added union in tinyusb configuration for configuration descriptor pointer Moved selecting user-defined or default descriptor based on tinyusb configuration to descriptors_control Changed default Kconfig level to 1 --- device/esp_tinyusb/CHANGELOG.md | 29 +-- device/esp_tinyusb/Kconfig | 4 +- device/esp_tinyusb/descriptors_control.c | 204 +++++++++++++-- device/esp_tinyusb/idf_component.yml | 2 +- device/esp_tinyusb/include/tinyusb.h | 17 +- .../include_private/descriptors_control.h | 24 +- .../include_private/usb_descriptors.h | 35 ++- device/esp_tinyusb/test/local/CMakeLists.txt | 8 + device/esp_tinyusb/test/local/libusb_test.c | 121 +++++++++ .../esp_tinyusb/test_app/main/CMakeLists.txt | 6 +- .../test_app/main/test_bvalid_sig.c | 13 +- .../test_app/main/test_bvalid_sig.h | 18 ++ .../test_app/main/test_descriptors_config.c | 235 ++++++++++++++++++ .../test_app/main/test_descriptors_config.h | 18 ++ .../esp_tinyusb/test_app/main/test_tud_cb.c | 28 +++ device/esp_tinyusb/tinyusb.c | 42 +--- device/esp_tinyusb/usb_descriptors.c | 69 ++++- 17 files changed, 759 insertions(+), 114 deletions(-) create mode 100644 device/esp_tinyusb/test/local/CMakeLists.txt create mode 100644 device/esp_tinyusb/test/local/libusb_test.c create mode 100644 device/esp_tinyusb/test_app/main/test_bvalid_sig.h create mode 100644 device/esp_tinyusb/test_app/main/test_descriptors_config.c create mode 100644 device/esp_tinyusb/test_app/main/test_descriptors_config.h create mode 100644 device/esp_tinyusb/test_app/main/test_tud_cb.c diff --git a/device/esp_tinyusb/CHANGELOG.md b/device/esp_tinyusb/CHANGELOG.md index 8138f07e..78608a7a 100644 --- a/device/esp_tinyusb/CHANGELOG.md +++ b/device/esp_tinyusb/CHANGELOG.md @@ -1,27 +1,28 @@ -## 1.4.4 (Unreleased) +## 1.4.4 -- CDC-ACM: Remove MIN() definition if already defined -- MSC: Set EP size in configuration descriptor based on speed +- esp_tinyusb: Added HighSpeed and Qualifier device descriptors in tinyusb configuration +- CDC-ACM: Removed MIN() definition if already defined +- MSC: Fixed EP size selecting in default configuration descriptor ## 1.4.3 -- esp_tinyusb: ESP32P4 HS only support +- esp_tinyusb: Added ESP32P4 support (HS only) ## 1.4.2 -- MSC: Fix maximum files open -- Add uninstall function +- MSC: Fixed maximum files open +- Added uninstall function ## 1.4.0 -- MSC: Fix integer overflows -- CDC-ACM: Remove intermediate RX ringbuffer -- CDC-ACM: Increase default FIFO size to 512 bytes -- CDC-ACM: Fix Virtual File System binding +- MSC: Fixed integer overflows +- CDC-ACM: Removed intermediate RX ringbuffer +- CDC-ACM: Increased default FIFO size to 512 bytes +- CDC-ACM: Fixed Virtual File System binding ## 1.3.0 -- Add NCM extension +- Added NCM extension ## 1.2.1 - 1.2.2 @@ -29,15 +30,15 @@ ## 1.2.0 -- Add MSC extension for accessing SPI Flash on memory card https://github.com/espressif/idf-extra-components/commit/a8c00d7707ba4ceeb0970c023d702c7768dba3dc +- Added MSC extension for accessing SPI Flash on memory card https://github.com/espressif/idf-extra-components/commit/a8c00d7707ba4ceeb0970c023d702c7768dba3dc ## 1.1.0 -- Add support for NCM, ECM/RNDIS, DFU and Bluetooth TinyUSB drivers https://github.com/espressif/idf-extra-components/commit/79f35c9b047b583080f93a63310e2ee7d82ef17b +- Added support for NCM, ECM/RNDIS, DFU and Bluetooth TinyUSB drivers https://github.com/espressif/idf-extra-components/commit/79f35c9b047b583080f93a63310e2ee7d82ef17b ## 1.0.4 -- Clean up string descriptors handling https://github.com/espressif/idf-extra-components/commit/046cc4b02f524d5c7e3e56480a473cfe844dc3d6 +- Cleaned up string descriptors handling https://github.com/espressif/idf-extra-components/commit/046cc4b02f524d5c7e3e56480a473cfe844dc3d6 ## 1.0.2 - 1.0.3 diff --git a/device/esp_tinyusb/Kconfig b/device/esp_tinyusb/Kconfig index a4adc141..7b01f4c3 100644 --- a/device/esp_tinyusb/Kconfig +++ b/device/esp_tinyusb/Kconfig @@ -1,7 +1,7 @@ menu "TinyUSB Stack" config TINYUSB_DEBUG_LEVEL int "TinyUSB log level (0-3)" - default 0 + default 1 range 0 3 help Specify verbosity of TinyUSB log output. @@ -12,7 +12,7 @@ menu "TinyUSB Stack" default TINYUSB_RHPORT_HS help Allows set the USB PHY Controller for TinyUSB: HS (USB OTG2.0 PHY for HighSpeed) - + config TINYUSB_RHPORT_HS bool "HS" endchoice diff --git a/device/esp_tinyusb/descriptors_control.c b/device/esp_tinyusb/descriptors_control.c index bff7fc23..67b6cb3e 100644 --- a/device/esp_tinyusb/descriptors_control.c +++ b/device/esp_tinyusb/descriptors_control.c @@ -1,20 +1,44 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #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) static const char *TAG = "tusb_desc"; -static const tusb_desc_device_t *s_device_descriptor; -static const uint8_t *s_configuration_descriptor; -static const char *s_str_descriptor[USB_STRING_DESCRIPTOR_ARRAY_SIZE]; // Array of pointers (strings). Statically allocated, can be made dynamic in the future. + +// ============================================================================= +// STRUCTS +// ============================================================================= + +/** + * @brief Descriptor pointers for tinyusb descriptor requests callbacks + * + */ +typedef struct { + const tusb_desc_device_t *dev; /*!< Pointer to device descriptor */ + union { + const uint8_t *cfg; /*!< Pointer to FullSpeed configuration descriptor when device one-speed only */ + const uint8_t *fs_cfg; /*!< Pointer to FullSpeed configuration descriptor when device support HighSpeed */ + }; +#if (TUD_OPT_HIGH_SPEED) + const uint8_t *hs_cfg; /*!< Pointer to HighSpeed configuration descriptor */ + const tusb_desc_device_qualifier_t *qualifier; /*!< Pointer to Qualifier descriptor */ + uint8_t *other_speed; /*!< Pointer for other speed configuration descriptor */ +#endif // TUD_OPT_HIGH_SPEED + const char *str[USB_STRING_DESCRIPTOR_ARRAY_SIZE]; /*!< Pointer to array of UTF-8 strings */ + int str_count; /*!< Number of descriptors in str */ +} tinyusb_descriptor_config_t; + +static tinyusb_descriptor_config_t s_desc_cfg; // ============================================================================= // CALLBACKS @@ -28,7 +52,8 @@ static const char *s_str_descriptor[USB_STRING_DESCRIPTOR_ARRAY_SIZE]; // Array */ uint8_t const *tud_descriptor_device_cb(void) { - return (uint8_t const *)s_device_descriptor; + assert(s_desc_cfg.dev); + return (uint8_t const *)s_desc_cfg.dev; } /** @@ -41,8 +66,53 @@ uint8_t const *tud_descriptor_device_cb(void) uint8_t const *tud_descriptor_configuration_cb(uint8_t index) { (void)index; // Unused, this driver supports only 1 configuration - return s_configuration_descriptor; + assert(s_desc_cfg.cfg); + +#if (TUD_OPT_HIGH_SPEED) + // HINT: cfg and fs_cfg are union, no need to assert(fs_cfg) + assert(s_desc_cfg.hs_cfg); + // Return configuration descriptor based on Host speed + return (TUSB_SPEED_HIGH == tud_speed_get()) + ? s_desc_cfg.hs_cfg + : s_desc_cfg.fs_cfg; +#else + return s_desc_cfg.cfg; +#endif // TUD_OPT_HIGH_SPEED +} + +#if (TUD_OPT_HIGH_SPEED) +/** + * @brief Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request + * Descriptor contents must exist long enough for transfer to complete + * If not highspeed capable stall this request + */ +uint8_t const *tud_descriptor_device_qualifier_cb(void) +{ + assert(s_desc_cfg.qualifier); + return (uint8_t const *)s_desc_cfg.qualifier; +} + +/** + * @brief Invoked when received GET OTHER SPEED CONFIGURATION DESCRIPTOR request + * Descriptor contents must exist long enough for transfer to complete + * Configuration descriptor in the other speed e.g if high speed then this is for full speed and vice versa + */ +uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) +{ + assert(s_desc_cfg.other_speed); + + const uint8_t *other_speed = (TUSB_SPEED_HIGH == tud_speed_get()) + ? s_desc_cfg.fs_cfg + : s_desc_cfg.hs_cfg; + + memcpy(s_desc_cfg.other_speed, + other_speed, + ((tusb_desc_configuration_t *)other_speed)->wTotalLength); + + ((tusb_desc_configuration_t *)s_desc_cfg.other_speed)->bDescriptorType = TUSB_DESC_OTHER_SPEED_CONFIG; + return s_desc_cfg.other_speed; } +#endif // TUD_OPT_HIGH_SPEED /** * @brief Invoked when received GET STRING DESCRIPTOR request @@ -54,11 +124,12 @@ uint8_t const *tud_descriptor_configuration_cb(uint8_t index) uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) { (void) langid; // Unused, this driver supports only one language in string descriptors + assert(s_desc_cfg.str); uint8_t chr_count; static uint16_t _desc_str[MAX_DESC_BUF_SIZE]; if (index == 0) { - memcpy(&_desc_str[1], s_str_descriptor[0], 2); + memcpy(&_desc_str[1], s_desc_cfg.str[0], 2); chr_count = 1; } else { if (index >= USB_STRING_DESCRIPTOR_ARRAY_SIZE) { @@ -66,12 +137,12 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) return NULL; } - if (s_str_descriptor[index] == NULL) { + if (s_desc_cfg.str[index] == NULL) { ESP_LOGW(TAG, "String index (%u) points to NULL, check your string descriptor", index); return NULL; } - const char *str = s_str_descriptor[index]; + const char *str = s_desc_cfg.str[index]; chr_count = strnlen(str, MAX_DESC_BUF_SIZE - 1); // Buffer len - header // Convert ASCII string into UTF-16 @@ -89,11 +160,83 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) // ============================================================================= // Driver functions // ============================================================================= - -void tinyusb_set_descriptor(const tusb_desc_device_t *dev_desc, const char **str_desc, int str_desc_count, const uint8_t *cfg_desc) +esp_err_t tinyusb_set_descriptors(const tinyusb_config_t *config) { - assert(dev_desc && str_desc && cfg_desc); - assert(str_desc_count <= USB_STRING_DESCRIPTOR_ARRAY_SIZE); + esp_err_t ret = ESP_FAIL; + assert(config); + const char **pstr_desc; + // Flush descriptors control struct + memset(&s_desc_cfg, 0x00, sizeof(tinyusb_descriptor_config_t)); + // Parse configuration and save descriptors's pointer + // Select Device Descriptor + if (config->device_descriptor == NULL) { + ESP_LOGW(TAG, "No Device descriptor provided, using default."); + s_desc_cfg.dev = &descriptor_dev_default; + } else { + s_desc_cfg.dev = config->device_descriptor; + } + + // Select FullSpeed configuration descriptor + if (config->configuration_descriptor == NULL) { + // 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_GOTO_ON_FALSE(config->configuration_descriptor, ESP_ERR_INVALID_ARG, fail, TAG, "Configuration descriptor must be provided for this device"); +#else + ESP_LOGW(TAG, "No FullSpeed configuration descriptor provided, using default."); + s_desc_cfg.cfg = descriptor_fs_cfg_default; +#endif + } else { + s_desc_cfg.cfg = config->configuration_descriptor; + } + +#if (TUD_OPT_HIGH_SPEED) + // High Speed + if (config->hs_configuration_descriptor == NULL) { + // 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_GOTO_ON_FALSE(config->hs_configuration_descriptor, ESP_ERR_INVALID_ARG, fail, TAG, "HighSpeed configuration descriptor must be provided for this device"); +#else + ESP_LOGW(TAG, "No HighSpeed configuration descriptor provided, using default."); + s_desc_cfg.hs_cfg = descriptor_hs_cfg_default; +#endif + } else { + s_desc_cfg.hs_cfg = config->hs_configuration_descriptor; + } + + // HS and FS cfg desc should be equal length + ESP_GOTO_ON_FALSE(((tusb_desc_configuration_t *)s_desc_cfg.hs_cfg)->wTotalLength == + ((tusb_desc_configuration_t *)s_desc_cfg.fs_cfg)->wTotalLength, + ESP_ERR_INVALID_ARG, fail, TAG, "HighSpeed and FullSpeed configuration descriptors must be same length"); + + // Qualifier Descriptor + if (config->qualifier_descriptor == NULL) { + ESP_GOTO_ON_FALSE((s_desc_cfg.dev == &descriptor_dev_default), ESP_ERR_INVALID_ARG, fail, TAG, "Qualifier descriptor must be present (Device Descriptor not default)."); + // Get default qualifier if device descriptor is default + ESP_LOGW(TAG, "No Qulifier descriptor provided, using default."); + s_desc_cfg.qualifier = &descriptor_qualifier_default; + } else { + s_desc_cfg.qualifier = config->qualifier_descriptor; + } + + // Other Speed buffer allocate + s_desc_cfg.other_speed = calloc(1, ((tusb_desc_configuration_t *)s_desc_cfg.hs_cfg)->wTotalLength); + ESP_GOTO_ON_FALSE(s_desc_cfg.other_speed, ESP_ERR_NO_MEM, fail, TAG, "Other speed memory allocation error"); +#endif // TUD_OPT_HIGH_SPEED + + // Select String Descriptors and count them + if (config->string_descriptor == NULL) { + ESP_LOGW(TAG, "No String descriptors provided, using default."); + pstr_desc = descriptor_str_default; + while (descriptor_str_default[++s_desc_cfg.str_count] != NULL); + } else { + pstr_desc = config->string_descriptor; + s_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! + } + + ESP_GOTO_ON_FALSE(s_desc_cfg.str_count <= USB_STRING_DESCRIPTOR_ARRAY_SIZE, ESP_ERR_NOT_SUPPORTED, fail, TAG, "String descriptors exceed limit"); + memcpy(s_desc_cfg.str, pstr_desc, s_desc_cfg.str_count * sizeof(pstr_desc[0])); ESP_LOGI(TAG, "\n" "┌─────────────────────────────────┐\n" @@ -121,20 +264,31 @@ 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])); + s_desc_cfg.dev->bDeviceClass, s_desc_cfg.dev->bDeviceSubClass, + s_desc_cfg.dev->bDeviceProtocol, s_desc_cfg.dev->bMaxPacketSize0, + s_desc_cfg.dev->idVendor, s_desc_cfg.dev->idProduct, s_desc_cfg.dev->bcdDevice, + s_desc_cfg.dev->iManufacturer, s_desc_cfg.dev->iProduct, s_desc_cfg.dev->iSerialNumber, + s_desc_cfg.dev->bNumConfigurations); + + return ESP_OK; + +fail: +#if (TUD_OPT_HIGH_SPEED) + free(s_desc_cfg.other_speed); +#endif // TUD_OPT_HIGH_SPEED + return ret; } void tinyusb_set_str_descriptor(const char *str, int str_idx) { assert(str_idx < USB_STRING_DESCRIPTOR_ARRAY_SIZE); - s_str_descriptor[str_idx] = str; + s_desc_cfg.str[str_idx] = str; +} + +void tinyusb_free_descriptors(void) +{ +#if (TUD_OPT_HIGH_SPEED) + assert(s_desc_cfg.other_speed); + free(s_desc_cfg.other_speed); +#endif // TUD_OPT_HIGH_SPEED } diff --git a/device/esp_tinyusb/idf_component.yml b/device/esp_tinyusb/idf_component.yml index 24229aaa..13a37f48 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.3" +version: "1.4.4" 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..484c86e6 100644 --- a/device/esp_tinyusb/include/tinyusb.h +++ b/device/esp_tinyusb/include/tinyusb.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -31,7 +31,20 @@ 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 */ + }; +#if (TUD_OPT_HIGH_SPEED) + struct { + const uint8_t *fs_configuration_descriptor; /*!< Pointer to a FullSpeed configuration descriptor. If set to NULL, TinyUSB device will use a default configuration descriptor whose values are set in Kconfig */ + }; + }; + const uint8_t *hs_configuration_descriptor; /*!< Pointer to a HighSpeed configuration descriptor. If set to NULL, TinyUSB device will use a default configuration descriptor whose values are set in Kconfig */ + const tusb_desc_device_qualifier_t *qualifier_descriptor; /*!< Pointer to a qualifier descriptor */ +#else + }; +#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..fcf35222 100644 --- a/device/esp_tinyusb/include_private/descriptors_control.h +++ b/device/esp_tinyusb/include_private/descriptors_control.h @@ -1,28 +1,30 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ #pragma once -#include "tusb.h" +#include "tinyusb.h" #ifdef __cplusplus extern "C" { #endif +#define USB_STRING_DESCRIPTOR_ARRAY_SIZE 8 // Max 8 string descriptors for a device. LANGID, Manufacturer, Product, Serial number + 4 user defined + /** - * @brief Set descriptors for this driver + * @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] 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] config tinyusb stack specific configuration + * @retval ESP_ERR_INVALID_ARG Default configuration descriptor is provided only for CDC, MSC and NCM classes + * @retval ESP_ERR_NO_MEM Memory allocation error + * @retval ESP_OK Descriptors configured without error */ -void tinyusb_set_descriptor(const tusb_desc_device_t *dev_desc, const char **str_desc, int str_desc_count, const uint8_t *cfg_desc); +esp_err_t tinyusb_set_descriptors(const tinyusb_config_t *config); /** * @brief Set specific string descriptor @@ -34,6 +36,12 @@ void tinyusb_set_descriptor(const tusb_desc_device_t *dev_desc, const char **str */ void tinyusb_set_str_descriptor(const char *str, int str_idx); +/** + * @brief Free memory allocated during tinyusb_set_descriptors + * + */ +void tinyusb_free_descriptors(void); + #ifdef __cplusplus } #endif diff --git a/device/esp_tinyusb/include_private/usb_descriptors.h b/device/esp_tinyusb/include_private/usb_descriptors.h index 98126bcd..be1979ab 100644 --- a/device/esp_tinyusb/include_private/usb_descriptors.h +++ b/device/esp_tinyusb/include_private/usb_descriptors.h @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -16,25 +16,44 @@ extern "C" { * @brief Device descriptor generated from Kconfig * * This descriptor is used by default. - * The user can provide his own device descriptor during tinyusb_driver_install() call + * The user can provide their own device descriptor via tinyusb_driver_install() call */ -extern const tusb_desc_device_t descriptor_dev_kconfig; +extern const tusb_desc_device_t descriptor_dev_default; + +#if (TUD_OPT_HIGH_SPEED) +/** + * @brief Qualifier Device descriptor generated from Kconfig + * + * This descriptor is used by default. + * The user can provide their own descriptor via tinyusb_driver_install() call + */ +extern const tusb_desc_device_qualifier_t descriptor_qualifier_default; +#endif // TUD_OPT_HIGH_SPEED /** * @brief Array of string descriptors generated from Kconfig * * This descriptor is used by default. - * The user can provide his own descriptor during tinyusb_driver_install() call + * The user can provide their own descriptor via tinyusb_driver_install() call + */ +extern const char *descriptor_str_default[]; + +/** + * @brief FullSpeed configuration descriptor generated from Kconfig + * This descriptor is used by default. + * The user can provide their own FullSpeed configuration descriptor via tinyusb_driver_install() call */ -extern const char *descriptor_str_kconfig[]; +extern const uint8_t descriptor_fs_cfg_default[]; +#if (TUD_OPT_HIGH_SPEED) /** - * @brief Configuration descriptor generated from Kconfig + * @brief HighSpeed Configuration descriptor generated from Kconfig * * This descriptor is used by default. - * The user can provide his own configuration descriptor during tinyusb_driver_install() call + * The user can provide their own HighSpeed configuration descriptor via tinyusb_driver_install() call */ -extern const uint8_t descriptor_cfg_kconfig[]; +extern const uint8_t descriptor_hs_cfg_default[]; +#endif // TUD_OPT_HIGH_SPEED uint8_t tusb_get_mac_string_id(void); diff --git a/device/esp_tinyusb/test/local/CMakeLists.txt b/device/esp_tinyusb/test/local/CMakeLists.txt new file mode 100644 index 00000000..637991e7 --- /dev/null +++ b/device/esp_tinyusb/test/local/CMakeLists.txt @@ -0,0 +1,8 @@ +cmake_minimum_required(VERSION 3.22) +project(libusb_test + LANGUAGES C +) + +add_executable(libusb_test libusb_test.c) +target_link_libraries(libusb_test -lusb-1.0) + diff --git a/device/esp_tinyusb/test/local/libusb_test.c b/device/esp_tinyusb/test/local/libusb_test.c new file mode 100644 index 00000000..3c86f44e --- /dev/null +++ b/device/esp_tinyusb/test/local/libusb_test.c @@ -0,0 +1,121 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#define TINYUSB_VENDOR 0x303A +#define TINYUSB_PRODUCT 0x4002 + +#define DESC_TYPE_DEVICE_QUALIFIER 0x06 +#define DESC_TYOE_OTHER_SPEED_CONFIG 0x07 + +// Buffer for descriptor data +unsigned char buffer[512] = { 0 }; + +// USB Other Speed Configuration Descriptor +typedef struct __attribute__ ((packed)) +{ + uint8_t bLength ; ///< Size of descriptor + uint8_t bDescriptorType ; ///< Other_speed_Configuration Type + uint16_t wTotalLength ; ///< Total length of data returned + + uint8_t bNumInterfaces ; ///< Number of interfaces supported by this speed configuration + uint8_t bConfigurationValue ; ///< Value to use to select configuration + uint8_t iConfiguration ; ///< Index of string descriptor + uint8_t bmAttributes ; ///< Same as Configuration descriptor + uint8_t bMaxPower ; ///< Same as Configuration descriptor +} desc_other_speed_t; + +// USB Device Qualifier Descriptor +typedef struct __attribute__ ((packed)) +{ + uint8_t bLength ; ///< Size of descriptor + uint8_t bDescriptorType ; ///< Device Qualifier Type + uint16_t bcdUSB ; ///< USB specification version number (e.g., 0200H for V2.00) + + uint8_t bDeviceClass ; ///< Class Code + uint8_t bDeviceSubClass ; ///< SubClass Code + uint8_t bDeviceProtocol ; ///< Protocol Code + + uint8_t bMaxPacketSize0 ; ///< Maximum packet size for other speed + uint8_t bNumConfigurations ; ///< Number of Other-speed Configurations + uint8_t bReserved ; ///< Reserved for future use, must be zero +} desc_device_qualifier_t; + +// printf helpers +static void _print_device_qulifier_desc(unsigned char *buffer, int length); +static void _print_other_speed_desc(unsigned char *buffer, int length); + +// +// MAIN +// +int main() +{ + libusb_context *context = NULL; + int rc = 0; + + rc = libusb_init(&context); + assert(rc == 0); + libusb_device_handle *dev_handle = libusb_open_device_with_vid_pid(context, + TINYUSB_VENDOR, + TINYUSB_PRODUCT); + + if (dev_handle != NULL) { + printf("TinyUSB Device has been found\n"); + + // Test Qualifier Descriprtor + // 1. Get Qualifier Descriptor + // 2. print descriptor data + rc = libusb_get_descriptor(dev_handle, DESC_TYPE_DEVICE_QUALIFIER, 0, buffer, 512); + _print_device_qulifier_desc(buffer, rc); + + // Test Other Speed Descriptor + // 1. Get Other Speed Descriptor + // 2. print descriptor data + rc = libusb_get_descriptor(dev_handle, DESC_TYOE_OTHER_SPEED_CONFIG, 0, buffer, 512); + _print_other_speed_desc(buffer, rc); + + libusb_close(dev_handle); + } else { + printf("TinyUSB Device has NOT been found\n"); + } + + libusb_exit(context); +} + + +// ============================================================================= +static void _print_device_qulifier_desc(unsigned char *buffer, int length) +{ + assert(buffer); + desc_device_qualifier_t *qualifier_desc = (desc_device_qualifier_t *) buffer; + printf("========= Device Qualifier ========== \n"); + printf("\t bLength: %d \n", qualifier_desc->bLength); + printf("\t bDescriptorType: %d (%#x)\n", qualifier_desc->bDescriptorType, qualifier_desc->bDescriptorType); + printf("\t bcdUSB: %d (%#x) \n", qualifier_desc->bcdUSB, qualifier_desc->bcdUSB); + printf("\t bDeviceClass: %d (%#x) \n", qualifier_desc->bDeviceClass, qualifier_desc->bDeviceClass); + printf("\t bDeviceSubClass: %d \n", qualifier_desc->bDeviceSubClass); + printf("\t bDeviceProtocol: %d \n", qualifier_desc->bDeviceProtocol); + printf("\t bMaxPacketSize0: %d \n", qualifier_desc->bMaxPacketSize0); + printf("\t bNumConfigurations: %d \n", qualifier_desc->bNumConfigurations); +} + +static void _print_other_speed_desc(unsigned char *buffer, int length) +{ + assert(buffer); + desc_other_speed_t *other_speed = (desc_other_speed_t *) buffer; + printf("============ Other Speed ============ \n"); + printf("\t bLength: %d \n", other_speed->bLength); + printf("\t bDescriptorType: %d (%#x) \n", other_speed->bDescriptorType, other_speed->bDescriptorType); + printf("\t wTotalLength: %d \n", other_speed->wTotalLength); + printf("\t bNumInterfaces: %d \n", other_speed->bNumInterfaces); + printf("\t bConfigurationValue: %d \n", other_speed->bConfigurationValue); + printf("\t iConfiguration: %d \n", other_speed->iConfiguration); + printf("\t bmAttributes: %d (%#x) \n", other_speed->bmAttributes, other_speed->bmAttributes); + printf("\t bMaxPower: %d (%#x) \n", other_speed->bMaxPower, other_speed->bMaxPower); +} diff --git a/device/esp_tinyusb/test_app/main/CMakeLists.txt b/device/esp_tinyusb/test_app/main/CMakeLists.txt index 5e19c76b..3cb6ad50 100644 --- a/device/esp_tinyusb/test_app/main/CMakeLists.txt +++ b/device/esp_tinyusb/test_app/main/CMakeLists.txt @@ -1,6 +1,6 @@ include($ENV{IDF_PATH}/tools/cmake/version.cmake) -idf_component_register(SRCS "test_esp_tinyusb.c" "test_bvalid_sig.c" "test_app_main.c" - INCLUDE_DIRS "." +idf_component_register(SRC_DIRS . + INCLUDE_DIRS . REQUIRES unity esp_tinyusb - WHOLE_ARCHIVE) \ No newline at end of file + WHOLE_ARCHIVE) diff --git a/device/esp_tinyusb/test_app/main/test_bvalid_sig.c b/device/esp_tinyusb/test_app/main/test_bvalid_sig.c index 6d66418c..b596564f 100644 --- a/device/esp_tinyusb/test_app/main/test_bvalid_sig.c +++ b/device/esp_tinyusb/test_app/main/test_bvalid_sig.c @@ -25,6 +25,10 @@ #define DEVICE_DETACH_TEST_ROUNDS 10 #define DEVICE_DETACH_ROUND_DELAY_MS 1000 +#if (CONFIG_IDF_TARGET_ESP32P4) +#define USB_SRP_BVALID_IN_IDX USB_SRP_BVALID_PAD_IN_IDX +#endif // CONFIG_IDF_TARGET_ESP32P4 + /* TinyUSB descriptors ********************************************************************* */ #define TUSB_DESC_TOTAL_LEN (TUD_CONFIG_DESC_LEN) @@ -54,14 +58,12 @@ static const tusb_desc_device_t test_device_descriptor = { .bNumConfigurations = 0x01 }; -// Invoked when device is mounted -void tud_mount_cb(void) +void test_bvalid_sig_mount_cb(void) { dev_mounted++; } -// Invoked when device is unmounted -void tud_umount_cb(void) +void test_bvalid_sig_umount_cb(void) { dev_umounted++; } @@ -78,6 +80,9 @@ TEST_CASE("bvalid_signal", "[esp_tinyusb][usb_device]") }; TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + dev_mounted = 0; + dev_umounted = 0; + 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); diff --git a/device/esp_tinyusb/test_app/main/test_bvalid_sig.h b/device/esp_tinyusb/test_app/main/test_bvalid_sig.h new file mode 100644 index 00000000..82dd31b9 --- /dev/null +++ b/device/esp_tinyusb/test_app/main/test_bvalid_sig.h @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void test_bvalid_sig_mount_cb(void); +void test_bvalid_sig_umount_cb(void); + +#ifdef __cplusplus +} +#endif //__cplusplus diff --git a/device/esp_tinyusb/test_app/main/test_descriptors_config.c b/device/esp_tinyusb/test_app/main/test_descriptors_config.c new file mode 100644 index 00000000..2b92b515 --- /dev/null +++ b/device/esp_tinyusb/test_app/main/test_descriptors_config.c @@ -0,0 +1,235 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "soc/soc_caps.h" + +#if SOC_USB_OTG_SUPPORTED + +#include +#include +#include "esp_system.h" +#include "esp_err.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/semphr.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 "tusb_tasks.h" + +#define DEVICE_MOUNT_TIMEOUT_MS 5000 + +// ========================= TinyUSB descriptors =============================== +#define TUSB_DESC_TOTAL_LEN (TUD_CONFIG_DESC_LEN) + +static uint8_t const test_fs_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), +}; + +#if (TUD_OPT_HIGH_SPEED) +static uint8_t const test_hs_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), +}; +#endif // TUD_OPT_HIGH_SPEED + +static const 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 +}; + +// ========================== Private logic ==================================== +SemaphoreHandle_t desc_config_device_mounted = NULL; + +static bool __test_prep(void) +{ + desc_config_device_mounted = xSemaphoreCreateBinary(); + return (desc_config_device_mounted != NULL); +} + +static esp_err_t __test_wait_conn(void) +{ + if (!desc_config_device_mounted) { + return ESP_ERR_INVALID_STATE; + } + + return ( xSemaphoreTake(desc_config_device_mounted, pdMS_TO_TICKS(DEVICE_MOUNT_TIMEOUT_MS)) + ? ESP_OK + : ESP_ERR_TIMEOUT ); +} + +static void __test_conn(void) +{ + if (desc_config_device_mounted) { + xSemaphoreGive(desc_config_device_mounted); + } +} + +static void __test_free(void) +{ + if (desc_config_device_mounted) { + vSemaphoreDelete(desc_config_device_mounted); + } +} + +// ========================== Callbacks ======================================== +// Invoked when device is mounted +void test_descriptors_config_mount_cb(void) +{ + __test_conn(); +} + +void test_descriptors_config_umount_cb(void) +{ + +} + +TEST_CASE("descriptors_config_all_default", "[esp_tinyusb][usb_device]") +{ + TEST_ASSERT_EQUAL(true, __test_prep()); + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = NULL, + .configuration_descriptor = NULL, +#if (TUD_OPT_HIGH_SPEED) + .hs_configuration_descriptor = NULL, +#endif // TUD_OPT_HIGH_SPEED + }; + // Install + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + // Wait for mounted callback + TEST_ASSERT_EQUAL(ESP_OK, __test_wait_conn()); + // Cleanup + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); + TEST_ASSERT_EQUAL(ESP_OK, tusb_stop_task()); + __test_free(); +} + +TEST_CASE("descriptors_config_device", "[esp_tinyusb][usb_device]") +{ + TEST_ASSERT_EQUAL(true, __test_prep()); + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = &test_device_descriptor, + .configuration_descriptor = NULL, +#if (TUD_OPT_HIGH_SPEED) + .hs_configuration_descriptor = NULL, +#endif // TUD_OPT_HIGH_SPEED + }; + // Install + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + // Wait for mounted callback + TEST_ASSERT_EQUAL(ESP_OK, __test_wait_conn()); + // Cleanup + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); + TEST_ASSERT_EQUAL(ESP_OK, tusb_stop_task()); + __test_free(); +} + +TEST_CASE("descriptors_config_device_and_config", "[esp_tinyusb][usb_device]") +{ + TEST_ASSERT_EQUAL(true, __test_prep()); + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = &test_device_descriptor, + .configuration_descriptor = test_fs_configuration_descriptor, +#if (TUD_OPT_HIGH_SPEED) + .hs_configuration_descriptor = NULL, +#endif // TUD_OPT_HIGH_SPEED + }; + // Install + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + // Wait for mounted callback + TEST_ASSERT_EQUAL(ESP_OK, __test_wait_conn()); + // Cleanup + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); + TEST_ASSERT_EQUAL(ESP_OK, tusb_stop_task()); + __test_free(); +} + +#if (TUD_OPT_HIGH_SPEED) +TEST_CASE("descriptors_config_device_and_fs_config_only", "[esp_tinyusb][usb_device]") +{ + TEST_ASSERT_EQUAL(true, __test_prep()); + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = &test_device_descriptor, + .configuration_descriptor = test_fs_configuration_descriptor, + .hs_configuration_descriptor = NULL, + }; + // Install + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + // Wait for mounted callback + TEST_ASSERT_EQUAL(ESP_OK, __test_wait_conn()); + // Cleanup + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); + TEST_ASSERT_EQUAL(ESP_OK, tusb_stop_task()); + __test_free(); +} + +TEST_CASE("descriptors_config_device_and_hs_config_only", "[esp_tinyusb][usb_device]") +{ + TEST_ASSERT_EQUAL(true, __test_prep()); + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = &test_device_descriptor, + .configuration_descriptor = NULL, + .hs_configuration_descriptor = test_hs_configuration_descriptor, + }; + // Install + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + // Wait for mounted callback + TEST_ASSERT_EQUAL(ESP_OK, __test_wait_conn()); + // Cleanup + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); + TEST_ASSERT_EQUAL(ESP_OK, tusb_stop_task()); + __test_free(); +} + +TEST_CASE("descriptors_config_all_configured", "[esp_tinyusb][usb_device]") +{ + TEST_ASSERT_EQUAL(true, __test_prep()); + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = &test_device_descriptor, + .fs_configuration_descriptor = test_fs_configuration_descriptor, + .hs_configuration_descriptor = test_hs_configuration_descriptor, + }; + // Install + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + // Wait for mounted callback + TEST_ASSERT_EQUAL(ESP_OK, __test_wait_conn()); + // Cleanup + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall()); + TEST_ASSERT_EQUAL(ESP_OK, tusb_stop_task()); + __test_free(); +} +#endif // TUD_OPT_HIGH_SPEED + +#endif // SOC_USB_OTG_SUPPORTED diff --git a/device/esp_tinyusb/test_app/main/test_descriptors_config.h b/device/esp_tinyusb/test_app/main/test_descriptors_config.h new file mode 100644 index 00000000..6bdd77b7 --- /dev/null +++ b/device/esp_tinyusb/test_app/main/test_descriptors_config.h @@ -0,0 +1,18 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +void test_descriptors_config_mount_cb(void); +void test_descriptors_config_umount_cb(void); + +#ifdef __cplusplus +} +#endif //__cplusplus diff --git a/device/esp_tinyusb/test_app/main/test_tud_cb.c b/device/esp_tinyusb/test_app/main/test_tud_cb.c new file mode 100644 index 00000000..37d0a333 --- /dev/null +++ b/device/esp_tinyusb/test_app/main/test_tud_cb.c @@ -0,0 +1,28 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "tinyusb.h" +#include "tusb_tasks.h" +#include "test_bvalid_sig.h" +#include "test_descriptors_config.h" + +// Invoked when device is mounted +void tud_mount_cb(void) +{ + printf("%s\n", __FUNCTION__); + test_bvalid_sig_mount_cb(); + test_descriptors_config_mount_cb(); +} + +// Invoked when device is unmounted +void tud_umount_cb(void) +{ + printf("%s\n", __FUNCTION__); + test_bvalid_sig_umount_cb(); + test_descriptors_config_umount_cb(); +} diff --git a/device/esp_tinyusb/tinyusb.c b/device/esp_tinyusb/tinyusb.c index a43a304c..52bc2aeb 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,10 @@ 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 + ESP_RETURN_ON_ERROR(tinyusb_set_descriptors(config), TAG, "Descriptors config failed"); - 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 @@ -103,5 +68,6 @@ esp_err_t tinyusb_driver_install(const tinyusb_config_t *config) esp_err_t tinyusb_driver_uninstall() { + tinyusb_free_descriptors(); return usb_del_phy(phy_hdl); } diff --git a/device/esp_tinyusb/usb_descriptors.c b/device/esp_tinyusb/usb_descriptors.c index 956cc0fb..89109133 100644 --- a/device/esp_tinyusb/usb_descriptors.c +++ b/device/esp_tinyusb/usb_descriptors.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -22,8 +22,8 @@ /**** Kconfig driven Descriptor ****/ //------------- Device Descriptor -------------// -const tusb_desc_device_t descriptor_dev_kconfig = { - .bLength = sizeof(descriptor_dev_kconfig), +const tusb_desc_device_t descriptor_dev_default = { + .bLength = sizeof(descriptor_dev_default), .bDescriptorType = TUSB_DESC_DEVICE, .bcdUSB = 0x0200, @@ -62,8 +62,32 @@ const tusb_desc_device_t descriptor_dev_kconfig = { .bNumConfigurations = 0x01 }; +#if (TUD_OPT_HIGH_SPEED) +const tusb_desc_device_qualifier_t descriptor_qualifier_default = { + .bLength = sizeof(tusb_desc_device_qualifier_t), + .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, + .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, + .bNumConfigurations = 0x01, + .bReserved = 0 +}; +#endif // TUD_OPT_HIGH_SPEED + //------------- Array of String Descriptors -------------// -const char *descriptor_str_kconfig[] = { +const char *descriptor_str_default[] = { // array of pointer to string descriptors (char[]){0x09, 0x04}, // 0: is supported language is English (0x0409) CONFIG_TINYUSB_DESC_MANUFACTURER_STRING, // 1: Manufacturer @@ -166,30 +190,57 @@ enum { }; //------------- Configuration Descriptor -------------// -uint8_t const descriptor_cfg_kconfig[] = { +uint8_t const descriptor_fs_cfg_default[] = { + // 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, STRID_CDC_INTERFACE, 0x80 | EPNUM_0_CDC_NOTIF, 8, EPNUM_0_CDC, 0x80 | EPNUM_0_CDC, 64), +#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, STRID_CDC_INTERFACE, 0x80 | EPNUM_1_CDC_NOTIF, 8, EPNUM_1_CDC, 0x80 | EPNUM_1_CDC, 64), +#endif + +#if CFG_TUD_MSC + // Interface number, string index, EP Out & EP In address, EP size + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, STRID_MSC_INTERFACE, EPNUM_MSC, 0x80 | EPNUM_MSC, 64), +#endif + +#if CFG_TUD_NCM + // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. + TUD_CDC_NCM_DESCRIPTOR(ITF_NUM_NET, STRID_NET_INTERFACE, STRID_MAC, (0x80 | EPNUM_NET_NOTIF), 64, EPNUM_NET_DATA, (0x80 | EPNUM_NET_DATA), 64, CFG_TUD_NET_MTU), +#endif +}; + +#if (TUD_OPT_HIGH_SPEED) +uint8_t const descriptor_hs_cfg_default[] = { // 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, STRID_CDC_INTERFACE, 0x80 | EPNUM_0_CDC_NOTIF, 8, EPNUM_0_CDC, 0x80 | EPNUM_0_CDC, CFG_TUD_CDC_EP_BUFSIZE), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, STRID_CDC_INTERFACE, 0x80 | EPNUM_0_CDC_NOTIF, 8, EPNUM_0_CDC, 0x80 | EPNUM_0_CDC, 512), #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, STRID_CDC_INTERFACE, 0x80 | EPNUM_1_CDC_NOTIF, 8, EPNUM_1_CDC, 0x80 | EPNUM_1_CDC, CFG_TUD_CDC_EP_BUFSIZE), + TUD_CDC_DESCRIPTOR(ITF_NUM_CDC1, STRID_CDC_INTERFACE, 0x80 | EPNUM_1_CDC_NOTIF, 8, EPNUM_1_CDC, 0x80 | EPNUM_1_CDC, 512), #endif #if CFG_TUD_MSC // Interface number, string index, EP Out & EP In address, EP size - TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, STRID_MSC_INTERFACE, EPNUM_MSC, 0x80 | EPNUM_MSC, TUD_OPT_HIGH_SPEED ? 512 : 64), + TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, STRID_MSC_INTERFACE, EPNUM_MSC, 0x80 | EPNUM_MSC, 512), #endif #if CFG_TUD_NCM // Interface number, description string index, MAC address string index, EP notification address and size, EP data address (out, in), and size, max segment size. - TUD_CDC_NCM_DESCRIPTOR(ITF_NUM_NET, STRID_NET_INTERFACE, STRID_MAC, (0x80 | EPNUM_NET_NOTIF), 64, EPNUM_NET_DATA, (0x80 | EPNUM_NET_DATA), CFG_TUD_NET_ENDPOINT_SIZE, CFG_TUD_NET_MTU), + TUD_CDC_NCM_DESCRIPTOR(ITF_NUM_NET, STRID_NET_INTERFACE, STRID_MAC, (0x80 | EPNUM_NET_NOTIF), 64, EPNUM_NET_DATA, (0x80 | EPNUM_NET_DATA), 512, CFG_TUD_NET_MTU), #endif }; +#endif // TUD_OPT_HIGH_SPEED #if CFG_TUD_NCM uint8_t tusb_get_mac_string_id(void)