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