From e659ac99453dfb0aa942f46fd77496527df587f3 Mon Sep 17 00:00:00 2001 From: Tomas Rezucha Date: Tue, 17 Sep 2024 15:29:23 +0200 Subject: [PATCH 1/2] fix(esp_tinyusb): Provide default descriptors for Vendor specific class Closes https://github.com/hathach/tinyusb/issues/2806 Closes https://github.com/espressif/esp-idf/issues/14589 --- device/esp_tinyusb/CHANGELOG.md | 3 +- device/esp_tinyusb/Kconfig | 9 ++++ device/esp_tinyusb/descriptors_control.c | 8 ++-- device/esp_tinyusb/idf_component.yml | 2 +- device/esp_tinyusb/include/tusb_config.h | 13 +++--- device/esp_tinyusb/usb_descriptors.c | 52 +++++++++++++++++++++--- 6 files changed, 68 insertions(+), 19 deletions(-) diff --git a/device/esp_tinyusb/CHANGELOG.md b/device/esp_tinyusb/CHANGELOG.md index 254b6116..17010403 100644 --- a/device/esp_tinyusb/CHANGELOG.md +++ b/device/esp_tinyusb/CHANGELOG.md @@ -1,6 +1,7 @@ -## Unreleased +## 1.4.5 - CDC-ACM: Fixed memory leak at VFS unregister +- Vendor specific: Provided default configuration ## 1.4.4 diff --git a/device/esp_tinyusb/Kconfig b/device/esp_tinyusb/Kconfig index 7b01f4c3..9edbce1b 100644 --- a/device/esp_tinyusb/Kconfig +++ b/device/esp_tinyusb/Kconfig @@ -269,4 +269,13 @@ menu "TinyUSB Stack" bool "None" endchoice endmenu # "Network driver (ECM/NCM/RNDIS)" + + menu "Vendor Specific Interface" + config TINYUSB_VENDOR_COUNT + int "TinyUSB Vendor specific interfaces count" + default 0 + range 0 2 + help + Setting value greater than 0 will enable TinyUSB Vendor specific feature. + endmenu # "Vendor Specific Interface" endmenu # "TinyUSB Stack" diff --git a/device/esp_tinyusb/descriptors_control.c b/device/esp_tinyusb/descriptors_control.c index 67b6cb3e..830bea56 100644 --- a/device/esp_tinyusb/descriptors_control.c +++ b/device/esp_tinyusb/descriptors_control.c @@ -178,8 +178,8 @@ esp_err_t tinyusb_set_descriptors(const tinyusb_config_t *config) // 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) + // Default configuration descriptor must be provided for the following classes +#if (CFG_TUD_HID > 0 || CFG_TUD_MIDI > 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."); @@ -192,8 +192,8 @@ esp_err_t tinyusb_set_descriptors(const tinyusb_config_t *config) #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) + // Default configuration descriptor must be provided for the following classes +#if (CFG_TUD_HID > 0 || CFG_TUD_MIDI > 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."); diff --git a/device/esp_tinyusb/idf_component.yml b/device/esp_tinyusb/idf_component.yml index 13a37f48..7aea4bee 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.5" 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/tusb_config.h b/device/esp_tinyusb/include/tusb_config.h index adcea7c3..71e76fd9 100644 --- a/device/esp_tinyusb/include/tusb_config.h +++ b/device/esp_tinyusb/include/tusb_config.h @@ -1,6 +1,6 @@ /* * SPDX-FileCopyrightText: 2019 Ha Thach (tinyusb.org), - * SPDX-FileContributor: 2020 Espressif Systems (Shanghai) CO LTD + * SPDX-FileContributor: 2020-2024 Espressif Systems (Shanghai) CO LTD * SPDX-License-Identifier: MIT * * Copyright (c) 2019 Ha Thach (tinyusb.org), @@ -55,8 +55,8 @@ extern "C" { # define CONFIG_TINYUSB_MIDI_COUNT 0 #endif -#ifndef CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED -# define CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED 0 +#ifndef CONFIG_TINYUSB_VENDOR_COUNT +# define CONFIG_TINYUSB_VENDOR_COUNT 0 #endif #ifndef CONFIG_TINYUSB_NET_MODE_ECM_RNDIS @@ -128,9 +128,8 @@ extern "C" { #define CFG_TUD_MIDI_TX_BUFSIZE 64 // Vendor FIFO size of TX and RX -// If not configured vendor endpoints will not be buffered -#define CFG_TUD_VENDOR_RX_BUFSIZE 64 -#define CFG_TUD_VENDOR_TX_BUFSIZE 64 +#define CFG_TUD_VENDOR_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) +#define CFG_TUD_VENDOR_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64) // DFU macros #define CFG_TUD_DFU_XFER_BUFSIZE CONFIG_TINYUSB_DFU_BUFSIZE @@ -143,7 +142,7 @@ extern "C" { #define CFG_TUD_MSC CONFIG_TINYUSB_MSC_ENABLED #define CFG_TUD_HID CONFIG_TINYUSB_HID_COUNT #define CFG_TUD_MIDI CONFIG_TINYUSB_MIDI_COUNT -#define CFG_TUD_CUSTOM_CLASS CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED +#define CFG_TUD_VENDOR CONFIG_TINYUSB_VENDOR_COUNT #define CFG_TUD_ECM_RNDIS CONFIG_TINYUSB_NET_MODE_ECM_RNDIS #define CFG_TUD_NCM CONFIG_TINYUSB_NET_MODE_NCM #define CFG_TUD_DFU CONFIG_TINYUSB_DFU_MODE_DFU diff --git a/device/esp_tinyusb/usb_descriptors.c b/device/esp_tinyusb/usb_descriptors.c index 89109133..39fd682f 100644 --- a/device/esp_tinyusb/usb_descriptors.c +++ b/device/esp_tinyusb/usb_descriptors.c @@ -17,7 +17,7 @@ */ #define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) #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) ) + _PID_MAP(MIDI, 3) | _PID_MAP(AUDIO, 4) | _PID_MAP(VENDOR, 5) ) /**** Kconfig driven Descriptor ****/ @@ -96,20 +96,20 @@ const char *descriptor_str_default[] = { #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_NET_MODE_ECM_RNDIS || CONFIG_TINYUSB_NET_MODE_NCM "USB net", // 6. NET Interface "", // 7. MAC #endif + +#if CFG_TUD_VENDOR + "Vendor specific", // 8. Vendor specific +#endif NULL // NULL: Must be last. Indicates end of array }; @@ -134,6 +134,14 @@ enum { ITF_NUM_NET_DATA, #endif +#if CFG_TUD_VENDOR + ITF_VENDOR, +#endif + +#if CFG_TUD_VENDOR > 1 + ITF_VENDOR1, +#endif + ITF_NUM_TOTAL }; @@ -141,7 +149,8 @@ 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_NCM * TUD_CDC_NCM_DESC_LEN + CFG_TUD_NCM * TUD_CDC_NCM_DESC_LEN + + CFG_TUD_VENDOR * TUD_VENDOR_DESC_LEN }; //------------- USB Endpoint numbers -------------// @@ -166,6 +175,14 @@ enum { EPNUM_NET_NOTIF, EPNUM_NET_DATA, #endif + +#if CFG_TUD_VENDOR + EPNUM_0_VENDOR, +#endif + +#if CFG_TUD_VENDOR > 1 + EPNUM_1_VENDOR +#endif }; //------------- STRID -------------// @@ -187,6 +204,9 @@ enum { STRID_MAC, #endif +#if CFG_TUD_VENDOR + STRID_VENDOR_INTERFACE, +#endif }; //------------- Configuration Descriptor -------------// @@ -213,6 +233,16 @@ uint8_t const descriptor_fs_cfg_default[] = { // 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 CFG_TUD_VENDOR + // Interface number, string index, EP Out & IN address, EP size + TUD_VENDOR_DESCRIPTOR(ITF_VENDOR, STRID_VENDOR_INTERFACE, EPNUM_0_VENDOR, 0x80 | EPNUM_0_VENDOR, 64), +#endif + +#if CFG_TUD_VENDOR > 1 + // Interface number, string index, EP Out & IN address, EP size + TUD_VENDOR_DESCRIPTOR(ITF_VENDOR1, STRID_VENDOR_INTERFACE, EPNUM_1_VENDOR, 0x80 | EPNUM_1_VENDOR, 64), +#endif }; #if (TUD_OPT_HIGH_SPEED) @@ -239,6 +269,16 @@ uint8_t const descriptor_hs_cfg_default[] = { // 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), 512, CFG_TUD_NET_MTU), #endif + +#if CFG_TUD_VENDOR + // Interface number, string index, EP Out & IN address, EP size + TUD_VENDOR_DESCRIPTOR(ITF_VENDOR, STRID_VENDOR_INTERFACE, EPNUM_0_VENDOR, 0x80 | EPNUM_0_VENDOR, 512), +#endif + +#if CFG_TUD_VENDOR > 1 + // Interface number, string index, EP Out & IN address, EP size + TUD_VENDOR_DESCRIPTOR(ITF_VENDOR1, STRID_VENDOR_INTERFACE, EPNUM_1_VENDOR, 0x80 | EPNUM_1_VENDOR, 512), +#endif }; #endif // TUD_OPT_HIGH_SPEED From cd6674f69fc666ab1bb2abc54624e21848b1fb48 Mon Sep 17 00:00:00 2001 From: Tomas Rezucha Date: Fri, 20 Sep 2024 13:41:25 +0200 Subject: [PATCH 2/2] ci(esp_tinyusb): Add test_app for Vendor specific class --- .../workflows/build_and_run_test_app_usb.yml | 2 +- device/esp_tinyusb/test_app/README.md | 4 - .../cdc_and_usb_device}/CMakeLists.txt | 2 +- .../cdc_and_usb_device}/main/CMakeLists.txt | 0 .../main/idf_component.yml | 2 +- .../cdc_and_usb_device}/main/test_app_main.c | 0 .../main/test_bvalid_sig.c | 0 .../main/test_bvalid_sig.h | 0 .../cdc_and_usb_device}/main/test_cdc.c | 0 .../main/test_descriptors_config.c | 0 .../main/test_descriptors_config.h | 0 .../cdc_and_usb_device}/main/tud_global_cb.c | 0 .../cdc_and_usb_device}/pytest_cdc.py | 0 .../cdc_and_usb_device}/pytest_usb_device.py | 0 .../cdc_and_usb_device}/sdkconfig.defaults | 0 .../test_apps/vendor/CMakeLists.txt | 9 ++ .../test_apps/vendor/main/CMakeLists.txt | 4 + .../test_apps/vendor/main/idf_component.yml | 5 + .../test_apps/vendor/main/test_app_main.c | 48 ++++++++++ .../test_apps/vendor/main/test_vendor.c | 67 +++++++++++++ .../test_apps/vendor/pytest_vendor.py | 96 +++++++++++++++++++ .../test_apps/vendor/sdkconfig.defaults | 15 +++ 22 files changed, 247 insertions(+), 7 deletions(-) delete mode 100644 device/esp_tinyusb/test_app/README.md rename device/esp_tinyusb/{test_app => test_apps/cdc_and_usb_device}/CMakeLists.txt (88%) rename device/esp_tinyusb/{test_app => test_apps/cdc_and_usb_device}/main/CMakeLists.txt (100%) rename device/esp_tinyusb/{test_app => test_apps/cdc_and_usb_device}/main/idf_component.yml (75%) rename device/esp_tinyusb/{test_app => test_apps/cdc_and_usb_device}/main/test_app_main.c (100%) rename device/esp_tinyusb/{test_app => test_apps/cdc_and_usb_device}/main/test_bvalid_sig.c (100%) rename device/esp_tinyusb/{test_app => test_apps/cdc_and_usb_device}/main/test_bvalid_sig.h (100%) rename device/esp_tinyusb/{test_app => test_apps/cdc_and_usb_device}/main/test_cdc.c (100%) rename device/esp_tinyusb/{test_app => test_apps/cdc_and_usb_device}/main/test_descriptors_config.c (100%) rename device/esp_tinyusb/{test_app => test_apps/cdc_and_usb_device}/main/test_descriptors_config.h (100%) rename device/esp_tinyusb/{test_app => test_apps/cdc_and_usb_device}/main/tud_global_cb.c (100%) rename device/esp_tinyusb/{test_app => test_apps/cdc_and_usb_device}/pytest_cdc.py (100%) rename device/esp_tinyusb/{test_app => test_apps/cdc_and_usb_device}/pytest_usb_device.py (100%) rename device/esp_tinyusb/{test_app => test_apps/cdc_and_usb_device}/sdkconfig.defaults (100%) create mode 100644 device/esp_tinyusb/test_apps/vendor/CMakeLists.txt create mode 100644 device/esp_tinyusb/test_apps/vendor/main/CMakeLists.txt create mode 100644 device/esp_tinyusb/test_apps/vendor/main/idf_component.yml create mode 100644 device/esp_tinyusb/test_apps/vendor/main/test_app_main.c create mode 100644 device/esp_tinyusb/test_apps/vendor/main/test_vendor.c create mode 100644 device/esp_tinyusb/test_apps/vendor/pytest_vendor.py create mode 100644 device/esp_tinyusb/test_apps/vendor/sdkconfig.defaults diff --git a/.github/workflows/build_and_run_test_app_usb.yml b/.github/workflows/build_and_run_test_app_usb.yml index 0d6fa3e7..c43bccbe 100644 --- a/.github/workflows/build_and_run_test_app_usb.yml +++ b/.github/workflows/build_and_run_test_app_usb.yml @@ -61,6 +61,6 @@ jobs: - name: Install Python packages env: PIP_EXTRA_INDEX_URL: "https://dl.espressif.com/pypi/" - run: pip install --only-binary cryptography pytest-embedded pytest-embedded-serial-esp pytest-embedded-idf pyserial + run: pip install --only-binary cryptography pytest-embedded pytest-embedded-serial-esp pytest-embedded-idf pyserial pyusb - name: Run USB Test App on target run: pytest --target=${{ matrix.idf_target }} -m usb_host --build-dir=build_${{ matrix.idf_target }} diff --git a/device/esp_tinyusb/test_app/README.md b/device/esp_tinyusb/test_app/README.md deleted file mode 100644 index fc650500..00000000 --- a/device/esp_tinyusb/test_app/README.md +++ /dev/null @@ -1,4 +0,0 @@ -| Supported Targets | ESP32-S2 | ESP32-S3 | ESP32-P4 | -| ----------------- | -------- | -------- | -------- | - -# USB: esp_tinyusb test application diff --git a/device/esp_tinyusb/test_app/CMakeLists.txt b/device/esp_tinyusb/test_apps/cdc_and_usb_device/CMakeLists.txt similarity index 88% rename from device/esp_tinyusb/test_app/CMakeLists.txt rename to device/esp_tinyusb/test_apps/cdc_and_usb_device/CMakeLists.txt index ff897526..fdba7348 100644 --- a/device/esp_tinyusb/test_app/CMakeLists.txt +++ b/device/esp_tinyusb/test_apps/cdc_and_usb_device/CMakeLists.txt @@ -6,4 +6,4 @@ include($ENV{IDF_PATH}/tools/cmake/project.cmake) # "Trim" the build. Include the minimal set of components, main, and anything it depends on. set(COMPONENTS main) -project(test_app_usb_device_esp_tinyusb) +project(test_app_cdc_and_usb_device) diff --git a/device/esp_tinyusb/test_app/main/CMakeLists.txt b/device/esp_tinyusb/test_apps/cdc_and_usb_device/main/CMakeLists.txt similarity index 100% rename from device/esp_tinyusb/test_app/main/CMakeLists.txt rename to device/esp_tinyusb/test_apps/cdc_and_usb_device/main/CMakeLists.txt diff --git a/device/esp_tinyusb/test_app/main/idf_component.yml b/device/esp_tinyusb/test_apps/cdc_and_usb_device/main/idf_component.yml similarity index 75% rename from device/esp_tinyusb/test_app/main/idf_component.yml rename to device/esp_tinyusb/test_apps/cdc_and_usb_device/main/idf_component.yml index 276df690..b1cb5b54 100644 --- a/device/esp_tinyusb/test_app/main/idf_component.yml +++ b/device/esp_tinyusb/test_apps/cdc_and_usb_device/main/idf_component.yml @@ -2,4 +2,4 @@ dependencies: espressif/esp_tinyusb: version: "*" - override_path: "../../" + override_path: "../../../" diff --git a/device/esp_tinyusb/test_app/main/test_app_main.c b/device/esp_tinyusb/test_apps/cdc_and_usb_device/main/test_app_main.c similarity index 100% rename from device/esp_tinyusb/test_app/main/test_app_main.c rename to device/esp_tinyusb/test_apps/cdc_and_usb_device/main/test_app_main.c diff --git a/device/esp_tinyusb/test_app/main/test_bvalid_sig.c b/device/esp_tinyusb/test_apps/cdc_and_usb_device/main/test_bvalid_sig.c similarity index 100% rename from device/esp_tinyusb/test_app/main/test_bvalid_sig.c rename to device/esp_tinyusb/test_apps/cdc_and_usb_device/main/test_bvalid_sig.c diff --git a/device/esp_tinyusb/test_app/main/test_bvalid_sig.h b/device/esp_tinyusb/test_apps/cdc_and_usb_device/main/test_bvalid_sig.h similarity index 100% rename from device/esp_tinyusb/test_app/main/test_bvalid_sig.h rename to device/esp_tinyusb/test_apps/cdc_and_usb_device/main/test_bvalid_sig.h diff --git a/device/esp_tinyusb/test_app/main/test_cdc.c b/device/esp_tinyusb/test_apps/cdc_and_usb_device/main/test_cdc.c similarity index 100% rename from device/esp_tinyusb/test_app/main/test_cdc.c rename to device/esp_tinyusb/test_apps/cdc_and_usb_device/main/test_cdc.c diff --git a/device/esp_tinyusb/test_app/main/test_descriptors_config.c b/device/esp_tinyusb/test_apps/cdc_and_usb_device/main/test_descriptors_config.c similarity index 100% rename from device/esp_tinyusb/test_app/main/test_descriptors_config.c rename to device/esp_tinyusb/test_apps/cdc_and_usb_device/main/test_descriptors_config.c diff --git a/device/esp_tinyusb/test_app/main/test_descriptors_config.h b/device/esp_tinyusb/test_apps/cdc_and_usb_device/main/test_descriptors_config.h similarity index 100% rename from device/esp_tinyusb/test_app/main/test_descriptors_config.h rename to device/esp_tinyusb/test_apps/cdc_and_usb_device/main/test_descriptors_config.h diff --git a/device/esp_tinyusb/test_app/main/tud_global_cb.c b/device/esp_tinyusb/test_apps/cdc_and_usb_device/main/tud_global_cb.c similarity index 100% rename from device/esp_tinyusb/test_app/main/tud_global_cb.c rename to device/esp_tinyusb/test_apps/cdc_and_usb_device/main/tud_global_cb.c diff --git a/device/esp_tinyusb/test_app/pytest_cdc.py b/device/esp_tinyusb/test_apps/cdc_and_usb_device/pytest_cdc.py similarity index 100% rename from device/esp_tinyusb/test_app/pytest_cdc.py rename to device/esp_tinyusb/test_apps/cdc_and_usb_device/pytest_cdc.py diff --git a/device/esp_tinyusb/test_app/pytest_usb_device.py b/device/esp_tinyusb/test_apps/cdc_and_usb_device/pytest_usb_device.py similarity index 100% rename from device/esp_tinyusb/test_app/pytest_usb_device.py rename to device/esp_tinyusb/test_apps/cdc_and_usb_device/pytest_usb_device.py diff --git a/device/esp_tinyusb/test_app/sdkconfig.defaults b/device/esp_tinyusb/test_apps/cdc_and_usb_device/sdkconfig.defaults similarity index 100% rename from device/esp_tinyusb/test_app/sdkconfig.defaults rename to device/esp_tinyusb/test_apps/cdc_and_usb_device/sdkconfig.defaults diff --git a/device/esp_tinyusb/test_apps/vendor/CMakeLists.txt b/device/esp_tinyusb/test_apps/vendor/CMakeLists.txt new file mode 100644 index 00000000..a600c6f2 --- /dev/null +++ b/device/esp_tinyusb/test_apps/vendor/CMakeLists.txt @@ -0,0 +1,9 @@ +# The following 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) + +# "Trim" the build. Include the minimal set of components, main, and anything it depends on. +set(COMPONENTS main) + +project(test_app_vendor_specific) diff --git a/device/esp_tinyusb/test_apps/vendor/main/CMakeLists.txt b/device/esp_tinyusb/test_apps/vendor/main/CMakeLists.txt new file mode 100644 index 00000000..e81e6278 --- /dev/null +++ b/device/esp_tinyusb/test_apps/vendor/main/CMakeLists.txt @@ -0,0 +1,4 @@ +idf_component_register(SRC_DIRS . + INCLUDE_DIRS . + REQUIRES unity + WHOLE_ARCHIVE) diff --git a/device/esp_tinyusb/test_apps/vendor/main/idf_component.yml b/device/esp_tinyusb/test_apps/vendor/main/idf_component.yml new file mode 100644 index 00000000..b1cb5b54 --- /dev/null +++ b/device/esp_tinyusb/test_apps/vendor/main/idf_component.yml @@ -0,0 +1,5 @@ +## IDF Component Manager Manifest File +dependencies: + espressif/esp_tinyusb: + version: "*" + override_path: "../../../" diff --git a/device/esp_tinyusb/test_apps/vendor/main/test_app_main.c b/device/esp_tinyusb/test_apps/vendor/main/test_app_main.c new file mode 100644 index 00000000..cce83dbd --- /dev/null +++ b/device/esp_tinyusb/test_apps/vendor/main/test_app_main.c @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include "unity.h" +#include "unity_test_runner.h" + +void app_main(void) +{ + /* + _ _ _ + | | (_) | | + ___ ___ _ __ | |_ _ _ __ _ _ _ _ ___| |__ + / _ \/ __| '_ \| __| | '_ \| | | | | | / __| '_ \ + | __/\__ \ |_) | |_| | | | | |_| | |_| \__ \ |_) | + \___||___/ .__/ \__|_|_| |_|\__, |\__,_|___/_.__/ + | |______ __/ | + |_|______| |___/ + _____ _____ _____ _____ + |_ _| ___/ ___|_ _| + | | | |__ \ `--. | | + | | | __| `--. \ | | + | | | |___/\__/ / | | + \_/ \____/\____/ \_/ + */ + + printf(" _ _ _ \n"); + printf(" | | (_) | | \n"); + printf(" ___ ___ _ __ | |_ _ _ __ _ _ _ _ ___| |__ \n"); + printf(" / _ \\/ __| '_ \\| __| | '_ \\| | | | | | / __| '_ \\ \n"); + printf("| __/\\__ \\ |_) | |_| | | | | |_| | |_| \\__ \\ |_) |\n"); + printf(" \\___||___/ .__/ \\__|_|_| |_|\\__, |\\__,_|___/_.__/ \n"); + printf(" | |______ __/ | \n"); + printf(" |_|______| |___/ \n"); + printf(" _____ _____ _____ _____ \n"); + printf("|_ _| ___/ ___|_ _| \n"); + printf(" | | | |__ \\ `--. | | \n"); + printf(" | | | __| `--. \\ | | \n"); + printf(" | | | |___/\\__/ / | | \n"); + printf(" \\_/ \\____/\\____/ \\_/ \n"); + + // We don't check memory leaks here because we cannot uninstall TinyUSB yet + unity_run_menu(); +} diff --git a/device/esp_tinyusb/test_apps/vendor/main/test_vendor.c b/device/esp_tinyusb/test_apps/vendor/main/test_vendor.c new file mode 100644 index 00000000..2e8f9857 --- /dev/null +++ b/device/esp_tinyusb/test_apps/vendor/main/test_vendor.c @@ -0,0 +1,67 @@ +/* + * 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 "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "esp_log.h" +#include "esp_err.h" + +#include "unity.h" +#include "tinyusb.h" + +static const char *TAG = "vendor_test"; + +char buffer_in[64]; +void tud_vendor_rx_cb(uint8_t itf) +{ + ESP_LOGI(TAG, "tud_vendor_rx_cb(itf=%d)", itf); + int available = tud_vendor_n_available(itf); + int read = tud_vendor_n_read(itf, buffer_in, available); + ESP_LOGI(TAG, "actual read: %d. buffer message: %s", read, buffer_in); +} + +// Invoked when a control transfer occurred on an interface of this class +// Driver response accordingly to the request and the transfer stage (setup/data/ack) +// return false to stall control endpoint (e.g unsupported request) +bool tud_vendor_control_xfer_cb(uint8_t rhport, uint8_t stage, tusb_control_request_t const *request) +{ + // nothing to with DATA & ACK stage + if (stage != CONTROL_STAGE_SETUP) { + return true; + } + // stall unknown request + return false; +} + +/** + * @brief TinyUSB Vendor specific testcase + */ +TEST_CASE("tinyusb_vendor", "[esp_tinyusb][vendor]") +{ + // Install TinyUSB driver + const tinyusb_config_t tusb_cfg = { + .external_phy = false, + .device_descriptor = NULL, +#if (TUD_OPT_HIGH_SPEED) + .fs_configuration_descriptor = NULL, + .hs_configuration_descriptor = NULL, + .qualifier_descriptor = NULL, +#else + .configuration_descriptor = NULL, +#endif // TUD_OPT_HIGH_SPEED + }; + TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_install(&tusb_cfg)); + + +} + +#endif diff --git a/device/esp_tinyusb/test_apps/vendor/pytest_vendor.py b/device/esp_tinyusb/test_apps/vendor/pytest_vendor.py new file mode 100644 index 00000000..28b225ab --- /dev/null +++ b/device/esp_tinyusb/test_apps/vendor/pytest_vendor.py @@ -0,0 +1,96 @@ +# SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD +# SPDX-License-Identifier: Apache-2.0 + +import pytest +from pytest_embedded_idf.dut import IdfDut +import usb.core +import usb.util +from time import sleep + + +def find_interface_by_index(device, interface_index): + ''' + Function to find the interface by index + ''' + for cfg in device: + for intf in cfg: + if intf.bInterfaceNumber == interface_index: + return intf + return None + + +def send_data_to_intf(VID, PID, interface_index): + ''' + Find a device, its interface and dual BULK endpoints + Send some data to it + ''' + # Find the USB device by VID and PID + dev = usb.core.find(idVendor=VID, idProduct=PID) + if dev is None: + raise ValueError("Device not found") + + # Find the interface by index + intf = find_interface_by_index(dev, interface_index) + if intf is None: + raise ValueError(f"Interface with index {interface_index} not found") + + if intf: + def ep_read(len): + try: + return ep_in.read(len, 100) + except: + return None + def ep_write(buf): + try: + ep_out.write(buf, 100) + except: + pass + + maximum_packet_size = 64 + + ep_in = usb.util.find_descriptor(intf, custom_match = \ + lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_IN) + + ep_out = usb.util.find_descriptor(intf, custom_match = \ + lambda e: usb.util.endpoint_direction(e.bEndpointAddress) == usb.util.ENDPOINT_OUT) + + #print(ep_in) + #print(ep_out) + buf = "IF{}\n".format(interface_index).encode('utf-8') + ep_write(bytes(buf)) + + ep_read(maximum_packet_size) + else: + print("NOT found") + + +@pytest.mark.esp32s2 +@pytest.mark.esp32s3 +@pytest.mark.esp32p4 +@pytest.mark.usb_device +def test_usb_device_esp_tinyusb(dut: IdfDut) -> None: + ''' + Running the test locally: + 1. Build the test app for your DUT + 2. Connect you DUT to your test runner (local machine) with USB port and flashing port + 3. Run `pytest --target esp32s3` + + Important note: On Windows you must manually assign a driver the device, otherwise it will never be configured. + On Linux this is automatic + + Test procedure: + 1. Run the test on the DUT + 2. Expect 2 Vendor specific interfaces in the system + 3. Send some data to it, check log output + ''' + dut.run_all_single_board_cases(group='vendor') + + sleep(2) # Wait until the device is enumerated + + VID = 0x303A # Replace with your device's Vendor ID + PID = 0x4040 # Replace with your device's Product ID + + send_data_to_intf(VID, PID, 0) + dut.expect_exact('vendor_test: actual read: 4. buffer message: IF0') + send_data_to_intf(VID, PID, 1) + dut.expect_exact('vendor_test: actual read: 4. buffer message: IF1') diff --git a/device/esp_tinyusb/test_apps/vendor/sdkconfig.defaults b/device/esp_tinyusb/test_apps/vendor/sdkconfig.defaults new file mode 100644 index 00000000..9b4072f3 --- /dev/null +++ b/device/esp_tinyusb/test_apps/vendor/sdkconfig.defaults @@ -0,0 +1,15 @@ +# Configure TinyUSB, it will be used to mock USB devices +CONFIG_TINYUSB_VENDOR_COUNT=2 + +# Disable watchdogs, they'd get triggered during unity interactive menu +CONFIG_ESP_INT_WDT=n +CONFIG_ESP_TASK_WDT=n + +# Run-time checks of Heap and Stack +CONFIG_HEAP_POISONING_COMPREHENSIVE=y +CONFIG_COMPILER_STACK_CHECK_MODE_STRONG=y +CONFIG_COMPILER_STACK_CHECK=y + +CONFIG_UNITY_ENABLE_BACKTRACE_ON_FAIL=y + +CONFIG_COMPILER_CXX_EXCEPTIONS=y