Quellcode durchsuchen

usb: Add HID device example

Closes https://github.com/espressif/esp-idf/issues/6839
Closes https://github.com/espressif/esp-idf/issues/7700
Tomas Rezucha vor 3 Jahren
Ursprung
Commit
45e8115dc6

+ 6 - 13
components/tinyusb/Kconfig

@@ -107,7 +107,7 @@ menu "TinyUSB Stack"
                     Name of the MSC device.
 
             config TINYUSB_DESC_HID_STRING
-                depends on TINYUSB_HID_ENABLED
+                depends on TINYUSB_HID_COUNT > 0
                 string "HID Device String"
                 default "Espressif HID Device"
                 help
@@ -177,19 +177,12 @@ menu "TinyUSB Stack"
         endmenu # "MIDI"
 
         menu "Human Interface Device Class (HID)"
-            config TINYUSB_HID_ENABLED
-                bool "Enable TinyUSB HID feature"
-                default n
-                help
-                    Enable TinyUSB HID feature.
-
-            config TINYUSB_HID_BUFSIZE
-                depends on TINYUSB_HID_ENABLED
-                int "Report buffer size of TinyUSB HID device"
-                default 16
+            config TINYUSB_HID_COUNT
+                int "TinyUSB HID interfaces count"
+                default 0
+                range 0 4
                 help
-                    Set TinyUSB HID device report buffer size.
+                    Setting value greater than 0 will enable TinyUSB HID feature.
         endmenu # "HID Device Class (HID)"
     endif # TINYUSB
-
 endmenu # "TinyUSB Stack"

+ 1 - 1
components/tinyusb/additions/include/tinyusb_types.h

