summaryrefslogtreecommitdiff
path: root/examples/dual
diff options
context:
space:
mode:
authorHiFiPhile <[email protected]>2026-06-22 21:30:58 +0200
committerHiFiPhile <[email protected]>2026-06-22 21:30:58 +0200
commit693cdce08e14833f26f4e8a1f26e4fd546be4c35 (patch)
tree7667d2223dc32d9f21b5b60ab200e64ed46e3e20 /examples/dual
parent41e9eaa65a935136085d78ec4b99c81ff991b560 (diff)
parentcd3561bf158afd5a5718904b8139a338d1e3b67c (diff)
Merge remote-tracking branch 'tinyusb/master' into pr-osal-spin-deinit
Signed-off-by: HiFiPhile <[email protected]>
Diffstat (limited to 'examples/dual')
-rw-r--r--examples/dual/CMakeLists.txt11
-rw-r--r--examples/dual/dynamic_switch/CMakeLists.txt30
-rw-r--r--examples/dual/dynamic_switch/CMakePresets.json6
-rw-r--r--examples/dual/dynamic_switch/Makefile16
-rw-r--r--examples/dual/dynamic_switch/README.md60
-rw-r--r--examples/dual/dynamic_switch/only.txt13
-rw-r--r--examples/dual/dynamic_switch/src/CMakeLists.txt4
-rw-r--r--examples/dual/dynamic_switch/src/main.c501
-rw-r--r--examples/dual/dynamic_switch/src/tusb_config.h160
-rw-r--r--examples/dual/dynamic_switch/src/usb_descriptors.c199
-rw-r--r--examples/dual/host_hid_to_device_cdc/CMakeLists.txt17
-rw-r--r--examples/dual/host_hid_to_device_cdc/Makefile10
-rw-r--r--examples/dual/host_hid_to_device_cdc/src/main.c4
-rw-r--r--examples/dual/host_hid_to_device_cdc/src/tusb_config.h6
-rw-r--r--examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c16
-rw-r--r--examples/dual/host_info_to_device_cdc/CMakeLists.txt22
-rw-r--r--examples/dual/host_info_to_device_cdc/Makefile10
-rw-r--r--examples/dual/host_info_to_device_cdc/only.txt1
-rw-r--r--examples/dual/host_info_to_device_cdc/src/CMakeLists.txt4
-rw-r--r--examples/dual/host_info_to_device_cdc/src/main.c161
-rw-r--r--examples/dual/host_info_to_device_cdc/src/tusb_config.h8
-rw-r--r--examples/dual/host_info_to_device_cdc/src/usb_descriptors.c16
22 files changed, 1191 insertions, 84 deletions
diff --git a/examples/dual/CMakeLists.txt b/examples/dual/CMakeLists.txt
index c5e3ffce4..8727ea938 100644
--- a/examples/dual/CMakeLists.txt
+++ b/examples/dual/CMakeLists.txt
@@ -9,6 +9,13 @@ if (FAMILY STREQUAL "rp2040" AND NOT TARGET tinyusb_pico_pio_usb)
message("Skipping dual host/device mode examples as Pico-PIO-USB is not available")
else ()
# family_add_subdirectory will filter what to actually add based on selected FAMILY
- family_add_subdirectory(host_hid_to_device_cdc)
- family_add_subdirectory(host_info_to_device_cdc)
+ set(EXAMPLE_LIST
+ host_hid_to_device_cdc
+ host_info_to_device_cdc
+ dynamic_switch
+ )
+
+ foreach (example ${EXAMPLE_LIST})
+ family_add_subdirectory(${example})
+ endforeach ()
endif ()
diff --git a/examples/dual/dynamic_switch/CMakeLists.txt b/examples/dual/dynamic_switch/CMakeLists.txt
new file mode 100644
index 000000000..7cad30727
--- /dev/null
+++ b/examples/dual/dynamic_switch/CMakeLists.txt
@@ -0,0 +1,30 @@
+cmake_minimum_required(VERSION 3.20)
+
+include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
+
+project(dynamic_switch C CXX ASM)
+
+# Checks this example is valid for the family and initializes the project
+family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR})
+
+# Espressif has its own cmake build system
+if(FAMILY STREQUAL "espressif")
+ return()
+endif()
+
+add_executable(${PROJECT_NAME})
+
+# Example source
+target_sources(${PROJECT_NAME} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
+ )
+
+# Example include
+target_include_directories(${PROJECT_NAME} PUBLIC
+ ${CMAKE_CURRENT_SOURCE_DIR}/src
+ )
+
+# Configure compilation flags and libraries for the example without RTOS.
+# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
+family_configure_dual_usb_example(${PROJECT_NAME} noos)
diff --git a/examples/dual/dynamic_switch/CMakePresets.json b/examples/dual/dynamic_switch/CMakePresets.json
new file mode 100644
index 000000000..5cd8971e9
--- /dev/null
+++ b/examples/dual/dynamic_switch/CMakePresets.json
@@ -0,0 +1,6 @@
+{
+ "version": 6,
+ "include": [
+ "../../../hw/bsp/BoardPresets.json"
+ ]
+}
diff --git a/examples/dual/dynamic_switch/Makefile b/examples/dual/dynamic_switch/Makefile
new file mode 100644
index 000000000..44ab54ad7
--- /dev/null
+++ b/examples/dual/dynamic_switch/Makefile
@@ -0,0 +1,16 @@
+include ../../../hw/bsp/family_support.mk
+
+INC += \
+ src \
+
+# Example source
+EXAMPLE_SOURCE += $(wildcard src/*.c)
+SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE))
+
+# Include device and host stack
+SRC_C += \
+ src/class/cdc/cdc_device.c \
+ src/host/hub.c \
+ src/host/usbh.c
+
+include ../../../hw/bsp/family_rules.mk
diff --git a/examples/dual/dynamic_switch/README.md b/examples/dual/dynamic_switch/README.md
new file mode 100644
index 000000000..034787f18
--- /dev/null
+++ b/examples/dual/dynamic_switch/README.md
@@ -0,0 +1,60 @@
+# Dynamic Switch Example
+
+This example demonstrates TinyUSB's dual-role capability by allowing runtime switching between USB device and host modes.
+
+## Features
+
+- **Button-triggered mode switching**: Press the board button to switch between device and host modes
+- **Device Mode**: Acts as a USB CDC (Virtual Serial Port) that echoes all received data
+- **Host Mode**: Enumerates connected USB devices and prints device information
+- **Dynamic switching**: Deinitializes the current stack and reinitializes in the new mode
+
+## Usage
+
+1. **Build and flash** the example to your board
+2. **Default behavior**: The board starts in **Device mode**
+3. **Device mode**:
+ - Connect the board to a PC
+ - Open a serial terminal (e.g., `screen /dev/ttyACM0` or PuTTY)
+ - Type characters - they will be echoed back to you
+4. **Switch to Host mode**:
+ - Press the board button
+ - Connect a USB device to the board
+ - The board will enumerate the device and print its descriptors to the debug console
+5. **Switch back to Device mode**: Press the button again
+
+## LED Patterns
+
+The onboard LED indicates the USB connection status:
+
+- **Fast blink (250ms)**: Not mounted/connected
+- **Slow blink (1000ms)**: Successfully mounted/connected
+- **Very slow blink (2500ms)**: Suspended (device mode only)
+
+## Serial Output
+
+The example prints status messages to the debug UART:
+
+```
+======================================
+TinyUSB Dynamic Switch Example
+Press button to switch between device and host modes
+Starting in DEVICE mode...
+======================================
+
+[DEVICE] Mounted
+
+--- Switching USB mode ---
+Stopping DEVICE mode...
+Starting HOST mode...
+Mode switch complete!
+
+[HOST] Device attached, address = 1
+Device 1: ID 1234:5678 SN ABC123
+Device Descriptor:
+ bLength 18
+ bDescriptorType 1
+ bcdUSB 0200
+ bDeviceClass 239
+ ...
+```
diff --git a/examples/dual/dynamic_switch/only.txt b/examples/dual/dynamic_switch/only.txt
new file mode 100644
index 000000000..e1038f9d4
--- /dev/null
+++ b/examples/dual/dynamic_switch/only.txt
@@ -0,0 +1,13 @@
+family:espressif
+mcu:LPC43XX
+mcu:MIMXRT1XXX
+mcu:STM32C0
+mcu:STM32C5
+mcu:STM32G0
+mcu:STM32H5
+mcu:STM32F2
+mcu:STM32F4
+mcu:STM32U5
+mcu:STM32F7
+mcu:STM32H7
+mcu:STM32H7RS
diff --git a/examples/dual/dynamic_switch/src/CMakeLists.txt b/examples/dual/dynamic_switch/src/CMakeLists.txt
new file mode 100644
index 000000000..cef2b46ee
--- /dev/null
+++ b/examples/dual/dynamic_switch/src/CMakeLists.txt
@@ -0,0 +1,4 @@
+# This file is for ESP-IDF only
+idf_component_register(SRCS "main.c" "usb_descriptors.c"
+ INCLUDE_DIRS "."
+ REQUIRES boards tinyusb_src)
diff --git a/examples/dual/dynamic_switch/src/main.c b/examples/dual/dynamic_switch/src/main.c
new file mode 100644
index 000000000..f67cd885c
--- /dev/null
+++ b/examples/dual/dynamic_switch/src/main.c
@@ -0,0 +1,501 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+/* This example demonstrates dynamic switching between device and host modes:
+ * - Press button to switch between device and host modes
+ * - Device mode: CDC echo (echoes input back to output)
+ * - Host mode: Prints connected device information
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "bsp/board_api.h"
+#include "tusb.h"
+
+#if CFG_TUSB_OS == OPT_OS_FREERTOS
+ #ifdef ESP_PLATFORM
+ #define USBD_STACK_SIZE 4096
+ #define USBH_STACK_SIZE 4096
+ #else
+ // Increase stack size when debug log is enabled
+ #define USBD_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1)
+ #define USBH_STACK_SIZE (3*configMINIMAL_STACK_SIZE/2) * (CFG_TUSB_DEBUG ? 2 : 1)
+ #endif
+
+ #define CDC_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 2 : 1))
+ #define BLINKY_STACK_SIZE configMINIMAL_STACK_SIZE
+#endif
+
+//--------------------------------------------------------------------+
+// MACRO CONSTANT TYPEDEF PROTOTYPES
+//--------------------------------------------------------------------+
+
+// English
+#define LANGUAGE_ID 0x0409
+
+/* Blink pattern
+ * - 250 ms : not mounted
+ * - 1000 ms : mounted
+ * - 2500 ms : suspended
+ */
+enum {
+ BLINK_NOT_MOUNTED = 250,
+ BLINK_MOUNTED = 1000,
+ BLINK_SUSPENDED = 2500,
+};
+
+#if CFG_TUSB_OS == OPT_OS_FREERTOS
+// static task for FreeRTOS
+#if configSUPPORT_STATIC_ALLOCATION
+StackType_t blinky_stack[BLINKY_STACK_SIZE];
+StaticTask_t blinky_taskdef;
+
+StackType_t usb_stack[USBD_STACK_SIZE > USBH_STACK_SIZE ? USBD_STACK_SIZE : USBH_STACK_SIZE];
+StaticTask_t usb_taskdef;
+
+StackType_t cdc_stack[CDC_STACK_SIZE];
+StaticTask_t cdc_taskdef;
+
+StackType_t devinfo_stack[USBH_STACK_SIZE];
+StaticTask_t devinfo_taskdef;
+#endif
+#endif
+
+static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
+static tusb_role_t current_role = TUSB_ROLE_DEVICE;
+
+#if CFG_TUSB_OS == OPT_OS_FREERTOS
+static void usb_task(void *param);
+#endif
+void led_blinking_task(void *param);
+void cdc_task(void *param);
+void print_devinfo_task(void *param);
+
+void usb_mode_switch(void);
+static void print_one_device(uint8_t daddr);
+static void print_utf16(uint16_t* temp_buf, size_t buf_len);
+
+// Declare buffer for USB transfer
+CFG_TUH_MEM_SECTION struct {
+ TUH_EPBUF_TYPE_DEF(tusb_desc_device_t, device);
+ TUH_EPBUF_DEF(serial, 64*sizeof(uint16_t));
+ TUH_EPBUF_DEF(buf, 128*sizeof(uint16_t));
+} desc;
+
+//--------------------------------------------------------------------+
+// Main
+//--------------------------------------------------------------------+
+
+int main(void) {
+ board_init();
+
+ printf("\r\n======================================\r\n");
+ printf("TinyUSB Dynamic Switch Example\r\n");
+ printf("Press button to switch between device and host modes\r\n");
+ printf("Starting in DEVICE mode...\r\n");
+ printf("======================================\r\n\r\n");
+
+#if CFG_TUSB_OS == OPT_OS_FREERTOS
+ // Create FreeRTOS tasks
+#if configSUPPORT_STATIC_ALLOCATION
+ xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef);
+ xTaskCreateStatic(usb_task, "usb", USBD_STACK_SIZE > USBH_STACK_SIZE ? USBD_STACK_SIZE : USBH_STACK_SIZE,
+ NULL, configMAX_PRIORITIES-1, usb_stack, &usb_taskdef);
+ xTaskCreateStatic(cdc_task, "cdc", CDC_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, cdc_stack, &cdc_taskdef);
+ xTaskCreateStatic(print_devinfo_task, "devinfo", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, devinfo_stack, &devinfo_taskdef);
+#else
+ xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL);
+ xTaskCreate(usb_task, "usb", USBD_STACK_SIZE > USBH_STACK_SIZE ? USBD_STACK_SIZE : USBH_STACK_SIZE,
+ NULL, configMAX_PRIORITIES - 1, NULL);
+ xTaskCreate(cdc_task, "cdc", CDC_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, NULL);
+ xTaskCreate(print_devinfo_task, "devinfo", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, NULL);
+#endif
+
+#ifndef ESP_PLATFORM
+ // only start scheduler for non-espressif mcu
+ vTaskStartScheduler();
+#endif
+
+#else
+ // Initialize in device mode by default
+ tusb_rhport_init_t dev_init = {
+ .role = TUSB_ROLE_DEVICE,
+ .speed = TUSB_SPEED_AUTO
+ };
+ tusb_init(BOARD_RHPORT, &dev_init);
+ current_role = TUSB_ROLE_DEVICE;
+
+ board_init_after_tusb();
+
+ while (1) {
+ // Check for button press to switch modes
+ static bool pending_switch = false;
+ if (board_button_read()) {
+ if (!pending_switch) {
+ pending_switch = true;
+ usb_mode_switch();
+ }
+ } else {
+ pending_switch = false;
+ }
+
+ // Process USB tasks based on current mode
+ if (current_role == TUSB_ROLE_DEVICE) {
+ tud_task();
+ cdc_task(NULL);
+ } else {
+ tuh_task();
+ print_devinfo_task(NULL);
+ }
+
+ led_blinking_task(NULL);
+ }
+#endif
+}
+
+#ifdef ESP_PLATFORM
+void app_main(void) {
+ main();
+}
+#endif
+
+#if CFG_TUSB_OS == OPT_OS_FREERTOS
+// USB Task for FreeRTOS
+// This top level thread processes all usb events and mode switching
+static void usb_task(void *param) {
+ (void) param;
+
+ // init device stack on configured roothub port
+ // This should be called after scheduler/kernel is started.
+ // Otherwise it could cause kernel issue since USB IRQ handler does use RTOS queue API.
+ tusb_rhport_init_t dev_init = {
+ .role = TUSB_ROLE_DEVICE,
+ .speed = TUSB_SPEED_AUTO
+ };
+ tusb_init(BOARD_RHPORT, &dev_init);
+ current_role = TUSB_ROLE_DEVICE;
+
+ board_init_after_tusb();
+
+ // RTOS forever loop
+ while (1) {
+ // Check for button press to switch modes
+ static bool pending_switch = false;
+ if (board_button_read()) {
+ if (!pending_switch) {
+ pending_switch = true;
+ usb_mode_switch();
+ }
+ } else {
+ pending_switch = false;
+ }
+
+ // Process USB tasks based on current mode
+ // Use _ext version to allow return and read button state
+ if (current_role == TUSB_ROLE_DEVICE) {
+ tud_task_ext(10, false);
+ } else {
+ tuh_task_ext(10, false);
+ }
+ }
+}
+#endif
+
+//--------------------------------------------------------------------+
+// Mode Switching
+//--------------------------------------------------------------------+
+
+void usb_mode_switch(void) {
+ printf("\r\n--- Switching USB mode ---\r\n");
+
+ // Snapshot then clear current_role BEFORE tusb_deinit() so concurrent
+ // tasks (cdc_task / print_devinfo_task on RTOS) see the role-change
+ // boundary and exit cleanly instead of calling host/device APIs against
+ // a deinitialised stack.
+ const tusb_role_t prev_role = current_role;
+ current_role = TUSB_ROLE_INVALID;
+
+ if (prev_role == TUSB_ROLE_DEVICE) {
+ printf("Stopping DEVICE mode...\r\n");
+ } else {
+ printf("Stopping HOST mode...\r\n");
+ }
+ tusb_deinit(BOARD_RHPORT);
+
+#if CFG_TUSB_OS == OPT_OS_FREERTOS
+ vTaskDelay(pdMS_TO_TICKS(100)); // Small delay for clean transition
+#else
+ tusb_time_delay_ms_api(100);
+#endif
+
+ // Switch to the other mode
+ if (prev_role == TUSB_ROLE_DEVICE) {
+ printf("Starting HOST mode...\r\n");
+ tusb_rhport_init_t host_init = {
+ .role = TUSB_ROLE_HOST,
+ .speed = TUSB_SPEED_AUTO
+ };
+ tusb_init(BOARD_RHPORT, &host_init);
+ current_role = TUSB_ROLE_HOST;
+ } else {
+ printf("Starting DEVICE mode...\r\n");
+ tusb_rhport_init_t dev_init = {
+ .role = TUSB_ROLE_DEVICE,
+ .speed = TUSB_SPEED_AUTO
+ };
+ tusb_init(BOARD_RHPORT, &dev_init);
+ current_role = TUSB_ROLE_DEVICE;
+ }
+
+ blink_interval_ms = BLINK_NOT_MOUNTED;
+ printf("Mode switch complete!\r\n\r\n");
+}
+
+//--------------------------------------------------------------------+
+// Device Mode: CDC Task
+//--------------------------------------------------------------------+
+
+void cdc_task(void *param) {
+ (void) param;
+#if CFG_TUSB_OS == OPT_OS_FREERTOS
+ while (1) {
+#endif
+ // Only touch device-CDC APIs while we're in device mode. After
+ // usb_mode_switch() sets current_role to INVALID and tusb_deinit() runs,
+ // calling tud_cdc_write_flush() here would hit a deinit'd device stack.
+ if (current_role == TUSB_ROLE_DEVICE) {
+ if (tud_cdc_available()) {
+ uint8_t buf[64];
+ const uint32_t count = tud_cdc_read(buf, sizeof(buf));
+ if (count) {
+ tud_cdc_write(buf, count);
+ }
+ }
+ tud_cdc_write_flush();
+ }
+#if CFG_TUSB_OS == OPT_OS_FREERTOS
+ vTaskDelay(pdMS_TO_TICKS(10));
+ }
+#endif
+}
+
+//--------------------------------------------------------------------+
+// Device Callbacks
+//--------------------------------------------------------------------+
+
+// Invoked when device is mounted
+void tud_mount_cb(void) {
+ printf("[DEVICE] Mounted\r\n");
+ blink_interval_ms = BLINK_MOUNTED;
+}
+
+// Invoked when device is unmounted
+void tud_umount_cb(void) {
+ printf("[DEVICE] Unmounted\r\n");
+ blink_interval_ms = BLINK_NOT_MOUNTED;
+}
+
+// Invoked when usb bus is suspended
+void tud_suspend_cb(bool remote_wakeup_en) {
+ (void) remote_wakeup_en;
+ printf("[DEVICE] Suspended\r\n");
+ blink_interval_ms = BLINK_SUSPENDED;
+}
+
+// Invoked when usb bus is resumed
+void tud_resume_cb(void) {
+ printf("[DEVICE] Resumed\r\n");
+ blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED;
+}
+
+//--------------------------------------------------------------------+
+// Host Callbacks
+//--------------------------------------------------------------------+
+
+// One flag per possible device address — set by tuh_mount_cb (host task) and
+// cleared by print_devinfo_task once the device's descriptors are printed.
+static volatile bool need_devinfo[CFG_TUH_DEVICE_MAX + 1];
+
+// Invoked when device is mounted (configured). Runs in the host task — keep
+// minimal; descriptor fetching happens in print_devinfo_task (different
+// context so sync helpers are safe).
+void tuh_mount_cb(uint8_t daddr) {
+ printf("[HOST] Device attached, address = %d\r\n", daddr);
+ blink_interval_ms = BLINK_MOUNTED;
+ if (daddr < TU_ARRAY_SIZE(need_devinfo)) {
+ need_devinfo[daddr] = true;
+ }
+}
+
+// Invoked when device is unmounted (unplugged)
+void tuh_umount_cb(uint8_t daddr) {
+ printf("[HOST] Device removed, address = %d\r\n", daddr);
+ blink_interval_ms = BLINK_NOT_MOUNTED;
+ if (daddr < TU_ARRAY_SIZE(need_devinfo)) {
+ need_devinfo[daddr] = false;
+ }
+}
+
+//--------------------------------------------------------------------+
+// Host Device Info — serialises descriptor fetching across all mounted
+// devices using sync helpers. Safe to call from main loop (OS_NONE) or a
+// dedicated task (FreeRTOS) — but NOT from a host-stack callback.
+//--------------------------------------------------------------------+
+
+void print_devinfo_task(void *param) {
+ (void) param;
+#if CFG_TUSB_OS == OPT_OS_FREERTOS
+ while (1) {
+#endif
+ if (current_role == TUSB_ROLE_HOST) {
+ for (uint8_t daddr = 1; daddr < TU_ARRAY_SIZE(need_devinfo); daddr++) {
+ if (need_devinfo[daddr]) {
+ need_devinfo[daddr] = false;
+ print_one_device(daddr);
+ }
+ }
+ }
+#if CFG_TUSB_OS == OPT_OS_FREERTOS
+ vTaskDelay(pdMS_TO_TICKS(10));
+ }
+#endif
+}
+
+static void print_one_device(uint8_t daddr) {
+ // Get Device Descriptor
+ uint8_t xfer_result = tuh_descriptor_get_device_sync(daddr, &desc.device, 18);
+ if (XFER_RESULT_SUCCESS != xfer_result) {
+ printf("Failed to get device descriptor\r\n");
+ return;
+ }
+
+ printf("Device %u: ID %04x:%04x SN ", daddr, desc.device.idVendor, desc.device.idProduct);
+
+ xfer_result = XFER_RESULT_FAILED;
+ if (desc.device.iSerialNumber != 0) {
+ xfer_result = tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, desc.serial, sizeof(desc.serial));
+ }
+ if (XFER_RESULT_SUCCESS != xfer_result) {
+ uint16_t* serial = (uint16_t*)(uintptr_t) desc.serial;
+ serial[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * 3 + 2));
+ serial[1] = 'n';
+ serial[2] = '/';
+ serial[3] = 'a';
+ serial[4] = 0;
+ }
+ print_utf16((uint16_t*)(uintptr_t) desc.serial, sizeof(desc.serial)/2);
+ printf("\r\n");
+
+ printf("Device Descriptor:\r\n");
+ printf(" bLength %u\r\n", desc.device.bLength);
+ printf(" bDescriptorType %u\r\n", desc.device.bDescriptorType);
+ printf(" bcdUSB %04x\r\n", desc.device.bcdUSB);
+ printf(" bDeviceClass %u\r\n", desc.device.bDeviceClass);
+ printf(" bDeviceSubClass %u\r\n", desc.device.bDeviceSubClass);
+ printf(" bDeviceProtocol %u\r\n", desc.device.bDeviceProtocol);
+ printf(" bMaxPacketSize0 %u\r\n", desc.device.bMaxPacketSize0);
+ printf(" idVendor 0x%04x\r\n", desc.device.idVendor);
+ printf(" idProduct 0x%04x\r\n", desc.device.idProduct);
+ printf(" bcdDevice %04x\r\n", desc.device.bcdDevice);
+
+ // Get Manufacturer string
+ if (desc.device.iManufacturer) {
+ if (XFER_RESULT_SUCCESS == tuh_descriptor_get_manufacturer_string_sync(daddr, LANGUAGE_ID, desc.buf, sizeof(desc.buf))) {
+ printf(" iManufacturer %u ", desc.device.iManufacturer);
+ print_utf16((uint16_t*)(uintptr_t) desc.buf, sizeof(desc.buf)/2);
+ printf("\r\n");
+ }
+ }
+
+ // Get Product string
+ if (desc.device.iProduct) {
+ if (XFER_RESULT_SUCCESS == tuh_descriptor_get_product_string_sync(daddr, LANGUAGE_ID, desc.buf, sizeof(desc.buf))) {
+ printf(" iProduct %u ", desc.device.iProduct);
+ print_utf16((uint16_t*)(uintptr_t) desc.buf, sizeof(desc.buf)/2);
+ printf("\r\n");
+ }
+ }
+
+ // Get Serial string
+ if (desc.device.iSerialNumber) {
+ printf(" iSerialNumber %u ", desc.device.iSerialNumber);
+ print_utf16((uint16_t*)(uintptr_t) desc.serial, sizeof(desc.serial)/2);
+ printf("\r\n");
+ } else {
+ printf(" iSerialNumber 0\r\n");
+ }
+
+ printf(" bNumConfigurations %u\r\n", desc.device.bNumConfigurations);
+ printf("\r\n");
+}
+
+static void print_utf16(uint16_t* temp_buf, size_t buf_len) {
+ if (temp_buf[0] == 0 || (temp_buf[0] >> 8) != TUSB_DESC_STRING) {
+ printf("(invalid)");
+ return;
+ }
+
+ size_t chr_count = (temp_buf[0] & 0xff) / 2 - 1;
+ if (chr_count > buf_len - 1) {
+ chr_count = buf_len - 1;
+ }
+
+ for (size_t i = 0; i < chr_count; i++) {
+ uint16_t ch = temp_buf[1 + i];
+ if (ch <= 0x7F) {
+ putchar((char) ch);
+ } else {
+ // TODO support UTF16 to UTF8 conversion
+ putchar('?');
+ }
+ }
+}
+
+//--------------------------------------------------------------------+
+// Blinking Task
+//--------------------------------------------------------------------+
+
+void led_blinking_task(void *param) {
+ (void) param;
+ static uint32_t start_ms = 0;
+ static bool led_state = false;
+#if CFG_TUSB_OS == OPT_OS_FREERTOS
+ while (1) {
+ vTaskDelay(pdMS_TO_TICKS(blink_interval_ms));
+ start_ms += blink_interval_ms;
+ board_led_write(led_state);
+ led_state = 1 - led_state;
+ }
+#else
+ if (tusb_time_millis_api() - start_ms < blink_interval_ms) {
+ return; // not enough time
+ }
+ start_ms += blink_interval_ms;
+ board_led_write(led_state);
+ led_state = 1 - led_state;
+#endif
+}
diff --git a/examples/dual/dynamic_switch/src/tusb_config.h b/examples/dual/dynamic_switch/src/tusb_config.h
new file mode 100644
index 000000000..f3e016305
--- /dev/null
+++ b/examples/dual/dynamic_switch/src/tusb_config.h
@@ -0,0 +1,160 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#ifndef _TUSB_CONFIG_H_
+#define _TUSB_CONFIG_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//--------------------------------------------------------------------+
+// Board Specific Configuration
+//--------------------------------------------------------------------+
+
+// RHPort number used can be defined by board.mk, default to port 0
+#ifndef BOARD_RHPORT
+ #if defined(BOARD_TUD_RHPORT)
+ #define BOARD_RHPORT BOARD_TUD_RHPORT
+ #else
+ #define BOARD_RHPORT 0
+ #define BOARD_TUD_RHPORT 0
+ #endif
+#endif
+
+#if defined(BOARD_TUH_RHPORT)
+ #if BOARD_TUH_RHPORT != BOARD_RHPORT
+ #undef BOARD_TUH_RHPORT
+ #define BOARD_TUH_RHPORT BOARD_RHPORT
+ #endif
+#else
+ #define BOARD_TUH_RHPORT BOARD_RHPORT
+#endif
+
+// RHPort max operational speed can defined by board.mk
+#ifndef BOARD_MAX_SPEED
+ #if defined(BOARD_TUD_MAX_SPEED)
+ #define BOARD_MAX_SPEED BOARD_TUD_MAX_SPEED
+ #else
+ #define BOARD_MAX_SPEED OPT_MODE_DEFAULT_SPEED
+ #endif
+#endif
+
+//--------------------------------------------------------------------
+// COMMON CONFIGURATION
+//--------------------------------------------------------------------
+
+// defined by compiler flags for flexibility
+#ifndef CFG_TUSB_MCU
+#error CFG_TUSB_MCU must be defined
+#endif
+
+#ifndef CFG_TUSB_OS
+#define CFG_TUSB_OS OPT_OS_NONE
+#endif
+
+#ifndef CFG_TUSB_DEBUG
+#define CFG_TUSB_DEBUG 0
+#endif
+
+// Enable Device and Host stacks (dual role)
+#define CFG_TUD_ENABLED 1
+#define CFG_TUH_ENABLED 1
+
+// Default is max speed that hardware controller could support with on-chip PHY
+#define CFG_TUD_MAX_SPEED BOARD_MAX_SPEED
+#define CFG_TUH_MAX_SPEED BOARD_MAX_SPEED
+
+/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
+ * Tinyusb use follows macros to declare transferring memory so that they can be put
+ * into those specific section.
+ * e.g
+ * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
+ * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
+ */
+#ifndef CFG_TUD_MEM_SECTION
+#define CFG_TUD_MEM_SECTION
+#endif
+
+#ifndef CFG_TUD_MEM_ALIGN
+#define CFG_TUD_MEM_ALIGN __attribute__((aligned(4)))
+#endif
+
+#ifndef CFG_TUH_MEM_SECTION
+#define CFG_TUH_MEM_SECTION CFG_TUD_MEM_SECTION
+#endif
+
+#ifndef CFG_TUH_MEM_ALIGN
+#define CFG_TUH_MEM_ALIGN CFG_TUD_MEM_ALIGN
+#endif
+
+//--------------------------------------------------------------------
+// DEVICE CONFIGURATION
+//--------------------------------------------------------------------
+
+#ifndef CFG_TUD_ENDPOINT0_SIZE
+#define CFG_TUD_ENDPOINT0_SIZE 64
+#endif
+
+//------------- CLASS -------------//
+#define CFG_TUD_CDC 1
+#define CFG_TUD_MSC 0
+#define CFG_TUD_HID 0
+#define CFG_TUD_MIDI 0
+#define CFG_TUD_VENDOR 0
+
+// CDC FIFO size of TX and RX
+#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+
+// CDC Endpoint transfer buffer size, default to max bulk packet size (HS 512, FS 64). Larger is faster.
+// Larger RX_EPSIZE requires CFG_TUD_CDC_RX_NEED_ZLP = 1 and host ZLP support
+#define CFG_TUD_CDC_RX_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+#define CFG_TUD_CDC_TX_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+
+//--------------------------------------------------------------------
+// HOST CONFIGURATION
+//--------------------------------------------------------------------
+
+// Size of buffer to hold descriptors and other data used for enumeration
+#define CFG_TUH_ENUMERATION_BUFSIZE 256
+
+#define CFG_TUH_HUB 1
+// max device support (excluding hub device)
+#define CFG_TUH_DEVICE_MAX (CFG_TUH_HUB ? 4 : 1) // hub typically has 4 ports
+
+#define CFG_TUH_CDC 0
+#define CFG_TUH_HID 0
+#define CFG_TUH_MSC 0
+#define CFG_TUH_VENDOR 0
+
+// max endpoint pair supported by each device
+#define CFG_TUH_ENDPOINT_MAX 16
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _TUSB_CONFIG_H_ */
diff --git a/examples/dual/dynamic_switch/src/usb_descriptors.c b/examples/dual/dynamic_switch/src/usb_descriptors.c
new file mode 100644
index 000000000..ef6d795b7
--- /dev/null
+++ b/examples/dual/dynamic_switch/src/usb_descriptors.c
@@ -0,0 +1,199 @@
+/*
+ * The MIT License (MIT)
+ *
+ * Copyright (c) 2019 Ha Thach (tinyusb.org)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ */
+
+#include "bsp/board_api.h"
+#include "tusb.h"
+
+/* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug.
+ * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC.
+ *
+ * Auto ProductID layout's Bitmap:
+ * [MSB] AUDIO | MIDI | HID | MSC | CDC [LSB]
+ */
+#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0)
+#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \
+ PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4))
+
+#define USB_VID 0xCafe
+#define USB_BCD 0x0200
+
+//--------------------------------------------------------------------+
+// Device Descriptors
+//--------------------------------------------------------------------+
+static tusb_desc_device_t const desc_device = {
+ .bLength = sizeof(tusb_desc_device_t),
+ .bDescriptorType = TUSB_DESC_DEVICE,
+ .bcdUSB = USB_BCD,
+ .bDeviceClass = TUSB_CLASS_MISC,
+ .bDeviceSubClass = MISC_SUBCLASS_COMMON,
+ .bDeviceProtocol = MISC_PROTOCOL_IAD,
+
+ .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
+
+ .idVendor = USB_VID,
+ .idProduct = USB_PID,
+ .bcdDevice = 0x0100,
+
+ .iManufacturer = 0x01,
+ .iProduct = 0x02,
+ .iSerialNumber = 0x03,
+
+ .bNumConfigurations = 0x01
+};
+
+// Invoked when received GET DEVICE DESCRIPTOR
+// Application return pointer to descriptor
+uint8_t const *tud_descriptor_device_cb(void) {
+ return (uint8_t const *) &desc_device;
+}
+
+//--------------------------------------------------------------------+
+// Configuration Descriptor
+//--------------------------------------------------------------------+
+
+enum {
+ ITF_NUM_CDC = 0,
+ ITF_NUM_CDC_DATA,
+ ITF_NUM_TOTAL
+};
+
+#if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX
+ // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number
+ // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In, 5 Bulk etc ...
+ #define EPNUM_CDC_NOTIF 0x81
+ #define EPNUM_CDC_OUT 0x02
+ #define EPNUM_CDC_IN 0x82
+
+#elif CFG_TUD_ENDPOINT_ONE_DIRECTION_ONLY
+ // MCUs that don't support a same endpoint number with different direction IN and OUT defined in tusb_mcu.h
+ // e.g EP1 OUT & EP1 IN cannot exist together
+ #define EPNUM_CDC_NOTIF 0x81
+ #define EPNUM_CDC_OUT 0x02
+ #define EPNUM_CDC_IN 0x83
+
+#else
+ #define EPNUM_CDC_NOTIF 0x81
+ #define EPNUM_CDC_OUT 0x02
+ #define EPNUM_CDC_IN 0x82
+
+#endif
+
+#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN)
+
+static uint8_t const desc_fs_configuration[] = {
+ // Config number, interface count, string index, total length, attribute, power in mA
+ TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
+
+ // Interface number, string index, EP notification address and size, EP data address (out, in) and size.
+ TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64),
+};
+
+#if TUD_OPT_HIGH_SPEED
+static uint8_t const desc_hs_configuration[] = {
+ // Config number, interface count, string index, total length, attribute, power in mA
+ TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
+
+ // Interface number, string index, EP notification address and size, EP data address (out, in) and size.
+ TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512),
+};
+#endif
+
+// Invoked when received GET CONFIGURATION DESCRIPTOR
+// Application return pointer to descriptor
+// Descriptor contents must exist long enough for transfer to complete
+uint8_t const *tud_descriptor_configuration_cb(uint8_t index) {
+ (void) index; // for multiple configurations
+
+#if TUD_OPT_HIGH_SPEED
+ // Although we are highspeed, host may be fullspeed.
+ return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration;
+#else
+ return desc_fs_configuration;
+#endif
+}
+
+//--------------------------------------------------------------------+
+// String Descriptors
+//--------------------------------------------------------------------+
+
+// String Descriptor Index
+enum {
+ STRID_LANGID = 0,
+ STRID_MANUFACTURER,
+ STRID_PRODUCT,
+ STRID_SERIAL,
+};
+
+// array of pointer to string descriptors
+static char const *string_desc_arr[] = {
+ (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
+ "TinyUSB", // 1: Manufacturer
+ "TinyUSB Device", // 2: Product
+ NULL, // 3: Serials, will use unique ID if possible
+ "TinyUSB CDC", // 4: CDC Interface
+};
+
+static uint16_t _desc_str[32 + 1];
+
+// Invoked when received GET STRING DESCRIPTOR request
+// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
+uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) {
+ (void) langid;
+ size_t chr_count;
+
+ switch (index) {
+ case STRID_LANGID:
+ memcpy(&_desc_str[1], string_desc_arr[0], 2);
+ chr_count = 1;
+ break;
+
+ case STRID_SERIAL:
+ chr_count = board_usb_get_serial(_desc_str + 1, 32);
+ break;
+
+ default:
+ // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
+ // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
+
+ if (!(index < sizeof(string_desc_arr) / sizeof(string_desc_arr[0]))) { return NULL; }
+
+ const char *str = string_desc_arr[index];
+
+ // Cap at max char
+ chr_count = strlen(str);
+ size_t const max_count = sizeof(_desc_str) / sizeof(_desc_str[0]) - 1; // -1 for string type
+ if (chr_count > max_count) { chr_count = max_count; }
+
+ // Convert ASCII string into UTF-16
+ for (size_t i = 0; i < chr_count; i++) {
+ _desc_str[1 + i] = str[i];
+ }
+ break;
+ }
+
+ // first byte is length (including header), second byte is string type
+ _desc_str[0] = (uint16_t) ((TUSB_DESC_STRING << 8) | (2 * chr_count + 2));
+ return _desc_str;
+}
diff --git a/examples/dual/host_hid_to_device_cdc/CMakeLists.txt b/examples/dual/host_hid_to_device_cdc/CMakeLists.txt
index 6ae5b5766..38c678cf2 100644
--- a/examples/dual/host_hid_to_device_cdc/CMakeLists.txt
+++ b/examples/dual/host_hid_to_device_cdc/CMakeLists.txt
@@ -2,34 +2,31 @@ cmake_minimum_required(VERSION 3.20)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
-# gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
-family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-
-project(${PROJECT} C CXX ASM)
+project(host_hid_to_device_cdc C CXX ASM)
# Checks this example is valid for the family and initializes the project
-family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
+family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR})
-add_executable(${PROJECT})
+add_executable(${PROJECT_NAME})
# Example source
-target_sources(${PROJECT} PUBLIC
+target_sources(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
)
# Example include
-target_include_directories(${PROJECT} PUBLIC
+target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# Configure compilation flags and libraries for the example without RTOS.
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
-family_configure_dual_usb_example(${PROJECT} noos)
+family_configure_dual_usb_example(${PROJECT_NAME} noos)
# due to warnings from Pico-PIO-USB
if (FAMILY STREQUAL rp2040)
- target_compile_options(${PROJECT} PUBLIC
+ target_compile_options(${PROJECT_NAME} PUBLIC
-Wno-error=shadow
-Wno-error=cast-align
-Wno-error=cast-qual
diff --git a/examples/dual/host_hid_to_device_cdc/Makefile b/examples/dual/host_hid_to_device_cdc/Makefile
index 474ae9814..595cd7dec 100644
--- a/examples/dual/host_hid_to_device_cdc/Makefile
+++ b/examples/dual/host_hid_to_device_cdc/Makefile
@@ -1,18 +1,18 @@
-include ../../build_system/make/make.mk
+include ../../../hw/bsp/family_support.mk
INC += \
src \
- $(TOP)/hw \
+
# Example source
EXAMPLE_SOURCE += $(wildcard src/*.c)
-SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
+SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE))
-CFLAGS_GCC += -Wno-error=cast-align -Wno-error=null-dereference
+CFLAGS += -Wno-error=cast-align -Wno-error=null-dereference
SRC_C += \
src/class/hid/hid_host.c \
src/host/hub.c \
src/host/usbh.c
-include ../../build_system/make/rules.mk
+include ../../../hw/bsp/family_rules.mk
diff --git a/examples/dual/host_hid_to_device_cdc/src/main.c b/examples/dual/host_hid_to_device_cdc/src/main.c
index 8c53588c3..c8fca48f8 100644
--- a/examples/dual/host_hid_to_device_cdc/src/main.c
+++ b/examples/dual/host_hid_to_device_cdc/src/main.c
@@ -98,8 +98,6 @@ int main(void) {
tuh_task(); // tinyusb host task
led_blinking_task();
}
-
- return 0;
}
//--------------------------------------------------------------------+
@@ -284,7 +282,7 @@ void led_blinking_task(void) {
static bool led_state = false;
// Blink every interval ms
- if (board_millis() - start_ms < blink_interval_ms) return; // not enough time
+ if (tusb_time_millis_api() - start_ms < blink_interval_ms) return; // not enough time
start_ms += blink_interval_ms;
board_led_write(led_state);
diff --git a/examples/dual/host_hid_to_device_cdc/src/tusb_config.h b/examples/dual/host_hid_to_device_cdc/src/tusb_config.h
index 2843e0b83..fb2a401b5 100644
--- a/examples/dual/host_hid_to_device_cdc/src/tusb_config.h
+++ b/examples/dual/host_hid_to_device_cdc/src/tusb_config.h
@@ -114,8 +114,10 @@
#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
-// CDC Endpoint transfer buffer size, more is faster
-#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+// CDC Endpoint transfer buffer size, default to max bulk packet size (HS 512, FS 64). Larger is faster.
+// Larger RX_EPSIZE requires CFG_TUD_CDC_RX_NEED_ZLP = 1 and host ZLP support
+#define CFG_TUD_CDC_RX_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+#define CFG_TUD_CDC_TX_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
//--------------------------------------------------------------------
// HOST CONFIGURATION
diff --git a/examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c b/examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c
index b7cffe23d..3efa30e20 100644
--- a/examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c
+++ b/examples/dual/host_hid_to_device_cdc/src/usb_descriptors.c
@@ -32,9 +32,9 @@
* Auto ProductID layout's Bitmap:
* [MSB] HID | MSC | CDC [LSB]
*/
-#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
-#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
- _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
+#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0)
+#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \
+ PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) )
#define USB_VID 0xCafe
#define USB_BCD 0x0200
@@ -42,7 +42,7 @@
//--------------------------------------------------------------------+
// Device Descriptors
//--------------------------------------------------------------------+
-tusb_desc_device_t const desc_device = {
+static tusb_desc_device_t const desc_device = {
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = USB_BCD,
@@ -122,7 +122,7 @@ enum {
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN)
// full speed configuration
-uint8_t const desc_fs_configuration[] = {
+static uint8_t const desc_fs_configuration[] = {
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
@@ -134,7 +134,7 @@ uint8_t const desc_fs_configuration[] = {
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
// high speed configuration
-uint8_t const desc_hs_configuration[] = {
+static uint8_t const desc_hs_configuration[] = {
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
@@ -143,10 +143,10 @@ uint8_t const desc_hs_configuration[] = {
};
// other speed configuration
-uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
+static uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
-tusb_desc_device_qualifier_t const desc_device_qualifier = {
+static tusb_desc_device_qualifier_t const desc_device_qualifier = {
.bLength = sizeof(tusb_desc_device_qualifier_t),
.bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
.bcdUSB = USB_BCD,
diff --git a/examples/dual/host_info_to_device_cdc/CMakeLists.txt b/examples/dual/host_info_to_device_cdc/CMakeLists.txt
index 6ae5b5766..87b5336f1 100644
--- a/examples/dual/host_info_to_device_cdc/CMakeLists.txt
+++ b/examples/dual/host_info_to_device_cdc/CMakeLists.txt
@@ -2,34 +2,36 @@ cmake_minimum_required(VERSION 3.20)
include(${CMAKE_CURRENT_SOURCE_DIR}/../../../hw/bsp/family_support.cmake)
-# gets PROJECT name for the example (e.g. <BOARD>-<DIR_NAME>)
-family_get_project_name(PROJECT ${CMAKE_CURRENT_LIST_DIR})
-
-project(${PROJECT} C CXX ASM)
+project(host_info_to_device_cdc C CXX ASM)
# Checks this example is valid for the family and initializes the project
-family_initialize_project(${PROJECT} ${CMAKE_CURRENT_LIST_DIR})
+family_initialize_project(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR})
+
+# Espressif has its own cmake build system
+if(FAMILY STREQUAL "espressif")
+ return()
+endif()
-add_executable(${PROJECT})
+add_executable(${PROJECT_NAME})
# Example source
-target_sources(${PROJECT} PUBLIC
+target_sources(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src/main.c
${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c
)
# Example include
-target_include_directories(${PROJECT} PUBLIC
+target_include_directories(${PROJECT_NAME} PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/src
)
# Configure compilation flags and libraries for the example without RTOS.
# See the corresponding function in hw/bsp/FAMILY/family.cmake for details.
-family_configure_dual_usb_example(${PROJECT} noos)
+family_configure_dual_usb_example(${PROJECT_NAME} ${RTOS})
# due to warnings from Pico-PIO-USB
if (FAMILY STREQUAL rp2040)
- target_compile_options(${PROJECT} PUBLIC
+ target_compile_options(${PROJECT_NAME} PUBLIC
-Wno-error=shadow
-Wno-error=cast-align
-Wno-error=cast-qual
diff --git a/examples/dual/host_info_to_device_cdc/Makefile b/examples/dual/host_info_to_device_cdc/Makefile
index 083c9169a..3a1d87f57 100644
--- a/examples/dual/host_info_to_device_cdc/Makefile
+++ b/examples/dual/host_info_to_device_cdc/Makefile
@@ -1,17 +1,17 @@
-include ../../build_system/make/make.mk
+include ../../../hw/bsp/family_support.mk
INC += \
src \
- $(TOP)/hw \
+
# Example source
EXAMPLE_SOURCE += $(wildcard src/*.c)
-SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE))
+SRC_C += $(addprefix $(EXAMPLE_PATH)/, $(EXAMPLE_SOURCE))
-CFLAGS_GCC += -Wno-error=cast-align -Wno-error=null-dereference
+CFLAGS += -Wno-error=cast-align -Wno-error=null-dereference
SRC_C += \
src/host/hub.c \
src/host/usbh.c
-include ../../build_system/make/rules.mk
+include ../../../hw/bsp/family_rules.mk
diff --git a/examples/dual/host_info_to_device_cdc/only.txt b/examples/dual/host_info_to_device_cdc/only.txt
index 35f896f1e..4431065ba 100644
--- a/examples/dual/host_info_to_device_cdc/only.txt
+++ b/examples/dual/host_info_to_device_cdc/only.txt
@@ -8,3 +8,4 @@ mcu:MAX3421
mcu:STM32F4
mcu:STM32F7
mcu:STM32H7
+mcu:ESP32P4
diff --git a/examples/dual/host_info_to_device_cdc/src/CMakeLists.txt b/examples/dual/host_info_to_device_cdc/src/CMakeLists.txt
new file mode 100644
index 000000000..cef2b46ee
--- /dev/null
+++ b/examples/dual/host_info_to_device_cdc/src/CMakeLists.txt
@@ -0,0 +1,4 @@
+# This file is for ESP-IDF only
+idf_component_register(SRCS "main.c" "usb_descriptors.c"
+ INCLUDE_DIRS "."
+ REQUIRES boards tinyusb_src)
diff --git a/examples/dual/host_info_to_device_cdc/src/main.c b/examples/dual/host_info_to_device_cdc/src/main.c
index 67e905b9d..5186f91dc 100644
--- a/examples/dual/host_info_to_device_cdc/src/main.c
+++ b/examples/dual/host_info_to_device_cdc/src/main.c
@@ -69,14 +69,18 @@ enum {
static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
-static bool is_print[CFG_TUH_DEVICE_MAX+1] = { 0 };
+static bool is_printable[CFG_TUH_DEVICE_MAX + 1] = {0};
static tusb_desc_device_t descriptor_device[CFG_TUH_DEVICE_MAX+1];
static void print_utf16(uint16_t *temp_buf, size_t buf_len);
static void print_device_info(uint8_t daddr, const tusb_desc_device_t* desc_device);
-void led_blinking_task(void);
-void cdc_task(void);
+static void led_blinking_task(void);
+static void cdc_task(void);
+
+#if CFG_TUSB_OS == OPT_OS_FREERTOS
+static void freertos_init(void);
+#endif
#define cdc_printf(...) \
do { \
@@ -94,37 +98,86 @@ void cdc_task(void);
} \
} while(0)
-/*------------- MAIN -------------*/
-int main(void) {
- board_init();
-
- printf("TinyUSB Host Information -> Device CDC Example\r\n");
+static void usb_device_init(void) {
// init device and host stack on configured roothub port
tusb_rhport_init_t dev_init = {
.role = TUSB_ROLE_DEVICE,
.speed = TUSB_SPEED_AUTO
};
tusb_init(BOARD_TUD_RHPORT, &dev_init);
+ board_init_after_tusb();
+}
+static void usb_host_init(void) {
+ // init host stack on configured roothub port
tusb_rhport_init_t host_init = {
.role = TUSB_ROLE_HOST,
.speed = TUSB_SPEED_AUTO
};
tusb_init(BOARD_TUH_RHPORT, &host_init);
-
board_init_after_tusb();
+}
+
+//--------------------------------------------------------------------+
+// Main
+//--------------------------------------------------------------------+
+static void main_task(void* param) {
+ (void) param;
while (1) {
- tud_task(); // tinyusb device task
- tuh_task(); // tinyusb host task
cdc_task();
led_blinking_task();
+
+ // preempted RTOS run device/host stack in its own task
+#if CFG_TUSB_OS_HAS_SCHEDULER == 0
+ tud_task(); // tinyusb device task
+ tuh_task(); // tinyusb host task
+#endif
}
+}
+
+int main(void) {
+ board_init();
+
+#if CFG_TUSB_OS_HAS_SCHEDULER == 0
+ printf("TinyUSB Host Information -> Device CDC Example\r\n");
+
+ usb_device_init();
+ usb_host_init();
+
+ main_task(NULL);
+#elif CFG_TUSB_OS == OPT_OS_FREERTOS
+ freertos_init(); // create RTOS tasks for device, host stack and main_task()
+#else
+ #error RTOS not supported
+#endif
return 0;
}
+#if CFG_TUSB_OS_HAS_SCHEDULER
+// USB Device Driver task for RTOS
+static void usb_device_task(void *param) {
+ (void) param;
+ usb_device_init();
+ while (1) {
+ // put this thread to waiting state until there is new events
+ tud_task();
+ }
+}
+
+static void usb_host_task(void *param) {
+ (void) param;
+ usb_host_init();
+ while (1) {
+ // put this thread to waiting state until there is new events
+ tuh_task();
+ }
+}
+#endif
+
+
//--------------------------------------------------------------------+
// Device CDC
//--------------------------------------------------------------------+
@@ -153,17 +206,23 @@ void tud_resume_cb(void) {
}
void cdc_task(void) {
+ static uint32_t connected_ms = 0;
+
if (!tud_cdc_connected()) {
- // delay a bit otherwise we can outpace host's terminal. Linux will set LineState (DTR) then Line Coding.
- // If we send data before Linux's terminal set Line Coding, it can be ignored --> missing data with hardware test loop
- board_delay(20);
+ connected_ms = tusb_time_millis_api();
return;
}
+ // delay a bit otherwise we can outpace host's terminal. Linux will set LineState (DTR) then Line Coding.
+ // If we send data before Linux's terminal set Line Coding, it can be ignored --> missing data with hardware test loop
+ if (tusb_time_millis_api() - connected_ms < 100) {
+ return; // wait for stable connection
+ }
+
for (uint8_t daddr = 1; daddr <= CFG_TUH_DEVICE_MAX; daddr++) {
if (tuh_mounted(daddr)) {
- if (is_print[daddr]) {
- is_print[daddr] = false;
+ if (is_printable[daddr]) {
+ is_printable[daddr] = false;
print_device_info(daddr, &descriptor_device[daddr]);
tud_cdc_write_flush();
}
@@ -183,10 +242,9 @@ static void print_device_info(uint8_t daddr, const tusb_desc_device_t* desc_devi
cdc_printf("Device %u: ID %04x:%04x SN ", daddr, desc_device->idVendor, desc_device->idProduct);
uint8_t xfer_result = tuh_descriptor_get_serial_string_sync(daddr, LANGUAGE_ID, serial, sizeof(serial));
if (XFER_RESULT_SUCCESS != xfer_result) {
- serial[0] = 'n';
- serial[1] = '/';
- serial[2] = 'a';
- serial[3] = 0;
+ serial[0] = (uint16_t)((TUSB_DESC_STRING << 8) | (2 * 1 + 2));
+ serial[1] = '0';
+ serial[2] = 0;
}
print_utf16(serial, TU_ARRAY_SIZE(serial));
cdc_printf("\r\n");
@@ -218,9 +276,7 @@ static void print_device_info(uint8_t daddr, const tusb_desc_device_t* desc_devi
cdc_printf("\r\n");
cdc_printf(" iSerialNumber %u " , desc_device->iSerialNumber);
- cdc_printf((char*)serial); // serial is already to UTF-8
- cdc_printf("\r\n");
-
+ cdc_printf("%s \r\n", (char*)serial); // serial is already to UTF-8
cdc_printf(" bNumConfigurations %u\r\n" , desc_device->bNumConfigurations);
}
@@ -232,13 +288,13 @@ void tuh_enum_descriptor_device_cb(uint8_t daddr, tusb_desc_device_t const* desc
void tuh_mount_cb(uint8_t daddr) {
cdc_printf("mounted device %u\r\n", daddr);
tud_cdc_write_flush();
- is_print[daddr] = true;
+ is_printable[daddr] = true;
}
void tuh_umount_cb(uint8_t daddr) {
cdc_printf("unmounted device %u\r\n", daddr);
tud_cdc_write_flush();
- is_print[daddr] = false;
+ is_printable[daddr] = false;
}
//--------------------------------------------------------------------+
@@ -249,7 +305,7 @@ void led_blinking_task(void) {
static bool led_state = false;
// Blink every interval ms
- if (board_millis() - start_ms < blink_interval_ms) {
+ if (tusb_time_millis_api() - start_ms < blink_interval_ms) {
return;// not enough time
}
start_ms += blink_interval_ms;
@@ -261,7 +317,6 @@ void led_blinking_task(void) {
//--------------------------------------------------------------------+
// String Descriptor Helper
//--------------------------------------------------------------------+
-
static void _convert_utf16le_to_utf8(const uint16_t *utf16, size_t utf16_len, uint8_t *utf8, size_t utf8_len) {
// TODO: Check for runover.
(void)utf8_len;
@@ -310,5 +365,55 @@ static void print_utf16(uint16_t *temp_buf, size_t buf_len) {
_convert_utf16le_to_utf8(temp_buf + 1, utf16_len, (uint8_t *) temp_buf, sizeof(uint16_t) * buf_len);
((uint8_t*) temp_buf)[utf8_len] = '\0';
- cdc_printf((char*) temp_buf);
+ cdc_printf("%s", (char*) temp_buf);
}
+
+//--------------------------------------------------------------------+
+// FreeRTOS
+//--------------------------------------------------------------------+
+#if CFG_TUSB_OS == OPT_OS_FREERTOS
+
+#ifdef ESP_PLATFORM
+ #define USBD_STACK_SIZE 4096
+ #define USBH_STACK_SIZE 4096
+ void app_main(void) {
+ main();
+ }
+#else
+ // Increase stack size when debug log is enabled
+ #define USBD_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 4 : 2))
+ #define USBH_STACK_SIZE (configMINIMAL_STACK_SIZE * (CFG_TUSB_DEBUG ? 4 : 2))
+#endif
+
+#define MAIN_STACK_SIZE (configMINIMAL_STACK_SIZE*4)
+
+// static task
+#if configSUPPORT_STATIC_ALLOCATION
+StackType_t main_stack[MAIN_STACK_SIZE];
+StaticTask_t main_taskdef;
+
+StackType_t usb_device_stack[USBD_STACK_SIZE];
+StaticTask_t usb_device_taskdef;
+
+StackType_t usb_host_stack[USBH_STACK_SIZE];
+StaticTask_t usb_host_taskdef;
+#endif
+
+void freertos_init(void) {
+ #if configSUPPORT_STATIC_ALLOCATION
+ xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef);
+ xTaskCreateStatic(usb_host_task, "usbh", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_host_stack, &usb_host_taskdef);
+ xTaskCreateStatic(main_task, "main", MAIN_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, main_stack, &main_taskdef);
+ #else
+ xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL);
+ xTaskCreate(usb_host_task, "usbh", USBH_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL);
+ xTaskCreate(main_task, "main", MAIN_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, NULL);
+ #endif
+
+ // only start scheduler for non-espressif mcu
+ #ifndef ESP_PLATFORM
+ vTaskStartScheduler();
+ #endif
+}
+
+#endif
diff --git a/examples/dual/host_info_to_device_cdc/src/tusb_config.h b/examples/dual/host_info_to_device_cdc/src/tusb_config.h
index bb47fbf4a..99e9315a4 100644
--- a/examples/dual/host_info_to_device_cdc/src/tusb_config.h
+++ b/examples/dual/host_info_to_device_cdc/src/tusb_config.h
@@ -112,10 +112,12 @@
// CDC FIFO size of TX and RX
#define CFG_TUD_CDC_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
-#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+#define CFG_TUD_CDC_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 256)
-// CDC Endpoint transfer buffer size, more is faster
-#define CFG_TUD_CDC_EP_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+// CDC Endpoint transfer buffer size, default to max bulk packet size (HS 512, FS 64). Larger is faster.
+// Larger RX_EPSIZE requires CFG_TUD_CDC_RX_NEED_ZLP = 1 and host ZLP support
+#define CFG_TUD_CDC_RX_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
+#define CFG_TUD_CDC_TX_EPSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
//--------------------------------------------------------------------
// HOST CONFIGURATION
diff --git a/examples/dual/host_info_to_device_cdc/src/usb_descriptors.c b/examples/dual/host_info_to_device_cdc/src/usb_descriptors.c
index b7cffe23d..3efa30e20 100644
--- a/examples/dual/host_info_to_device_cdc/src/usb_descriptors.c
+++ b/examples/dual/host_info_to_device_cdc/src/usb_descriptors.c
@@ -32,9 +32,9 @@
* Auto ProductID layout's Bitmap:
* [MSB] HID | MSC | CDC [LSB]
*/
-#define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) )
-#define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \
- _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) )
+#define PID_MAP(itf, n) ((CFG_TUD_##itf) ? (1 << (n)) : 0)
+#define USB_PID (0x4000 | PID_MAP(CDC, 0) | PID_MAP(MSC, 1) | PID_MAP(HID, 2) | \
+ PID_MAP(MIDI, 3) | PID_MAP(VENDOR, 4) )
#define USB_VID 0xCafe
#define USB_BCD 0x0200
@@ -42,7 +42,7 @@
//--------------------------------------------------------------------+
// Device Descriptors
//--------------------------------------------------------------------+
-tusb_desc_device_t const desc_device = {
+static tusb_desc_device_t const desc_device = {
.bLength = sizeof(tusb_desc_device_t),
.bDescriptorType = TUSB_DESC_DEVICE,
.bcdUSB = USB_BCD,
@@ -122,7 +122,7 @@ enum {
#define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN)
// full speed configuration
-uint8_t const desc_fs_configuration[] = {
+static uint8_t const desc_fs_configuration[] = {
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
@@ -134,7 +134,7 @@ uint8_t const desc_fs_configuration[] = {
// Per USB specs: high speed capable device must report device_qualifier and other_speed_configuration
// high speed configuration
-uint8_t const desc_hs_configuration[] = {
+static uint8_t const desc_hs_configuration[] = {
// Config number, interface count, string index, total length, attribute, power in mA
TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, 0x00, 100),
@@ -143,10 +143,10 @@ uint8_t const desc_hs_configuration[] = {
};
// other speed configuration
-uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
+static uint8_t desc_other_speed_config[CONFIG_TOTAL_LEN];
// device qualifier is mostly similar to device descriptor since we don't change configuration based on speed
-tusb_desc_device_qualifier_t const desc_device_qualifier = {
+static tusb_desc_device_qualifier_t const desc_device_qualifier = {
.bLength = sizeof(tusb_desc_device_qualifier_t),
.bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER,
.bcdUSB = USB_BCD,