move fuzz into test/fuzz
This commit is contained in:
		
							
								
								
									
										174
									
								
								test/fuzz/device/cdc/src/fuzz.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								test/fuzz/device/cdc/src/fuzz.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,174 @@ | ||||
| /* | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2022 Nathaniel Brough | ||||
|  * | ||||
|  * 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 <cassert> | ||||
| #include <fuzzer/FuzzedDataProvider.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
|  | ||||
| #include "class/cdc/cdc_device.h" | ||||
| #include "fuzz/fuzz.h" | ||||
| #include "tusb.h" | ||||
| #include <cstdint> | ||||
| #include <string> | ||||
| #include <vector> | ||||
|  | ||||
| extern "C" { | ||||
|  | ||||
| #define FUZZ_ITERATIONS 500 | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // MACRO CONSTANT TYPEDEF PROTYPES | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| void cdc_task(FuzzedDataProvider *provider); | ||||
|  | ||||
| extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { | ||||
|   FuzzedDataProvider provider(Data, Size); | ||||
|   std::vector<uint8_t> callback_data = provider.ConsumeBytes<uint8_t>( | ||||
|       provider.ConsumeIntegralInRange<size_t>(0, Size)); | ||||
|   fuzz_init(callback_data.data(), callback_data.size()); | ||||
|   // init device stack on configured roothub port | ||||
|   tud_init(BOARD_TUD_RHPORT); | ||||
|  | ||||
|   for (int i = 0; i < FUZZ_ITERATIONS; i++) { | ||||
|     if (provider.remaining_bytes() == 0) { | ||||
|       return 0; | ||||
|     } | ||||
|     tud_int_handler(provider.ConsumeIntegral<uint8_t>()); | ||||
|     tud_task(); // tinyusb device task | ||||
|     cdc_task(&provider); | ||||
|   } | ||||
|  | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // USB CDC | ||||
| //--------------------------------------------------------------------+ | ||||
| enum CdcApiFuncs { | ||||
|   kCdcNConnected, | ||||
|   kCdcNGetLineState, | ||||
|   kCdcNGetLineCoding, | ||||
|   kCdcNSetWantedChar, | ||||
|   kCdcNAvailable, | ||||
|   kCdcNRead, | ||||
|   kCdcNReadChar, | ||||
|   kCdcNReadFlush, | ||||
|   kCdcNPeek, | ||||
|   kCdcNWrite, | ||||
|   kCdcNWriteChar, | ||||
|   kCdcNWriteStr, | ||||
|   kCdcNWriteFlush, | ||||
|   kCdcNWriteAvailable, | ||||
|   kCdcNWriteClear, | ||||
|   // We don't need to fuzz tud_cdc_<not n>* as they are just wrappers | ||||
|   // calling with n==0. | ||||
|   kMaxValue, | ||||
| }; | ||||
|  | ||||
| void cdc_task(FuzzedDataProvider *provider) { | ||||
|  | ||||
|   assert(provider != NULL); | ||||
|   const int kMaxBufferSize = 4096; | ||||
|   switch (provider->ConsumeEnum<CdcApiFuncs>()) { | ||||
|   case kCdcNConnected: | ||||
|     // TODO: Fuzz interface number | ||||
|     (void)tud_cdc_n_connected(0); | ||||
|     break; | ||||
|   case kCdcNGetLineState: | ||||
|     // TODO: Fuzz interface number | ||||
|     (void)tud_cdc_n_get_line_state(0); | ||||
|     break; | ||||
|   case kCdcNGetLineCoding: { | ||||
|     cdc_line_coding_t coding; | ||||
|     // TODO: Fuzz interface number | ||||
|     (void)tud_cdc_n_get_line_coding(0, &coding); | ||||
|   } break; | ||||
|   case kCdcNSetWantedChar: | ||||
|     // TODO: Fuzz interface number | ||||
|     (void)tud_cdc_n_set_wanted_char(0, provider->ConsumeIntegral<char>()); | ||||
|     break; | ||||
|   case kCdcNAvailable: | ||||
|     // TODO: Fuzz interface number | ||||
|     (void)tud_cdc_n_available(0); | ||||
|     break; | ||||
|   case kCdcNRead: { | ||||
|     std::vector<uint8_t> buffer; | ||||
|     buffer.resize(provider->ConsumeIntegralInRange<size_t>(0, kMaxBufferSize)); | ||||
|     // TODO: Fuzz interface number | ||||
|     (void)tud_cdc_n_read(0, buffer.data(), buffer.size()); | ||||
|     break; | ||||
|   } | ||||
|   case kCdcNReadChar: | ||||
|     // TODO: Fuzz interface number | ||||
|     tud_cdc_n_read_char(0); | ||||
|     break; | ||||
|   case kCdcNReadFlush: | ||||
|     // TODO: Fuzz interface number | ||||
|     tud_cdc_n_read_flush(0); | ||||
|     break; | ||||
|   case kCdcNPeek: { | ||||
|     uint8_t peak = 0; | ||||
|     tud_cdc_n_peek(0, &peak); | ||||
|     break; | ||||
|   } | ||||
|   case kCdcNWrite: { | ||||
|     std::vector<uint8_t> buffer = provider->ConsumeBytes<uint8_t>( | ||||
|         provider->ConsumeIntegralInRange<size_t>(0, kMaxBufferSize)); | ||||
|  | ||||
|     // TODO: Fuzz interface number | ||||
|     (void)tud_cdc_n_write(0, buffer.data(), buffer.size()); | ||||
|   } break; | ||||
|    | ||||
| case kCdcNWriteChar: | ||||
|   // TODO: Fuzz interface number | ||||
|   (void)tud_cdc_n_write_char(0, provider->ConsumeIntegral<char>()); | ||||
|   break; | ||||
| case kCdcNWriteStr: { | ||||
|   std::string str = provider->ConsumeRandomLengthString(kMaxBufferSize); | ||||
|   // TODO: Fuzz interface number | ||||
|   (void)tud_cdc_n_write_str(0, str.c_str()); | ||||
|   break; | ||||
| } | ||||
| case kCdcNWriteFlush: | ||||
|   // TODO: Fuzz interface number | ||||
|   (void)tud_cdc_n_write_flush(0); | ||||
|   break; | ||||
| case kCdcNWriteAvailable: | ||||
|   // TODO: Fuzz interface number | ||||
|   (void)tud_cdc_n_write_available(0); | ||||
|   break; | ||||
| case kCdcNWriteClear: | ||||
|   // TODO: Fuzz interface number | ||||
|   (void)tud_cdc_n_write_clear(0); | ||||
|   break; | ||||
| case kMaxValue: | ||||
|   // Noop. | ||||
|   break; | ||||
| } | ||||
| } | ||||
| } | ||||
							
								
								
									
										114
									
								
								test/fuzz/device/cdc/src/tusb_config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										114
									
								
								test/fuzz/device/cdc/src/tusb_config.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,114 @@ | ||||
| /* | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2022 Nathaniel Brough | ||||
|  * | ||||
|  * 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_NONE | ||||
| #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              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, more is faster | ||||
| #define CFG_TUD_CDC_EP_BUFSIZE   (TUD_OPT_HIGH_SPEED ? 512 : 64) | ||||
|  | ||||
| // MSC Buffer size of Device Mass storage | ||||
| #define CFG_TUD_MSC_EP_BUFSIZE   512 | ||||
|  | ||||
| #ifdef __cplusplus | ||||
|  } | ||||
| #endif | ||||
|  | ||||
| #endif /* _TUSB_CONFIG_H_ */ | ||||
							
								
								
									
										229
									
								
								test/fuzz/device/cdc/src/usb_descriptors.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										229
									
								
								test/fuzz/device/cdc/src/usb_descriptors.cc
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,229 @@ | ||||
| /* | ||||
|  * The MIT License (MIT) | ||||
|  * | ||||
|  * Copyright (c) 2022 Nathaniel Brough | ||||
|  * | ||||
|  * 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 "tusb.h" | ||||
|  | ||||
| /* A combination of interfaces must have a unique product id, since PC will save | ||||
|  * device driver after the first plug. | ||||
|  * Auto ProductID layout's Bitmap: | ||||
|  *   [MSB]         HID | CDC          [LSB] | ||||
|  */ | ||||
| #define _PID_MAP(itf, n) ((CFG_TUD_##itf) << (n)) | ||||
| #define USB_PID                                                                \ | ||||
|   (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(HID, 2) | _PID_MAP(MIDI, 3) |          \ | ||||
|    _PID_MAP(VENDOR, 4)) | ||||
|  | ||||
| #define USB_VID 0xCafe | ||||
| #define USB_BCD 0x0200 | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // Device Descriptors | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| // Invoked when received GET DEVICE DESCRIPTOR | ||||
| // Application return pointer to descriptor | ||||
| uint8_t const *tud_descriptor_device_cb(void) { | ||||
|   static tusb_desc_device_t const desc_device = { | ||||
|       .bLength = sizeof(tusb_desc_device_t), | ||||
|       .bDescriptorType = TUSB_DESC_DEVICE, | ||||
|       .bcdUSB = USB_BCD, | ||||
|  | ||||
|       // Use Interface Association Descriptor (IAD) for CDC | ||||
|       // As required by USB Specs IAD's subclass must be common class (2) and | ||||
|       // protocol must be IAD (1) | ||||
|       .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}; | ||||
|  | ||||
|   return (uint8_t const *)&desc_device; | ||||
| } | ||||
|  | ||||
| //--------------------------------------------------------------------+ | ||||
| // Configuration Descriptor | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| enum { ITF_NUM_CDC = 0, ITF_NUM_CDC_DATA, ITF_NUM_TOTAL }; | ||||
|  | ||||
| #define EPNUM_CDC_NOTIF 0x81 | ||||
| #define EPNUM_CDC_OUT 0x02 | ||||
| #define EPNUM_CDC_IN 0x82 | ||||
|  | ||||
| #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN) | ||||
|  | ||||
| // full speed configuration | ||||
| 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 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 | ||||
| // Per USB specs: high speed capable device must report device_qualifier and | ||||
| // other_speed_configuration | ||||
|  | ||||
| // high speed configuration | ||||
| 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 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), | ||||
| }; | ||||
|  | ||||
| // other speed configuration | ||||
| 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 = { | ||||
|     .bLength = sizeof(tusb_desc_device_qualifier_t), | ||||
|     .bDescriptorType = TUSB_DESC_DEVICE_QUALIFIER, | ||||
|     .bcdUSB = USB_BCD, | ||||
|  | ||||
|     .bDeviceClass = TUSB_CLASS_MISC, | ||||
|     .bDeviceSubClass = MISC_SUBCLASS_COMMON, | ||||
|     .bDeviceProtocol = MISC_PROTOCOL_IAD, | ||||
|  | ||||
|     .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, | ||||
|     .bNumConfigurations = 0x01, | ||||
|     .bReserved = 0x00}; | ||||
|  | ||||
| // Invoked when received GET DEVICE QUALIFIER DESCRIPTOR request | ||||
| // Application return pointer to descriptor, whose contents must exist long | ||||
| // enough for transfer to complete. device_qualifier descriptor describes | ||||
| // information about a high-speed capable device that would change if the device | ||||
| // were operating at the other speed. If not highspeed capable stall this | ||||
| // request. | ||||
| uint8_t const *tud_descriptor_device_qualifier_cb(void) { | ||||
|   return (uint8_t const *)&desc_device_qualifier; | ||||
| } | ||||
|  | ||||
| // Invoked when received GET OTHER SEED CONFIGURATION DESCRIPTOR request | ||||
| // Application return pointer to descriptor, whose contents must exist long | ||||
| // enough for transfer to complete Configuration descriptor in the other speed | ||||
| // e.g if high speed then this is for full speed and vice versa | ||||
| uint8_t const *tud_descriptor_other_speed_configuration_cb(uint8_t index) { | ||||
|   (void)index; // for multiple configurations | ||||
|  | ||||
|   // if link speed is high return fullspeed config, and vice versa | ||||
|   // Note: the descriptor type is OHER_SPEED_CONFIG instead of CONFIG | ||||
|   memcpy(desc_other_speed_config, | ||||
|          (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_fs_configuration | ||||
|                                               : desc_hs_configuration, | ||||
|          CONFIG_TOTAL_LEN); | ||||
|  | ||||
|   desc_other_speed_config[1] = TUSB_DESC_OTHER_SPEED_CONFIG; | ||||
|  | ||||
|   return desc_other_speed_config; | ||||
| } | ||||
|  | ||||
| #endif // highspeed | ||||
|  | ||||
| // 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 | ||||
| //--------------------------------------------------------------------+ | ||||
|  | ||||
| // 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 | ||||
|     "123456789012",             // 3: Serials, should use chip ID | ||||
|     "TinyUSB CDC",              // 4: CDC Interface | ||||
| }; | ||||
|  | ||||
| static uint16_t _desc_str[32]; | ||||
|  | ||||
| // 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; | ||||
|  | ||||
|   uint8_t chr_count; | ||||
|  | ||||
|   if (index == 0) { | ||||
|     memcpy(&_desc_str[1], string_desc_arr[0], 2); | ||||
|     chr_count = 1; | ||||
|   } else { | ||||
|     // 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 = (uint8_t)strlen(str); | ||||
|     if (chr_count > 31) | ||||
|       chr_count = 31; | ||||
|  | ||||
|     // Convert ASCII string into UTF-16 | ||||
|     for (uint8_t i = 0; i < chr_count; i++) { | ||||
|       _desc_str[1 + i] = str[i]; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // 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
	 hathach
					hathach