@@ -11,7 +11,7 @@ extern "C" {
 #endif
 
 #define USB_ESPRESSIF_VID 0x303A
-#define USB_STRING_DESCRIPTOR_ARRAY_SIZE 8
+#define USB_STRING_DESCRIPTOR_ARRAY_SIZE 7
 
 typedef enum{
     TINYUSB_USBDEV_0,

+ 3 - 6
components/tinyusb/additions/include/tusb_config.h

@@ -41,8 +41,8 @@ extern "C" {
 #   define CONFIG_TINYUSB_MSC_ENABLED 0
 #endif
 
-#ifndef CONFIG_TINYUSB_HID_ENABLED
-#   define CONFIG_TINYUSB_HID_ENABLED 0
+#ifndef CONFIG_TINYUSB_HID_COUNT
+#   define CONFIG_TINYUSB_HID_COUNT 0
 #endif
 
 #ifndef CONFIG_TINYUSB_MIDI_ENABLED
@@ -82,9 +82,6 @@ extern "C" {
 // MSC Buffer size of Device Mass storage
 #define CFG_TUD_MSC_BUFSIZE         CONFIG_TINYUSB_MSC_BUFSIZE
 
-// HID buffer size Should be sufficient to hold ID (if any) + Data
-#define CFG_TUD_HID_BUFSIZE         CONFIG_TINYUSB_HID_BUFSIZE
-
 #define CFG_TUD_MIDI_EP_BUFSIZE     64
 #define CFG_TUD_MIDI_EPSIZE         CFG_TUD_MIDI_EP_BUFSIZE
 #define CFG_TUD_MIDI_RX_BUFSIZE     64
@@ -97,7 +94,7 @@ extern "C" {
 #define CFG_TUD_CDC                 0
 #endif
 #define CFG_TUD_MSC                 CONFIG_TINYUSB_MSC_ENABLED
-#define CFG_TUD_HID                 CONFIG_TINYUSB_HID_ENABLED
+#define CFG_TUD_HID                 CONFIG_TINYUSB_HID_COUNT
 #define CFG_TUD_MIDI                CONFIG_TINYUSB_MIDI_ENABLED
 #define CFG_TUD_CUSTOM_CLASS        CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED
 

+ 10 - 6
components/tinyusb/additions/src/tinyusb.c

@@ -33,12 +33,12 @@ esp_err_t tinyusb_driver_install(const tinyusb_config_t *config)
         .otg_mode = USB_OTG_MODE_DEVICE,
     };
     usb_phy_gpio_conf_t gpio_conf = {
-    .vp_io_num = USBPHY_VP_NUM,
-    .vm_io_num = USBPHY_VM_NUM,
-    .rcv_io_num = USBPHY_RCV_NUM,
-    .oen_io_num = USBPHY_OEN_NUM,
-    .vpo_io_num = USBPHY_VPO_NUM,
-    .vmo_io_num = USBPHY_VMO_NUM,
+        .vp_io_num = USBPHY_VP_NUM,
+        .vm_io_num = USBPHY_VM_NUM,
+        .rcv_io_num = USBPHY_RCV_NUM,
+        .oen_io_num = USBPHY_OEN_NUM,
+        .vpo_io_num = USBPHY_VPO_NUM,
+        .vmo_io_num = USBPHY_VMO_NUM,
     };
     if (config->external_phy) {
         phy_conf.target = USB_PHY_TARGET_EXT;
@@ -48,6 +48,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_TINYUSB_HID_COUNT > 0)
+    // For HID device, configuration descriptor must be provided
+    ESP_RETURN_ON_FALSE(config->configuration_descriptor, ESP_ERR_INVALID_ARG, TAG, "Configuration descriptor must be provided for HID device");
+#endif
     dev_descriptor = config->device_descriptor ? config->device_descriptor : &descriptor_dev_kconfig;
     string_descriptor = config->string_descriptor ? config->string_descriptor : descriptor_str_kconfig;
     cfg_descriptor = config->configuration_descriptor ? config->configuration_descriptor : descriptor_cfg_kconfig;

+ 4 - 40
components/tinyusb/additions/src/usb_descriptors.c

@@ -56,8 +56,7 @@ tusb_desc_strarray_device_t descriptor_str_tinyusb = {
     "123456",             // 3: Serials, should use chip ID
     "TinyUSB CDC",        // 4: CDC Interface
     "TinyUSB MSC",        // 5: MSC Interface
-    "TinyUSB HID",        // 6: HID
-    "TinyUSB MIDI"        // 7: MIDI
+    "TinyUSB MIDI"        // 6: MIDI
 };
 /* End of TinyUSB default */
 
@@ -121,28 +120,14 @@ tusb_desc_strarray_device_t descriptor_str_kconfig = {
     "",
 #endif
 
-#if CONFIG_TINYUSB_HID_ENABLED
-    CONFIG_TINYUSB_DESC_HID_STRING           // 6: HIDs
-#else
-    "",
-#endif
-
 #if CONFIG_TINYUSB_MIDI_ENABLED
-    CONFIG_TINYUSB_DESC_MIDI_STRING           // 7: MIDI
+    CONFIG_TINYUSB_DESC_MIDI_STRING           // 6: MIDI
 #else
     "",
 #endif
 
 };
 
-//------------- HID Report Descriptor -------------//
-#if CFG_TUD_HID
-enum {
-    REPORT_ID_KEYBOARD = 1,
-    REPORT_ID_MOUSE
-};
-#endif
-
 //------------- Configuration Descriptor -------------//
 enum {
 #if CFG_TUD_CDC
@@ -159,10 +144,6 @@ enum {
     ITF_NUM_MSC,
 #endif
 
-#if CFG_TUD_HID
-    ITF_NUM_HID,
-#endif
-
 #if CFG_TUD_MIDI
     ITF_NUM_MIDI,
     ITF_NUM_MIDI_STREAMING,
@@ -175,7 +156,6 @@ 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_HID * TUD_HID_DESC_LEN +
                         CFG_TUD_MIDI * TUD_MIDI_DESC_LEN
 };
 
@@ -197,24 +177,13 @@ enum {
     EPNUM_MSC,
 #endif
 
-#if CFG_TUD_HID
-    EPNUM_HID,
-#endif
-
 #if CFG_TUD_MIDI
     EPNUM_MIDI,
 #endif
 };
 
-#if CFG_TUD_HID //HID Report Descriptor
-uint8_t const desc_hid_report[] = {
-    TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(REPORT_ID_KEYBOARD), ),
-    TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(REPORT_ID_MOUSE), )
-};
-#endif
-
 uint8_t const descriptor_cfg_kconfig[] = {
-    // interface count, string index, total length, attribute, power in mA
+    // 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
@@ -232,14 +201,9 @@ uint8_t const descriptor_cfg_kconfig[] = {
     TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC, 0x80 | EPNUM_MSC, 64), // highspeed 512
 #endif
 
-#if CFG_TUD_HID
-    // Interface number, string index, protocol, report descriptor len, EP In address, size & polling interval
-    TUD_HID_DESCRIPTOR(ITF_NUM_HID, 6, HID_PROTOCOL_NONE, sizeof(desc_hid_report), 0x80 | EPNUM_HID, 16, 10)
-#endif
-
 #if CFG_TUD_MIDI
     // Interface number, string index, EP Out & EP In address, EP size
-    TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 7, EPNUM_MIDI, 0x80 | EPNUM_MIDI, 64) // highspeed 512
+    TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 6, EPNUM_MIDI, 0x80 | EPNUM_MIDI, 64) // highspeed 512
 #endif
 };
 

+ 7 - 1
examples/peripherals/usb/device/tusb_console/main/tusb_console_main.c

@@ -28,7 +28,13 @@ void app_main(void)
     /* Setting TinyUSB up */
     ESP_LOGI(TAG, "USB initialization");
 
-    tinyusb_config_t tusb_cfg = { 0 }; // the configuration uses default values
+    const tinyusb_config_t tusb_cfg = {
+        .device_descriptor = NULL,
+        .string_descriptor = NULL,
+        .external_phy = false, // In the most cases you need to use a `false` value
+        .configuration_descriptor = NULL,
+    };
+
     ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));
 
     tinyusb_config_cdcacm_t acm_cfg = { 0 }; // the configuration uses default values

