From 169d746c49e2e33c5f0f1fa6530133bd639c0f72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adam=20M=C3=BAdry?= Date: Thu, 4 Aug 2022 16:18:53 +0200 Subject: [PATCH] usb: Refactor USB MIDI example --- components/tinyusb/Kconfig | 27 ++----- .../tinyusb/additions/include/tinyusb_types.h | 2 +- .../tinyusb/additions/include/tusb_config.h | 14 ++-- .../additions/src/descriptors_control.c | 6 ++ components/tinyusb/additions/src/tinyusb.c | 30 ++++++-- .../tinyusb/additions/src/usb_descriptors.c | 29 +------- .../tusb_hid/main/tusb_hid_example_main.c | 16 ++++- .../device/tusb_midi/main/tusb_midi_main.c | 70 +++++++++++++++++-- .../usb/device/tusb_midi/sdkconfig.defaults | 2 +- 9 files changed, 125 insertions(+), 71 deletions(-) diff --git a/components/tinyusb/Kconfig b/components/tinyusb/Kconfig index 891d5831cc37..c4adf0bbefd7 100644 --- a/components/tinyusb/Kconfig +++ b/components/tinyusb/Kconfig @@ -105,20 +105,6 @@ menu "TinyUSB Stack" default "Espressif MSC Device" help Name of the MSC device. - - config TINYUSB_DESC_HID_STRING - depends on TINYUSB_HID_COUNT > 0 - string "HID Device String" - default "Espressif HID Device" - help - Name of the HID device - - config TINYUSB_DESC_MIDI_STRING - depends on TINYUSB_MIDI_ENABLED - string "MIDI Device String" - default "Espressif MIDI Device" - help - Name of the MIDI device endmenu # "Descriptor configuration" menu "Massive Storage Class (MSC)" @@ -168,13 +154,14 @@ menu "TinyUSB Stack" CDC FIFO size of TX channel. endmenu # "Communication Device Class" - menu "MIDI" - config TINYUSB_MIDI_ENABLED - bool "Enable TinyUSB MIDI feature" - default n + menu "Musical Instrument Digital Interface (MIDI)" + config TINYUSB_MIDI_COUNT + int "TinyUSB MIDI interfaces count" + default 0 + range 0 2 help - Enable TinyUSB MIDI feature. - endmenu # "MIDI" + Setting value greater than 0 will enable TinyUSB MIDI feature. + endmenu # "Musical Instrument Digital Interface (MIDI)" menu "Human Interface Device Class (HID)" config TINYUSB_HID_COUNT diff --git a/components/tinyusb/additions/include/tinyusb_types.h b/components/tinyusb/additions/include/tinyusb_types.h index 2c59f114a63f..1f01fe132e65 100644 --- a/components/tinyusb/additions/include/tinyusb_types.h +++ b/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 7 +#define USB_STRING_DESCRIPTOR_ARRAY_SIZE 8 // (4 + TINYUSB_STR_DESC_LEN) typedef enum{ TINYUSB_USBDEV_0, diff --git a/components/tinyusb/additions/include/tusb_config.h b/components/tinyusb/additions/include/tusb_config.h index 36dbc5b4fbfd..da2a5f9e7b78 100644 --- a/components/tinyusb/additions/include/tusb_config.h +++ b/components/tinyusb/additions/include/tusb_config.h @@ -37,6 +37,10 @@ extern "C" { # define CONFIG_TINYUSB_CDC_ENABLED 0 #endif +#ifndef CONFIG_TINYUSB_CDC_COUNT +# define CONFIG_TINYUSB_CDC_COUNT 0 +#endif + #ifndef CONFIG_TINYUSB_MSC_ENABLED # define CONFIG_TINYUSB_MSC_ENABLED 0 #endif @@ -45,8 +49,8 @@ extern "C" { # define CONFIG_TINYUSB_HID_COUNT 0 #endif -#ifndef CONFIG_TINYUSB_MIDI_ENABLED -# define CONFIG_TINYUSB_MIDI_ENABLED 0 +#ifndef CONFIG_TINYUSB_MIDI_COUNT +# define CONFIG_TINYUSB_MIDI_COUNT 0 #endif #ifndef CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED @@ -88,14 +92,10 @@ extern "C" { #define CFG_TUD_MIDI_TX_BUFSIZE 64 // Enabled device class driver -#if defined(CONFIG_TINYUSB_CDC_COUNT) #define CFG_TUD_CDC CONFIG_TINYUSB_CDC_COUNT -#else -#define CFG_TUD_CDC 0 -#endif #define CFG_TUD_MSC CONFIG_TINYUSB_MSC_ENABLED #define CFG_TUD_HID CONFIG_TINYUSB_HID_COUNT -#define CFG_TUD_MIDI CONFIG_TINYUSB_MIDI_ENABLED +#define CFG_TUD_MIDI CONFIG_TINYUSB_MIDI_COUNT #define CFG_TUD_CUSTOM_CLASS CONFIG_TINYUSB_CUSTOM_CLASS_ENABLED #ifdef __cplusplus diff --git a/components/tinyusb/additions/src/descriptors_control.c b/components/tinyusb/additions/src/descriptors_control.c index 3857e2ebcb68..7e9ed4cbeaa0 100644 --- a/components/tinyusb/additions/src/descriptors_control.c +++ b/components/tinyusb/additions/src/descriptors_control.c @@ -59,6 +59,12 @@ uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid) // Convert ASCII string into UTF-16 if ( index >= sizeof(s_str_descriptor) / sizeof(s_str_descriptor[0]) ) { + ESP_LOGE(TAG, "String index (%u) is out of bounds, check your string descriptor", index); + return NULL; + } + + if (s_str_descriptor[index] == NULL) { + ESP_LOGE(TAG, "String index (%u) points to NULL, check your string descriptor", index); return NULL; } diff --git a/components/tinyusb/additions/src/tinyusb.c b/components/tinyusb/additions/src/tinyusb.c index 3045ec0aef98..069001fc0f59 100644 --- a/components/tinyusb/additions/src/tinyusb.c +++ b/components/tinyusb/additions/src/tinyusb.c @@ -48,13 +48,31 @@ 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"); + if (config->configuration_descriptor) { + cfg_descriptor = config->configuration_descriptor; + } else { +#if (CONFIG_TINYUSB_HID_COUNT > 0 || CONFIG_TINYUSB_MIDI_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 this device"); +#else + cfg_descriptor = descriptor_cfg_kconfig; + ESP_LOGW(TAG, "The device's configuration descriptor is not provided by user, using default."); #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; + } + + if (config->string_descriptor) { + string_descriptor = config->string_descriptor; + } else { + string_descriptor = descriptor_str_kconfig; + ESP_LOGW(TAG, "The device's string descriptor is not provided by user, using default."); + } + + if (config->device_descriptor) { + dev_descriptor = config->device_descriptor; + } else { + dev_descriptor = &descriptor_dev_kconfig; + ESP_LOGW(TAG, "The device's device descriptor is not provided by user, using default."); + } tusb_set_descriptor(dev_descriptor, string_descriptor, cfg_descriptor); diff --git a/components/tinyusb/additions/src/usb_descriptors.c b/components/tinyusb/additions/src/usb_descriptors.c index ccb99089111c..18da01883aac 100644 --- a/components/tinyusb/additions/src/usb_descriptors.c +++ b/components/tinyusb/additions/src/usb_descriptors.c @@ -54,9 +54,6 @@ tusb_desc_strarray_device_t descriptor_str_tinyusb = { "TinyUSB", // 1: Manufacturer "TinyUSB Device", // 2: Product "123456", // 3: Serials, should use chip ID - "TinyUSB CDC", // 4: CDC Interface - "TinyUSB MSC", // 5: MSC Interface - "TinyUSB MIDI" // 6: MIDI }; /* End of TinyUSB default */ @@ -108,7 +105,7 @@ tusb_desc_strarray_device_t descriptor_str_kconfig = { CONFIG_TINYUSB_DESC_PRODUCT_STRING, // 2: Product CONFIG_TINYUSB_DESC_SERIAL_STRING, // 3: Serials, should use chip ID -#if CONFIG_TINYUSB_CDC_ENABLED + #if CONFIG_TINYUSB_CDC_ENABLED CONFIG_TINYUSB_DESC_CDC_STRING, // 4: CDC Interface #else "", @@ -120,12 +117,6 @@ tusb_desc_strarray_device_t descriptor_str_kconfig = { "", #endif -#if CONFIG_TINYUSB_MIDI_ENABLED - CONFIG_TINYUSB_DESC_MIDI_STRING // 6: MIDI -#else - "", -#endif - }; //------------- Configuration Descriptor -------------// @@ -143,20 +134,13 @@ enum { #if CFG_TUD_MSC ITF_NUM_MSC, #endif - -#if CFG_TUD_MIDI - ITF_NUM_MIDI, - ITF_NUM_MIDI_STREAMING, -#endif - ITF_NUM_TOTAL }; 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_MIDI * TUD_MIDI_DESC_LEN + CFG_TUD_MSC * TUD_MSC_DESC_LEN }; //------------- USB Endpoint numbers -------------// @@ -176,10 +160,6 @@ enum { #if CFG_TUD_MSC EPNUM_MSC, #endif - -#if CFG_TUD_MIDI - EPNUM_MIDI, -#endif }; uint8_t const descriptor_cfg_kconfig[] = { @@ -200,11 +180,6 @@ uint8_t const descriptor_cfg_kconfig[] = { // Interface number, string index, EP Out & EP In address, EP size TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC, 0x80 | EPNUM_MSC, 64), // highspeed 512 #endif - -#if CFG_TUD_MIDI - // Interface number, string index, EP Out & EP In address, EP size - TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 6, EPNUM_MIDI, 0x80 | EPNUM_MIDI, 64) // highspeed 512 -#endif }; /* End of Kconfig driven Descriptor */ diff --git a/examples/peripherals/usb/device/tusb_hid/main/tusb_hid_example_main.c b/examples/peripherals/usb/device/tusb_hid/main/tusb_hid_example_main.c index 5cbb11b555a6..617602e87490 100644 --- a/examples/peripherals/usb/device/tusb_hid/main/tusb_hid_example_main.c +++ b/examples/peripherals/usb/device/tusb_hid/main/tusb_hid_example_main.c @@ -30,6 +30,18 @@ const uint8_t hid_report_descriptor[] = { TUD_HID_REPORT_DESC_MOUSE(HID_REPORT_ID(HID_ITF_PROTOCOL_MOUSE) ) }; +/** + * @brief String descriptor + */ +const char* hid_string_descriptor[5] = { + // array of pointer to string descriptors + (char[]){0x09, 0x04}, // 0: is supported language is English (0x0409) + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + "123456", // 3: Serials, should use chip ID + "Example HID interface", // 4: HID +}; + /** * @brief Configuration descriptor * @@ -40,7 +52,7 @@ static const uint8_t hid_configuration_descriptor[] = { 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), + TUD_HID_DESCRIPTOR(0, 4, false, sizeof(hid_report_descriptor), 0x81, 16, 10), }; /********* TinyUSB HID callbacks ***************/ @@ -154,7 +166,7 @@ void app_main(void) ESP_LOGI(TAG, "USB initialization"); const tinyusb_config_t tusb_cfg = { .device_descriptor = NULL, - .string_descriptor = NULL, + .string_descriptor = hid_string_descriptor, .external_phy = false, .configuration_descriptor = hid_configuration_descriptor, }; diff --git a/examples/peripherals/usb/device/tusb_midi/main/tusb_midi_main.c b/examples/peripherals/usb/device/tusb_midi/main/tusb_midi_main.c index c6dccf8392d3..4f67323792f1 100644 --- a/examples/peripherals/usb/device/tusb_midi/main/tusb_midi_main.c +++ b/examples/peripherals/usb/device/tusb_midi/main/tusb_midi_main.c @@ -15,6 +15,55 @@ static const char *TAG = "example"; +/** Helper defines **/ + +// Interface counter +enum interface_count { +#if CFG_TUD_MIDI + ITF_NUM_MIDI = 0, + ITF_NUM_MIDI_STREAMING, +#endif + ITF_COUNT +}; + +// USB Endpoint numbers +enum usb_endpoints { + // Available USB Endpoints: 5 IN/OUT EPs and 1 IN EP + EP_EMPTY = 0, +#if CFG_TUD_MIDI + EPNUM_MIDI, +#endif +}; + +/** TinyUSB descriptors **/ + +#define TUSB_DESCRIPTOR_TOTAL_LEN (TUD_CONFIG_DESC_LEN + CFG_TUD_MIDI * TUD_MIDI_DESC_LEN) + +/** + * @brief String descriptor + */ +static const char* s_str_desc[5] = { + // array of pointer to string descriptors + (char[]){0x09, 0x04}, // 0: is supported language is English (0x0409) + "TinyUSB", // 1: Manufacturer + "TinyUSB Device", // 2: Product + "123456", // 3: Serials, should use chip ID + "Example MIDI device", // 4: MIDI +}; + +/** + * @brief Configuration descriptor + * + * This is a simple configuration descriptor that defines 1 configuration and a MIDI interface + */ +static const uint8_t s_midi_cfg_desc[] = { + // Configuration number, interface count, string index, total length, attribute, power in mA + TUD_CONFIG_DESCRIPTOR(1, ITF_COUNT, 0, TUSB_DESCRIPTOR_TOTAL_LEN, 0, 100), + + // Interface number, string index, EP Out & EP In address, EP size + TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 4, EPNUM_MIDI, (0x80 | EPNUM_MIDI), 64), +}; + static void midi_task_read_example(void *arg) { // The MIDI interface always creates input and output port/jack descriptors @@ -34,6 +83,10 @@ static void midi_task_read_example(void *arg) } } +// Basic MIDI Messages +#define NOTE_OFF 0x80 +#define NOTE_ON 0x90 + static void periodic_midi_write_example_cb(void *arg) { // Example melody stored as an array of note values @@ -58,12 +111,15 @@ static void periodic_midi_write_example_cb(void *arg) // Send Note On for current position at full velocity (127) on channel 1. ESP_LOGI(TAG, "Writing MIDI data %d", note_sequence[note_pos]); - uint8_t note_on[3] = {0x90 | channel, note_sequence[note_pos], 127}; - tud_midi_stream_write(cable_num, note_on, 3); - // Send Note Off for previous note. - uint8_t note_off[3] = {0x80 | channel, note_sequence[previous], 0}; - tud_midi_stream_write(cable_num, note_off, 3); + if (tud_midi_mounted()) { + uint8_t note_on[3] = {NOTE_ON | channel, note_sequence[note_pos], 127}; + tud_midi_stream_write(cable_num, note_on, 3); + + // Send Note Off for previous note. + uint8_t note_off[3] = {NOTE_OFF | channel, note_sequence[previous], 0}; + tud_midi_stream_write(cable_num, note_off, 3); + } // Increment position note_pos++; @@ -80,9 +136,9 @@ 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, + .string_descriptor = s_str_desc, .external_phy = false, - .configuration_descriptor = NULL, + .configuration_descriptor = s_midi_cfg_desc, }; ESP_ERROR_CHECK(tinyusb_driver_install(&tusb_cfg)); diff --git a/examples/peripherals/usb/device/tusb_midi/sdkconfig.defaults b/examples/peripherals/usb/device/tusb_midi/sdkconfig.defaults index 09a9f567e4d0..ae6cac9acab3 100644 --- a/examples/peripherals/usb/device/tusb_midi/sdkconfig.defaults +++ b/examples/peripherals/usb/device/tusb_midi/sdkconfig.defaults @@ -1,2 +1,2 @@ CONFIG_TINYUSB=y -CONFIG_TINYUSB_MIDI_ENABLED=y +CONFIG_TINYUSB_MIDI_COUNT=1