1 /*
2 * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdint.h>
8 #include <stdbool.h>
9 #include <stdlib.h>
10 #include <assert.h>
11 #include <stdio.h>
12 #include <string.h>
13 #include "usb/usb_helpers.h"
14 #include "usb/usb_types_ch9.h"
15 #include "esp_check.h"
16 #include "usb/usb_host.h"
17
18 // ---------------------------------------- Configuration Descriptor Parsing -------------------------------------------
19
usb_parse_next_descriptor(const usb_standard_desc_t * cur_desc,uint16_t wTotalLength,int * offset)20 const usb_standard_desc_t *usb_parse_next_descriptor(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, int *offset)
21 {
22 assert(cur_desc != NULL && offset != NULL);
23 if (*offset >= wTotalLength) {
24 return NULL; //We have traversed the entire configuration descriptor
25 }
26 if (*offset + cur_desc->bLength >= wTotalLength) {
27 return NULL; //Next descriptor is out of bounds
28 }
29 //Return the next descriptor, update offset
30 const usb_standard_desc_t *ret_desc = (const usb_standard_desc_t *)(((uint32_t)cur_desc) + cur_desc->bLength);
31 *offset += cur_desc->bLength;
32 return ret_desc;
33 }
34
usb_parse_next_descriptor_of_type(const usb_standard_desc_t * cur_desc,uint16_t wTotalLength,uint8_t bDescriptorType,int * offset)35 const usb_standard_desc_t *usb_parse_next_descriptor_of_type(const usb_standard_desc_t *cur_desc, uint16_t wTotalLength, uint8_t bDescriptorType, int *offset)
36 {
37 assert(cur_desc != NULL && offset != NULL);
38 int offset_temp = *offset; //We only want to update offset if we've actually found a descriptor
39 //Keep stepping over descriptors until we find one of bDescriptorType or until we go out of bounds
40 const usb_standard_desc_t *ret_desc = usb_parse_next_descriptor(cur_desc, wTotalLength, &offset_temp);
41 while (ret_desc != NULL) {
42 if (ret_desc->bDescriptorType == bDescriptorType) {
43 break;
44 }
45 ret_desc = usb_parse_next_descriptor(ret_desc, wTotalLength, &offset_temp);
46 }
47 if (ret_desc != NULL) {
48 //We've found a descriptor. Update the offset
49 *offset = offset_temp;
50 }
51 return ret_desc;
52 }
53
usb_parse_interface_number_of_alternate(const usb_config_desc_t * config_desc,uint8_t bInterfaceNumber)54 int usb_parse_interface_number_of_alternate(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber)
55 {
56 assert(config_desc != NULL);
57 int offset = 0;
58 //Find the first interface descriptor of bInterfaceNumber
59 const usb_intf_desc_t *first_intf_desc = usb_parse_interface_descriptor(config_desc, bInterfaceNumber, 0, &offset);
60 if (first_intf_desc == NULL) {
61 return -1; //bInterfaceNumber not found
62 }
63
64 int num_alt_setting = 0;
65 const usb_intf_desc_t *next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)first_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset);
66 while (next_intf_desc != NULL) {
67 if (next_intf_desc->bInterfaceNumber != bInterfaceNumber) {
68 break;
69 }
70 num_alt_setting++;
71 next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset);
72 }
73 return num_alt_setting;
74 }
75
usb_parse_interface_descriptor(const usb_config_desc_t * config_desc,uint8_t bInterfaceNumber,uint8_t bAlternateSetting,int * offset)76 const usb_intf_desc_t *usb_parse_interface_descriptor(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, int *offset)
77 {
78 assert(config_desc != NULL);
79 if (bInterfaceNumber >= config_desc->bNumInterfaces) {
80 return NULL; //bInterfaceNumber is out of range
81 }
82
83 //Walk to first interface descriptor of bInterfaceNumber
84 int offset_temp = 0;
85 const usb_intf_desc_t *next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)config_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp);
86 while (next_intf_desc != NULL) {
87 if (next_intf_desc->bInterfaceNumber == bInterfaceNumber) {
88 break; //We found the first interface descriptor with matching bInterfaceNumber
89 }
90 next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp);
91 }
92 if (next_intf_desc == NULL) {
93 return NULL; //Couldn't find a interface with bInterfaceNumber
94 }
95
96 //Keep walking until an interface descriptor matching bInterfaceNumber and bAlternateSetting is found
97 while (next_intf_desc != NULL) {
98 if (next_intf_desc->bInterfaceNumber == bInterfaceNumber + 1) {
99 //We've walked past our target bInterfaceNumber
100 next_intf_desc = NULL;
101 break;
102 }
103 if (next_intf_desc->bAlternateSetting == bAlternateSetting) {
104 //We've found our target interface descriptor
105 break;
106 }
107 //Get the next interface descriptor
108 next_intf_desc = (const usb_intf_desc_t *)usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_intf_desc, config_desc->wTotalLength, USB_B_DESCRIPTOR_TYPE_INTERFACE, &offset_temp);
109 }
110 if (next_intf_desc != NULL && offset != NULL) {
111 *offset = offset_temp;
112 }
113 return next_intf_desc;
114 }
115
usb_parse_endpoint_descriptor_by_index(const usb_intf_desc_t * intf_desc,int index,uint16_t wTotalLength,int * offset)116 const usb_ep_desc_t *usb_parse_endpoint_descriptor_by_index(const usb_intf_desc_t *intf_desc, int index, uint16_t wTotalLength, int *offset)
117 {
118 assert(intf_desc != NULL && offset != NULL);
119 if (index >= intf_desc->bNumEndpoints) {
120 return NULL; //Index is out of range
121 }
122 //Walk to the Nth endpoint descriptor we find
123 int offset_temp = *offset;
124 bool ep_found = true;
125 const usb_standard_desc_t *next_desc = (const usb_standard_desc_t *)intf_desc;
126 for (int i = 0; i <= index; i++) {
127 next_desc = usb_parse_next_descriptor_of_type((const usb_standard_desc_t *)next_desc, wTotalLength, USB_B_DESCRIPTOR_TYPE_ENDPOINT, &offset_temp);
128 if (next_desc == NULL) {
129 ep_found = false;
130 break;
131 }
132 }
133 if (ep_found) {
134 *offset = offset_temp;
135 return (const usb_ep_desc_t *)next_desc;
136 }
137 return NULL;
138 }
139
usb_parse_endpoint_descriptor_by_address(const usb_config_desc_t * config_desc,uint8_t bInterfaceNumber,uint8_t bAlternateSetting,uint8_t bEndpointAddress,int * offset)140 const usb_ep_desc_t *usb_parse_endpoint_descriptor_by_address(const usb_config_desc_t *config_desc, uint8_t bInterfaceNumber, uint8_t bAlternateSetting, uint8_t bEndpointAddress, int *offset)
141 {
142 assert(config_desc != NULL);
143
144 //Find the interface descriptor
145 int offset_intf;
146 const usb_intf_desc_t *intf_desc = usb_parse_interface_descriptor(config_desc, bInterfaceNumber, bAlternateSetting, &offset_intf);
147 if (intf_desc == NULL) {
148 return NULL;
149 }
150
151 //Walk endpoint descriptors until one matching bEndpointAddress is found
152 int offset_ep;
153 bool ep_found = false;
154 const usb_ep_desc_t *ep_desc = NULL;
155 for (int index = 0; index < intf_desc->bNumEndpoints; index++) {
156 offset_ep = offset_intf;
157 ep_desc = usb_parse_endpoint_descriptor_by_index(intf_desc, index, config_desc->wTotalLength, &offset_ep);
158 if (ep_desc == NULL) {
159 break;
160 }
161 if (ep_desc->bEndpointAddress == bEndpointAddress) {
162 ep_found = true;
163 break;
164 }
165 }
166 if (ep_found && offset != NULL) {
167 *offset = offset_ep;
168 }
169 return ep_desc;
170 }
171
172 // ----------------------------------------------- Descriptor Printing -------------------------------------------------
173
print_ep_desc(const usb_ep_desc_t * ep_desc)174 static void print_ep_desc(const usb_ep_desc_t *ep_desc)
175 {
176 const char *ep_type_str;
177 int type = ep_desc->bmAttributes & USB_BM_ATTRIBUTES_XFERTYPE_MASK;
178
179 switch (type) {
180 case USB_BM_ATTRIBUTES_XFER_CONTROL:
181 ep_type_str = "CTRL";
182 break;
183 case USB_BM_ATTRIBUTES_XFER_ISOC:
184 ep_type_str = "ISOC";
185 break;
186 case USB_BM_ATTRIBUTES_XFER_BULK:
187 ep_type_str = "BULK";
188 break;
189 case USB_BM_ATTRIBUTES_XFER_INT:
190 ep_type_str = "INT";
191 break;
192 default:
193 ep_type_str = NULL;
194 break;
195 }
196
197 printf("\t\t*** Endpoint descriptor ***\n");
198 printf("\t\tbLength %d\n", ep_desc->bLength);
199 printf("\t\tbDescriptorType %d\n", ep_desc->bDescriptorType);
200 printf("\t\tbEndpointAddress 0x%x\tEP %d %s\n", ep_desc->bEndpointAddress,
201 USB_EP_DESC_GET_EP_NUM(ep_desc),
202 USB_EP_DESC_GET_EP_DIR(ep_desc) ? "IN" : "OUT");
203 printf("\t\tbmAttributes 0x%x\t%s\n", ep_desc->bmAttributes, ep_type_str);
204 printf("\t\twMaxPacketSize %d\n", ep_desc->wMaxPacketSize);
205 printf("\t\tbInterval %d\n", ep_desc->bInterval);
206 }
207
usbh_print_intf_desc(const usb_intf_desc_t * intf_desc)208 static void usbh_print_intf_desc(const usb_intf_desc_t *intf_desc)
209 {
210 printf("\t*** Interface descriptor ***\n");
211 printf("\tbLength %d\n", intf_desc->bLength);
212 printf("\tbDescriptorType %d\n", intf_desc->bDescriptorType);
213 printf("\tbInterfaceNumber %d\n", intf_desc->bInterfaceNumber);
214 printf("\tbAlternateSetting %d\n", intf_desc->bAlternateSetting);
215 printf("\tbNumEndpoints %d\n", intf_desc->bNumEndpoints);
216 printf("\tbInterfaceClass 0x%x\n", intf_desc->bInterfaceProtocol);
217 printf("\tiInterface %d\n", intf_desc->iInterface);
218 }
219
usbh_print_cfg_desc(const usb_config_desc_t * cfg_desc)220 static void usbh_print_cfg_desc(const usb_config_desc_t *cfg_desc)
221 {
222 printf("*** Configuration descriptor ***\n");
223 printf("bLength %d\n", cfg_desc->bLength);
224 printf("bDescriptorType %d\n", cfg_desc->bDescriptorType);
225 printf("wTotalLength %d\n", cfg_desc->wTotalLength);
226 printf("bNumInterfaces %d\n", cfg_desc->bNumInterfaces);
227 printf("bConfigurationValue %d\n", cfg_desc->bConfigurationValue);
228 printf("iConfiguration %d\n", cfg_desc->iConfiguration);
229 printf("bmAttributes 0x%x\n", cfg_desc->bmAttributes);
230 printf("bMaxPower %dmA\n", cfg_desc->bMaxPower * 2);
231 }
232
usb_print_device_descriptor(const usb_device_desc_t * devc_desc)233 void usb_print_device_descriptor(const usb_device_desc_t *devc_desc)
234 {
235 if (devc_desc == NULL) {
236 return;
237 }
238
239 printf("*** Device descriptor ***\n");
240 printf("bLength %d\n", devc_desc->bLength);
241 printf("bDescriptorType %d\n", devc_desc->bDescriptorType);
242 printf("bcdUSB %d.%d0\n", ((devc_desc->bcdUSB >> 8) & 0xF), ((devc_desc->bcdUSB >> 4) & 0xF));
243 printf("bDeviceClass 0x%x\n", devc_desc->bDeviceClass);
244 printf("bDeviceSubClass 0x%x\n", devc_desc->bDeviceSubClass);
245 printf("bDeviceProtocol 0x%x\n", devc_desc->bDeviceProtocol);
246 printf("bMaxPacketSize0 %d\n", devc_desc->bMaxPacketSize0);
247 printf("idVendor 0x%x\n", devc_desc->idVendor);
248 printf("idProduct 0x%x\n", devc_desc->idProduct);
249 printf("bcdDevice %d.%d0\n", ((devc_desc->bcdDevice >> 8) & 0xF), ((devc_desc->bcdDevice >> 4) & 0xF));
250 printf("iManufacturer %d\n", devc_desc->iManufacturer);
251 printf("iProduct %d\n", devc_desc->iProduct);
252 printf("iSerialNumber %d\n", devc_desc->iSerialNumber);
253 printf("bNumConfigurations %d\n", devc_desc->bNumConfigurations);
254 }
255
usb_print_config_descriptor(const usb_config_desc_t * cfg_desc,print_class_descriptor_cb class_specific_cb)256 void usb_print_config_descriptor(const usb_config_desc_t *cfg_desc, print_class_descriptor_cb class_specific_cb)
257 {
258 if (cfg_desc == NULL) {
259 return;
260 }
261
262 int offset = 0;
263 uint16_t wTotalLength = cfg_desc->wTotalLength;
264 const usb_standard_desc_t *next_desc = (const usb_standard_desc_t *)cfg_desc;
265
266 do {
267 switch (next_desc->bDescriptorType) {
268 case USB_W_VALUE_DT_CONFIG:
269 usbh_print_cfg_desc((const usb_config_desc_t *)next_desc);
270 break;
271 case USB_W_VALUE_DT_INTERFACE:
272 usbh_print_intf_desc((const usb_intf_desc_t *)next_desc);
273 break;
274 case USB_W_VALUE_DT_ENDPOINT:
275 print_ep_desc((const usb_ep_desc_t *)next_desc);
276 break;
277 default:
278 if(class_specific_cb) {
279 class_specific_cb(next_desc);
280 }
281 break;
282 }
283
284 next_desc = usb_parse_next_descriptor(next_desc, wTotalLength, &offset);
285
286 } while (next_desc != NULL);
287 }
288
usb_print_string_descriptor(const usb_str_desc_t * str_desc)289 void usb_print_string_descriptor(const usb_str_desc_t *str_desc)
290 {
291 if (str_desc == NULL) {
292 return;
293 }
294
295 for (int i = 0; i < str_desc->bLength/2; i++) {
296 /*
297 USB String descriptors of UTF-16.
298 Right now We just skip any character larger than 0xFF to stay in BMP Basic Latin and Latin-1 Supplement range.
299 */
300 if (str_desc->wData[i] > 0xFF) {
301 continue;
302 }
303 printf("%c", (char)str_desc->wData[i]);
304 }
305 printf("\n");
306 }
307