+ 8 - 0
examples/peripherals/usb/device/tusb_hid/CMakeLists.txt

@@ -0,0 +1,8 @@
+# For more information about build system see
+# https://docs.espressif.com/projects/esp-idf/en/latest/api-guides/build-system.html
+# The following five 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)
+project(tusb_hid)

+ 80 - 0
examples/peripherals/usb/device/tusb_hid/README.md

@@ -0,0 +1,80 @@
+| Supported Targets | ESP32-S2 | ESP32-S3 |
+| ----------------- | -------- | -------- |
+
+# TinyUSB Human Interface Device Example
+
+(See the README.md file in the upper level 'examples' directory for more information about examples.)
+
+Human interface devices (HID) are one of the most common USB devices, it is implemented in various devices such as keyboards, mice, game controllers, sensors and alphanumeric display devices.
+In this example, we implement USB keyboard and mouse.
+Upon connection to USB host (PC), the example application will sent 'key a/A pressed & released' events and move mouse in a square trajectory. To send these HID reports again, press the BOOT button, that is present on most ESP development boards (GPIO0).
+
+As a USB stack, a TinyUSB component is used.
+
+## How to use example
+
+### Hardware Required
+
+Any ESP board that have USB-OTG supported.
+
+#### Pin Assignment
+
+_Note:_ In case your board doesn't have micro-USB connector connected to USB-OTG peripheral, you may have to DIY a cable and connect **D+** and **D-** to the pins listed below.
+
+See common pin assignments for USB Device examples from [upper level](../../README.md#common-pin-assignments).
+
+Boot signal (GPIO0) is used to send HID reports to USB host.
+
+### Build and Flash
+
+Build the project and flash it to the board, then run monitor tool to view serial output:
+
+```bash
+idf.py -p PORT flash monitor
+```
+
+(Replace PORT with the name of the serial port to use.)
+
+(To exit the serial monitor, type ``Ctrl-]``.)
+
+See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
+
+## Example Output
+
+After the flashing you should see the output at idf monitor:
+
+```
+I (290) cpu_start: Starting scheduler on PRO CPU.
+I (0) cpu_start: Starting scheduler on APP CPU.
+I (310) example: USB initialization
+I (310) tusb_desc:
+┌─────────────────────────────────┐
+│  USB Device Descriptor Summary  │
+├───────────────────┬─────────────┤
+│bDeviceClass       │ 0           │
+├───────────────────┼─────────────┤
+│bDeviceSubClass    │ 0           │
+├───────────────────┼─────────────┤
+│bDeviceProtocol    │ 0           │
+├───────────────────┼─────────────┤
+│bMaxPacketSize0    │ 64          │
+├───────────────────┼─────────────┤
+│idVendor           │ 0x303a      │
+├───────────────────┼─────────────┤
+│idProduct          │ 0x4004      │
+├───────────────────┼─────────────┤
+│bcdDevice          │ 0x100       │
+├───────────────────┼─────────────┤
+│iManufacturer      │ 0x1         │
+├───────────────────┼─────────────┤
+│iProduct           │ 0x2         │
+├───────────────────┼─────────────┤
+│iSerialNumber      │ 0x3         │
+├───────────────────┼─────────────┤
+│bNumConfigurations │ 0x1         │
+└───────────────────┴─────────────┘
+I (480) TinyUSB: TinyUSB Driver installed
+I (480) example: USB initialization DONE
+I (2490) example: Sending Keyboard report
+I (3040) example: Sending Mouse report
+```

