1 /*
2  * Copyright (c) 2022, sakumisu
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include "usbh_core.h"
7 
8 #undef USB_DBG_TAG
9 #define USB_DBG_TAG "usbh_core"
10 #include "usb_log.h"
11 
12 struct usbh_class_info *usbh_class_info_table_begin = NULL;
13 struct usbh_class_info *usbh_class_info_table_end = NULL;
14 
15 usb_slist_t g_bus_head = USB_SLIST_OBJECT_INIT(g_bus_head);
16 
17 struct setup_align_buffer {
18     uint8_t buffer[USB_ALIGN_UP(8, CONFIG_USB_ALIGN_SIZE)];
19 };
20 
21 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX uint8_t ep0_request_buffer[CONFIG_USBHOST_MAX_BUS][USB_ALIGN_UP(CONFIG_USBHOST_REQUEST_BUFFER_LEN, CONFIG_USB_ALIGN_SIZE)];
22 USB_NOCACHE_RAM_SECTION USB_MEM_ALIGNX struct setup_align_buffer g_setup_buffer[CONFIG_USBHOST_MAX_BUS][CONFIG_USBHOST_MAX_EXTHUBS + 1][CONFIG_USBHOST_MAX_EHPORTS];
23 
24 struct usbh_bus g_usbhost_bus[CONFIG_USBHOST_MAX_BUS];
25 
26 /* general descriptor field offsets */
27 #define DESC_bLength         0 /** Length offset */
28 #define DESC_bDescriptorType 1 /** Descriptor type offset */
29 
30 #define USB_DEV_ADDR_MAX         0x7f
31 #define USB_DEV_ADDR_MARK_OFFSET 5
32 #define USB_DEV_ADDR_MARK_MASK   0x1f
33 
usbh_allocate_devaddr(struct usbh_devaddr_map * devgen)34 static int usbh_allocate_devaddr(struct usbh_devaddr_map *devgen)
35 {
36     uint8_t startaddr = devgen->next;
37     uint8_t devaddr;
38     int index;
39     int bitno;
40 
41     for (;;) {
42         devaddr = devgen->next;
43         if (devgen->next >= 0x7f) {
44             devgen->next = 2;
45         } else {
46             devgen->next++;
47         }
48 
49         index = devaddr >> 5;
50         bitno = devaddr & 0x1f;
51         if ((devgen->alloctab[index] & (1 << bitno)) == 0) {
52             devgen->alloctab[index] |= (1 << bitno);
53             return (int)devaddr;
54         }
55 
56         if (startaddr == devaddr) {
57             return -USB_ERR_NOMEM;
58         }
59     }
60 }
61 
__usbh_free_devaddr(struct usbh_devaddr_map * devgen,uint8_t devaddr)62 static int __usbh_free_devaddr(struct usbh_devaddr_map *devgen, uint8_t devaddr)
63 {
64     int index;
65     int bitno;
66 
67     if ((devaddr > 0) && (devaddr < USB_DEV_ADDR_MAX)) {
68         index = devaddr >> USB_DEV_ADDR_MARK_OFFSET;
69         bitno = devaddr & USB_DEV_ADDR_MARK_MASK;
70 
71         /* Free the address  */
72         if ((devgen->alloctab[index] |= (1 << bitno)) != 0) {
73             devgen->alloctab[index] &= ~(1 << bitno);
74         } else {
75             return -1;
76         }
77 
78         if (devaddr < devgen->next) {
79             devgen->next = devaddr;
80         }
81     }
82 
83     return 0;
84 }
85 
usbh_free_devaddr(struct usbh_hubport * hport)86 static int usbh_free_devaddr(struct usbh_hubport *hport)
87 {
88     if (hport->dev_addr > 0) {
89         __usbh_free_devaddr(&hport->bus->devgen, hport->dev_addr);
90     }
91     return 0;
92 }
93 
usbh_find_class_driver(uint8_t class,uint8_t subclass,uint8_t protocol,uint16_t vid,uint16_t pid)94 static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uint8_t subclass, uint8_t protocol,
95                                                               uint16_t vid, uint16_t pid)
96 {
97     struct usbh_class_info *index = NULL;
98 
99     for (index = usbh_class_info_table_begin; index < usbh_class_info_table_end; index++) {
100         if ((index->match_flags & USB_CLASS_MATCH_INTF_CLASS) && !(index->bInterfaceClass == class)) {
101             continue;
102         }
103         if ((index->match_flags & USB_CLASS_MATCH_INTF_SUBCLASS) && !(index->bInterfaceSubClass == subclass)) {
104             continue;
105         }
106         if ((index->match_flags & USB_CLASS_MATCH_INTF_PROTOCOL) && !(index->bInterfaceProtocol == protocol)) {
107             continue;
108         }
109         if (index->match_flags & USB_CLASS_MATCH_VID_PID && index->id_table) {
110             /* scan id table */
111             uint32_t i;
112             for (i = 0; index->id_table[i][0]; i++) {
113                 if (index->id_table[i][0] == vid && index->id_table[i][1] == pid) {
114                     break;
115                 }
116             }
117             /* do not match, continue next */
118             if (!index->id_table[i][0]) {
119                 continue;
120             }
121         }
122         return index->class_driver;
123     }
124     return NULL;
125 }
126 
parse_device_descriptor(struct usbh_hubport * hport,struct usb_device_descriptor * desc,uint16_t length)127 static int parse_device_descriptor(struct usbh_hubport *hport, struct usb_device_descriptor *desc, uint16_t length)
128 {
129     if (desc->bLength != USB_SIZEOF_DEVICE_DESC) {
130         USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
131         return -USB_ERR_INVAL;
132     } else if (desc->bDescriptorType != USB_DESCRIPTOR_TYPE_DEVICE) {
133         USB_LOG_ERR("unexpected device descriptor 0x%02x\r\n", desc->bDescriptorType);
134         return -USB_ERR_INVAL;
135     } else {
136         if (length <= 8) {
137             return 0;
138         }
139 #if 0
140         USB_LOG_DBG("Device Descriptor:\r\n");
141         USB_LOG_DBG("bLength: 0x%02x           \r\n", desc->bLength);
142         USB_LOG_DBG("bDescriptorType: 0x%02x   \r\n", desc->bDescriptorType);
143         USB_LOG_DBG("bcdUSB: 0x%04x            \r\n", desc->bcdUSB);
144         USB_LOG_DBG("bDeviceClass: 0x%02x      \r\n", desc->bDeviceClass);
145         USB_LOG_DBG("bDeviceSubClass: 0x%02x   \r\n", desc->bDeviceSubClass);
146         USB_LOG_DBG("bDeviceProtocol: 0x%02x   \r\n", desc->bDeviceProtocol);
147         USB_LOG_DBG("bMaxPacketSize0: 0x%02x   \r\n", desc->bMaxPacketSize0);
148         USB_LOG_DBG("idVendor: 0x%04x          \r\n", desc->idVendor);
149         USB_LOG_DBG("idProduct: 0x%04x         \r\n", desc->idProduct);
150         USB_LOG_DBG("bcdDevice: 0x%04x         \r\n", desc->bcdDevice);
151         USB_LOG_DBG("iManufacturer: 0x%02x     \r\n", desc->iManufacturer);
152         USB_LOG_DBG("iProduct: 0x%02x          \r\n", desc->iProduct);
153         USB_LOG_DBG("iSerialNumber: 0x%02x     \r\n", desc->iSerialNumber);
154         USB_LOG_DBG("bNumConfigurations: 0x%02x\r\n", desc->bNumConfigurations);
155 #endif
156         hport->device_desc.bLength = desc->bLength;
157         hport->device_desc.bDescriptorType = desc->bDescriptorType;
158         hport->device_desc.bcdUSB = desc->bcdUSB;
159         hport->device_desc.bDeviceClass = desc->bDeviceClass;
160         hport->device_desc.bDeviceSubClass = desc->bDeviceSubClass;
161         hport->device_desc.bDeviceProtocol = desc->bDeviceProtocol;
162         hport->device_desc.bMaxPacketSize0 = desc->bMaxPacketSize0;
163         hport->device_desc.idVendor = desc->idVendor;
164         hport->device_desc.idProduct = desc->idProduct;
165         hport->device_desc.bcdDevice = desc->bcdDevice;
166         hport->device_desc.iManufacturer = desc->iManufacturer;
167         hport->device_desc.iProduct = desc->iProduct;
168         hport->device_desc.iSerialNumber = desc->iSerialNumber;
169         hport->device_desc.bNumConfigurations = desc->bNumConfigurations;
170     }
171     return 0;
172 }
173 
parse_config_descriptor(struct usbh_hubport * hport,struct usb_configuration_descriptor * desc,uint16_t length)174 static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_configuration_descriptor *desc, uint16_t length)
175 {
176     struct usb_interface_descriptor *intf_desc;
177     struct usb_endpoint_descriptor *ep_desc;
178     uint8_t cur_alt_setting = 0xff;
179     uint8_t cur_iface = 0xff;
180     uint8_t cur_ep = 0xff;
181     uint8_t cur_ep_num = 0xff;
182     uint32_t desc_len = 0;
183     uint8_t *p;
184 
185     if (desc->bLength != USB_SIZEOF_CONFIG_DESC) {
186         USB_LOG_ERR("invalid config bLength 0x%02x\r\n", desc->bLength);
187         return -USB_ERR_INVAL;
188     } else if (desc->bDescriptorType != USB_DESCRIPTOR_TYPE_CONFIGURATION) {
189         USB_LOG_ERR("unexpected config descriptor 0x%02x\r\n", desc->bDescriptorType);
190         return -USB_ERR_INVAL;
191     } else {
192         if (length <= USB_SIZEOF_CONFIG_DESC) {
193             return 0;
194         }
195 #if 0
196         USB_LOG_DBG("Config Descriptor:\r\n");
197         USB_LOG_DBG("bLength: 0x%02x             \r\n", desc->bLength);
198         USB_LOG_DBG("bDescriptorType: 0x%02x     \r\n", desc->bDescriptorType);
199         USB_LOG_DBG("wTotalLength: 0x%04x        \r\n", desc->wTotalLength);
200         USB_LOG_DBG("bNumInterfaces: 0x%02x      \r\n", desc->bNumInterfaces);
201         USB_LOG_DBG("bConfigurationValue: 0x%02x \r\n", desc->bConfigurationValue);
202         USB_LOG_DBG("iConfiguration: 0x%02x      \r\n", desc->iConfiguration);
203         USB_LOG_DBG("bmAttributes: 0x%02x        \r\n", desc->bmAttributes);
204         USB_LOG_DBG("bMaxPower: 0x%02x           \r\n", desc->bMaxPower);
205 #endif
206         hport->config.config_desc.bLength = desc->bLength;
207         hport->config.config_desc.bDescriptorType = desc->bDescriptorType;
208         hport->config.config_desc.wTotalLength = desc->wTotalLength;
209         hport->config.config_desc.bNumInterfaces = desc->bNumInterfaces;
210         hport->config.config_desc.bConfigurationValue = desc->bConfigurationValue;
211         hport->config.config_desc.iConfiguration = desc->iConfiguration;
212         hport->config.config_desc.iConfiguration = desc->iConfiguration;
213         hport->config.config_desc.bmAttributes = desc->bmAttributes;
214         hport->config.config_desc.bMaxPower = desc->bMaxPower;
215 
216         p = (uint8_t *)desc;
217         p += USB_SIZEOF_CONFIG_DESC;
218         desc_len = USB_SIZEOF_CONFIG_DESC;
219 
220         memset(hport->config.intf, 0, sizeof(struct usbh_interface) * CONFIG_USBHOST_MAX_INTERFACES);
221 
222         while (p[DESC_bLength] && (desc_len <= length)) {
223             switch (p[DESC_bDescriptorType]) {
224                 case USB_DESCRIPTOR_TYPE_INTERFACE:
225                     intf_desc = (struct usb_interface_descriptor *)p;
226                     cur_iface = intf_desc->bInterfaceNumber;
227                     cur_alt_setting = intf_desc->bAlternateSetting;
228                     cur_ep_num = intf_desc->bNumEndpoints;
229                     cur_ep = 0;
230 
231                     if (cur_iface >= CONFIG_USBHOST_MAX_INTERFACES) {
232                         USB_LOG_ERR("Interface num %d overflow\r\n", cur_iface);
233                         return -USB_ERR_NOMEM;
234                     }
235 
236                     if (cur_ep_num >= CONFIG_USBHOST_MAX_ENDPOINTS) {
237                         USB_LOG_ERR("Endpoint num %d overflow\r\n", cur_ep_num);
238                         return -USB_ERR_NOMEM;
239                     }
240 
241                     if (cur_alt_setting >= CONFIG_USBHOST_MAX_INTF_ALTSETTINGS) {
242                         USB_LOG_ERR("Interface altsetting num %d overflow\r\n", cur_alt_setting);
243                         return -USB_ERR_NOMEM;
244                     }
245 
246 #if 0
247                     USB_LOG_DBG("Interface Descriptor:\r\n");
248                     USB_LOG_DBG("bLength: 0x%02x            \r\n", intf_desc->bLength);
249                     USB_LOG_DBG("bDescriptorType: 0x%02x    \r\n", intf_desc->bDescriptorType);
250                     USB_LOG_DBG("bInterfaceNumber: 0x%02x   \r\n", intf_desc->bInterfaceNumber);
251                     USB_LOG_DBG("bAlternateSetting: 0x%02x  \r\n", intf_desc->bAlternateSetting);
252                     USB_LOG_DBG("bNumEndpoints: 0x%02x      \r\n", intf_desc->bNumEndpoints);
253                     USB_LOG_DBG("bInterfaceClass: 0x%02x    \r\n", intf_desc->bInterfaceClass);
254                     USB_LOG_DBG("bInterfaceSubClass: 0x%02x \r\n", intf_desc->bInterfaceSubClass);
255                     USB_LOG_DBG("bInterfaceProtocol: 0x%02x \r\n", intf_desc->bInterfaceProtocol);
256                     USB_LOG_DBG("iInterface: 0x%02x         \r\n", intf_desc->iInterface);
257 #endif
258                     memcpy(&hport->config.intf[cur_iface].altsetting[cur_alt_setting].intf_desc, intf_desc, 9);
259                     hport->config.intf[cur_iface].altsetting_num = cur_alt_setting + 1;
260                     break;
261                 case USB_DESCRIPTOR_TYPE_ENDPOINT:
262                     ep_desc = (struct usb_endpoint_descriptor *)p;
263                     memcpy(&hport->config.intf[cur_iface].altsetting[cur_alt_setting].ep[cur_ep].ep_desc, ep_desc, 7);
264                     cur_ep++;
265                     break;
266 
267                 default:
268                     break;
269             }
270             /* skip to next descriptor */
271             p += p[DESC_bLength];
272             desc_len += p[DESC_bLength];
273         }
274     }
275     return 0;
276 }
277 
usbh_print_hubport_info(struct usbh_hubport * hport)278 static void usbh_print_hubport_info(struct usbh_hubport *hport)
279 {
280     USB_LOG_RAW("Device Descriptor:\r\n");
281     USB_LOG_RAW("bLength: 0x%02x           \r\n", hport->device_desc.bLength);
282     USB_LOG_RAW("bDescriptorType: 0x%02x   \r\n", hport->device_desc.bDescriptorType);
283     USB_LOG_RAW("bcdUSB: 0x%04x            \r\n", hport->device_desc.bcdUSB);
284     USB_LOG_RAW("bDeviceClass: 0x%02x      \r\n", hport->device_desc.bDeviceClass);
285     USB_LOG_RAW("bDeviceSubClass: 0x%02x   \r\n", hport->device_desc.bDeviceSubClass);
286     USB_LOG_RAW("bDeviceProtocol: 0x%02x   \r\n", hport->device_desc.bDeviceProtocol);
287     USB_LOG_RAW("bMaxPacketSize0: 0x%02x   \r\n", hport->device_desc.bMaxPacketSize0);
288     USB_LOG_RAW("idVendor: 0x%04x          \r\n", hport->device_desc.idVendor);
289     USB_LOG_RAW("idProduct: 0x%04x         \r\n", hport->device_desc.idProduct);
290     USB_LOG_RAW("bcdDevice: 0x%04x         \r\n", hport->device_desc.bcdDevice);
291     USB_LOG_RAW("iManufacturer: 0x%02x     \r\n", hport->device_desc.iManufacturer);
292     USB_LOG_RAW("iProduct: 0x%02x          \r\n", hport->device_desc.iProduct);
293     USB_LOG_RAW("iSerialNumber: 0x%02x     \r\n", hport->device_desc.iSerialNumber);
294     USB_LOG_RAW("bNumConfigurations: 0x%02x\r\n", hport->device_desc.bNumConfigurations);
295 
296     USB_LOG_RAW("Config Descriptor:\r\n");
297     USB_LOG_RAW("bLength: 0x%02x             \r\n", hport->config.config_desc.bLength);
298     USB_LOG_RAW("bDescriptorType: 0x%02x     \r\n", hport->config.config_desc.bDescriptorType);
299     USB_LOG_RAW("wTotalLength: 0x%04x        \r\n", hport->config.config_desc.wTotalLength);
300     USB_LOG_RAW("bNumInterfaces: 0x%02x      \r\n", hport->config.config_desc.bNumInterfaces);
301     USB_LOG_RAW("bConfigurationValue: 0x%02x \r\n", hport->config.config_desc.bConfigurationValue);
302     USB_LOG_RAW("iConfiguration: 0x%02x      \r\n", hport->config.config_desc.iConfiguration);
303     USB_LOG_RAW("bmAttributes: 0x%02x        \r\n", hport->config.config_desc.bmAttributes);
304     USB_LOG_RAW("bMaxPower: 0x%02x           \r\n", hport->config.config_desc.bMaxPower);
305 
306     for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
307         for (uint8_t j = 0; j < hport->config.intf[i].altsetting_num; j++) {
308             USB_LOG_RAW("\tInterface Descriptor:\r\n");
309             USB_LOG_RAW("\tbLength: 0x%02x            \r\n", hport->config.intf[i].altsetting[j].intf_desc.bLength);
310             USB_LOG_RAW("\tbDescriptorType: 0x%02x    \r\n", hport->config.intf[i].altsetting[j].intf_desc.bDescriptorType);
311             USB_LOG_RAW("\tbInterfaceNumber: 0x%02x   \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceNumber);
312             USB_LOG_RAW("\tbAlternateSetting: 0x%02x  \r\n", hport->config.intf[i].altsetting[j].intf_desc.bAlternateSetting);
313             USB_LOG_RAW("\tbNumEndpoints: 0x%02x      \r\n", hport->config.intf[i].altsetting[j].intf_desc.bNumEndpoints);
314             USB_LOG_RAW("\tbInterfaceClass: 0x%02x    \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceClass);
315             USB_LOG_RAW("\tbInterfaceSubClass: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceSubClass);
316             USB_LOG_RAW("\tbInterfaceProtocol: 0x%02x \r\n", hport->config.intf[i].altsetting[j].intf_desc.bInterfaceProtocol);
317             USB_LOG_RAW("\tiInterface: 0x%02x         \r\n", hport->config.intf[i].altsetting[j].intf_desc.iInterface);
318 
319             for (uint8_t k = 0; k < hport->config.intf[i].altsetting[j].intf_desc.bNumEndpoints; k++) {
320                 USB_LOG_RAW("\t\tEndpoint Descriptor:\r\n");
321                 USB_LOG_RAW("\t\tbLength: 0x%02x          \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bLength);
322                 USB_LOG_RAW("\t\tbDescriptorType: 0x%02x  \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bDescriptorType);
323                 USB_LOG_RAW("\t\tbEndpointAddress: 0x%02x \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bEndpointAddress);
324                 USB_LOG_RAW("\t\tbmAttributes: 0x%02x     \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bmAttributes);
325                 USB_LOG_RAW("\t\twMaxPacketSize: 0x%04x   \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.wMaxPacketSize);
326                 USB_LOG_RAW("\t\tbInterval: 0x%02x        \r\n", hport->config.intf[i].altsetting[j].ep[k].ep_desc.bInterval);
327             }
328         }
329     }
330 }
331 
usbh_print_setup(struct usb_setup_packet * setup)332 static void usbh_print_setup(struct usb_setup_packet *setup)
333 {
334     (void)setup;
335 
336     USB_LOG_DBG("Setup: "
337                 "bmRequestType 0x%02x, bRequest 0x%02x, wValue 0x%04x, wIndex 0x%04x, wLength 0x%04x\r\n",
338                 setup->bmRequestType,
339                 setup->bRequest,
340                 setup->wValue,
341                 setup->wIndex,
342                 setup->wLength);
343 }
344 
usbh_get_default_mps(int speed)345 static int usbh_get_default_mps(int speed)
346 {
347     switch (speed) {
348         case USB_SPEED_LOW: /* For low speed, we use 8 bytes */
349             return 8;
350         case USB_SPEED_FULL: /* For full or high speed, we use 64 bytes */
351         case USB_SPEED_HIGH:
352             return 64;
353         case USB_SPEED_SUPER: /* For super speed , we must use 512 bytes */
354         case USB_SPEED_SUPER_PLUS:
355             return 512;
356         default:
357             return 64;
358     }
359 }
360 
usbh_enumerate(struct usbh_hubport * hport)361 int usbh_enumerate(struct usbh_hubport *hport)
362 {
363     struct usb_interface_descriptor *intf_desc;
364     struct usb_setup_packet *setup;
365     struct usb_device_descriptor *dev_desc;
366     struct usb_endpoint_descriptor *ep;
367     int dev_addr;
368     uint16_t ep_mps;
369     uint8_t config_value;
370     uint8_t config_index;
371     int ret;
372 
373     hport->setup = (struct usb_setup_packet *)&g_setup_buffer[hport->bus->busid][hport->parent->index - 1][hport->port - 1];
374     setup = hport->setup;
375     ep = &hport->ep0;
376 
377     /* Config EP0 mps from speed */
378     ep->bEndpointAddress = 0x00;
379     ep->bDescriptorType = USB_DESCRIPTOR_TYPE_ENDPOINT;
380     ep->bmAttributes = USB_ENDPOINT_TYPE_CONTROL;
381     ep->wMaxPacketSize = usbh_get_default_mps(hport->speed);
382     ep->bInterval = 0;
383     ep->bLength = 7;
384 
385     /* Configure EP0 with zero address */
386     hport->dev_addr = 0;
387 
388     /* Read the first 8 bytes of the device descriptor */
389     setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
390     setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
391     setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_DEVICE << 8) | 0);
392     setup->wIndex = 0;
393     setup->wLength = 8;
394 
395     ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
396     if (ret < 0) {
397         USB_LOG_ERR("Failed to get device descriptor,errorcode:%d\r\n", ret);
398         goto errout;
399     }
400 
401     ret = parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid], 8);
402     if (ret < 0) {
403         USB_LOG_ERR("Parse device descriptor fail\r\n");
404         goto errout;
405     }
406 
407     /* Extract the correct max packetsize from the device descriptor */
408     dev_desc = (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid];
409     if (dev_desc->bcdUSB >= USB_3_0) {
410         ep_mps = 1 << dev_desc->bMaxPacketSize0;
411     } else {
412         ep_mps = dev_desc->bMaxPacketSize0;
413     }
414 
415     USB_LOG_DBG("Device rev=%04x cls=%02x sub=%02x proto=%02x size=%d\r\n",
416                 dev_desc->bcdUSB, dev_desc->bDeviceClass, dev_desc->bDeviceSubClass,
417                 dev_desc->bDeviceProtocol, ep_mps);
418 
419     /* Reconfigure EP0 with the correct maximum packet size */
420     ep->wMaxPacketSize = ep_mps;
421 
422     /* Assign a function address to the device connected to this port */
423     dev_addr = usbh_allocate_devaddr(&hport->bus->devgen);
424     if (dev_addr < 0) {
425         USB_LOG_ERR("Failed to allocate devaddr,errorcode:%d\r\n", ret);
426         goto errout;
427     }
428 
429     /* Set the USB device address */
430     setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
431     setup->bRequest = USB_REQUEST_SET_ADDRESS;
432     setup->wValue = dev_addr;
433     setup->wIndex = 0;
434     setup->wLength = 0;
435 
436     ret = usbh_control_transfer(hport, setup, NULL);
437     if (ret < 0) {
438         USB_LOG_ERR("Failed to set devaddr,errorcode:%d\r\n", ret);
439         goto errout;
440     }
441 
442     /* Wait device set address completely */
443     usb_osal_msleep(10);
444 
445     /*Reconfigure EP0 with the correct address */
446     hport->dev_addr = dev_addr;
447 
448     /* Read the full device descriptor */
449     setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
450     setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
451     setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_DEVICE << 8) | 0);
452     setup->wIndex = 0;
453     setup->wLength = USB_SIZEOF_DEVICE_DESC;
454 
455     ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
456     if (ret < 0) {
457         USB_LOG_ERR("Failed to get full device descriptor,errorcode:%d\r\n", ret);
458         goto errout;
459     }
460 
461     parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid], USB_SIZEOF_DEVICE_DESC);
462     USB_LOG_INFO("New device found,idVendor:%04x,idProduct:%04x,bcdDevice:%04x\r\n",
463                  ((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->idVendor,
464                  ((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->idProduct,
465                  ((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->bcdDevice);
466 
467     USB_LOG_INFO("The device has %d bNumConfigurations\r\n", ((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->bNumConfigurations);
468 
469     config_index = 0;
470     USB_LOG_DBG("The device selects config %d\r\n", config_index);
471 
472     /* Read the first 9 bytes of the config descriptor */
473     setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
474     setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
475     setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_CONFIGURATION << 8) | config_index);
476     setup->wIndex = 0;
477     setup->wLength = USB_SIZEOF_CONFIG_DESC;
478 
479     ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
480     if (ret < 0) {
481         USB_LOG_ERR("Failed to get config descriptor,errorcode:%d\r\n", ret);
482         goto errout;
483     }
484 
485     ret = parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid], USB_SIZEOF_CONFIG_DESC);
486     if (ret < 0) {
487         USB_LOG_ERR("Parse config descriptor fail\r\n");
488         goto errout;
489     }
490 
491     /* Read the full size of the configuration data */
492     uint16_t wTotalLength = ((struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid])->wTotalLength;
493 
494     if (wTotalLength > CONFIG_USBHOST_REQUEST_BUFFER_LEN) {
495         ret = -USB_ERR_NOMEM;
496         USB_LOG_ERR("wTotalLength %d is overflow, default is %d\r\n", wTotalLength, (unsigned int)CONFIG_USBHOST_REQUEST_BUFFER_LEN);
497         goto errout;
498     }
499 
500     setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
501     setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
502     setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_CONFIGURATION << 8) | config_index);
503     setup->wIndex = 0;
504     setup->wLength = wTotalLength;
505 
506     ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
507     if (ret < 0) {
508         USB_LOG_ERR("Failed to get full config descriptor,errorcode:%d\r\n", ret);
509         goto errout;
510     }
511 
512     ret = parse_config_descriptor(hport, (struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid], wTotalLength);
513     if (ret < 0) {
514         USB_LOG_ERR("Parse config descriptor fail\r\n");
515         goto errout;
516     }
517 
518     USB_LOG_INFO("The device has %d interfaces\r\n", ((struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid])->bNumInterfaces);
519     hport->raw_config_desc = usb_osal_malloc(wTotalLength + 1);
520     if (hport->raw_config_desc == NULL) {
521         ret = -USB_ERR_NOMEM;
522         USB_LOG_ERR("No memory to alloc for raw_config_desc\r\n");
523         goto errout;
524     }
525 
526     config_value = ((struct usb_configuration_descriptor *)ep0_request_buffer[hport->bus->busid])->bConfigurationValue;
527     memcpy(hport->raw_config_desc, ep0_request_buffer[hport->bus->busid], wTotalLength);
528     hport->raw_config_desc[wTotalLength] = '\0';
529 
530 #ifdef CONFIG_USBHOST_GET_STRING_DESC
531     uint8_t string_buffer[128];
532 
533     if (hport->device_desc.iManufacturer > 0) {
534         /* Get Manufacturer string */
535         memset(string_buffer, 0, 128);
536         ret = usbh_get_string_desc(hport, USB_STRING_MFC_INDEX, string_buffer, 128);
537         if (ret < 0) {
538             USB_LOG_ERR("Failed to get Manufacturer string,errorcode:%d\r\n", ret);
539             goto errout;
540         }
541 
542         USB_LOG_INFO("Manufacturer: %s\r\n", string_buffer);
543     } else {
544         USB_LOG_WRN("Do not support Manufacturer string\r\n");
545     }
546 
547     if (hport->device_desc.iProduct > 0) {
548         /* Get Product string */
549         memset(string_buffer, 0, 128);
550         ret = usbh_get_string_desc(hport, USB_STRING_PRODUCT_INDEX, string_buffer, 128);
551         if (ret < 0) {
552             USB_LOG_ERR("Failed to get Product string,errorcode:%d\r\n", ret);
553             goto errout;
554         }
555 
556         USB_LOG_INFO("Product: %s\r\n", string_buffer);
557     } else {
558         USB_LOG_WRN("Do not support Product string\r\n");
559     }
560 
561     if (hport->device_desc.iSerialNumber > 0) {
562         /* Get SerialNumber string */
563         memset(string_buffer, 0, 128);
564         ret = usbh_get_string_desc(hport, USB_STRING_SERIAL_INDEX, string_buffer, 128);
565         if (ret < 0) {
566             USB_LOG_ERR("Failed to get SerialNumber string,errorcode:%d\r\n", ret);
567             goto errout;
568         }
569 
570         USB_LOG_INFO("SerialNumber: %s\r\n", string_buffer);
571     } else {
572         USB_LOG_WRN("Do not support SerialNumber string\r\n");
573     }
574 #endif
575     /* Select device configuration 1 */
576     setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
577     setup->bRequest = USB_REQUEST_SET_CONFIGURATION;
578     setup->wValue = config_value;
579     setup->wIndex = 0;
580     setup->wLength = 0;
581 
582     ret = usbh_control_transfer(hport, setup, NULL);
583     if (ret < 0) {
584         USB_LOG_ERR("Failed to set configuration,errorcode:%d\r\n", ret);
585         goto errout;
586     }
587 
588 #ifdef CONFIG_USBHOST_MSOS_ENABLE
589     setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_VENDOR | USB_REQUEST_RECIPIENT_DEVICE;
590     setup->bRequest = CONFIG_USBHOST_MSOS_VENDOR_CODE;
591     setup->wValue = 0;
592     setup->wIndex = 0x0004;
593     setup->wLength = 16;
594 
595     ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
596     if (ret < 0 && (ret != -USB_ERR_STALL)) {
597         USB_LOG_ERR("Failed to get msosv1 compat id,errorcode:%d\r\n", ret);
598         goto errout;
599     }
600 #endif
601     USB_LOG_INFO("Enumeration success, start loading class driver\r\n");
602     /*search supported class driver*/
603     for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
604         intf_desc = &hport->config.intf[i].altsetting[0].intf_desc;
605 
606         struct usbh_class_driver *class_driver = (struct usbh_class_driver *)usbh_find_class_driver(intf_desc->bInterfaceClass, intf_desc->bInterfaceSubClass, intf_desc->bInterfaceProtocol, hport->device_desc.idVendor, hport->device_desc.idProduct);
607 
608         if (class_driver == NULL) {
609             USB_LOG_ERR("do not support Class:0x%02x,Subclass:0x%02x,Protocl:0x%02x\r\n",
610                         intf_desc->bInterfaceClass,
611                         intf_desc->bInterfaceSubClass,
612                         intf_desc->bInterfaceProtocol);
613 
614             continue;
615         }
616         hport->config.intf[i].class_driver = class_driver;
617         USB_LOG_INFO("Loading %s class driver\r\n", class_driver->driver_name);
618         ret = CLASS_CONNECT(hport, i);
619     }
620 
621 errout:
622     if (hport->raw_config_desc) {
623         usb_osal_free(hport->raw_config_desc);
624         hport->raw_config_desc = NULL;
625     }
626     return ret;
627 }
628 
usbh_hubport_release(struct usbh_hubport * hport)629 void usbh_hubport_release(struct usbh_hubport *hport)
630 {
631     if (hport->connected) {
632         hport->connected = false;
633         usbh_free_devaddr(hport);
634         for (uint8_t i = 0; i < hport->config.config_desc.bNumInterfaces; i++) {
635             if (hport->config.intf[i].class_driver && hport->config.intf[i].class_driver->disconnect) {
636                 CLASS_DISCONNECT(hport, i);
637             }
638         }
639         hport->config.config_desc.bNumInterfaces = 0;
640         usbh_kill_urb(&hport->ep0_urb);
641         if (hport->mutex) {
642             usb_osal_mutex_delete(hport->mutex);
643         }
644     }
645 }
646 
usbh_bus_init(struct usbh_bus * bus,uint8_t busid,uintptr_t reg_base)647 static void usbh_bus_init(struct usbh_bus *bus, uint8_t busid, uintptr_t reg_base)
648 {
649     memset(bus, 0, sizeof(struct usbh_bus));
650     bus->busid = busid;
651     bus->hcd.hcd_id = busid;
652     bus->hcd.reg_base = reg_base;
653 
654     /* devaddr 1 is for roothub */
655     bus->devgen.next = 2;
656 
657     usb_slist_add_tail(&g_bus_head, &bus->list);
658 }
659 
usbh_initialize(uint8_t busid,uintptr_t reg_base)660 int usbh_initialize(uint8_t busid, uintptr_t reg_base)
661 {
662     struct usbh_bus *bus;
663 
664     if (busid >= CONFIG_USBHOST_MAX_BUS) {
665         USB_LOG_ERR("bus overflow\r\n");
666         while (1) {
667         }
668     }
669 
670     bus = &g_usbhost_bus[busid];
671 
672     usbh_bus_init(bus, busid, reg_base);
673 
674 #ifdef __ARMCC_VERSION /* ARM C Compiler */
675     extern const int usbh_class_info$$Base;
676     extern const int usbh_class_info$$Limit;
677     usbh_class_info_table_begin = (struct usbh_class_info *)&usbh_class_info$$Base;
678     usbh_class_info_table_end = (struct usbh_class_info *)&usbh_class_info$$Limit;
679 #elif defined(__GNUC__)
680     extern uint32_t __usbh_class_info_start__;
681     extern uint32_t __usbh_class_info_end__;
682     usbh_class_info_table_begin = (struct usbh_class_info *)&__usbh_class_info_start__;
683     usbh_class_info_table_end = (struct usbh_class_info *)&__usbh_class_info_end__;
684 #elif defined(__ICCARM__) || defined(__ICCRX__) || defined(__ICCRISCV__)
685     usbh_class_info_table_begin = (struct usbh_class_info *)__section_begin(".usbh_class_info");
686     usbh_class_info_table_end = (struct usbh_class_info *)__section_end(".usbh_class_info");
687 #endif
688     usbh_hub_initialize(bus);
689     return 0;
690 }
691 
usbh_deinitialize(uint8_t busid)692 int usbh_deinitialize(uint8_t busid)
693 {
694     struct usbh_bus *bus;
695 
696     if (busid >= CONFIG_USBHOST_MAX_BUS) {
697         USB_LOG_ERR("bus overflow\r\n");
698         while (1) {
699         }
700     }
701 
702     bus = &g_usbhost_bus[busid];
703 
704     usbh_hub_deinitialize(bus);
705 
706     usb_slist_remove(&g_bus_head, &bus->list);
707 
708     return 0;
709 }
710 
usbh_control_transfer(struct usbh_hubport * hport,struct usb_setup_packet * setup,uint8_t * buffer)711 int usbh_control_transfer(struct usbh_hubport *hport, struct usb_setup_packet *setup, uint8_t *buffer)
712 {
713     struct usbh_urb *urb;
714     int ret;
715 
716     if (!hport || !setup) {
717         return -USB_ERR_INVAL;
718     }
719 
720     urb = &hport->ep0_urb;
721 
722     usb_osal_mutex_take(hport->mutex);
723 
724     usbh_print_setup(setup);
725 
726     usbh_control_urb_fill(urb, hport, setup, buffer, setup->wLength, CONFIG_USBHOST_CONTROL_TRANSFER_TIMEOUT, NULL, NULL);
727     ret = usbh_submit_urb(urb);
728     if (ret == 0) {
729         ret = urb->actual_length;
730     }
731 
732     usb_osal_mutex_give(hport->mutex);
733     return ret;
734 }
735 
usbh_get_string_desc(struct usbh_hubport * hport,uint8_t index,uint8_t * output,uint16_t output_len)736 int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *output, uint16_t output_len)
737 {
738     struct usb_setup_packet *setup = hport->setup;
739     int ret;
740     uint8_t *src;
741     uint8_t *dst;
742     uint16_t len;
743     uint16_t i = 2;
744     uint16_t j = 0;
745 
746     /* Get Manufacturer string */
747     setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
748     setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
749     setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_STRING << 8) | index);
750     setup->wIndex = 0x0409;
751     setup->wLength = 255;
752 
753     ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
754     if (ret < 0) {
755         return ret;
756     }
757 
758     src = ep0_request_buffer[hport->bus->busid];
759     dst = output;
760     len = src[0];
761 
762     if (((len - 2) / 2) > output_len) {
763         return -USB_ERR_NOMEM;
764     }
765 
766     while (i < len) {
767         dst[j] = src[i];
768         i += 2;
769         j++;
770     }
771 
772     return 0;
773 }
774 
usbh_set_interface(struct usbh_hubport * hport,uint8_t intf,uint8_t altsetting)775 int usbh_set_interface(struct usbh_hubport *hport, uint8_t intf, uint8_t altsetting)
776 {
777     struct usb_setup_packet *setup = hport->setup;
778 
779     setup->bmRequestType = USB_REQUEST_DIR_OUT | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_INTERFACE;
780     setup->bRequest = USB_REQUEST_SET_INTERFACE;
781     setup->wValue = altsetting;
782     setup->wIndex = intf;
783     setup->wLength = 0;
784 
785     return usbh_control_transfer(hport, setup, NULL);
786 }
787 
usbh_list_all_interface_name(struct usbh_hub * hub,const char * devname)788 static void *usbh_list_all_interface_name(struct usbh_hub *hub, const char *devname)
789 {
790     struct usbh_hubport *hport;
791     struct usbh_hub *hub_next;
792     void *priv;
793 
794     for (uint8_t port = 0; port < hub->nports; port++) {
795         hport = &hub->child[port];
796         if (hport->connected) {
797             for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
798                 if (hport->config.intf[itf].class_driver && hport->config.intf[itf].class_driver->driver_name) {
799                     if ((strncmp(hport->config.intf[itf].devname, devname, CONFIG_USBHOST_DEV_NAMELEN) == 0) && hport->config.intf[itf].priv)
800                         return hport->config.intf[itf].priv;
801 
802                     if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) {
803                         hub_next = hport->config.intf[itf].priv;
804 
805                         if (hub_next && hub_next->connected) {
806                             priv = usbh_list_all_interface_name(hub_next, devname);
807                             if (priv) {
808                                 return priv;
809                             }
810                         }
811                     }
812                 }
813             }
814         }
815     }
816     return NULL;
817 }
818 
usbh_list_all_interface_driver(struct usbh_hub * hub)819 static void usbh_list_all_interface_driver(struct usbh_hub *hub)
820 {
821     struct usbh_hubport *hport;
822     struct usbh_hub *hub_next;
823     const char *speed_table[] = { "error-speed", "low-speed", "full-speed", "high-speed", "wireless-speed", "super-speed", "superplus-speed" };
824 
825     for (uint8_t port = 0; port < hub->nports; port++) {
826         hport = &hub->child[port];
827         if (hport->connected) {
828             for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
829                 if (hport->config.intf[itf].class_driver && hport->config.intf[itf].class_driver->driver_name) {
830                     for (uint8_t j = 0; j < hub->index; j++) {
831                         USB_LOG_RAW("\t");
832                     }
833 
834                     USB_LOG_RAW("|__Port %u, dev addr:0x%02x, If %u, ClassDriver=%s, %s\r\n",
835                                 hport->port,
836                                 hport->dev_addr,
837                                 itf,
838                                 hport->config.intf[itf].class_driver->driver_name,
839                                 speed_table[hport->speed]);
840 
841                     if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) {
842                         hub_next = hport->config.intf[itf].priv;
843 
844                         if (hub_next && hub_next->connected) {
845                             usbh_list_all_interface_driver(hub_next);
846                         }
847                     }
848                 }
849             }
850         }
851     }
852 }
853 
usbh_list_all_interface_desc(struct usbh_bus * bus,struct usbh_hub * hub)854 static void usbh_list_all_interface_desc(struct usbh_bus *bus, struct usbh_hub *hub)
855 {
856     struct usbh_hubport *hport;
857     struct usbh_hub *hub_next;
858 
859     for (uint8_t port = 0; port < hub->nports; port++) {
860         hport = &hub->child[port];
861         if (hport->connected) {
862             USB_LOG_RAW("\r\nBus %u, Hub %u, Port %u, dev addr:0x%02x, VID:PID 0x%04x:0x%04x\r\n",
863                         bus->busid,
864                         hub->index,
865                         hport->port,
866                         hport->dev_addr,
867                         hport->device_desc.idVendor,
868                         hport->device_desc.idProduct);
869             usbh_print_hubport_info(hport);
870 
871             for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
872                 if (hport->config.intf[itf].class_driver && hport->config.intf[itf].class_driver->driver_name) {
873                     if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) {
874                         hub_next = hport->config.intf[itf].priv;
875 
876                         if (hub_next && hub_next->connected) {
877                             usbh_list_all_interface_desc(bus, hub_next);
878                         }
879                     }
880                 }
881             }
882         }
883     }
884 }
885 
usbh_list_all_hubport(struct usbh_hub * hub,uint8_t hub_index,uint8_t hub_port)886 static struct usbh_hubport *usbh_list_all_hubport(struct usbh_hub *hub, uint8_t hub_index, uint8_t hub_port)
887 {
888     struct usbh_hubport *hport;
889     struct usbh_hub *hub_next;
890 
891     if (hub->index == hub_index) {
892         hport = &hub->child[hub_port - 1];
893         if (hport->connected) {
894             return hport;
895         } else {
896             return NULL;
897         }
898     } else {
899         for (uint8_t port = 0; port < hub->nports; port++) {
900             hport = &hub->child[port];
901             if (hport->connected) {
902                 for (uint8_t itf = 0; itf < hport->config.config_desc.bNumInterfaces; itf++) {
903                     if (hport->config.intf[itf].class_driver && hport->config.intf[itf].class_driver->driver_name) {
904                         if (strcmp(hport->config.intf[itf].class_driver->driver_name, "hub") == 0) {
905                             hub_next = hport->config.intf[itf].priv;
906 
907                             if (hub_next && hub_next->connected) {
908                                 hport = usbh_list_all_hubport(hub_next, hub_index, hub_port);
909                                 if (hport) {
910                                     return hport;
911                                 }
912                             }
913                         }
914                     }
915                 }
916             }
917         }
918     }
919     return NULL;
920 }
921 
usbh_find_class_instance(const char * devname)922 void *usbh_find_class_instance(const char *devname)
923 {
924     usb_slist_t *bus_list;
925     struct usbh_hub *hub;
926     struct usbh_bus *bus;
927     void *priv;
928     size_t flags;
929 
930     flags = usb_osal_enter_critical_section();
931     usb_slist_for_each(bus_list, &g_bus_head)
932     {
933         bus = usb_slist_entry(bus_list, struct usbh_bus, list);
934         hub = &bus->hcd.roothub;
935 
936         priv = usbh_list_all_interface_name(hub, devname);
937         if (priv) {
938             usb_osal_leave_critical_section(flags);
939             return priv;
940         }
941     }
942     usb_osal_leave_critical_section(flags);
943     return NULL;
944 }
945 
usbh_find_hubport(uint8_t busid,uint8_t hub_index,uint8_t hub_port)946 struct usbh_hubport *usbh_find_hubport(uint8_t busid, uint8_t hub_index, uint8_t hub_port)
947 {
948     struct usbh_hub *hub;
949     struct usbh_bus *bus;
950     struct usbh_hubport *hport;
951     size_t flags;
952 
953     flags = usb_osal_enter_critical_section();
954 
955     bus = &g_usbhost_bus[busid];
956     hub = &bus->hcd.roothub;
957 
958     hport = usbh_list_all_hubport(hub, hub_index, hub_port);
959     usb_osal_leave_critical_section(flags);
960     return hport;
961 }
962 
lsusb(int argc,char ** argv)963 int lsusb(int argc, char **argv)
964 {
965     usb_slist_t *bus_list;
966     struct usbh_hub *hub;
967     struct usbh_bus *bus;
968     size_t flags;
969 
970     if (argc < 2) {
971         USB_LOG_RAW("Usage: lsusb [options]...\r\n");
972         USB_LOG_RAW("List USB devices\r\n");
973         USB_LOG_RAW("  -v, --verbose\r\n");
974         USB_LOG_RAW("      Increase verbosity (show descriptors)\r\n");
975         // USB_LOG_RAW("  -s [[bus]:[devnum]]\r\n");
976         // USB_LOG_RAW("      Show only devices with specified device and/or bus numbers (in decimal)\r\n");
977         // USB_LOG_RAW("  -d vendor:[product]\r\n");
978         // USB_LOG_RAW("      Show only devices with the specified vendor and product ID numbers (in hexadecimal)\r\n");
979         USB_LOG_RAW("  -t, --tree\r\n");
980         USB_LOG_RAW("      Dump the physical USB device hierachy as a tree\r\n");
981         USB_LOG_RAW("  -V, --version\r\n");
982         USB_LOG_RAW("      Show version of program\r\n");
983         USB_LOG_RAW("  -h, --help\r\n");
984         USB_LOG_RAW("      Show usage and help\r\n");
985         return 0;
986     }
987     if (argc > 3) {
988         return 0;
989     }
990 
991     flags = usb_osal_enter_critical_section();
992 
993     if (strcmp(argv[1], "-V") == 0) {
994         USB_LOG_RAW("CherryUSB Version %s\r\n", CHERRYUSB_VERSION_STR);
995     }
996 
997     if (strcmp(argv[1], "-t") == 0) {
998         usb_slist_for_each(bus_list, &g_bus_head)
999         {
1000             bus = usb_slist_entry(bus_list, struct usbh_bus, list);
1001             hub = &bus->hcd.roothub;
1002 
1003             USB_LOG_RAW("/: Bus %u, Hub %u, ports=%u, is roothub\r\n",
1004                         bus->busid,
1005                         hub->index,
1006                         hub->nports);
1007             usbh_list_all_interface_driver(hub);
1008         }
1009     }
1010 
1011     if (strcmp(argv[1], "-v") == 0) {
1012         usb_slist_for_each(bus_list, &g_bus_head)
1013         {
1014             bus = usb_slist_entry(bus_list, struct usbh_bus, list);
1015             hub = &bus->hcd.roothub;
1016 
1017             usbh_list_all_interface_desc(bus, hub);
1018         }
1019     }
1020 
1021     usb_osal_leave_critical_section(flags);
1022     return 0;
1023 }
1024