M480 BSP V3.05.005
The Board Support Package for M480 Series
usb_core.c
Go to the documentation of this file.
1/**************************************************************************/
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13
14#include "NuMicro.h"
15
16#include "usb.h"
17#include "hub.h"
18
19
21
22USBH_T *_ohci;
23HSUSBH_T *_ehci;
24
25int _IsInUsbInterrupt = 0;
26
27static UDEV_DRV_T * _drivers[MAX_UDEV_DRIVER];
28
29static CONN_FUNC *g_conn_func, *g_disconn_func;
30
32
33
40{
41 NVIC_DisableIRQ(HSUSBH_IRQn);
42 NVIC_DisableIRQ(USBH_IRQn);
43
44 _ohci = USBH;
45 _ehci = HSUSBH;
46
47 memset(_drivers, 0, sizeof(_drivers));
48
49 g_conn_func = NULL;
50 g_disconn_func = NULL;
51
52 usbh_hub_init();
53
54 if ((SYS->CSERVER & SYS_CSERVER_VERSION_Msk) == 0x0) /* Only M480MD has EHCI. */
55 {
56 _ehci->USBPCR0 = 0x160; /* enable PHY 0 */
57 _ehci->USBPCR1 = 0x520; /* enable PHY 1 */
58 }
59
60 usbh_memory_init();
61
62 _ohci->HcMiscControl |= USBH_HcMiscControl_OCAL_Msk; /* Over-current active low */
63 //_ohci->HcMiscControl &= ~USBH_HcMiscControl_OCAL_Msk; /* Over-current active high */
64
65#ifdef ENABLE_OHCI
66 ohci_driver.init();
67 ENABLE_OHCI_IRQ();
68#endif
69
70#ifdef ENABLE_EHCI
71 if ((SYS->CSERVER & SYS_CSERVER_VERSION_Msk) == 0x0) /* Only M480MD has EHCI. */
72 {
73 ehci_driver.init();
74 ENABLE_EHCI_IRQ();
75 }
76#endif
77}
78
86void usbh_install_conn_callback(CONN_FUNC *conn_func, CONN_FUNC *disconn_func)
87{
88 g_conn_func = conn_func;
89 g_disconn_func = disconn_func;
90}
91
92static int reset_device(UDEV_T *udev)
93{
94 if (udev->parent == NULL)
95 {
96 if (udev->hc_driver)
97 return udev->hc_driver->rthub_port_reset(udev->port_num-1);
98 else
99 return USBH_ERR_NOT_FOUND;
100 }
101 else
102 {
103 return udev->parent->port_reset(udev->parent, udev->port_num);
104 }
105}
106
107#ifdef ENABLE_EHCI
108static uint32_t ehci_UCMDR;
109#endif
110
116{
117#ifdef ENABLE_EHCI
118 int time_out = 10; /* ms */
119#endif
120
121#ifdef ENABLE_OHCI
122 /* set port suspend if connected */
123 if ((SYS->CSERVER & SYS_CSERVER_VERSION_Msk) == 0x0)
124 {
125 /* M480MD has port1, but M480LD has not port1 */
127 _ohci->HcRhPortStatus[0] = USBH_HcRhPortStatus_PSS_Msk; /* set port suspend */
128 }
129
131 _ohci->HcRhPortStatus[1] = USBH_HcRhPortStatus_PSS_Msk; /* set port suspend */
132
133 /* enable Device Remote Wakeup */
135
136 /* enable USBH RHSC interrupt for system wakeup */
138
139 /* set Host Controller enter suspend state */
140 _ohci->HcControl = (_ohci->HcControl & ~USBH_HcControl_HCFS_Msk) | (3 << USBH_HcControl_HCFS_Pos);
141#endif
142
143#ifdef ENABLE_EHCI
144 if ((SYS->CSERVER & SYS_CSERVER_VERSION_Msk) == 0x0) /* Only M480MD has EHCI. */
145 {
146 ehci_UCMDR = _ehci->UCMDR;
147
148 if (_ehci->UPSCR[0] & HSUSBH_UPSCR_PE_Msk)
149 {
150 _ehci->UPSCR[0] |= HSUSBH_UPSCR_SUSPEND_Msk;
151 delay_us(2000); /* wait 2 ms */
152 }
153
155 while (time_out > 0)
156 {
157 if (!(_ehci->UCMDR & HSUSBH_UCMDR_RUN_Msk) && (_ehci->USTSR & HSUSBH_USTSR_HCHalted_Msk))
158 {
159 break;
160 }
161 }
162 if (time_out == 0)
163 {
164 USB_error("usbh_suspend - RUN/HCHalted error!\n");
165 }
166 delay_us(100);
167 }
168#endif
169}
170
171
176void usbh_resume(void)
177{
178#ifdef ENABLE_OHCI
179 _ohci->HcControl = (_ohci->HcControl & ~USBH_HcControl_HCFS_Msk) | (1 << USBH_HcControl_HCFS_Pos);
180
181 if ((SYS->CSERVER & SYS_CSERVER_VERSION_Msk) == 0x0)
182 {
184 _ohci->HcRhPortStatus[0] = USBH_HcRhPortStatus_POCI_Msk; /* clear suspend status */
185 }
187 _ohci->HcRhPortStatus[1] = USBH_HcRhPortStatus_POCI_Msk; /* clear suspend status */
188
189 delay_us(30000); /* wait at least 20ms for Host to resume device */
190
191 /* enter operational state */
192 _ohci->HcControl = (_ohci->HcControl & ~USBH_HcControl_HCFS_Msk) | (2 << USBH_HcControl_HCFS_Pos);
193#endif
194
195#ifdef ENABLE_EHCI
196 if ((SYS->CSERVER & SYS_CSERVER_VERSION_Msk) == 0x0) /* Only M480MD has EHCI. */
197 {
198 _ehci->UCMDR = ehci_UCMDR;
199
200 if (_ehci->UPSCR[0] & HSUSBH_UPSCR_PE_Msk)
201 {
202 _ehci->UPSCR[0] |= HSUSBH_UPSCR_FPR_Msk;
203 delay_us(20000); /* keep resume signal for 20 ms */
204 _ehci->UPSCR[0] &= ~HSUSBH_UPSCR_FPR_Msk;
205 }
206 delay_us(1000);
207 }
208#endif
209}
210
211
212
214
223int usbh_register_driver(UDEV_DRV_T *udrv)
224{
225 int i;
226
227 for (i = 0; i < MAX_UDEV_DRIVER; i++)
228 {
229 if (_drivers[i] == udrv)
230 return 0; /* already registered, do nothing */
231
232 if (_drivers[i] == NULL)
233 {
234 _drivers[i] = udrv; /* register this driver */
235 return 0;
236 }
237 }
238 return USBH_ERR_MEMORY_OUT; /* reached MAX_UDEV_DRIVER limitation, aborted */
239}
240
241
258int usbh_ctrl_xfer(UDEV_T *udev, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
259 uint16_t wLength, uint8_t *buff, uint32_t *xfer_len, uint32_t timeout)
260{
261 UTR_T *utr;
262 uint32_t t0;
263 int status;
264
265 *xfer_len = 0;
266
267 //if (check_device(udev))
268 // return USBH_ERR_INVALID_PARAM;
269
270 utr = alloc_utr(udev);
271 if (utr == NULL)
272 return USBH_ERR_MEMORY_OUT;
273
274 utr->setup.bmRequestType = bmRequestType;
275 utr->setup.bRequest = bRequest;
276 utr->setup.wValue = wValue;
277 utr->setup.wIndex = wIndex;
278 utr->setup.wLength = wLength;
279
280 utr->buff = buff;
281 utr->data_len = wLength;
282 utr->bIsTransferDone = 0;
283 status = udev->hc_driver->ctrl_xfer(utr);
284 if (status < 0)
285 {
286 udev->ep0.hw_pipe = NULL;
287 free_utr(utr);
288 return status;
289 }
290
291 t0 = get_ticks();
292 while (utr->bIsTransferDone == 0)
293 {
294 if (get_ticks() - t0 > timeout)
295 {
296 usbh_quit_utr(utr);
297 free_utr(utr);
298 udev->ep0.hw_pipe = NULL;
299 return USBH_ERR_TIMEOUT;
300 }
301 }
302
303 status = utr->status;
304
305 if (status == 0)
306 {
307 *xfer_len = utr->xfer_len;
308 }
309 free_utr(utr);
310
311 return status;
312}
313
314
323int usbh_bulk_xfer(UTR_T *utr)
324{
325 return utr->udev->hc_driver->bulk_xfer(utr);
326}
327
336int usbh_int_xfer(UTR_T *utr)
337{
338 return utr->udev->hc_driver->int_xfer(utr);
339}
340
349int usbh_iso_xfer(UTR_T *utr)
350{
351 if (utr->udev->hc_driver == NULL)
352 {
353 printf("hc_driver - 0x%x\n", (int)utr->udev->hc_driver);
354 return -1;
355 }
356 if (utr->udev->hc_driver->iso_xfer == NULL)
357 {
358 printf("iso_xfer - 0x%x\n", (int)utr->udev->hc_driver->iso_xfer);
359 return -1;
360 }
361 return utr->udev->hc_driver->iso_xfer(utr);
362}
363
370int usbh_quit_utr(UTR_T *utr)
371{
372 if (!utr || !utr->udev)
373 return USBH_ERR_NOT_FOUND;
374
375 return utr->udev->hc_driver->quit_xfer(utr, NULL);
376}
377
378
386int usbh_quit_xfer(UDEV_T *udev, EP_INFO_T *ep)
387{
388 return udev->hc_driver->quit_xfer(NULL, ep);
389}
390
391
392void dump_device_descriptor(DESC_DEV_T *desc)
393{
394 USB_debug("\n[Device Descriptor]\n");
395 USB_debug("----------------------------------------------\n");
396 USB_debug(" Length = %2d\n", desc->bLength);
397 USB_debug(" DescriptorType = 0x%02x\n", desc->bDescriptorType);
398 USB_debug(" USB version = %x.%02x\n",
399 desc->bcdUSB >> 8, desc->bcdUSB & 0xff);
400 USB_debug(" Vendor:Product = %04x:%04x\n",
401 desc->idVendor, desc->idProduct);
402 USB_debug(" MaxPacketSize0 = %d\n", desc->bMaxPacketSize0);
403 USB_debug(" NumConfigurations = %d\n", desc->bNumConfigurations);
404 USB_debug(" Device version = %x.%02x\n",
405 desc->bcdDevice >> 8, desc->bcdDevice & 0xff);
406 USB_debug(" Device Class:SubClass:Protocol = %02x:%02x:%02x\n",
407 desc->bDeviceClass, desc->bDeviceSubClass, desc->bDeviceProtocol);
408}
409
410void usbh_dump_interface_descriptor(DESC_IF_T *if_desc)
411{
412 USB_debug("\n [Interface Descriptor]\n");
413 USB_debug(" ----------------------------------------------\n");
414 USB_debug(" Length = %2d\n", if_desc->bLength);
415 USB_debug(" DescriptorType = %02x\n", if_desc->bDescriptorType);
416 USB_debug(" bInterfaceNumber = %d\n", if_desc->bInterfaceNumber);
417 USB_debug(" bAlternateSetting = %d\n", if_desc->bAlternateSetting);
418 USB_debug(" bNumEndpoints = %d\n", if_desc->bNumEndpoints);
419 USB_debug(" bInterfaceClass = 0x%02x\n", if_desc->bInterfaceClass);
420 USB_debug(" bInterfaceSubClass = 0x%02x\n", if_desc->bInterfaceSubClass);
421 USB_debug(" bInterfaceProtocol = 0x%02x\n", if_desc->bInterfaceProtocol);
422 USB_debug(" iInterface = %d\n", if_desc->iInterface);
423}
424
425void usbh_dump_endpoint_descriptor(DESC_EP_T *ep_desc)
426{
427 USB_debug("\n [Endpoint Descriptor]\n");
428 USB_debug(" ----------------------------------------------\n");
429 USB_debug(" Length = %2d\n", ep_desc->bLength);
430 USB_debug(" DescriptorType = %02x\n", ep_desc->bDescriptorType);
431 USB_debug(" bEndpointAddress = 0x%02x\n", ep_desc->bEndpointAddress);
432 USB_debug(" bmAttributes = 0x%02x\n", ep_desc->bmAttributes);
433 USB_debug(" wMaxPacketSize = %d\n", ep_desc->wMaxPacketSize);
434 USB_debug(" bInterval = %d\n", ep_desc->bInterval);
435 USB_debug(" bRefresh = %d\n", ep_desc->bRefresh);
436 USB_debug(" bSynchAddress = %d\n", ep_desc->bSynchAddress);
437}
438
439void dump_config_descriptor(DESC_CONF_T *desc)
440{
441 uint8_t *bptr = (uint8_t *)desc;
442 DESC_HDR_T *hdr;
443 int tlen = desc->wTotalLength;
444
445 while (tlen > 0)
446 {
447 switch (bptr[1])
448 {
449 case USB_DT_CONFIGURATION:
450 USB_debug("\n[Configuration Descriptor]\n");
451 USB_debug("----------------------------------------------\n");
452 USB_debug(" Length = %2d\n", desc->bLength);
453 USB_debug(" DescriptorType = %02x\n", desc->bDescriptorType);
454 USB_debug(" wTotalLength = %2d\n", desc->wTotalLength);
455 USB_debug(" bNumInterfaces = %d\n", desc->bNumInterfaces);
456 USB_debug(" bConfigurationValue = %d\n", desc->bConfigurationValue);
457 USB_debug(" iConfiguration = %d\n", desc->iConfiguration);
458 USB_debug(" bmAttributes = 0x%02x\n", desc->bmAttributes);
459 USB_debug(" MaxPower = %d\n", desc->MaxPower);
460 break;
461
462 case USB_DT_INTERFACE:
463 usbh_dump_interface_descriptor((DESC_IF_T *)bptr);
464 break;
465
466 case USB_DT_ENDPOINT:
467 usbh_dump_endpoint_descriptor((DESC_EP_T *)bptr);
468 break;
469
470 default:
471 hdr = (DESC_HDR_T *)bptr;
472 USB_debug("\n!![Unknown Descriptor]\n");
473 USB_debug("----------------------------------------------\n");
474 USB_debug("Length = %2d\n", hdr->bLength);
475 USB_debug("DescriptorType = %02x\n", hdr->bDescriptorType);
476 break;
477 }
478 if (bptr[0] == 0)
479 break;
480 tlen -= bptr[0];
481 bptr += bptr[0];
482 }
483}
484
490int usbh_set_address(UDEV_T *udev)
491{
492 uint32_t read_len;
493 int dev_num, ret;
494
495 if (udev->dev_num != 0)
497
498 dev_num = alloc_dev_address();
499
500 /*------------------------------------------------------------------------------------*/
501 /* Issue SET ADDRESS command to set device address */
502 /*------------------------------------------------------------------------------------*/
503 ret = usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_STD_DEV | REQ_TYPE_TO_DEV,
504 USB_REQ_SET_ADDRESS, dev_num, 0, 0,
505 NULL, &read_len, 100);
506 if (ret < 0)
507 {
508 free_dev_address(dev_num);
509 return ret;
510 }
511
512 udev->dev_num = dev_num;
513
514 return 0;
515}
516
522int usbh_set_configuration(UDEV_T *udev, uint8_t conf_val)
523{
524 uint32_t read_len;
525 int ret;
526
527 /* Current configuration is the same. Do nothing. */
528 if (udev->cur_conf == conf_val)
529 return 0;
530
531 /* Set another configuration is currently not supported! */
532 if (udev->cur_conf != -1)
533 return USBH_ERR_SET_CONFIG;
534
535 /*------------------------------------------------------------------------------------*/
536 /* Issue SET CONFIGURATION command to select device configuration */
537 /*------------------------------------------------------------------------------------*/
538 ret = usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_STD_DEV | REQ_TYPE_TO_DEV,
539 USB_REQ_SET_CONFIGURATION, conf_val, 0, 0,
540 NULL, &read_len, 300);
541 if (ret < 0)
542 return ret;
543
544 udev->cur_conf = (int8_t)conf_val;
545
546 return 0;
547}
548
556int usbh_set_interface(IFACE_T *iface, uint16_t alt_setting)
557{
558 ALT_IFACE_T *aif = NULL;
559 uint32_t xfer_len;
560 int i, ret;
561
562 for (i = 0; i < iface->num_alt; i++)
563 {
564 if (iface->alt[i].ifd->bAlternateSetting == alt_setting)
565 {
566 aif = &iface->alt[i];
567 break;
568 }
569 }
570 if (aif == NULL)
571 return USBH_ERR_NOT_FOUND; /* cannot find desired alternative setting */
572
573 ret = usbh_ctrl_xfer(iface->udev, REQ_TYPE_OUT | REQ_TYPE_STD_DEV | REQ_TYPE_TO_IFACE,
574 USB_REQ_SET_INTERFACE, alt_setting, iface->if_num, 0,
575 NULL, &xfer_len, 100);
576 if (ret == 0)
577 iface->aif = aif; /* change active alternative setting */
578 return ret;
579}
580
588int usbh_get_device_descriptor(UDEV_T *udev, DESC_DEV_T *desc_buff)
589{
590 uint32_t read_len;
591 int ret, retry;
592 int timeout = 10;
593
594 for (retry = 0; retry < 3; retry++)
595 {
596 ret = usbh_ctrl_xfer(udev, REQ_TYPE_IN | REQ_TYPE_STD_DEV | REQ_TYPE_TO_DEV,
597 USB_REQ_GET_DESCRIPTOR,
598 ((USB_DT_STANDARD | USB_DT_DEVICE) << 8), 0, sizeof(DESC_DEV_T),
599 (uint8_t *)desc_buff, &read_len, timeout);
600 if (ret == 0)
601 return 0;
602
603 USB_debug("Get device descriptor failed - %d, retry!\n", ret);
604 }
605 return ret;
606}
607
616int usbh_get_config_descriptor(UDEV_T *udev, uint8_t *desc_buff, int buff_len)
617{
618 uint32_t read_len;
619 DESC_CONF_T *conf = (DESC_CONF_T *)desc_buff;
620 int ret;
621
622 /*------------------------------------------------------------------------------------*/
623 /* Issue GET DESCRIPTOR command to get configuration descriptor */
624 /*------------------------------------------------------------------------------------*/
625 ret = usbh_ctrl_xfer(udev, REQ_TYPE_IN | REQ_TYPE_STD_DEV | REQ_TYPE_TO_DEV,
626 USB_REQ_GET_DESCRIPTOR,
627 ((USB_DT_STANDARD | USB_DT_CONFIGURATION) << 8), 0, 9,
628 desc_buff, &read_len, 200);
629 if (ret < 0)
630 return ret;
631
632 if (conf->wTotalLength > buff_len)
633 {
634 USB_error("Device configuration %d length > %d!\n", conf->wTotalLength, buff_len);
636 }
637
638 read_len = conf->wTotalLength;
639
640 ret = usbh_ctrl_xfer(udev, REQ_TYPE_IN | REQ_TYPE_STD_DEV | REQ_TYPE_TO_DEV,
641 USB_REQ_GET_DESCRIPTOR,
642 ((USB_DT_STANDARD | USB_DT_CONFIGURATION) << 8), 0, read_len,
643 desc_buff, &read_len, 200);
644 if (ret < 0)
645 return ret;
646
647 return 0;
648}
649
660int usbh_get_string_descriptor(UDEV_T *udev, int index, uint8_t *desc_buff, int buff_len)
661{
662 uint32_t read_len;
663 int ret;
664
665 /*------------------------------------------------------------------------------------*/
666 /* Issue GET DESCRIPTOR command to get configuration descriptor */
667 /*------------------------------------------------------------------------------------*/
668 ret = usbh_ctrl_xfer(udev, REQ_TYPE_IN | REQ_TYPE_STD_DEV | REQ_TYPE_TO_DEV,
669 USB_REQ_GET_DESCRIPTOR,
670 ((USB_DT_STANDARD | USB_DT_STRING) << 8) | index, 0x0409, buff_len,
671 desc_buff, &read_len, 200);
672 return ret;
673}
674
682int usbh_clear_halt(UDEV_T *udev, uint16_t ep_addr)
683{
684 uint32_t read_len;
685
686 USB_debug("Clear endpoint 0x%x halt.\n", ep_addr);
687 return usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_STD_DEV | REQ_TYPE_TO_EP,
688 USB_REQ_CLEAR_FEATURE, 0, ep_addr, 0,
689 NULL, &read_len, 100);
690}
691
692static int usbh_parse_endpoint(ALT_IFACE_T *alt, int ep_idx, uint8_t *desc_buff, int len)
693{
694 DESC_EP_T *ep_desc;
695 int parsed_len = 0;
696 int pksz;
697
698 while (len > 0)
699 {
700 ep_desc = (DESC_EP_T *)desc_buff;
701
702 if ((len < ep_desc->bLength) || (ep_desc->bLength < 2))
703 {
704 USB_error("ERR DESCRIPTOR EP LEN [0x%X %d]\n", ep_desc->bDescriptorType, ep_desc->bLength);
705 return USBH_ERR_DESCRIPTOR;
706 }
707
708 if (ep_desc->bDescriptorType == USB_DT_ENDPOINT)
709 break; /* endpoint descriptor found */
710
711 /* unrecognized descriptor */
712 USB_vdebug("ignore descriptor 0x%X %d\n", ep_desc->bDescriptorType, ep_desc->bLength);
713 desc_buff += ep_desc->bLength;
714 parsed_len += ep_desc->bLength;
715 len -= ep_desc->bLength;
716 }
717
718 USB_vdebug("Descriptor Found - Alt: %d, Endpoint 0x%x, remaining len: %d\n", alt->ifd->bAlternateSetting, ep_desc->bEndpointAddress, len);
719
720 alt->ep[ep_idx].bEndpointAddress = ep_desc->bEndpointAddress;
721 alt->ep[ep_idx].bmAttributes = ep_desc->bmAttributes;
722 alt->ep[ep_idx].bInterval = ep_desc->bInterval;
723 pksz = ep_desc->wMaxPacketSize;
724 pksz = (pksz & 0x07ff) * (1 + ((pksz >> 11) & 3));
725 alt->ep[ep_idx].wMaxPacketSize = pksz;
726 alt->ep[ep_idx].hw_pipe = NULL;
727
728 return parsed_len + ep_desc->bLength;
729}
730
740static int usbh_parse_interface(UDEV_T *udev, uint8_t *desc_buff, int len)
741{
742 int i, matched, parsed_len = 0;
743 DESC_HDR_T *hdr;
744 DESC_IF_T *if_desc;
745 IFACE_T *iface = NULL;
746 int ret;
747
748 iface = usbh_alloc_mem(sizeof(*iface)); /* create an interface */
749 if (iface == NULL)
750 return USBH_ERR_MEMORY_OUT;
751 iface->udev = udev;
752 iface->aif = &iface->alt[0]; /* Default active interface should be the
753 first found alternative interface */
754 iface->if_num = ((DESC_IF_T *)desc_buff)->bInterfaceNumber;
755
756 while (len > 0)
757 {
758 /*--------------------------------------------------------------------------------*/
759 /* Find the first/next interface descriptor */
760 /*--------------------------------------------------------------------------------*/
761 if_desc = (DESC_IF_T *)desc_buff;
762
763 if (if_desc->bDescriptorType != USB_DT_INTERFACE)
764 {
765 desc_buff += if_desc->bLength;
766 parsed_len += if_desc->bLength;
767 len -= if_desc->bLength;
768 continue;
769 }
770
771 if (if_desc->bInterfaceNumber != iface->if_num)
772 {
773 goto parse_done;
774 }
775
776 if (if_desc->bNumEndpoints > MAX_EP_PER_IFACE)
777 {
778 USB_error("IF EP LIMITE %d\n", if_desc->bNumEndpoints);
780 goto err_out;
781 }
782
783 /* Step over the interface descriptor */
784 desc_buff += if_desc->bLength;
785 parsed_len += if_desc->bLength;
786 len -= if_desc->bLength;
787 USB_vdebug("Descriptor Found - Interface %d, Alt: %d, num_alt:%d, remaining len: %d\n", if_desc->bInterfaceNumber, if_desc->bAlternateSetting, iface->num_alt, len);
788
789 /*--------------------------------------------------------------------------------*/
790 /* Add to alternative interface list */
791 /*--------------------------------------------------------------------------------*/
792 if (iface->num_alt >= MAX_ALT_PER_IFACE)
793 {
795 goto err_out;
796 }
797
798 /*--------------------------------------------------------------------------------*/
799 /* Find the next alternative interface or endpoint descriptor */
800 /*--------------------------------------------------------------------------------*/
801 while (len > 0)
802 {
803 hdr = (DESC_HDR_T *)desc_buff;
804
805 if ((len < hdr->bLength) || (hdr->bLength < 2))
806 {
807 USB_error("ERR DESCRIPTOR IF LEN [0x%X %d]\n", hdr->bDescriptorType, hdr->bLength);
809 goto err_out;
810 }
811
812 if (hdr->bDescriptorType == USB_DT_CONFIGURATION)
813 goto parse_done; /* is other configuration, parsing completed */
814
815 if ((hdr->bDescriptorType == USB_DT_INTERFACE) || (hdr->bDescriptorType == USB_DT_ENDPOINT))
816 break; /* the first endpoint descriptor found */
817
818 /* unrecognized descriptor */
819 USB_vdebug("ignore descriptor 0x%X %d\n", hdr->bDescriptorType, hdr->bLength);
820 desc_buff += hdr->bLength;
821 parsed_len += hdr->bLength;
822 len -= hdr->bLength;
823 }
824
825 iface->alt[iface->num_alt].ifd = if_desc;
826 iface->num_alt++;
827
828 if (len == 0)
829 goto parse_done;
830
831 if (hdr->bDescriptorType == USB_DT_INTERFACE)
832 continue; /* is the next interface descriptor */
833
834 USB_vdebug("Finding %d endpoints of interface %d, alt %d...\n", if_desc->bNumEndpoints, if_desc->bInterfaceNumber, if_desc->bAlternateSetting);
835
836 /* parsign all endpoint descriptors */
837 for (i = 0; i < if_desc->bNumEndpoints; i++)
838 {
839 ret = usbh_parse_endpoint(&iface->alt[iface->num_alt-1], i, desc_buff, len);
840 if (ret < 0)
841 goto err_out;
842
843 desc_buff += ret;
844 parsed_len += ret;
845 len -= ret;
846 USB_vdebug("EP parse remaining %d\n", len);
847 }
848 }
849
850parse_done:
851
852 /*
853 * Probing all registered USB device drivers to find a matched driver.
854 */
855 matched = 0;
856 for (i = 0; i < MAX_UDEV_DRIVER; i++)
857 {
858 if ((_drivers[i] != NULL) && (_drivers[i]->probe(iface) == 0))
859 {
860 matched = 1;
861 break;
862 }
863 }
864
865 if (matched)
866 {
867 iface->driver = _drivers[i]; /* have a driver now */
868 iface->next = NULL;
869
870 /* Added this interface to USB device interface list */
871 if (udev->iface_list == NULL)
872 udev->iface_list = iface;
873 else
874 {
875 iface->next = udev->iface_list;
876 udev->iface_list = iface;
877 }
878 }
879 else
880 {
881 usbh_free_mem(iface, sizeof(*iface));
882 iface = NULL;
883 }
884
885 return parsed_len;
886
887err_out:
888 usbh_free_mem(iface, sizeof(*iface));
889 return ret;
890}
891
892
893static int usbh_parse_configuration(UDEV_T *udev, uint8_t *desc_buff)
894{
895 DESC_CONF_T *config = (DESC_CONF_T *)desc_buff;
896 DESC_HDR_T *hdr;
897 int i, ret, len;
898
899 len = config->wTotalLength;
900
901 desc_buff += config->bLength;
902 len -= config->bLength;
903
904 USB_vdebug("Parsing CONFIG =>\n");
905
906 for (i = 0; i < config->bNumInterfaces; i++)
907 {
908 /*
909 * find the next interface descriptor
910 */
911 while (len >= sizeof(DESC_HDR_T))
912 {
913 hdr = (DESC_HDR_T *)desc_buff;
914
915 if ((hdr->bLength > len) || (hdr->bLength < 2))
916 {
917 USB_error("ERR DESCRIPTOR CONFIG [%d]\n", hdr->bLength);
918 return USBH_ERR_DESCRIPTOR;
919 }
920
921 if (hdr->bDescriptorType == USB_DT_INTERFACE)
922 break;
923
924 USB_debug("ignore descriptor 0x%X %d\n", hdr->bDescriptorType, hdr->bLength);
925
926 desc_buff += hdr->bLength;
927 len -= hdr->bLength;
928 }
929
930 ret = usbh_parse_interface(udev, desc_buff, len);
931 if (ret < 0)
932 return ret;
933
934 desc_buff += ret;
935 len -= ret;
936 USB_vdebug("IFACE parse remaining %d\n", len);
937 }
938
939 if (len > 0)
940 {
941 USB_debug("ERR DESCRIPTOR CONFIG LEN %d\n", len);
942 return USBH_ERR_DESCRIPTOR;
943 }
944 return len;
945}
946
947void print_usb_string(char *lead, uint8_t *str)
948{
949 int len, i = 2;
950
951 USB_debug("%s", lead);
952 len = str[0];
953 while (i < len)
954 {
955 USB_debug("%c", str[i]);
956 i += 2;
957 }
958 USB_debug("\n");
959}
960
961int connect_device(UDEV_T *udev)
962{
963 DESC_CONF_T *conf;
964 uint32_t read_len;
965 int ret;
966
967 USB_debug("Connect device =>\n");
968
969 delay_us(100 * 1000); /* initially, give 100 ms delay */
970
971 usbh_get_device_descriptor(udev, &udev->descriptor);
972
973 reset_device(udev);
974
975 delay_us(100 * 1000);
976
977 ret = usbh_set_address(udev);
978 if (ret < 0)
979 {
980 USB_debug("Set address command failed!!\n");
981 return ret;
982 }
983
984 delay_us(100 * 1000); /* after set address, give 100 ms delay */
985
986 USB_debug("New %s device address %d assigned.\n", (udev->speed == SPEED_HIGH) ? "high-speed" : ((udev->speed == SPEED_FULL) ? "full-speed" : "low-speed"), udev->dev_num);
987
988 /* Get device descriptor again with new device address */
989 ret = usbh_get_device_descriptor(udev, &udev->descriptor);
990 if (ret < 0)
991 {
992 free_dev_address(udev->dev_num);
993 return ret;
994 }
995
996#if defined(DUMP_DESCRIPTOR) && defined(ENABLE_DEBUG_MSG)
997 dump_device_descriptor(&udev->descriptor);
998#endif
999
1000 if (udev->descriptor.bNumConfigurations != 1)
1001 {
1002 USB_debug("Warning! This device has multiple configurations [%d]. \n", udev->descriptor.bNumConfigurations);
1003 }
1004
1005 conf = (DESC_CONF_T *)usbh_alloc_mem(MAX_DESC_BUFF_SIZE);
1006 if (conf == NULL)
1007 {
1008 free_dev_address(udev->dev_num);
1009 return USBH_ERR_MEMORY_OUT;
1010 }
1011
1012 udev->cfd_buff = (uint8_t *)conf;
1013
1014 /* Get configuration descriptor again with new device address */
1015 ret = usbh_get_config_descriptor(udev, (uint8_t *)conf, MAX_DESC_BUFF_SIZE);
1016 if (ret < 0)
1017 {
1018 free_dev_address(udev->dev_num);
1019 return ret;
1020 }
1021
1022#if defined(DUMP_DESCRIPTOR) && defined(ENABLE_DEBUG_MSG)
1023 dump_config_descriptor(conf);
1024#endif
1025
1026#if 0 /* printf string descriptors, for debug only */
1027 str_buff = (uint8_t *)usbh_alloc_mem(MAX_DESC_BUFF_SIZE);
1028 if (udev->descriptor.iManufacturer != 0)
1029 {
1030 usbh_get_string_descriptor(udev, udev->descriptor.iManufacturer, str_buff, MAX_DESC_BUFF_SIZE);
1031 print_usb_string("Manufactor: ", str_buff);
1032 }
1033 if (udev->descriptor.iProduct != 0)
1034 {
1035 usbh_get_string_descriptor(udev, udev->descriptor.iProduct, str_buff, MAX_DESC_BUFF_SIZE);
1036 print_usb_string("Product: ", str_buff);
1037 }
1038 if (udev->descriptor.iSerialNumber != 0)
1039 {
1040 usbh_get_string_descriptor(udev, udev->descriptor.iSerialNumber, str_buff, MAX_DESC_BUFF_SIZE);
1041 print_usb_string("Serial Number: ", str_buff);
1042 }
1043 usbh_free_mem(str_buff, MAX_DESC_BUFF_SIZE);
1044#endif
1045
1046 /* Always select the first configuration */
1047 ret = usbh_set_configuration(udev, conf->bConfigurationValue);
1048 if (ret < 0)
1049 {
1050 USB_debug("Set configuration %d failed!\n", conf->bConfigurationValue);
1051 free_dev_address(udev->dev_num);
1052 return ret;
1053 }
1054
1055 /* Parse the configuration/interface/endpoint descriptors and find corresponding drivers. */
1056 ret = usbh_parse_configuration(udev, (uint8_t *)conf);
1057 if (ret < 0)
1058 {
1059 USB_debug("Parse configuration %d failed!\n", conf->bConfigurationValue);
1060 free_dev_address(udev->dev_num);
1061 return ret;
1062 }
1063
1064 if (conf->bmAttributes & (1<<5))
1065 {
1066 /* If this configuration supports remote wakeup, enable it. */
1067 if (usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_STD_DEV | REQ_TYPE_TO_DEV,
1068 USB_REQ_SET_FEATURE, 0x01, 0x0000, 0x0000,
1069 NULL, &read_len, 300) < 0)
1070 {
1071 USB_debug("Device does not accept remote wakeup enable command.\n");
1072 }
1073 }
1074
1075 if (g_conn_func)
1076 g_conn_func(udev, 0);
1077
1078 return ret;
1079}
1080
1081int usbh_reset_device(UDEV_T *udev)
1082{
1083 IFACE_T *iface;
1084 DESC_CONF_T *conf;
1085 uint32_t read_len;
1086 int dev_num, ret;
1087
1088 USB_debug("Reset device =>\n");
1089
1091
1092 /*------------------------------------------------------------------------------------*/
1093 /* Disconnect device */
1094 /*------------------------------------------------------------------------------------*/
1095
1096 if (g_disconn_func)
1097 g_disconn_func(udev, 0);
1098
1099 usbh_quit_xfer(udev, &(udev->ep0)); /* Quit control transfer if hw_pipe is not NULL. */
1100
1101 /* Notified all actived interface device driver */
1102 iface = udev->iface_list;
1103 while (iface != NULL)
1104 {
1105 udev->iface_list = iface->next;
1106 iface->driver->disconnect(iface);
1107 usbh_free_mem(iface, sizeof(*iface));
1108 iface = udev->iface_list;
1109 }
1110
1111 /*------------------------------------------------------------------------------------*/
1112 /* Reset device */
1113 /*------------------------------------------------------------------------------------*/
1114
1115 reset_device(udev);
1116
1117 delay_us(100 * 1000);
1118
1119 /*------------------------------------------------------------------------------------*/
1120 /* Set address (use current address) */
1121 /*------------------------------------------------------------------------------------*/
1122
1123 dev_num = udev->dev_num;
1124 udev->dev_num = 0;
1125 /* Issue SET ADDRESS command to set the same device address */
1126 ret = usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_STD_DEV | REQ_TYPE_TO_DEV,
1127 USB_REQ_SET_ADDRESS, dev_num, 0, 0,
1128 NULL, &read_len, 100);
1129 udev->dev_num = dev_num;
1130 if (ret < 0)
1131 return ret;
1132
1133 delay_us(100 * 1000); /* after set address, give 100 ms delay */
1134
1135 /*------------------------------------------------------------------------------------*/
1136 /* Get device descriptor */
1137 /*------------------------------------------------------------------------------------*/
1138
1139 /* Get device descriptor again with new device address */
1140 ret = usbh_get_device_descriptor(udev, &udev->descriptor);
1141 if (ret < 0)
1142 return ret;
1143
1144 /*------------------------------------------------------------------------------------*/
1145 /* Get configuration descriptor */
1146 /*------------------------------------------------------------------------------------*/
1147
1148 conf = (DESC_CONF_T *)udev->cfd_buff; /* using the previously allocated buffer */
1149
1150 /* Get configuration descriptor again with new device address */
1151 ret = usbh_get_config_descriptor(udev, (uint8_t *)conf, MAX_DESC_BUFF_SIZE);
1152 if (ret < 0)
1153 return ret;
1154
1155 /* Always select the first configuration */
1156 ret = usbh_set_configuration(udev, udev->cur_conf);
1157 if (ret < 0)
1158 {
1159 USB_debug("Set configuration %d failed!\n", udev->cur_conf);
1160 return ret;
1161 }
1162
1163 /* Parse the configuration/interface/endpoint descriptors and find corresponding drivers. */
1164 ret = usbh_parse_configuration(udev, (uint8_t *)conf);
1165 if (ret < 0)
1166 {
1167 USB_debug("Parse configuration %d failed!\n", conf->bConfigurationValue);
1168 return ret;
1169 }
1170
1171 /* Enable remote wakeup */
1172 if (usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_STD_DEV | REQ_TYPE_TO_DEV,
1173 USB_REQ_SET_FEATURE, 0x01, 0x0000, 0x0000,
1174 NULL, &read_len, 300) < 0)
1175 {
1176 USB_debug("Device not accept remote wakeup enable command.\n");
1177 }
1178
1179 if (g_conn_func)
1180 g_conn_func(udev, 0);
1181
1182 return ret;
1183}
1184
1185void disconnect_device(UDEV_T *udev)
1186{
1187 IFACE_T *iface;
1188
1189 USB_debug("disconnect device...\n");
1190
1191 if (g_disconn_func)
1192 g_disconn_func(udev, 0);
1193
1194 usbh_quit_xfer(udev, &(udev->ep0)); /* Quit control transfer if hw_pipe is not NULL. */
1195
1196 /* Notified all actived interface device driver */
1197 iface = udev->iface_list;
1198 while (iface != NULL)
1199 {
1200 udev->iface_list = iface->next;
1201 iface->driver->disconnect(iface);
1202 usbh_free_mem(iface, sizeof(*iface));
1203 iface = udev->iface_list;
1204 }
1205
1206 /* remove device from global device list */
1207 free_dev_address(udev->dev_num);
1208 free_device(udev);
1209
1210 usbh_memory_used();
1211}
1212
1213#if 0
1214static int check_device(UDEV_T *udev)
1215{
1216 UDEV_T *d;
1217
1218 if (udev == NULL)
1220
1221 //if ((udev->hc_driver != &ohci_driver) && (udev->hc_driver != &ehci_driver))
1222 // return USBH_ERR_INVALID_PARAM;
1223
1224 d = g_udev_list;
1225 while (d)
1226 {
1227 if (d == udev)
1228 return USBH_OK;
1229 d = d->next;
1230 }
1232}
1233#endif
1234
1235EP_INFO_T * usbh_iface_find_ep(IFACE_T *iface, uint8_t ep_addr, uint8_t dir_type)
1236{
1237 ALT_IFACE_T *aif = iface->aif;
1238 int i;
1239
1240 if (ep_addr == 0) /* find the first EP matched with specified direction and type */
1241 {
1242 for (i = 0; i < aif->ifd->bNumEndpoints; i++)
1243 {
1244 if (((aif->ep[i].bEndpointAddress & EP_ADDR_DIR_MASK) == (dir_type & EP_ADDR_DIR_MASK)) &&
1245 ((aif->ep[i].bmAttributes & EP_ATTR_TT_MASK) == (dir_type & EP_ATTR_TT_MASK)))
1246 return &aif->ep[i];
1247 }
1248 }
1249 else /* find the EP with specified endpoint address */
1250 {
1251 for (i = 0; i < aif->ifd->bNumEndpoints; i++)
1252 {
1253 if (aif->ep[i].bEndpointAddress == ep_addr)
1254 return &aif->ep[i];
1255 }
1256 }
1257 return NULL;
1258}
1259
1260void usbh_dump_buff_bytes(uint8_t *buff, int nSize)
1261{
1262 int nIdx, i;
1263
1264 nIdx = 0;
1265 while (nSize > 0)
1266 {
1267 printf("0x%04X ", nIdx);
1268 for (i = 0; i < 16; i++)
1269 printf("%02x ", buff[nIdx + i]);
1270 printf(" ");
1271 for (i = 0; i < 16; i++)
1272 {
1273 if ((buff[nIdx + i] >= 0x20) && (buff[nIdx + i] < 127))
1274 printf("%c", buff[nIdx + i]);
1275 else
1276 printf(".");
1277 nSize--;
1278 }
1279 nIdx += 16;
1280 printf("\n");
1281 }
1282 printf("\n");
1283}
1284
1285void usbh_dump_iface(IFACE_T *iface)
1286{
1287 USB_debug("\n [IFACE info] (0x%x)\n", (int)iface);
1288 USB_debug(" ----------------------------------------------\n");
1289 USB_debug(" udev = 0x%x\n", iface->udev);
1290 USB_debug(" if_num = %d\n", iface->if_num);
1291 USB_debug(" driver = 0x%x\n", (int)iface->driver);
1292 USB_debug(" next = 0x%x\n", (int)iface->next);
1293 usbh_dump_interface_descriptor(iface->aif->ifd);
1294}
1295
1296void usbh_dump_ep_info(EP_INFO_T *ep)
1297{
1298 USB_debug("\n [Endpoint Info] (0x%x)\n", (int)ep);
1299 USB_debug(" ----------------------------------------------\n");
1300 USB_debug(" bEndpointAddress = 0x%02x\n", ep->bEndpointAddress);
1301 USB_debug(" bmAttributes = 0x%02x\n", ep->bmAttributes);
1302 USB_debug(" bInterval = %d\n", ep->bInterval);
1303 USB_debug(" wMaxPacketSize = %d\n", ep->wMaxPacketSize);
1304 USB_debug(" hw_pipe = 0x%x\n", (int)ep->hw_pipe);
1305}
1306
1308
1309
1310/*** (C) COPYRIGHT 2017 Nuvoton Technology Corp. ***/
NuMicro peripheral access layer header file.
@ USBH_IRQn
Definition: M480.h:134
@ HSUSBH_IRQn
Definition: M480.h:167
#define NULL
NULL pointer.
Definition: M480.h:605
#define HSUSBH
Definition: M480.h:389
#define USBH
Definition: M480.h:388
#define SYS
Definition: M480.h:367
#define HSUSBH_UCMDR_RUN_Msk
Definition: hsusbh_reg.h:1026
#define SYS_CSERVER_VERSION_Msk
Definition: sys_reg.h:6034
#define HSUSBH_UPSCR_PE_Msk
Definition: hsusbh_reg.h:1116
#define USBH_HcRhStatus_DRWE_Msk
Definition: usbh_reg.h:1380
#define HSUSBH_UCMDR_ASEN_Msk
Definition: hsusbh_reg.h:1038
#define USBH_HcRhPortStatus_PSS_Msk
Definition: usbh_reg.h:1398
#define HSUSBH_USTSR_HCHalted_Msk
Definition: hsusbh_reg.h:1065
#define HSUSBH_UPSCR_SUSPEND_Msk
Definition: hsusbh_reg.h:1131
#define USBH_HcMiscControl_OCAL_Msk
Definition: usbh_reg.h:1434
#define USBH_HcInterruptEnable_RD_Msk
Definition: usbh_reg.h:1281
#define HSUSBH_UCMDR_PSEN_Msk
Definition: hsusbh_reg.h:1035
#define USBH_HcInterruptEnable_RHSC_Msk
Definition: usbh_reg.h:1287
#define USBH_HcControl_HCFS_Pos
Definition: usbh_reg.h:1238
#define USBH_HcRhPortStatus_CCS_Msk
Definition: usbh_reg.h:1392
#define USBH_HcRhPortStatus_POCI_Msk
Definition: usbh_reg.h:1401
#define HSUSBH_UPSCR_FPR_Msk
Definition: hsusbh_reg.h:1128
#define USBH_ERR_TIMEOUT
Definition: usbh_lib.h:46
#define USBH_ERR_SET_CONFIG
Definition: usbh_lib.h:43
#define USBH_ERR_SET_DEV_ADDR
Definition: usbh_lib.h:42
#define USBH_OK
Definition: usbh_lib.h:31
#define USBH_ERR_INVALID_PARAM
Definition: usbh_lib.h:38
#define USBH_ERR_IF_EP_LIMIT
Definition: usbh_lib.h:34
#define USBH_ERR_NOT_FOUND
Definition: usbh_lib.h:39
#define USBH_ERR_DESCRIPTOR
Definition: usbh_lib.h:41
#define USBH_ERR_DATA_OVERRUN
Definition: usbh_lib.h:64
#define USBH_ERR_IF_ALT_LIMIT
Definition: usbh_lib.h:33
#define USBH_ERR_MEMORY_OUT
Definition: usbh_lib.h:32
void usbh_suspend()
Suspend USB Host Controller and devices.
Definition: usb_core.c:115
int usbh_pooling_hubs(void)
Let USB stack polls all root hubs and downstream hubs. If there's any hub port change found,...
Definition: hub.c:637
HIDDEN_SYMBOLS void usbh_core_init()
Initialize M480 USB Host controller and USB stack.
Definition: usb_core.c:39
void usbh_install_conn_callback(CONN_FUNC *conn_func, CONN_FUNC *disconn_func)
Install device connect and disconnect callback function.
Definition: usb_core.c:86
uint32_t get_ticks(void)
A function return current tick count.
void usbh_resume(void)
Resume USB Host controller and devices.
Definition: usb_core.c:176
void() CONN_FUNC(struct udev_t *udev, int param)
Definition: usbh_lib.h:116
USB Host hub class driver header file.
__IO uint32_t USBPCR1
Definition: hsusbh_reg.h:983
__IO uint32_t UPSCR[2]
Definition: hsusbh_reg.h:978
__IO uint32_t UCMDR
Definition: hsusbh_reg.h:964
__IO uint32_t USTSR
Definition: hsusbh_reg.h:965
__IO uint32_t USBPCR0
Definition: hsusbh_reg.h:982
__IO uint32_t HcRhPortStatus[2]
Definition: usbh_reg.h:1206
__IO uint32_t HcControl
Definition: usbh_reg.h:1186
__IO uint32_t HcMiscControl
Definition: usbh_reg.h:1211
__IO uint32_t HcRhStatus
Definition: usbh_reg.h:1205
__IO uint32_t HcInterruptEnable
Definition: usbh_reg.h:1189
USB Host library header file.
static int reset_device(UDEV_T *udev)
Definition: usb_core.c:92