+ 5 - 0
examples/peripherals/usb/device/tusb_hid/main/CMakeLists.txt

@@ -0,0 +1,5 @@
+idf_component_register(
+    SRCS "tusb_hid_example_main.c"
+    INCLUDE_DIRS "."
+    REQUIRES driver tinyusb
+    )

+ 175 - 0
examples/peripherals/usb/device/tusb_hid/main/tusb_hid_example_main.c

@@ -0,0 +1,175 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Unlicense OR CC0-1.0
+ */
+
+#include <stdlib.h>
+#include "esp_log.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "tinyusb.h"
+#include "class/hid/hid_device.h"
+#include "driver/gpio.h"
+
+#define APP_BUTTON (GPIO_NUM_0) // Use BOOT signal by default
+static const char *TAG = "example";
+
+/************* TinyUSB descriptors ****************/
+
+#define TUSB_DESC_TOTAL_LEN      (TUD_CONFIG_DESC_LEN + CFG_TUD_HID * TUD_HID_DESC_LEN)
+
+/**
+ * @brief HID report descriptor
+ *
+ * In this example we implement Keyboard + Mouse HID device,
+ * so we must define both report descriptors
+ */
+const uint8_t hid_report_descriptor[] = {
+    TUD_HID_REPORT_DESC_KEYBOARD(HID_REPORT_ID(HID_ITF_PROTOCOL_KEYBOARD) ),
+    TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(HID_ITF_PROTOCOL_MOUSE) )
+};
+
+/**
+ * @brief Configuration descriptor
+ *
+ * This is a simple configuration descriptor that defines 1 configuration and 1 HID interface
+ */
+static const uint8_t hid_configuration_descriptor[] = {
+    // Configuration number, interface count, string index, total length, attribute, power in mA
+    TUD_CONFIG_DESCRIPTOR(1, 1, 0, TUSB_DESC_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100),
+
+    // Interface number, string index, boot protocol, report descriptor len, EP In address, size & polling interval
+    TUD_HID_DESCRIPTOR(0, 0, false, sizeof(hid_report_descriptor), 0x81, 16, 10),
+};
+
+/********* TinyUSB HID callbacks ***************/
+
+// Invoked when received GET HID REPORT DESCRIPTOR request
+// Application return pointer to descriptor, whose contents must exist long enough for transfer to complete
+uint8_t const *tud_hid_descriptor_report_cb(uint8_t instance)
+{
+    // We use only one interface and one HID report descriptor, so we can ignore parameter 'instance'
+    return hid_report_descriptor;
+}
+
+// Invoked when received GET_REPORT control request
+// Application must fill buffer report's content and return its length.
+// Return zero will cause the stack to STALL request
+uint16_t tud_hid_get_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
+{
+  (void) instance;
+  (void) report_id;
+  (void) report_type;
+  (void) buffer;
+  (void) reqlen;
+
+  return 0;
+}
+
+// Invoked when received SET_REPORT control request or
+// received data on OUT endpoint ( Report ID = 0, Type = 0 )
+void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
+{
+}
+
+/********* Application ***************/
+
+typedef enum {
+    MOUSE_DIR_RIGHT,
+    MOUSE_DIR_DOWN,
+    MOUSE_DIR_LEFT,
+    MOUSE_DIR_UP,
+    MOUSE_DIR_MAX,
+} mouse_dir_t;
+
+#define DISTANCE_MAX        125
+#define DELTA_SCALAR        5
+
+static void mouse_draw_square_next_delta(int8_t *delta_x_ret, int8_t *delta_y_ret)
+{
+    static mouse_dir_t cur_dir = MOUSE_DIR_RIGHT;
+    static uint32_t distance = 0;
+
+    // Calculate next delta
+    if (cur_dir == MOUSE_DIR_RIGHT) {
+        *delta_x_ret = DELTA_SCALAR;
+        *delta_y_ret = 0;
+    } else if (cur_dir == MOUSE_DIR_DOWN) {
+        *delta_x_ret = 0;
+        *delta_y_ret = DELTA_SCALAR;
+    } else if (cur_dir == MOUSE_DIR_LEFT) {
+        *delta_x_ret = -DELTA_SCALAR;
+        *delta_y_ret = 0;
+    } else if (cur_dir == MOUSE_DIR_UP) {
+        *delta_x_ret = 0;
+        *delta_y_ret = -DELTA_SCALAR;
+    }
+
+    // Update cumulative distance for current direction
+    distance += DELTA_SCALAR;
+    // Check if we need to change direction
+    if (distance >= DISTANCE_MAX) {
+        distance = 0;
+        cur_dir++;
+        if (cur_dir == MOUSE_DIR_MAX) {
+            cur_dir = 0;
+        }
+    }
+}
+
+static void app_send_hid_demo(void)
+{
+    // Keyboard output: Send key 'a/A' pressed and released
+    ESP_LOGI(TAG, "Sending Keyboard report");
+    uint8_t keycode[6] = {HID_KEY_A};
+    tud_hid_keyboard_report(HID_ITF_PROTOCOL_KEYBOARD, 0, keycode);
+    vTaskDelay(pdMS_TO_TICKS(50));
+    tud_hid_keyboard_report(HID_ITF_PROTOCOL_KEYBOARD, 0, NULL);
+
+    // Mouse output: Move mouse cursor in square trajectory
+    ESP_LOGI(TAG, "Sending Mouse report");
+    int8_t delta_x;
+    int8_t delta_y;
+    for (int i = 0; i < (DISTANCE_MAX / DELTA_SCALAR) * 4; i++) {
+        // Get the next x and y delta in the draw square pattern
+        mouse_draw_square_next_delta(&delta_x, &delta_y);
+        tud_hid_mouse_report(HID_ITF_PROTOCOL_MOUSE, 0x00, delta_x, delta_y, 0, 0);
+        vTaskDelay(pdMS_TO_TICKS(20));
+    }
+}
+
+void app_main(void)
+{
+    // Initialize button that will trigger HID reports
+    const gpio_config_t boot_button_config = {
+        .pin_bit_mask = BIT64(APP_BUTTON),
+        .mode = GPIO_MODE_INPUT,
+        .intr_type = GPIO_INTR_DISABLE,
+        .pull_up_en = true,
+        .pull_down_en = false,
+    };
+    ESP_ERROR_CHECK(gpio_config(&boot_button_config));
+
+    ESP_LOGI(TAG, "USB initialization");
+    const tinyusb_config_t tusb_cfg = {
+        .device_descriptor = NULL,
+        .string_descriptor = NULL,
+        .external_phy = false,
+        .configuration_descriptor = hid_configuration_descriptor,
+    };
+
+    ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));
+    ESP_LOGI(TAG, "USB initialization DONE");
+
+    while (1) {
+        if (tud_mounted()) {
+            static bool send_hid_data = true;
+            if (send_hid_data) {
+                app_send_hid_demo();
+            }
+            send_hid_data = !gpio_get_level(APP_BUTTON);
+        }
+        vTaskDelay(pdMS_TO_TICKS(100));
+    }
+}

