Merge branch 'master' into pigrew-ZLP_Request2
This commit is contained in:
		
							
								
								
									
										12
									
								
								examples/device/dfu_rt/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								examples/device/dfu_rt/Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | include ../../../tools/top.mk | ||||||
|  | include ../../make.mk | ||||||
|  |  | ||||||
|  | INC += \ | ||||||
|  | 	src \ | ||||||
|  | 	$(TOP)/hw \ | ||||||
|  |  | ||||||
|  | # Example source | ||||||
|  | EXAMPLE_SOURCE += $(wildcard src/*.c) | ||||||
|  | SRC_C += $(addprefix $(CURRENT_PATH)/, $(EXAMPLE_SOURCE)) | ||||||
|  |  | ||||||
|  | include ../../rules.mk | ||||||
							
								
								
									
										151
									
								
								examples/device/dfu_rt/src/main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										151
									
								
								examples/device/dfu_rt/src/main.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,151 @@ | |||||||
|  | /*  | ||||||
|  |  * 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.h" | ||||||
|  | #include "tusb.h" | ||||||
|  |  | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | // MACRO CONSTANT TYPEDEF PROTYPES | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  |  | ||||||
|  | /* Blink pattern | ||||||
|  |  * - 1000 ms : device should reboot | ||||||
|  |  * - 250 ms  : device not mounted | ||||||
|  |  * - 0 ms : device mounted | ||||||
|  |  * - 2500 ms : device is suspended | ||||||
|  |  */ | ||||||
|  | enum  { | ||||||
|  |   BLINK_DFU_MODE = 1000, | ||||||
|  |   BLINK_NOT_MOUNTED = 250, | ||||||
|  |   BLINK_MOUNTED = 0, | ||||||
|  |   BLINK_SUSPENDED = 2500, | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED; | ||||||
|  |  | ||||||
|  | void led_blinking_task(void); | ||||||
|  |  | ||||||
|  | /*------------- MAIN -------------*/ | ||||||
|  | int main(void) | ||||||
|  | { | ||||||
|  |   board_init(); | ||||||
|  |  | ||||||
|  |   tusb_init(); | ||||||
|  |  | ||||||
|  |   while (1) | ||||||
|  |   { | ||||||
|  |     tud_task(); // tinyusb device task | ||||||
|  |     led_blinking_task(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | // 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 = BLINK_MOUNTED; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // Invoked on DFU_DETACH request to reboot to the bootloader | ||||||
|  | void tud_dfu_rt_reboot_to_dfu(void) | ||||||
|  | { | ||||||
|  |   blink_interval_ms = BLINK_DFU_MODE; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | // BLINKING TASK + Indicator pulse | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  |  | ||||||
|  |  | ||||||
|  | volatile uint8_t doPulse = false; | ||||||
|  | // called from USB context | ||||||
|  | void led_indicator_pulse(void) { | ||||||
|  | 	doPulse = true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void led_blinking_task(void) | ||||||
|  | { | ||||||
|  |   static uint32_t start_ms = 0; | ||||||
|  |   static bool led_state = false; | ||||||
|  |   if(blink_interval_ms == BLINK_MOUNTED) // Mounted | ||||||
|  |   { | ||||||
|  |     if(doPulse) | ||||||
|  |     { | ||||||
|  |       led_state = true; | ||||||
|  |       board_led_write(true); | ||||||
|  |       start_ms = board_millis(); | ||||||
|  |       doPulse = false; | ||||||
|  |     } | ||||||
|  |     else if (led_state == true) | ||||||
|  |     { | ||||||
|  |       if ( board_millis() - start_ms < 750) //Spec says blink must be between 500 and 1000 ms. | ||||||
|  |       { | ||||||
|  |         return; // not enough time | ||||||
|  |       } | ||||||
|  |       led_state = false; | ||||||
|  |       board_led_write(false); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   else | ||||||
|  |   { | ||||||
|  |     // Blink every interval ms | ||||||
|  |     if ( board_millis() - start_ms < blink_interval_ms) return; // not enough time | ||||||
|  |     start_ms += blink_interval_ms; | ||||||
|  |  | ||||||
|  |     board_led_write(led_state); | ||||||
|  |     led_state = 1 - led_state; // toggle | ||||||
|  |   } | ||||||
|  | } | ||||||
							
								
								
									
										5
									
								
								examples/device/dfu_rt/src/main.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								examples/device/dfu_rt/src/main.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | |||||||
|  | #ifndef MAIN_H | ||||||
|  | #define MAIN_H | ||||||
|  | void led_indicator_pulse(void); | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										64
									
								
								examples/device/dfu_rt/src/tusb_config.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								examples/device/dfu_rt/src/tusb_config.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | |||||||
|  | /* | ||||||
|  |  * tusb_config.h | ||||||
|  |  * | ||||||
|  |  *  Created on: Oct 28, 2019 | ||||||
|  |  *      Author: Sylvain Munaut | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef TUSB_CONFIG_H_ | ||||||
|  | #define TUSB_CONFIG_H_ | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  |  extern "C" { | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | //-------------------------------------------------------------------- | ||||||
|  | // COMMON CONFIGURATION | ||||||
|  | //-------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | // defined by compiler flags for flexibility | ||||||
|  | #ifndef CFG_TUSB_MCU | ||||||
|  |   #error CFG_TUSB_MCU must be defined | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_LPC18XX | ||||||
|  | #define CFG_TUSB_RHPORT0_MODE       (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) | ||||||
|  | #else | ||||||
|  | #define CFG_TUSB_RHPORT0_MODE       OPT_MODE_DEVICE | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #define CFG_TUSB_OS                 OPT_OS_NONE | ||||||
|  |  | ||||||
|  | // CFG_TUSB_DEBUG is defined by compiler in DEBUG build | ||||||
|  | // #define CFG_TUSB_DEBUG           0 | ||||||
|  |  | ||||||
|  | /* 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 | ||||||
|  | //-------------------------------------------------------------------- | ||||||
|  |  | ||||||
|  | #define CFG_TUD_ENDPOINT0_SIZE    64 | ||||||
|  |  | ||||||
|  | //------------- CLASS -------------// | ||||||
|  |  | ||||||
|  | #define CFG_TUD_DFU_RT 1 | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  |  } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif /* TUSB_CONFIG_H_ */ | ||||||
							
								
								
									
										229
									
								
								examples/device/dfu_rt/src/usb_descriptors.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										229
									
								
								examples/device/dfu_rt/src/usb_descriptors.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,229 @@ | |||||||
|  | /* | ||||||
|  |  * 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 "tusb.h" | ||||||
|  | #include "class/dfu/dfu_rt_device.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, | ||||||
|  |  | ||||||
|  |   #if CFG_TUD_CDC | ||||||
|  |     // 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, | ||||||
|  |   #else | ||||||
|  |     .bDeviceClass       = 0x00, | ||||||
|  |     .bDeviceSubClass    = 0x00, | ||||||
|  |     .bDeviceProtocol    = 0x00, | ||||||
|  |   #endif | ||||||
|  |  | ||||||
|  |     .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; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | // HID Report Descriptor | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | #if CFG_TUD_HID | ||||||
|  |  | ||||||
|  | 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), ) | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | // Invoked when received GET HID REPORT DESCRIPTOR | ||||||
|  | // Application return pointer to descriptor | ||||||
|  | // Descriptor contents must exist long enough for transfer to complete | ||||||
|  | uint8_t const * tud_hid_descriptor_report_cb(void) | ||||||
|  | { | ||||||
|  |   return desc_hid_report; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | // Configuration Descriptor | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  |  | ||||||
|  | enum | ||||||
|  | { | ||||||
|  | #if CFG_TUD_CDC | ||||||
|  |   ITF_NUM_CDC = 0, | ||||||
|  |   ITF_NUM_CDC_DATA, | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if CFG_TUD_MSC | ||||||
|  |   ITF_NUM_MSC, | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if CFG_TUD_HID | ||||||
|  |   ITF_NUM_HID, | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if CFG_TUD_DFU_RT | ||||||
|  |   ITF_NUM_DFU_RT, | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |   ITF_NUM_TOTAL | ||||||
|  | }; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | #define CONFIG_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_DFU_RT)*TUD_DFU_RT_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 ... | ||||||
|  |   // Note: since CDC EP ( 1 & 2), HID (4) are spot-on, thus we only need to force | ||||||
|  |   // endpoint number for MSC to 5 | ||||||
|  |   #define EPNUM_MSC   0x05 | ||||||
|  | #else | ||||||
|  |   #define EPNUM_MSC   0x03 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  | uint8_t const desc_configuration[] = | ||||||
|  | { | ||||||
|  |   // Interface count, string index, total length, attribute, power in mA | ||||||
|  |   TUD_CONFIG_DESCRIPTOR(ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), | ||||||
|  |  | ||||||
|  | #if CFG_TUD_CDC | ||||||
|  |   // Interface number, string index, EP notification address and size, EP data address (out, in) and size. | ||||||
|  |   TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 1, 0x81, 8, 0x02, 0x82, 64), | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if CFG_TUD_MSC | ||||||
|  |   // Interface number, string index, EP Out & EP In address, EP size | ||||||
|  |   TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC, 0x80 | EPNUM_MSC, (CFG_TUSB_RHPORT0_MODE & OPT_MODE_HIGH_SPEED) ? 512 : 64), | ||||||
|  | #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), 0x84, 16, 10), | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #if CFG_TUD_DFU_RT | ||||||
|  |   // Interface number, string index, attributes, detach timeout, transfer size */ | ||||||
|  |   TUD_DFU_RT_DESCRIPTOR(ITF_NUM_DFU_RT, 7, 0x0d, 1000, 4096), | ||||||
|  | #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 | ||||||
|  |   return desc_configuration; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | // 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 | ||||||
|  |   "123456",                      // 3: Serials, should use chip ID | ||||||
|  |   "TinyUSB DFU runtime",         // 4: DFU runtime | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | 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) | ||||||
|  | { | ||||||
|  |   size_t chr_count; | ||||||
|  |  | ||||||
|  |   if ( index == 0) | ||||||
|  |   { | ||||||
|  |     memcpy(&_desc_str[1], string_desc_arr[0], 2); | ||||||
|  |     chr_count = 1; | ||||||
|  |   } | ||||||
|  |   else | ||||||
|  |   { | ||||||
|  |     // Convert ASCII string into UTF-16 | ||||||
|  |  | ||||||
|  |     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); | ||||||
|  |     if ( chr_count > 31 ) { | ||||||
|  |       chr_count = 31; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     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)((((uint16_t)TUSB_DESC_STRING) << 8 ) | (2u*chr_count + 2u)); | ||||||
|  |  | ||||||
|  |   return _desc_str; | ||||||
|  | } | ||||||
| @@ -17,6 +17,7 @@ SRC_C += \ | |||||||
| 	src/device/usbd_control.c \ | 	src/device/usbd_control.c \ | ||||||
| 	src/class/msc/msc_device.c \ | 	src/class/msc/msc_device.c \ | ||||||
| 	src/class/cdc/cdc_device.c \ | 	src/class/cdc/cdc_device.c \ | ||||||
|  | 	src/class/dfu/dfu_rt_device.c \ | ||||||
| 	src/class/hid/hid_device.c \ | 	src/class/hid/hid_device.c \ | ||||||
| 	src/class/midi/midi_device.c \ | 	src/class/midi/midi_device.c \ | ||||||
| 	src/class/usbtmc/usbtmc_device.c \ | 	src/class/usbtmc/usbtmc_device.c \ | ||||||
|   | |||||||
							
								
								
									
										120
									
								
								src/class/dfu/dfu_rt_device.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								src/class/dfu/dfu_rt_device.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,120 @@ | |||||||
|  | /* | ||||||
|  |  * The MIT License (MIT) | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2019 Sylvain Munaut <tnt@246tNt.com> | ||||||
|  |  * | ||||||
|  |  * 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 file is part of the TinyUSB stack. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include "tusb_option.h" | ||||||
|  |  | ||||||
|  | #if (TUSB_OPT_DEVICE_ENABLED && CFG_TUD_DFU_RT) | ||||||
|  |  | ||||||
|  | #include "dfu_rt_device.h" | ||||||
|  | #include "device/usbd_pvt.h" | ||||||
|  |  | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | // MACRO CONSTANT TYPEDEF | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | typedef enum { | ||||||
|  |   DFU_REQUEST_DETACH      = 0, | ||||||
|  |   DFU_REQUEST_DNLOAD      = 1, | ||||||
|  |   DFU_REQUEST_UPLOAD      = 2, | ||||||
|  |   DFU_REQUEST_GETSTATUS   = 3, | ||||||
|  |   DFU_REQUEST_CLRSTATUS   = 4, | ||||||
|  |   DFU_REQUEST_GETSTATE    = 5, | ||||||
|  |   DFU_REQUEST_ABORT       = 6, | ||||||
|  | } dfu_requests_t; | ||||||
|  |  | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | // USBD Driver API | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | void dfu_rtd_init(void) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void dfu_rtd_reset(uint8_t rhport) | ||||||
|  | { | ||||||
|  |   (void) rhport; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length) | ||||||
|  | { | ||||||
|  |   (void) rhport; | ||||||
|  |  | ||||||
|  |   // Ensure this is DFU Runtime | ||||||
|  |   TU_ASSERT(itf_desc->bInterfaceSubClass == TUD_DFU_APP_SUBCLASS); | ||||||
|  |   TU_ASSERT(itf_desc->bInterfaceProtocol == DFU_PROTOCOL_RT); | ||||||
|  |  | ||||||
|  |   uint8_t const * p_desc = tu_desc_next( itf_desc ); | ||||||
|  |   (*p_length) = sizeof(tusb_desc_interface_t); | ||||||
|  |  | ||||||
|  |   if ( TUSB_DESC_FUNCTIONAL == tu_desc_type(p_desc) ) | ||||||
|  |   { | ||||||
|  |     (*p_length) += p_desc[DESC_OFFSET_LEN]; | ||||||
|  |     p_desc = tu_desc_next(p_desc); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request) | ||||||
|  | { | ||||||
|  |   (void) rhport; | ||||||
|  |  | ||||||
|  |   //------------- Class Specific Request -------------// | ||||||
|  |   TU_VERIFY(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); | ||||||
|  |   TU_VERIFY(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); | ||||||
|  |  | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * request) | ||||||
|  | { | ||||||
|  |   (void) rhport; | ||||||
|  |  | ||||||
|  |   //------------- Class Specific Request -------------// | ||||||
|  |   TU_ASSERT(request->bmRequestType_bit.type == TUSB_REQ_TYPE_CLASS); | ||||||
|  |   TU_ASSERT(request->bmRequestType_bit.recipient == TUSB_REQ_RCPT_INTERFACE); | ||||||
|  |  | ||||||
|  |   switch ( request->bRequest ) | ||||||
|  |   { | ||||||
|  |     case DFU_REQUEST_DETACH: | ||||||
|  |       tud_control_status(rhport, request); | ||||||
|  |       tud_dfu_rt_reboot_to_dfu(); | ||||||
|  |     break; | ||||||
|  |  | ||||||
|  |     default: return false; // stall unsupported request | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | bool dfu_rtd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) | ||||||
|  | { | ||||||
|  |   (void) rhport; | ||||||
|  |   (void) ep_addr; | ||||||
|  |   (void) result; | ||||||
|  |   (void) xferred_bytes; | ||||||
|  |   return true; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | #endif | ||||||
							
								
								
									
										77
									
								
								src/class/dfu/dfu_rt_device.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/class/dfu/dfu_rt_device.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | |||||||
|  | /* | ||||||
|  |  * The MIT License (MIT) | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2019 Sylvain Munaut <tnt@246tNt.com> | ||||||
|  |  * | ||||||
|  |  * 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 file is part of the TinyUSB stack. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef _TUSB_DFU_RT_DEVICE_H_ | ||||||
|  | #define _TUSB_DFU_RT_DEVICE_H_ | ||||||
|  |  | ||||||
|  | #include "common/tusb_common.h" | ||||||
|  | #include "device/usbd.h" | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  |  extern "C" { | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | // Common Definitions | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  |  | ||||||
|  | // DFU Protocol | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |   DFU_PROTOCOL_RT  = 1, | ||||||
|  |   DFU_PROTOCOL_DFU = 2, | ||||||
|  | } dfu_protocol_type_t; | ||||||
|  |  | ||||||
|  | // DFU Descriptor Type | ||||||
|  | typedef enum | ||||||
|  | { | ||||||
|  |   DFU_DESC_FUNCTIONAL = 0x21, | ||||||
|  | } dfu_descriptor_type_t; | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | // Application Callback API (weak is optional) | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  |  | ||||||
|  | // Invoked when received new data | ||||||
|  | TU_ATTR_WEAK void tud_dfu_rt_reboot_to_dfu(void); | ||||||
|  |  | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | // Internal Class Driver API | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | void dfu_rtd_init(void); | ||||||
|  | void dfu_rtd_reset(uint8_t rhport); | ||||||
|  | bool dfu_rtd_open(uint8_t rhport, tusb_desc_interface_t const * itf_desc, uint16_t *p_length); | ||||||
|  | bool dfu_rtd_control_request(uint8_t rhport, tusb_control_request_t const * request); | ||||||
|  | bool dfu_rtd_control_complete(uint8_t rhport, tusb_control_request_t const * request); | ||||||
|  | bool dfu_rtd_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t event, uint32_t xferred_bytes); | ||||||
|  |  | ||||||
|  | #ifdef __cplusplus | ||||||
|  |  } | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  | #endif /* _TUSB_DFU_RT_DEVICE_H_ */ | ||||||
| @@ -86,6 +86,8 @@ typedef enum | |||||||
|   TUSB_DESC_BOS                   = 0x0F, |   TUSB_DESC_BOS                   = 0x0F, | ||||||
|   TUSB_DESC_DEVICE_CAPABILITY     = 0x10, |   TUSB_DESC_DEVICE_CAPABILITY     = 0x10, | ||||||
|  |  | ||||||
|  |   TUSB_DESC_FUNCTIONAL            = 0x21, | ||||||
|  |  | ||||||
|   // Class Specific Descriptor |   // Class Specific Descriptor | ||||||
|   TUSB_DESC_CS_DEVICE             = 0x21, |   TUSB_DESC_CS_DEVICE             = 0x21, | ||||||
|   TUSB_DESC_CS_CONFIGURATION      = 0x22, |   TUSB_DESC_CS_CONFIGURATION      = 0x22, | ||||||
|   | |||||||
| @@ -79,7 +79,7 @@ typedef struct TU_ATTR_ALIGNED(4) | |||||||
|   }; |   }; | ||||||
| } dcd_event_t; | } dcd_event_t; | ||||||
|  |  | ||||||
| TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct"); | //TU_VERIFY_STATIC(sizeof(dcd_event_t) <= 12, "size is not correct"); | ||||||
|  |  | ||||||
| /*------------------------------------------------------------------*/ | /*------------------------------------------------------------------*/ | ||||||
| /* Device API | /* Device API | ||||||
| @@ -119,20 +119,51 @@ void dcd_edpt_stall       (uint8_t rhport, uint8_t ep_addr); | |||||||
| // clear stall, data toggle is also reset to DATA0 | // clear stall, data toggle is also reset to DATA0 | ||||||
| void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); | void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); | ||||||
|  |  | ||||||
| /*------------------------------------------------------------------*/ | //--------------------------------------------------------------------+ | ||||||
| /* Event Function | // Event API | ||||||
|  * Called by DCD to notify device stack | //--------------------------------------------------------------------+ | ||||||
|  *------------------------------------------------------------------*/ |  | ||||||
| void dcd_event_handler(dcd_event_t const * event, bool in_isr); | // Called by DCD to notify device stack | ||||||
|  | extern void dcd_event_handler(dcd_event_t const * event, bool in_isr); | ||||||
|  |  | ||||||
| // helper to send bus signal event | // helper to send bus signal event | ||||||
| void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr); | static inline void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr); | ||||||
|  |  | ||||||
| // helper to send setup received | // helper to send setup received | ||||||
| void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr); | static inline void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr); | ||||||
|  |  | ||||||
| // helper to send transfer complete event | // helper to send transfer complete event | ||||||
| void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr); | static inline void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr); | ||||||
|  |  | ||||||
|  |  | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | // Inline helper | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  |  | ||||||
|  | static inline void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr) | ||||||
|  | { | ||||||
|  |   dcd_event_t event = { .rhport = rhport, .event_id = eid, }; | ||||||
|  |   dcd_event_handler(&event, in_isr); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr) | ||||||
|  | { | ||||||
|  |   dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SETUP_RECEIVED }; | ||||||
|  |   memcpy(&event.setup_received, setup, 8); | ||||||
|  |  | ||||||
|  |   dcd_event_handler(&event, in_isr); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static inline void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr) | ||||||
|  | { | ||||||
|  |   dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_XFER_COMPLETE }; | ||||||
|  |  | ||||||
|  |   event.xfer_complete.ep_addr = ep_addr; | ||||||
|  |   event.xfer_complete.len     = xferred_bytes; | ||||||
|  |   event.xfer_complete.result  = result; | ||||||
|  |  | ||||||
|  |   dcd_event_handler(&event, in_isr); | ||||||
|  | } | ||||||
|  |  | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
|  } |  } | ||||||
|   | |||||||
| @@ -167,6 +167,20 @@ static usbd_class_driver_t const usbd_class_drivers[] = | |||||||
|       .sof              = NULL |       .sof              = NULL | ||||||
|   }, |   }, | ||||||
|   #endif |   #endif | ||||||
|  |  | ||||||
|  |   #if CFG_TUD_DFU_RT | ||||||
|  |   { | ||||||
|  |       .class_code       = TUD_DFU_APP_CLASS, | ||||||
|  |     //.subclass_code    = TUD_DFU_APP_SUBCLASS | ||||||
|  |       .init             = dfu_rtd_init, | ||||||
|  |       .reset            = dfu_rtd_reset, | ||||||
|  |       .open             = dfu_rtd_open, | ||||||
|  |       .control_request  = dfu_rtd_control_request, | ||||||
|  |       .control_complete = dfu_rtd_control_complete, | ||||||
|  |       .xfer_cb          = dfu_rtd_xfer_cb, | ||||||
|  |       .sof              = NULL | ||||||
|  |   }, | ||||||
|  |   #endif | ||||||
| }; | }; | ||||||
|  |  | ||||||
| enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(usbd_class_drivers) }; | enum { USBD_CLASS_DRIVER_COUNT = TU_ARRAY_SIZE(usbd_class_drivers) }; | ||||||
| @@ -276,7 +290,7 @@ bool tud_remote_wakeup(void) | |||||||
| //--------------------------------------------------------------------+ | //--------------------------------------------------------------------+ | ||||||
| // USBD Task | // USBD Task | ||||||
| //--------------------------------------------------------------------+ | //--------------------------------------------------------------------+ | ||||||
| bool usbd_init (void) | bool tud_init (void) | ||||||
| { | { | ||||||
|   TU_LOG2("USBD init\r\n"); |   TU_LOG2("USBD init\r\n"); | ||||||
|  |  | ||||||
| @@ -870,34 +884,6 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) | |||||||
|   } |   } | ||||||
| } | } | ||||||
|  |  | ||||||
| // helper to send bus signal event |  | ||||||
| void dcd_event_bus_signal (uint8_t rhport, dcd_eventid_t eid, bool in_isr) |  | ||||||
| { |  | ||||||
|   dcd_event_t event = { .rhport = rhport, .event_id = eid, }; |  | ||||||
|   dcd_event_handler(&event, in_isr); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // helper to send setup received |  | ||||||
| void dcd_event_setup_received(uint8_t rhport, uint8_t const * setup, bool in_isr) |  | ||||||
| { |  | ||||||
|   dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_SETUP_RECEIVED }; |  | ||||||
|   memcpy(&event.setup_received, setup, 8); |  | ||||||
|  |  | ||||||
|   dcd_event_handler(&event, in_isr); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // helper to send transfer complete event |  | ||||||
| void dcd_event_xfer_complete (uint8_t rhport, uint8_t ep_addr, uint32_t xferred_bytes, uint8_t result, bool in_isr) |  | ||||||
| { |  | ||||||
|   dcd_event_t event = { .rhport = rhport, .event_id = DCD_EVENT_XFER_COMPLETE }; |  | ||||||
|  |  | ||||||
|   event.xfer_complete.ep_addr = ep_addr; |  | ||||||
|   event.xfer_complete.len     = xferred_bytes; |  | ||||||
|   event.xfer_complete.result  = result; |  | ||||||
|  |  | ||||||
|   dcd_event_handler(&event, in_isr); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| //--------------------------------------------------------------------+ | //--------------------------------------------------------------------+ | ||||||
| // Helper | // Helper | ||||||
| //--------------------------------------------------------------------+ | //--------------------------------------------------------------------+ | ||||||
|   | |||||||
| @@ -41,6 +41,9 @@ | |||||||
| // Application API | // Application API | ||||||
| //--------------------------------------------------------------------+ | //--------------------------------------------------------------------+ | ||||||
|  |  | ||||||
|  | // Init device stack | ||||||
|  | bool tud_init (void); | ||||||
|  |  | ||||||
| // Task function should be called in main/rtos loop | // Task function should be called in main/rtos loop | ||||||
| void tud_task (void); | void tud_task (void); | ||||||
|  |  | ||||||
| @@ -304,6 +307,21 @@ TU_ATTR_WEAK bool tud_vendor_control_complete_cb(uint8_t rhport, tusb_control_re | |||||||
|   /* Endpoint In */\ |   /* Endpoint In */\ | ||||||
|   7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 |   7, TUSB_DESC_ENDPOINT, _epin, TUSB_XFER_BULK, U16_TO_U8S_LE(_epsize), 0 | ||||||
|  |  | ||||||
|  | //------------- DFU Runtime -------------// | ||||||
|  | #define TUD_DFU_APP_CLASS    (TUSB_CLASS_APPLICATION_SPECIFIC) | ||||||
|  | #define TUD_DFU_APP_SUBCLASS 0x01u | ||||||
|  |  | ||||||
|  | // Length of template descriptr: 18 bytes | ||||||
|  | #define TUD_DFU_RT_DESC_LEN (9 + 9) | ||||||
|  |  | ||||||
|  | // DFU runtime descriptor | ||||||
|  | // Interface number, string index, attributes, detach timeout, transfer size | ||||||
|  | #define TUD_DFU_RT_DESCRIPTOR(_itfnum, _stridx, _attr, _timeout, _xfer_size) \ | ||||||
|  |   /* Interface */ \ | ||||||
|  |   9, TUSB_DESC_INTERFACE, _itfnum, 0, 0, TUD_DFU_APP_CLASS, TUD_DFU_APP_SUBCLASS, DFU_PROTOCOL_RT, _stridx, \ | ||||||
|  |   /* Function */ \ | ||||||
|  |   9, DFU_DESC_FUNCTIONAL, _attr, U16_TO_U8S_LE(_timeout), U16_TO_U8S_LE(_xfer_size), U16_TO_U8S_LE(0x0101) | ||||||
|  |  | ||||||
|  |  | ||||||
| #ifdef __cplusplus | #ifdef __cplusplus | ||||||
|  } |  } | ||||||
|   | |||||||
| @@ -33,8 +33,6 @@ | |||||||
|  extern "C" { |  extern "C" { | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
| bool usbd_init (void); |  | ||||||
|  |  | ||||||
| //--------------------------------------------------------------------+ | //--------------------------------------------------------------------+ | ||||||
| // USBD Endpoint API | // USBD Endpoint API | ||||||
| //--------------------------------------------------------------------+ | //--------------------------------------------------------------------+ | ||||||
|   | |||||||
| @@ -47,7 +47,7 @@ bool tusb_init(void) | |||||||
| #endif | #endif | ||||||
|  |  | ||||||
| #if TUSB_OPT_DEVICE_ENABLED | #if TUSB_OPT_DEVICE_ENABLED | ||||||
|   TU_ASSERT ( usbd_init() ); // init device stack |   TU_ASSERT ( tud_init() ); // init device stack | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|   _initialized = true; |   _initialized = true; | ||||||
|   | |||||||
| @@ -87,6 +87,10 @@ | |||||||
|   #if CFG_TUD_USBTMC |   #if CFG_TUD_USBTMC | ||||||
|     #include "class/usbtmc/usbtmc_device.h" |     #include "class/usbtmc/usbtmc_device.h" | ||||||
|   #endif |   #endif | ||||||
|  |  | ||||||
|  |   #if CFG_TUD_DFU_RT | ||||||
|  |     #include "class/dfu/dfu_rt_device.h" | ||||||
|  |   #endif | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
| @@ -188,6 +188,10 @@ | |||||||
|   #define CFG_TUD_USBTMC          0 |   #define CFG_TUD_USBTMC          0 | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | #ifndef CFG_TUD_DFU_RT | ||||||
|  |   #define CFG_TUD_DFU_RT          0 | ||||||
|  | #endif | ||||||
|  |  | ||||||
|  |  | ||||||
| //-------------------------------------------------------------------- | //-------------------------------------------------------------------- | ||||||
| // HOST OPTIONS | // HOST OPTIONS | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ | |||||||
|   :use_exceptions: TRUE |   :use_exceptions: TRUE | ||||||
|   :use_test_preprocessor: TRUE |   :use_test_preprocessor: TRUE | ||||||
|   :use_auxiliary_dependencies: TRUE |   :use_auxiliary_dependencies: TRUE | ||||||
|  |   :use_deep_dependencies: TRUE | ||||||
|   :build_root: _build |   :build_root: _build | ||||||
| #  :release_build: TRUE | #  :release_build: TRUE | ||||||
|   :test_file_prefix: test_ |   :test_file_prefix: test_ | ||||||
| @@ -41,10 +42,10 @@ | |||||||
|   :commmon: &common_defines [] |   :commmon: &common_defines [] | ||||||
|   :test: |   :test: | ||||||
|     - *common_defines |     - *common_defines | ||||||
|     - TEST |     - _TEST_ | ||||||
|   :test_preprocess: |   :test_preprocess: | ||||||
|     - *common_defines |     - *common_defines | ||||||
|     - TEST |     - _TEST_ | ||||||
|  |  | ||||||
| :cmock: | :cmock: | ||||||
|   :mock_prefix: mock_ |   :mock_prefix: mock_ | ||||||
| @@ -53,6 +54,7 @@ | |||||||
|   :plugins: |   :plugins: | ||||||
|     - :ignore |     - :ignore | ||||||
|     - :callback |     - :callback | ||||||
|  |     - :array | ||||||
|   :treat_as: |   :treat_as: | ||||||
|     uint8:    HEX8 |     uint8:    HEX8 | ||||||
|     uint16:   HEX16 |     uint16:   HEX16 | ||||||
|   | |||||||
							
								
								
									
										138
									
								
								test/test/device/usbd/test_usbd.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								test/test/device/usbd/test_usbd.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,138 @@ | |||||||
|  | /*  | ||||||
|  |  * The MIT License (MIT) | ||||||
|  |  * | ||||||
|  |  * Copyright (c) 2019 hathach for Adafruit Industries | ||||||
|  |  * | ||||||
|  |  * 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 "unity.h" | ||||||
|  |  | ||||||
|  | // Files to test | ||||||
|  | #include "tusb_fifo.h" | ||||||
|  | #include "tusb.h" | ||||||
|  | #include "usbd.h" | ||||||
|  | TEST_FILE("usbd_control.c") | ||||||
|  | //TEST_FILE("usb_descriptors.c") | ||||||
|  |  | ||||||
|  | // Mock File | ||||||
|  | #include "mock_dcd.h" | ||||||
|  |  | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | // MACRO TYPEDEF CONSTANT ENUM DECLARATION | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  |  | ||||||
|  | uint8_t const rhport = 0; | ||||||
|  |  | ||||||
|  | tusb_desc_device_t const desc_device = | ||||||
|  | { | ||||||
|  |     .bLength            = sizeof(tusb_desc_device_t), | ||||||
|  |     .bDescriptorType    = TUSB_DESC_DEVICE, | ||||||
|  |     .bcdUSB             = 0x0200, | ||||||
|  |  | ||||||
|  |     // 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           = 0xCafe, | ||||||
|  |     .idProduct          = 0xCafe, | ||||||
|  |     .bcdDevice          = 0x0100, | ||||||
|  |  | ||||||
|  |     .iManufacturer      = 0x01, | ||||||
|  |     .iProduct           = 0x02, | ||||||
|  |     .iSerialNumber      = 0x03, | ||||||
|  |  | ||||||
|  |     .bNumConfigurations = 0x01 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | tusb_control_request_t const req_get_desc_device = | ||||||
|  | { | ||||||
|  |   .bmRequestType = 0x80, | ||||||
|  |   .bRequest = TUSB_REQ_GET_DESCRIPTOR, | ||||||
|  |   .wValue = (TUSB_DESC_DEVICE << 8), | ||||||
|  |   .wIndex = 0x0000, | ||||||
|  |   .wLength = 64 | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | // | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | uint8_t const * ptr_desc_device; | ||||||
|  |  | ||||||
|  | uint8_t const * tud_descriptor_device_cb(void) | ||||||
|  | { | ||||||
|  |   return ptr_desc_device; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | uint8_t const * tud_descriptor_configuration_cb(uint8_t index) | ||||||
|  | { | ||||||
|  |   TEST_FAIL(); | ||||||
|  |   return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | uint16_t const* tud_descriptor_string_cb(uint8_t index) | ||||||
|  | { | ||||||
|  |   return NULL; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void setUp(void) | ||||||
|  | { | ||||||
|  |   dcd_int_disable_Ignore(); | ||||||
|  |   dcd_int_enable_Ignore(); | ||||||
|  |  | ||||||
|  |   if ( !tusb_inited() ) | ||||||
|  |   { | ||||||
|  |     dcd_init_Expect(rhport); | ||||||
|  |     tusb_init(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   ptr_desc_device = (uint8_t const *) &desc_device; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void tearDown(void) | ||||||
|  | { | ||||||
|  | } | ||||||
|  |  | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | // | ||||||
|  | //--------------------------------------------------------------------+ | ||||||
|  | void test_usbd_get_device_descriptor(void) | ||||||
|  | { | ||||||
|  |   dcd_event_setup_received(rhport, (uint8_t*) &req_get_desc_device, false); | ||||||
|  |  | ||||||
|  |   dcd_edpt_xfer_ExpectWithArrayAndReturn(rhport, 0x80, (uint8_t*)&desc_device, sizeof(tusb_desc_device_t), sizeof(tusb_desc_device_t), true); | ||||||
|  |  | ||||||
|  |   tud_task(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void test_usbd_get_device_descriptor_null(void) | ||||||
|  | { | ||||||
|  |   ptr_desc_device = NULL; | ||||||
|  |  | ||||||
|  |   dcd_event_setup_received(rhport, (uint8_t*) &req_get_desc_device, false); | ||||||
|  |  | ||||||
|  |   dcd_edpt_stall_Expect(rhport, 0); | ||||||
|  |   dcd_edpt_stall_Expect(rhport, 0x80); | ||||||
|  |  | ||||||
|  |   tud_task(); | ||||||
|  | } | ||||||
| @@ -73,12 +73,11 @@ | |||||||
| #define CFG_TUD_ENDOINT0_SIZE    64 | #define CFG_TUD_ENDOINT0_SIZE    64 | ||||||
|  |  | ||||||
| //------------- CLASS -------------// | //------------- CLASS -------------// | ||||||
| #define CFG_TUD_CDC              1 | #define CFG_TUD_CDC              0 | ||||||
| #define CFG_TUD_MSC              1 | #define CFG_TUD_MSC              0 | ||||||
| #define CFG_TUD_HID              1 | #define CFG_TUD_HID              0 | ||||||
|  | #define CFG_TUD_MIDI             0 | ||||||
| #define CFG_TUD_MIDI             1 | #define CFG_TUD_VENDOR           0 | ||||||
| #define CFG_TUD_VENDOR           1 |  | ||||||
|  |  | ||||||
| //------------- CDC -------------// | //------------- CDC -------------// | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 hathach
					hathach