diff options
Diffstat (limited to 'lib/chibios-contrib/demos/STM32/RT-STM32F407-DISCOVERY-TinyUSB-CDC-MSC/usb_descriptors.c')
-rw-r--r-- | lib/chibios-contrib/demos/STM32/RT-STM32F407-DISCOVERY-TinyUSB-CDC-MSC/usb_descriptors.c | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/lib/chibios-contrib/demos/STM32/RT-STM32F407-DISCOVERY-TinyUSB-CDC-MSC/usb_descriptors.c b/lib/chibios-contrib/demos/STM32/RT-STM32F407-DISCOVERY-TinyUSB-CDC-MSC/usb_descriptors.c new file mode 100644 index 000000000..75b5ce7bb --- /dev/null +++ b/lib/chibios-contrib/demos/STM32/RT-STM32F407-DISCOVERY-TinyUSB-CDC-MSC/usb_descriptors.c | |||
@@ -0,0 +1,211 @@ | |||
1 | /* | ||
2 | * The MIT License (MIT) | ||
3 | * | ||
4 | * Copyright (c) 2019 Ha Thach (tinyusb.org) | ||
5 | * | ||
6 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
7 | * of this software and associated documentation files (the "Software"), to deal | ||
8 | * in the Software without restriction, including without limitation the rights | ||
9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
10 | * copies of the Software, and to permit persons to whom the Software is | ||
11 | * furnished to do so, subject to the following conditions: | ||
12 | * | ||
13 | * The above copyright notice and this permission notice shall be included in | ||
14 | * all copies or substantial portions of the Software. | ||
15 | * | ||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
22 | * THE SOFTWARE. | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #include "tusb.h" | ||
27 | |||
28 | /* A combination of interfaces must have a unique product id, since PC will save device driver after the first plug. | ||
29 | * Same VID/PID with different interface e.g MSC (first), then CDC (later) will possibly cause system error on PC. | ||
30 | * | ||
31 | * Auto ProductID layout's Bitmap: | ||
32 | * [MSB] HID | MSC | CDC [LSB] | ||
33 | */ | ||
34 | #define _PID_MAP(itf, n) ( (CFG_TUD_##itf) << (n) ) | ||
35 | #define USB_PID (0x4000 | _PID_MAP(CDC, 0) | _PID_MAP(MSC, 1) | _PID_MAP(HID, 2) | \ | ||
36 | _PID_MAP(MIDI, 3) | _PID_MAP(VENDOR, 4) ) | ||
37 | |||
38 | //--------------------------------------------------------------------+ | ||
39 | // Device Descriptors | ||
40 | //--------------------------------------------------------------------+ | ||
41 | tusb_desc_device_t const desc_device = | ||
42 | { | ||
43 | .bLength = sizeof(tusb_desc_device_t), | ||
44 | .bDescriptorType = TUSB_DESC_DEVICE, | ||
45 | .bcdUSB = 0x0200, | ||
46 | |||
47 | // Use Interface Association Descriptor (IAD) for CDC | ||
48 | // As required by USB Specs IAD's subclass must be common class (2) and protocol must be IAD (1) | ||
49 | .bDeviceClass = TUSB_CLASS_MISC, | ||
50 | .bDeviceSubClass = MISC_SUBCLASS_COMMON, | ||
51 | .bDeviceProtocol = MISC_PROTOCOL_IAD, | ||
52 | |||
53 | .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE, | ||
54 | |||
55 | .idVendor = 0xCafe, | ||
56 | .idProduct = USB_PID, | ||
57 | .bcdDevice = 0x0100, | ||
58 | |||
59 | .iManufacturer = 0x01, | ||
60 | .iProduct = 0x02, | ||
61 | .iSerialNumber = 0x03, | ||
62 | |||
63 | .bNumConfigurations = 0x01 | ||
64 | }; | ||
65 | |||
66 | // Invoked when received GET DEVICE DESCRIPTOR | ||
67 | // Application return pointer to descriptor | ||
68 | uint8_t const * tud_descriptor_device_cb(void) | ||
69 | { | ||
70 | return (uint8_t const *) &desc_device; | ||
71 | } | ||
72 | |||
73 | //--------------------------------------------------------------------+ | ||
74 | // Configuration Descriptor | ||
75 | //--------------------------------------------------------------------+ | ||
76 | |||
77 | enum | ||
78 | { | ||
79 | ITF_NUM_CDC = 0, | ||
80 | ITF_NUM_CDC_DATA, | ||
81 | ITF_NUM_MSC, | ||
82 | ITF_NUM_TOTAL | ||
83 | }; | ||
84 | |||
85 | #define CONFIG_TOTAL_LEN (TUD_CONFIG_DESC_LEN + TUD_CDC_DESC_LEN + TUD_MSC_DESC_LEN) | ||
86 | |||
87 | #if CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX | ||
88 | // LPC 17xx and 40xx endpoint type (bulk/interrupt/iso) are fixed by its number | ||
89 | // 0 control, 1 In, 2 Bulk, 3 Iso, 4 In, 5 Bulk etc ... | ||
90 | #define EPNUM_CDC_NOTIF 0x81 | ||
91 | #define EPNUM_CDC_OUT 0x02 | ||
92 | #define EPNUM_CDC_IN 0x82 | ||
93 | |||
94 | #define EPNUM_MSC_OUT 0x05 | ||
95 | #define EPNUM_MSC_IN 0x85 | ||
96 | |||
97 | #elif CFG_TUSB_MCU == OPT_MCU_SAMG | ||
98 | // SAMG doesn't support a same endpoint number with different direction IN and OUT | ||
99 | // e.g EP1 OUT & EP1 IN cannot exist together | ||
100 | #define EPNUM_CDC_NOTIF 0x81 | ||
101 | #define EPNUM_CDC_OUT 0x02 | ||
102 | #define EPNUM_CDC_IN 0x83 | ||
103 | |||
104 | #define EPNUM_MSC_OUT 0x04 | ||
105 | #define EPNUM_MSC_IN 0x85 | ||
106 | |||
107 | #else | ||
108 | #define EPNUM_CDC_NOTIF 0x81 | ||
109 | #define EPNUM_CDC_OUT 0x02 | ||
110 | #define EPNUM_CDC_IN 0x82 | ||
111 | |||
112 | #define EPNUM_MSC_OUT 0x03 | ||
113 | #define EPNUM_MSC_IN 0x83 | ||
114 | |||
115 | #endif | ||
116 | |||
117 | uint8_t const desc_fs_configuration[] = | ||
118 | { | ||
119 | // Config number, interface count, string index, total length, attribute, power in mA | ||
120 | TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), | ||
121 | |||
122 | // Interface number, string index, EP notification address and size, EP data address (out, in) and size. | ||
123 | TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 64), | ||
124 | |||
125 | // Interface number, string index, EP Out & EP In address, EP size | ||
126 | TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 64), | ||
127 | }; | ||
128 | |||
129 | #if TUD_OPT_HIGH_SPEED | ||
130 | uint8_t const desc_hs_configuration[] = | ||
131 | { | ||
132 | // Config number, interface count, string index, total length, attribute, power in mA | ||
133 | TUD_CONFIG_DESCRIPTOR(1, ITF_NUM_TOTAL, 0, CONFIG_TOTAL_LEN, TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP, 100), | ||
134 | |||
135 | // Interface number, string index, EP notification address and size, EP data address (out, in) and size. | ||
136 | TUD_CDC_DESCRIPTOR(ITF_NUM_CDC, 4, EPNUM_CDC_NOTIF, 8, EPNUM_CDC_OUT, EPNUM_CDC_IN, 512), | ||
137 | |||
138 | // Interface number, string index, EP Out & EP In address, EP size | ||
139 | TUD_MSC_DESCRIPTOR(ITF_NUM_MSC, 5, EPNUM_MSC_OUT, EPNUM_MSC_IN, 512), | ||
140 | }; | ||
141 | #endif | ||
142 | |||
143 | // Invoked when received GET CONFIGURATION DESCRIPTOR | ||
144 | // Application return pointer to descriptor | ||
145 | // Descriptor contents must exist long enough for transfer to complete | ||
146 | uint8_t const * tud_descriptor_configuration_cb(uint8_t index) | ||
147 | { | ||
148 | (void) index; // for multiple configurations | ||
149 | |||
150 | #if TUD_OPT_HIGH_SPEED | ||
151 | // Although we are highspeed, host may be fullspeed. | ||
152 | return (tud_speed_get() == TUSB_SPEED_HIGH) ? desc_hs_configuration : desc_fs_configuration; | ||
153 | #else | ||
154 | return desc_fs_configuration; | ||
155 | #endif | ||
156 | } | ||
157 | |||
158 | //--------------------------------------------------------------------+ | ||
159 | // String Descriptors | ||
160 | //--------------------------------------------------------------------+ | ||
161 | |||
162 | // array of pointer to string descriptors | ||
163 | char const* string_desc_arr [] = | ||
164 | { | ||
165 | (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409) | ||
166 | "TinyUSB", // 1: Manufacturer | ||
167 | "TinyUSB Device", // 2: Product | ||
168 | "123456", // 3: Serials, should use chip ID | ||
169 | "TinyUSB CDC", // 4: CDC Interface | ||
170 | "TinyUSB MSC", // 5: MSC Interface | ||
171 | }; | ||
172 | |||
173 | static uint16_t _desc_str[32]; | ||
174 | |||
175 | // Invoked when received GET STRING DESCRIPTOR request | ||
176 | // Application return pointer to descriptor, whose contents must exist long enough for transfer to complete | ||
177 | uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid) | ||
178 | { | ||
179 | (void) langid; | ||
180 | |||
181 | uint8_t chr_count; | ||
182 | |||
183 | if ( index == 0) | ||
184 | { | ||
185 | memcpy(&_desc_str[1], string_desc_arr[0], 2); | ||
186 | chr_count = 1; | ||
187 | }else | ||
188 | { | ||
189 | // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors. | ||
190 | // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors | ||
191 | |||
192 | if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) ) return NULL; | ||
193 | |||
194 | const char* str = string_desc_arr[index]; | ||
195 | |||
196 | // Cap at max char | ||
197 | chr_count = strlen(str); | ||
198 | if ( chr_count > 31 ) chr_count = 31; | ||
199 | |||
200 | // Convert ASCII string into UTF-16 | ||
201 | for(uint8_t i=0; i<chr_count; i++) | ||
202 | { | ||
203 | _desc_str[1+i] = str[i]; | ||
204 | } | ||
205 | } | ||
206 | |||
207 | // first byte is length (including header), second byte is string type | ||
208 | _desc_str[0] = (TUSB_DESC_STRING << 8 ) | (2*chr_count + 2); | ||
209 | |||
210 | return _desc_str; | ||
211 | } | ||