合并TinyUSB仓库
This commit is contained in:
		| @@ -0,0 +1,239 @@ | ||||
| /* | ||||
|  * 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 <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "bsp/board_api.h" | ||||
| #include "tusb.h" | ||||
|  | ||||
| /* This MIDI example send sequence of note (on/off) repeatedly. To test on PC, you need to install | ||||
|  * synth software and midi connection management software. On | ||||
|  * - Linux (Ubuntu): install qsynth, qjackctl. Then connect TinyUSB output port to FLUID Synth input port | ||||
|  * - Windows: install MIDI-OX | ||||
|  * - MacOS: SimpleSynth | ||||
|  */ | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // MACRO CONSTANT TYPEDEF PROTYPES | ||||
| //--------------------------------------------------------------------+ | ||||
| #ifdef ESP_PLATFORM | ||||
|   #define USBD_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) | ||||
| #endif | ||||
|  | ||||
| #define BLINKY_STACK_SIZE   configMINIMAL_STACK_SIZE | ||||
| #define MIDI_STACK_SIZE     configMINIMAL_STACK_SIZE | ||||
|  | ||||
| // static task | ||||
| #if configSUPPORT_STATIC_ALLOCATION | ||||
| StackType_t blinky_stack[BLINKY_STACK_SIZE]; | ||||
| StaticTask_t blinky_taskdef; | ||||
|  | ||||
| StackType_t  usb_device_stack[USBD_STACK_SIZE]; | ||||
| StaticTask_t usb_device_taskdef; | ||||
|  | ||||
| StackType_t  midi_stack[MIDI_STACK_SIZE]; | ||||
| StaticTask_t midi_taskdef; | ||||
| #endif | ||||
|  | ||||
| /* Blink pattern | ||||
|  * - 250 ms  : device not mounted | ||||
|  * - 1000 ms : device mounted | ||||
|  * - 2500 ms : device is suspended | ||||
|  */ | ||||
| enum  { | ||||
|   BLINK_NOT_MOUNTED = 250, | ||||
|   BLINK_MOUNTED = 1000, | ||||
|   BLINK_SUSPENDED = 2500, | ||||
| }; | ||||
|  | ||||
| static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; | ||||
|  | ||||
| void usb_device_task(void *param); | ||||
| void led_blinking_task(void* param); | ||||
| void midi_task(void* param); | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // Main | ||||
| //--------------------------------------------------------------------+ | ||||
| int main(void) { | ||||
|   board_init(); | ||||
|  | ||||
| #if configSUPPORT_STATIC_ALLOCATION | ||||
|   xTaskCreateStatic(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, blinky_stack, &blinky_taskdef); | ||||
|   xTaskCreateStatic(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES-1, usb_device_stack, &usb_device_taskdef); | ||||
|   xTaskCreateStatic(midi_task, "midi", MIDI_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, midi_stack, &midi_taskdef); | ||||
| #else | ||||
|   xTaskCreate(led_blinking_task, "blinky", BLINKY_STACK_SIZE, NULL, 1, NULL); | ||||
|   xTaskCreate(usb_device_task, "usbd", USBD_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, NULL); | ||||
|   xTaskCreate(midi_task, "midi", MIDI_STACK_SIZE, NULL, configMAX_PRIORITIES - 2, NULL); | ||||
| #endif | ||||
|  | ||||
| #ifndef ESP_PLATFORM | ||||
|   // only start scheduler for non-espressif mcu | ||||
|   vTaskStartScheduler(); | ||||
| #endif | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| #ifdef ESP_PLATFORM | ||||
| void app_main(void) { | ||||
|   main(); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| // USB Device Driver task | ||||
| // This top level thread process all usb events and invoke callbacks | ||||
| void usb_device_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_TUD_RHPORT, &dev_init); | ||||
|  | ||||
|   if (board_init_after_tusb) { | ||||
|     board_init_after_tusb(); | ||||
|   } | ||||
|  | ||||
|   // RTOS forever loop | ||||
|   while (1) { | ||||
|     // put this thread to waiting state until there is new events | ||||
|     tud_task(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // Device callbacks | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| // Invoked when device is mounted | ||||
| void tud_mount_cb(void) { | ||||
|   blink_interval_ms = BLINK_MOUNTED; | ||||
| } | ||||
|  | ||||
| // Invoked when device is unmounted | ||||
| void tud_umount_cb(void) { | ||||
|   blink_interval_ms = BLINK_NOT_MOUNTED; | ||||
| } | ||||
|  | ||||
| // Invoked when usb bus is suspended | ||||
| // remote_wakeup_en : if host allow us  to perform remote wakeup | ||||
| // Within 7ms, device must draw an average of current less than 2.5 mA from bus | ||||
| void tud_suspend_cb(bool remote_wakeup_en) { | ||||
|   (void) remote_wakeup_en; | ||||
|   blink_interval_ms = BLINK_SUSPENDED; | ||||
| } | ||||
|  | ||||
| // Invoked when usb bus is resumed | ||||
| void tud_resume_cb(void) { | ||||
|   blink_interval_ms = tud_mounted() ? BLINK_MOUNTED : BLINK_NOT_MOUNTED; | ||||
| } | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // MIDI Task | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| // Store example melody as an array of note values | ||||
| const uint8_t note_sequence[] = { | ||||
|   74,78,81,86,90,93,98,102,57,61,66,69,73,78,81,85,88,92,97,100,97,92,88,85,81,78, | ||||
|   74,69,66,62,57,62,66,69,74,78,81,86,90,93,97,102,97,93,90,85,81,78,73,68,64,61, | ||||
|   56,61,64,68,74,78,81,86,90,93,98,102 | ||||
| }; | ||||
|  | ||||
| void midi_task(void* param) { | ||||
|   (void) param; | ||||
|  | ||||
|   const uint8_t cable_num = 0; // MIDI jack associated with USB endpoint | ||||
|   const uint8_t channel   = 0; // 0 for channel 1 | ||||
|  | ||||
|   // Variable that holds the current position in the sequence. | ||||
|   uint32_t note_pos = 0; | ||||
|  | ||||
|   while (1) { | ||||
|     // send note periodically | ||||
|     vTaskDelay(286  / portTICK_PERIOD_MS); | ||||
|  | ||||
|     // Previous positions in the note sequence. | ||||
|     int previous = (int) (note_pos - 1); | ||||
|  | ||||
|     // If we currently are at position 0, set the | ||||
|     // previous position to the last note in the sequence. | ||||
|     if (previous < 0) { | ||||
|       previous = sizeof(note_sequence) - 1; | ||||
|     } | ||||
|  | ||||
|     // Send Note On for current position at full velocity (127) on channel 1. | ||||
|     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); | ||||
|  | ||||
|     // Increment position | ||||
|     note_pos++; | ||||
|  | ||||
|     // If we are at the end of the sequence, start over. | ||||
|     if (note_pos >= sizeof(note_sequence)) { | ||||
|       note_pos = 0; | ||||
|     } | ||||
|  | ||||
|     // The MIDI interface always creates input and output port/jack descriptors | ||||
|     // regardless of these being used or not. Therefore incoming traffic should be read | ||||
|     // (possibly just discarded) to avoid the sender blocking in IO | ||||
|     while (tud_midi_available()) { | ||||
|       uint8_t packet[4]; | ||||
|       tud_midi_packet_read(packet); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // BLINKING TASK | ||||
| //--------------------------------------------------------------------+ | ||||
| void led_blinking_task(void* param) { | ||||
|   (void) param; | ||||
|   static uint32_t start_ms = 0; | ||||
|   static bool led_state = false; | ||||
|  | ||||
|   while (1) { | ||||
|     // Blink every interval ms | ||||
|     vTaskDelay(blink_interval_ms / portTICK_PERIOD_MS); | ||||
|     start_ms += blink_interval_ms; | ||||
|  | ||||
|     board_led_write(led_state); | ||||
|     led_state = 1 - led_state; // toggle | ||||
|   } | ||||
| } | ||||
| @@ -0,0 +1,108 @@ | ||||
| /* | ||||
|  * 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 for device can be defined by board.mk, default to port 0 | ||||
| #ifndef BOARD_TUD_RHPORT | ||||
| #define BOARD_TUD_RHPORT      0 | ||||
| #endif | ||||
|  | ||||
| // RHPort max operational speed can defined by board.mk | ||||
| #ifndef BOARD_TUD_MAX_SPEED | ||||
| #define BOARD_TUD_MAX_SPEED   OPT_MODE_DEFAULT_SPEED | ||||
| #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_FREERTOS | ||||
| #endif | ||||
|  | ||||
| #ifndef CFG_TUSB_DEBUG | ||||
| #define CFG_TUSB_DEBUG        0 | ||||
| #endif | ||||
|  | ||||
| // Enable Device stack | ||||
| #define CFG_TUD_ENABLED       1 | ||||
|  | ||||
| // Default is max speed that hardware controller could support with on-chip PHY | ||||
| #define CFG_TUD_MAX_SPEED     BOARD_TUD_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_TUSB_MEM_SECTION | ||||
| #define CFG_TUSB_MEM_SECTION | ||||
| #endif | ||||
|  | ||||
| #ifndef CFG_TUSB_MEM_ALIGN | ||||
| #define CFG_TUSB_MEM_ALIGN        __attribute__ ((aligned(4))) | ||||
| #endif | ||||
|  | ||||
| //-------------------------------------------------------------------- | ||||
| // DEVICE CONFIGURATION | ||||
| //-------------------------------------------------------------------- | ||||
|  | ||||
| #ifndef CFG_TUD_ENDPOINT0_SIZE | ||||
| #define CFG_TUD_ENDPOINT0_SIZE    64 | ||||
| #endif | ||||
|  | ||||
| //------------- CLASS -------------// | ||||
| #define CFG_TUD_CDC               0 | ||||
| #define CFG_TUD_MSC               0 | ||||
| #define CFG_TUD_HID               0 | ||||
| #define CFG_TUD_MIDI              1 | ||||
| #define CFG_TUD_VENDOR            0 | ||||
|  | ||||
| // MIDI FIFO size of TX and RX | ||||
| #define CFG_TUD_MIDI_RX_BUFSIZE   (TUD_OPT_HIGH_SPEED ? 512 : 64) | ||||
| #define CFG_TUD_MIDI_TX_BUFSIZE   (TUD_OPT_HIGH_SPEED ? 512 : 64) | ||||
|  | ||||
| #ifdef __cplusplus | ||||
|  } | ||||
| #endif | ||||
|  | ||||
| #endif /* _TUSB_CONFIG_H_ */ | ||||
| @@ -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]         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) ) | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // Device Descriptors | ||||
| //--------------------------------------------------------------------+ | ||||
| tusb_desc_device_t const desc_device = { | ||||
|     .bLength            = sizeof(tusb_desc_device_t), | ||||
|     .bDescriptorType    = TUSB_DESC_DEVICE, | ||||
|     .bcdUSB             = 0x0200, | ||||
|     .bDeviceClass       = 0x00, | ||||
|     .bDeviceSubClass    = 0x00, | ||||
|     .bDeviceProtocol    = 0x00, | ||||
|     .bMaxPacketSize0    = CFG_TUD_ENDPOINT0_SIZE, | ||||
|  | ||||
|     .idVendor           = 0xCafe, | ||||
|     .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_MIDI = 0, | ||||
|   ITF_NUM_MIDI_STREAMING, | ||||
|   ITF_NUM_TOTAL | ||||
| }; | ||||
|  | ||||
| #define CONFIG_TOTAL_LEN  (TUD_CONFIG_DESC_LEN + TUD_MIDI_DESC_LEN) | ||||
|  | ||||
| #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 etc ... | ||||
|   #define EPNUM_MIDI_OUT  0x02 | ||||
|   #define EPNUM_MIDI_IN   0x82 | ||||
|  | ||||
| #elif CFG_TUSB_MCU == OPT_MCU_CXD56 | ||||
|   // CXD56 USB driver has fixed endpoint type (bulk/interrupt/iso) and direction (IN/OUT) by its number | ||||
|   // 0 control (IN/OUT), 1 Bulk (IN), 2 Bulk (OUT), 3 In (IN), 4 Bulk (IN), 5 Bulk (OUT), 6 In (IN) | ||||
|   #define EPNUM_MIDI_OUT  0x02 | ||||
|   #define EPNUM_MIDI_IN   0x81 | ||||
|  | ||||
| #elif defined(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_MIDI_OUT  0x01 | ||||
|   #define EPNUM_MIDI_IN   0x82 | ||||
|  | ||||
| #else | ||||
|   #define EPNUM_MIDI_OUT  0x01 | ||||
|   #define EPNUM_MIDI_IN   0x81 | ||||
| #endif | ||||
|  | ||||
| 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), | ||||
|  | ||||
|   // Interface number, string index, EP Out & EP In address, EP size | ||||
|   TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI_OUT, (0x80 | EPNUM_MIDI_IN), 64) | ||||
| }; | ||||
|  | ||||
| #if TUD_OPT_HIGH_SPEED | ||||
| 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), | ||||
|  | ||||
|   // Interface number, string index, EP Out & EP In address, EP size | ||||
|   TUD_MIDI_DESCRIPTOR(ITF_NUM_MIDI, 0, EPNUM_MIDI_OUT, (0x80 | EPNUM_MIDI_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 | ||||
| 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 | ||||
| }; | ||||
|  | ||||
| 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); | ||||
|       const size_t 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; | ||||
| } | ||||
		Reference in New Issue
	
	Block a user