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