+ 5 - 0
examples/peripherals/usb/device/tusb_hid/sdkconfig.defaults

@@ -0,0 +1,5 @@
+# This file was generated using idf.py save-defconfig. It can be edited manually.
+# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
+#
+CONFIG_TINYUSB=y
+CONFIG_TINYUSB_HID_COUNT=1

+ 2 - 1
examples/peripherals/usb/device/tusb_midi/main/tusb_midi_main.c

@@ -80,7 +80,8 @@ void app_main(void)
     tinyusb_config_t const tusb_cfg = {
         .device_descriptor = NULL, // If device_descriptor is NULL, tinyusb_driver_install() will use Kconfig
         .string_descriptor = NULL,
-        .external_phy = false // In the most cases you need to use a `false` value
+        .external_phy = false,
+        .configuration_descriptor = NULL,
     };
     ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));
 

+ 7 - 5
examples/peripherals/usb/device/tusb_sample_descriptor/main/tusb_sample_descriptor_main.c

@@ -47,18 +47,20 @@ void app_main(void)
         "012-345",            // 3: Serials, should use chip ID
     };
 
-    tinyusb_config_t tusb_cfg = {
+    const tinyusb_config_t tusb_cfg = {
         .descriptor = &my_descriptor,
         .string_descriptor = my_string_descriptor,
-        .external_phy = false // In the most cases you need to use a `false` value
+        .external_phy = false,
+        .configuration_descriptor = NULL,
     };
 
 #else
 
-    tinyusb_config_t tusb_cfg = {
-        .descriptor = NULL,
+    const tinyusb_config_t tusb_cfg = {
+        .device_descriptor = NULL,
         .string_descriptor = NULL,
-        .external_phy = false // In the most cases you need to use a `false` value
+        .external_phy = false,
+        .configuration_descriptor = NULL,
     };
 
 #endif

+ 7 - 1
examples/peripherals/usb/device/tusb_serial_device/main/tusb_serial_device_main.c

@@ -44,7 +44,13 @@ void tinyusb_cdc_line_state_changed_callback(int itf, cdcacm_event_t *event)
 void app_main(void)
 {
     ESP_LOGI(TAG, "USB initialization");
-    const tinyusb_config_t tusb_cfg = {}; // the configuration using default values
+    const tinyusb_config_t tusb_cfg = {
+        .device_descriptor = NULL,
+        .string_descriptor = NULL,
+        .external_phy = false,
+        .configuration_descriptor = NULL,
+    };
+
     ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg));
 
     tinyusb_config_cdcacm_t acm_cfg = {