M480 BSP V3.05.006
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
31static int _ovc_active_high = 0;
32
34
35
42{
43 NVIC_DisableIRQ(HSUSBH_IRQn);
44 NVIC_DisableIRQ(USBH_IRQn);
45
46 _ohci = USBH;
47 _ehci = HSUSBH;
48
49 memset(_drivers, 0, sizeof(_drivers));
50
51 g_conn_func = NULL;
52 g_disconn_func = NULL;
53
54 usbh_hub_init();
55
56 if ((SYS->CSERVER & SYS_CSERVER_VERSION_Msk) == 0x0) /* Only M480MD has EHCI. */
57 {
58 _ehci->USBPCR0 = 0x160; /* enable PHY 0 */
59 _ehci->USBPCR1 = 0x520; /* enable PHY 1 */
60 }
61
62 usbh_memory_init();
63
64 if (_ovc_active_high)
65 _ohci->HcMiscControl &= ~USBH_HcMiscControl_OCAL_Msk; /* Over-current active high */
66 else
67 _ohci->HcMiscControl |= USBH_HcMiscControl_OCAL_Msk; /* Over-current active low */
68
69#ifdef ENABLE_OHCI
70 ohci_driver.init();
71 ENABLE_OHCI_IRQ();
72#endif
73
74#ifdef ENABLE_EHCI
75 if ((SYS->CSERVER & SYS_CSERVER_VERSION_Msk) == 0x0) /* Only M480MD has EHCI. */
76 {
77 ehci_driver.init();
78 ENABLE_EHCI_IRQ();
79 }
80#endif
81}
82
91void usbh_core_init_ex(int ovc_alv)
92{
93 _ovc_active_high = ovc_alv;
95}
96
104void usbh_install_conn_callback(CONN_FUNC *conn_func, CONN_FUNC *disconn_func)
105{
106 g_conn_func = conn_func;
107 g_disconn_func = disconn_func;
108}
109
110static int reset_device(UDEV_T *udev)
111{
112 if (udev->parent == NULL)
113 {
114 if (udev->hc_driver)
115 return udev->hc_driver->rthub_port_reset(udev->port_num-1);
116 else
117 return USBH_ERR_NOT_FOUND;
118 }
119 else
120 {
121 return udev->parent->port_reset(udev->parent, udev->port_num);
122 }
123}
124
125#ifdef ENABLE_EHCI
126static uint32_t ehci_UCMDR;
127#endif
128
134{
135#ifdef ENABLE_EHCI
136 int time_out = 10; /* ms */
137#endif
138
139#ifdef ENABLE_OHCI
140 /* set port suspend if connected */
141 if ((SYS->CSERVER & SYS_CSERVER_VERSION_Msk) == 0x0)
142 {
143 /* M480MD has port1, but M480LD has not port1 */
145 _ohci->HcRhPortStatus[0] = USBH_HcRhPortStatus_PSS_Msk; /* set port suspend */
146 }
147
149 _ohci->HcRhPortStatus[1] = USBH_HcRhPortStatus_PSS_Msk; /* set port suspend */
150
151 /* enable Device Remote Wakeup */
153
154 /* enable USBH RHSC interrupt for system wakeup */
156
157 /* set Host Controller enter suspend state */
158 _ohci->HcControl = (_ohci->HcControl & ~USBH_HcControl_HCFS_Msk) | (3 << USBH_HcControl_HCFS_Pos);
159#endif
160
161#ifdef ENABLE_EHCI
162 if ((SYS->CSERVER & SYS_CSERVER_VERSION_Msk) == 0x0) /* Only M480MD has EHCI. */
163 {
164 ehci_UCMDR = _ehci->UCMDR;
165
166 if (_ehci->UPSCR[0] & HSUSBH_UPSCR_PE_Msk)
167 {
168 _ehci->UPSCR[0] |= HSUSBH_UPSCR_SUSPEND_Msk;
169 delay_us(2000); /* wait 2 ms */
170 }
171
173 while (time_out > 0)
174 {
175 if (!(_ehci->UCMDR & HSUSBH_UCMDR_RUN_Msk) && (_ehci->USTSR & HSUSBH_USTSR_HCHalted_Msk))
176 {
177 break;
178 }
179 }
180 if (time_out == 0)
181 {
182 USB_error("usbh_suspend - RUN/HCHalted error!\n");
183 }
184 delay_us(100);
185 }
186#endif
187}
188
189
194void usbh_resume(void)
195{
196#ifdef ENABLE_OHCI
197 _ohci->HcControl = (_ohci->HcControl & ~USBH_HcControl_HCFS_Msk) | (1 << USBH_HcControl_HCFS_Pos);
198
199 if ((SYS->CSERVER & SYS_CSERVER_VERSION_Msk) == 0x0)
200 {
202 _ohci->HcRhPortStatus[0] = USBH_HcRhPortStatus_POCI_Msk; /* clear suspend status */
203 }
205 _ohci->HcRhPortStatus[1] = USBH_HcRhPortStatus_POCI_Msk; /* clear suspend status */
206
207 delay_us(30000); /* wait at least 20ms for Host to resume device */
208
209 /* enter operational state */
210 _ohci->HcControl = (_ohci->HcControl & ~USBH_HcControl_HCFS_Msk) | (2 << USBH_HcControl_HCFS_Pos);
211#endif
212
213#ifdef ENABLE_EHCI
214 if ((SYS->CSERVER & SYS_CSERVER_VERSION_Msk) == 0x0) /* Only M480MD has EHCI. */
215 {
216 _ehci->UCMDR = ehci_UCMDR;
217
218 if (_ehci->UPSCR[0] & HSUSBH_UPSCR_PE_Msk)
219 {
220 _ehci->UPSCR[0] |= HSUSBH_UPSCR_FPR_Msk;
221 delay_us(20000); /* keep resume signal for 20 ms */
222 _ehci->UPSCR[0] &= ~HSUSBH_UPSCR_FPR_Msk;
223 }
224 delay_us(1000);
225 }
226#endif
227}
228
229
230
232
241int usbh_register_driver(UDEV_DRV_T *udrv)
242{
243 int i;
244
245 for (i = 0; i < MAX_UDEV_DRIVER; i++)
246 {
247 if (_drivers[i] == udrv)
248 return 0; /* already registered, do nothing */
249
250 if (_drivers[i] == NULL)
251 {
252 _drivers[i] = udrv; /* register this driver */
253 return 0;
254 }
255 }
256 return USBH_ERR_MEMORY_OUT; /* reached MAX_UDEV_DRIVER limitation, aborted */
257}
258
259
276int usbh_ctrl_xfer(UDEV_T *udev, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex,
277 uint16_t wLength, uint8_t *buff, uint32_t *xfer_len, uint32_t timeout)
278{
279 UTR_T *utr;
280 uint32_t t0;
281 int status;
282
283 *xfer_len = 0;
284
285 //if (check_device(udev))
286 // return USBH_ERR_INVALID_PARAM;
287
288 utr = alloc_utr(udev);
289 if (utr == NULL)
290 return USBH_ERR_MEMORY_OUT;
291
292 utr->setup.bmRequestType = bmRequestType;
293 utr->setup.bRequest = bRequest;
294 utr->setup.wValue = wValue;
295 utr->setup.wIndex = wIndex;
296 utr->setup.wLength = wLength;
297
298 utr->buff = buff;
299 utr->data_len = wLength;
300 utr->bIsTransferDone = 0;
301 status = udev->hc_driver->ctrl_xfer(utr);
302 if (status < 0)
303 {
304 udev->ep0.hw_pipe = NULL;
305 free_utr(utr);
306 return status;
307 }
308
309 t0 = get_ticks();
310 while (utr->bIsTransferDone == 0)
311 {
312 if (get_ticks() - t0 > timeout)
313 {
314 usbh_quit_utr(utr);
315 free_utr(utr);
316 udev->ep0.hw_pipe = NULL;
317 return USBH_ERR_TIMEOUT;
318 }
319 }
320
321 status = utr->status;
322
323 if (status == 0)
324 {
325 *xfer_len = utr->xfer_len;
326 }
327 free_utr(utr);
328
329 return status;
330}
331
332
341int usbh_bulk_xfer(UTR_T *utr)
342{
343 return utr->udev->hc_driver->bulk_xfer(utr);
344}
345
354int usbh_int_xfer(UTR_T *utr)
355{
356 return utr->udev->hc_driver->int_xfer(utr);
357}
358
367int usbh_iso_xfer(UTR_T *utr)
368{
369 if (utr->udev->hc_driver == NULL)
370 {
371 printf("hc_driver - 0x%x\n", (int)utr->udev->hc_driver);
372 return -1;
373 }
374 if (utr->udev->hc_driver->iso_xfer == NULL)
375 {
376 printf("iso_xfer - 0x%x\n", (int)utr->udev->hc_driver->iso_xfer);
377 return -1;
378 }
379 return utr->udev->hc_driver->iso_xfer(utr);
380}
381
388int usbh_quit_utr(UTR_T *utr)
389{
390 if (!utr || !utr->udev)
391 return USBH_ERR_NOT_FOUND;
392
393 return utr->udev->hc_driver->quit_xfer(utr, NULL);
394}
395
396
404int usbh_quit_xfer(UDEV_T *udev, EP_INFO_T *ep)
405{
406 return udev->hc_driver->quit_xfer(NULL, ep);
407}
408
409
410void dump_device_descriptor(DESC_DEV_T *desc)
411{
412 USB_debug("\n[Device Descriptor]\n");
413 USB_debug("----------------------------------------------\n");
414 USB_debug(" Length = %2d\n", desc->bLength);
415 USB_debug(" DescriptorType = 0x%02x\n", desc->bDescriptorType);
416 USB_debug(" USB version = %x.%02x\n",
417 desc->bcdUSB >> 8, desc->bcdUSB & 0xff);
418 USB_debug(" Vendor:Product = %04x:%04x\n",
419 desc->idVendor, desc->idProduct);
420 USB_debug(" MaxPacketSize0 = %d\n", desc->bMaxPacketSize0);
421 USB_debug(" NumConfigurations = %d\n", desc->bNumConfigurations);
422 USB_debug(" Device version = %x.%02x\n",
423 desc->bcdDevice >> 8, desc->bcdDevice & 0xff);
424 USB_debug(" Device Class:SubClass:Protocol = %02x:%02x:%02x\n",
425 desc->bDeviceClass, desc->bDeviceSubClass, desc->bDeviceProtocol);
426}
427
428void usbh_dump_interface_descriptor(DESC_IF_T *if_desc)
429{
430 USB_debug("\n [Interface Descriptor]\n");
431 USB_debug(" ----------------------------------------------\n");
432 USB_debug(" Length = %2d\n", if_desc->bLength);
433 USB_debug(" DescriptorType = %02x\n", if_desc->bDescriptorType);
434 USB_debug(" bInterfaceNumber = %d\n", if_desc->bInterfaceNumber);
435 USB_debug(" bAlternateSetting = %d\n", if_desc->bAlternateSetting);
436 USB_debug(" bNumEndpoints = %d\n", if_desc->bNumEndpoints);
437 USB_debug(" bInterfaceClass = 0x%02x\n", if_desc->bInterfaceClass);
438 USB_debug(" bInterfaceSubClass = 0x%02x\n", if_desc->bInterfaceSubClass);
439 USB_debug(" bInterfaceProtocol = 0x%02x\n", if_desc->bInterfaceProtocol);
440 USB_debug(" iInterface = %d\n", if_desc->iInterface);
441}
442
443void usbh_dump_endpoint_descriptor(DESC_EP_T *ep_desc)
444{
445 USB_debug("\n [Endpoint Descriptor]\n");
446 USB_debug(" ----------------------------------------------\n");
447 USB_debug(" Length = %2d\n", ep_desc->bLength);
448 USB_debug(" DescriptorType = %02x\n", ep_desc->bDescriptorType);
449 USB_debug(" bEndpointAddress = 0x%02x\n", ep_desc->bEndpointAddress);
450 USB_debug(" bmAttributes = 0x%02x\n", ep_desc->bmAttributes);
451 USB_debug(" wMaxPacketSize = %d\n", ep_desc->wMaxPacketSize);
452 USB_debug(" bInterval = %d\n", ep_desc->bInterval);
453 USB_debug(" bRefresh = %d\n", ep_desc->bRefresh);
454 USB_debug(" bSynchAddress = %d\n", ep_desc->bSynchAddress);
455}
456
457void dump_config_descriptor(DESC_CONF_T *desc)
458{
459 uint8_t *bptr = (uint8_t *)desc;
460 DESC_HDR_T *hdr;
461 int tlen = desc->wTotalLength;
462
463 while (tlen > 0)
464 {
465 switch (bptr[1])
466 {
467 case USB_DT_CONFIGURATION:
468 USB_debug("\n[Configuration Descriptor]\n");
469 USB_debug("----------------------------------------------\n");
470 USB_debug(" Length = %2d\n", desc->bLength);
471 USB_debug(" DescriptorType = %02x\n", desc->bDescriptorType);
472 USB_debug(" wTotalLength = %2d\n", desc->wTotalLength);
473 USB_debug(" bNumInterfaces = %d\n", desc->bNumInterfaces);
474 USB_debug(" bConfigurationValue = %d\n", desc->bConfigurationValue);
475 USB_debug(" iConfiguration = %d\n", desc->iConfiguration);
476 USB_debug(" bmAttributes = 0x%02x\n", desc->bmAttributes);
477 USB_debug(" MaxPower = %d\n", desc->MaxPower);
478 break;
479
480 case USB_DT_INTERFACE:
481 usbh_dump_interface_descriptor((DESC_IF_T *)bptr);
482 break;
483
484 case USB_DT_ENDPOINT:
485 usbh_dump_endpoint_descriptor((DESC_EP_T *)bptr);
486 break;
487
488 default:
489 hdr = (DESC_HDR_T *)bptr;
490 USB_debug("\n!![Unknown Descriptor]\n");
491 USB_debug("----------------------------------------------\n");
492 USB_debug("Length = %2d\n", hdr->bLength);
493 USB_debug("DescriptorType = %02x\n", hdr->bDescriptorType);
494 break;
495 }
496 if (bptr[0] == 0)
497 break;
498 tlen -= bptr[0];
499 bptr += bptr[0];
500 }
501}
502
508int usbh_set_address(UDEV_T *udev)
509{
510 uint32_t read_len;
511 int dev_num, ret;
512
513 if (udev->dev_num != 0)
515
516 dev_num = alloc_dev_address();
517
518 /*------------------------------------------------------------------------------------*/
519 /* Issue SET ADDRESS command to set device address */
520 /*------------------------------------------------------------------------------------*/
521 ret = usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_STD_DEV | REQ_TYPE_TO_DEV,
522 USB_REQ_SET_ADDRESS, dev_num, 0, 0,
523 NULL, &read_len, 100);
524 if (ret < 0)
525 {
526 free_dev_address(dev_num);
527 return ret;
528 }
529
530 udev->dev_num = dev_num;
531
532 return 0;
533}
534
540int usbh_set_configuration(UDEV_T *udev, uint8_t conf_val)
541{
542 uint32_t read_len;
543 int ret;
544
545 /* Current configuration is the same. Do nothing. */
546 if (udev->cur_conf == conf_val)
547 return 0;
548
549 /* Set another configuration is currently not supported! */
550 if (udev->cur_conf != -1)
551 return USBH_ERR_SET_CONFIG;
552
553 /*------------------------------------------------------------------------------------*/
554 /* Issue SET CONFIGURATION command to select device configuration */
555 /*------------------------------------------------------------------------------------*/
556 ret = usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_STD_DEV | REQ_TYPE_TO_DEV,
557 USB_REQ_SET_CONFIGURATION, conf_val, 0, 0,
558 NULL, &read_len, 300);
559 if (ret < 0)
560 return ret;
561
562 udev->cur_conf = (int8_t)conf_val;
563
564 return 0;
565}
566
574int usbh_set_interface(IFACE_T *iface, uint16_t alt_setting)
575{
576 ALT_IFACE_T *aif = NULL;
577 uint32_t xfer_len;
578 int i, ret;
579
580 for (i = 0; i < iface->num_alt; i++)
581 {
582 if (iface->alt[i].ifd->bAlternateSetting == alt_setting)
583 {
584 aif = &iface->alt[i];
585 break;
586 }
587 }
588 if (aif == NULL)
589 return USBH_ERR_NOT_FOUND; /* cannot find desired alternative setting */
590
591 ret = usbh_ctrl_xfer(iface->udev, REQ_TYPE_OUT | REQ_TYPE_STD_DEV | REQ_TYPE_TO_IFACE,
592 USB_REQ_SET_INTERFACE, alt_setting, iface->if_num, 0,
593 NULL, &xfer_len, 100);
594 if (ret == 0)
595 iface->aif = aif; /* change active alternative setting */
596 return ret;
597}
598
606int usbh_get_device_descriptor(UDEV_T *udev, DESC_DEV_T *desc_buff)
607{
608 uint32_t read_len;
609 int ret, retry;
610 int timeout = 10;
611
612 for (retry = 0; retry < 3; retry++)
613 {
614 ret = usbh_ctrl_xfer(udev, REQ_TYPE_IN | REQ_TYPE_STD_DEV | REQ_TYPE_TO_DEV,
615 USB_REQ_GET_DESCRIPTOR,
616 ((USB_DT_STANDARD | USB_DT_DEVICE) << 8), 0, sizeof(DESC_DEV_T),
617 (uint8_t *)desc_buff, &read_len, timeout);
618 if (ret == 0)
619 return 0;
620
621 USB_debug("Get device descriptor failed - %d, retry!\n", ret);
622 }
623 return ret;
624}
625
634int usbh_get_config_descriptor(UDEV_T *udev, uint8_t *desc_buff, int buff_len)
635{
636 uint32_t read_len;
637 DESC_CONF_T *conf = (DESC_CONF_T *)desc_buff;
638 int ret;
639
640 /*------------------------------------------------------------------------------------*/
641 /* Issue GET DESCRIPTOR command to get configuration descriptor */
642 /*------------------------------------------------------------------------------------*/
643 ret = usbh_ctrl_xfer(udev, REQ_TYPE_IN | REQ_TYPE_STD_DEV | REQ_TYPE_TO_DEV,
644 USB_REQ_GET_DESCRIPTOR,
645 ((USB_DT_STANDARD | USB_DT_CONFIGURATION) << 8), 0, 9,
646 desc_buff, &read_len, 200);
647 if (ret < 0)
648 return ret;
649
650 if (conf->wTotalLength > buff_len)
651 {
652 USB_error("Device configuration %d length > %d!\n", conf->wTotalLength, buff_len);
654 }
655
656 read_len = conf->wTotalLength;
657
658 ret = usbh_ctrl_xfer(udev, REQ_TYPE_IN | REQ_TYPE_STD_DEV | REQ_TYPE_TO_DEV,
659 USB_REQ_GET_DESCRIPTOR,
660 ((USB_DT_STANDARD | USB_DT_CONFIGURATION) << 8), 0, read_len,
661 desc_buff, &read_len, 200);
662 if (ret < 0)
663 return ret;
664
665 return 0;
666}
667
678int usbh_get_string_descriptor(UDEV_T *udev, int index, uint8_t *desc_buff, int buff_len)
679{
680 uint32_t read_len;
681 int ret;
682
683 /*------------------------------------------------------------------------------------*/
684 /* Issue GET DESCRIPTOR command to get configuration descriptor */
685 /*------------------------------------------------------------------------------------*/
686 ret = usbh_ctrl_xfer(udev, REQ_TYPE_IN | REQ_TYPE_STD_DEV | REQ_TYPE_TO_DEV,
687 USB_REQ_GET_DESCRIPTOR,
688 ((USB_DT_STANDARD | USB_DT_STRING) << 8) | index, 0x0409, buff_len,
689 desc_buff, &read_len, 200);
690 return ret;
691}
692
700int usbh_clear_halt(UDEV_T *udev, uint16_t ep_addr)
701{
702 uint32_t read_len;
703
704 USB_debug("Clear endpoint 0x%x halt.\n", ep_addr);
705 return usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_STD_DEV | REQ_TYPE_TO_EP,
706 USB_REQ_CLEAR_FEATURE, 0, ep_addr, 0,
707 NULL, &read_len, 100);
708}
709
710static int usbh_parse_endpoint(ALT_IFACE_T *alt, int ep_idx, uint8_t *desc_buff, int len)
711{
712 DESC_EP_T *ep_desc;
713 int parsed_len = 0;
714 int pksz;
715
716 while (len > 0)
717 {
718 ep_desc = (DESC_EP_T *)desc_buff;
719
720 if ((len < ep_desc->bLength) || (ep_desc->bLength < 2))
721 {
722 USB_error("ERR DESCRIPTOR EP LEN [0x%X %d]\n", ep_desc->bDescriptorType, ep_desc->bLength);
723 return USBH_ERR_DESCRIPTOR;
724 }
725
726 if (ep_desc->bDescriptorType == USB_DT_ENDPOINT)
727 break; /* endpoint descriptor found */
728
729 /* unrecognized descriptor */
730 USB_vdebug("ignore descriptor 0x%X %d\n", ep_desc->bDescriptorType, ep_desc->bLength);
731 desc_buff += ep_desc->bLength;
732 parsed_len += ep_desc->bLength;
733 len -= ep_desc->bLength;
734 }
735
736 USB_vdebug("Descriptor Found - Alt: %d, Endpoint 0x%x, remaining len: %d\n", alt->ifd->bAlternateSetting, ep_desc->bEndpointAddress, len);
737
738 alt->ep[ep_idx].bEndpointAddress = ep_desc->bEndpointAddress;
739 alt->ep[ep_idx].bmAttributes = ep_desc->bmAttributes;
740 alt->ep[ep_idx].bInterval = ep_desc->bInterval;
741 pksz = ep_desc->wMaxPacketSize;
742 pksz = (pksz & 0x07ff) * (1 + ((pksz >> 11) & 3));
743 alt->ep[ep_idx].wMaxPacketSize = pksz;
744 alt->ep[ep_idx].hw_pipe = NULL;
745
746 return parsed_len + ep_desc->bLength;
747}
748
758static int usbh_parse_interface(UDEV_T *udev, uint8_t *desc_buff, int len)
759{
760 int i, matched, parsed_len = 0;
761 DESC_HDR_T *hdr;
762 DESC_IF_T *if_desc;
763 IFACE_T *iface = NULL;
764 int ret;
765
766 iface = usbh_alloc_mem(sizeof(*iface)); /* create an interface */
767 if (iface == NULL)
768 return USBH_ERR_MEMORY_OUT;
769 iface->udev = udev;
770 iface->aif = &iface->alt[0]; /* Default active interface should be the
771 first found alternative interface */
772 iface->if_num = ((DESC_IF_T *)desc_buff)->bInterfaceNumber;
773
774 while (len > 0)
775 {
776 /*--------------------------------------------------------------------------------*/
777 /* Find the first/next interface descriptor */
778 /*--------------------------------------------------------------------------------*/
779 if_desc = (DESC_IF_T *)desc_buff;
780
781 if (if_desc->bDescriptorType != USB_DT_INTERFACE)
782 {
783 desc_buff += if_desc->bLength;
784 parsed_len += if_desc->bLength;
785 len -= if_desc->bLength;
786 continue;
787 }
788
789 if (if_desc->bInterfaceNumber != iface->if_num)
790 {
791 goto parse_done;
792 }
793
794 if (if_desc->bNumEndpoints > MAX_EP_PER_IFACE)
795 {
796 USB_error("IF EP LIMITE %d\n", if_desc->bNumEndpoints);
798 goto err_out;
799 }
800
801 /* Step over the interface descriptor */
802 desc_buff += if_desc->bLength;
803 parsed_len += if_desc->bLength;
804 len -= if_desc->bLength;
805 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);
806
807 /*--------------------------------------------------------------------------------*/
808 /* Add to alternative interface list */
809 /*--------------------------------------------------------------------------------*/
810 if (iface->num_alt >= MAX_ALT_PER_IFACE)
811 {
813 goto err_out;
814 }
815
816 /*--------------------------------------------------------------------------------*/
817 /* Find the next alternative interface or endpoint descriptor */
818 /*--------------------------------------------------------------------------------*/
819 while (len > 0)
820 {
821 hdr = (DESC_HDR_T *)desc_buff;
822
823 if ((len < hdr->bLength) || (hdr->bLength < 2))
824 {
825 USB_error("ERR DESCRIPTOR IF LEN [0x%X %d]\n", hdr->bDescriptorType, hdr->bLength);
827 goto err_out;
828 }
829
830 if (hdr->bDescriptorType == USB_DT_CONFIGURATION)
831 goto parse_done; /* is other configuration, parsing completed */
832
833 if ((hdr->bDescriptorType == USB_DT_INTERFACE) || (hdr->bDescriptorType == USB_DT_ENDPOINT))
834 break; /* the first endpoint descriptor found */
835
836 /* unrecognized descriptor */
837 USB_vdebug("ignore descriptor 0x%X %d\n", hdr->bDescriptorType, hdr->bLength);
838 desc_buff += hdr->bLength;
839 parsed_len += hdr->bLength;
840 len -= hdr->bLength;
841 }
842
843 iface->alt[iface->num_alt].ifd = if_desc;
844 iface->num_alt++;
845
846 if (len == 0)
847 goto parse_done;
848
849 if (hdr->bDescriptorType == USB_DT_INTERFACE)
850 continue; /* is the next interface descriptor */
851
852 USB_vdebug("Finding %d endpoints of interface %d, alt %d...\n", if_desc->bNumEndpoints, if_desc->bInterfaceNumber, if_desc->bAlternateSetting);
853
854 /* parsign all endpoint descriptors */
855 for (i = 0; i < if_desc->bNumEndpoints; i++)
856 {
857 ret = usbh_parse_endpoint(&iface->alt[iface->num_alt-1], i, desc_buff, len);
858 if (ret < 0)
859 goto err_out;
860
861 desc_buff += ret;
862 parsed_len += ret;
863 len -= ret;
864 USB_vdebug("EP parse remaining %d\n", len);
865 }
866 }
867
868parse_done:
869
870 /*
871 * Probing all registered USB device drivers to find a matched driver.
872 */
873 matched = 0;
874 for (i = 0; i < MAX_UDEV_DRIVER; i++)
875 {
876 if ((_drivers[i] != NULL) && (_drivers[i]->probe(iface) == 0))
877 {
878 matched = 1;
879 break;
880 }
881 }
882
883 if (matched)
884 {
885 iface->driver = _drivers[i]; /* have a driver now */
886 iface->next = NULL;
887
888 /* Added this interface to USB device interface list */
889 if (udev->iface_list == NULL)
890 udev->iface_list = iface;
891 else
892 {
893 iface->next = udev->iface_list;
894 udev->iface_list = iface;
895 }
896 }
897 else
898 {
899 usbh_free_mem(iface, sizeof(*iface));
900 iface = NULL;
901 }
902
903 return parsed_len;
904
905err_out:
906 usbh_free_mem(iface, sizeof(*iface));
907 return ret;
908}
909
910
911static int usbh_parse_configuration(UDEV_T *udev, uint8_t *desc_buff)
912{
913 DESC_CONF_T *config = (DESC_CONF_T *)desc_buff;
914 DESC_HDR_T *hdr;
915 int i, ret, len;
916
917 len = config->wTotalLength;
918
919 desc_buff += config->bLength;
920 len -= config->bLength;
921
922 USB_vdebug("Parsing CONFIG =>\n");
923
924 for (i = 0; i < config->bNumInterfaces; i++)
925 {
926 /*
927 * find the next interface descriptor
928 */
929 while (len >= sizeof(DESC_HDR_T))
930 {
931 hdr = (DESC_HDR_T *)desc_buff;
932
933 if ((hdr->bLength > len) || (hdr->bLength < 2))
934 {
935 USB_error("ERR DESCRIPTOR CONFIG [%d]\n", hdr->bLength);
936 return USBH_ERR_DESCRIPTOR;
937 }
938
939 if (hdr->bDescriptorType == USB_DT_INTERFACE)
940 break;
941
942 USB_debug("ignore descriptor 0x%X %d\n", hdr->bDescriptorType, hdr->bLength);
943
944 desc_buff += hdr->bLength;
945 len -= hdr->bLength;
946 }
947
948 ret = usbh_parse_interface(udev, desc_buff, len);
949 if (ret < 0)
950 return ret;
951
952 desc_buff += ret;
953 len -= ret;
954 USB_vdebug("IFACE parse remaining %d\n", len);
955 }
956
957 if (len > 0)
958 {
959 USB_debug("ERR DESCRIPTOR CONFIG LEN %d\n", len);
960 return USBH_ERR_DESCRIPTOR;
961 }
962 return len;
963}
964
965void print_usb_string(char *lead, uint8_t *str)
966{
967 int len, i = 2;
968
969 USB_debug("%s", lead);
970 len = str[0];
971 while (i < len)
972 {
973 USB_debug("%c", str[i]);
974 i += 2;
975 }
976 USB_debug("\n");
977}
978
979int connect_device(UDEV_T *udev)
980{
981 DESC_CONF_T *conf;
982 uint32_t read_len;
983 int ret;
984
985 USB_debug("Connect device =>\n");
986
987 delay_us(100 * 1000); /* initially, give 100 ms delay */
988
989 usbh_get_device_descriptor(udev, &udev->descriptor);
990
991 reset_device(udev);
992
993 delay_us(100 * 1000);
994
995 ret = usbh_set_address(udev);
996 if (ret < 0)
997 {
998 USB_debug("Set address command failed!!\n");
999 return ret;
1000 }
1001
1002 delay_us(100 * 1000); /* after set address, give 100 ms delay */
1003
1004 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);
1005
1006 /* Get device descriptor again with new device address */
1007 ret = usbh_get_device_descriptor(udev, &udev->descriptor);
1008 if (ret < 0)
1009 {
1010 free_dev_address(udev->dev_num);
1011 return ret;
1012 }
1013
1014#if defined(DUMP_DESCRIPTOR) && defined(ENABLE_DEBUG_MSG)
1015 dump_device_descriptor(&udev->descriptor);
1016#endif
1017
1018 if (udev->descriptor.bNumConfigurations != 1)
1019 {
1020 USB_debug("Warning! This device has multiple configurations [%d]. \n", udev->descriptor.bNumConfigurations);
1021 }
1022
1023 conf = (DESC_CONF_T *)usbh_alloc_mem(MAX_DESC_BUFF_SIZE);
1024 if (conf == NULL)
1025 {
1026 free_dev_address(udev->dev_num);
1027 return USBH_ERR_MEMORY_OUT;
1028 }
1029
1030 udev->cfd_buff = (uint8_t *)conf;
1031
1032 /* Get configuration descriptor again with new device address */
1033 ret = usbh_get_config_descriptor(udev, (uint8_t *)conf, MAX_DESC_BUFF_SIZE);
1034 if (ret < 0)
1035 {
1036 free_dev_address(udev->dev_num);
1037 return ret;
1038 }
1039
1040#if defined(DUMP_DESCRIPTOR) && defined(ENABLE_DEBUG_MSG)
1041 dump_config_descriptor(conf);
1042#endif
1043
1044#if 0 /* printf string descriptors, for debug only */
1045 str_buff = (uint8_t *)usbh_alloc_mem(MAX_DESC_BUFF_SIZE);
1046 if (udev->descriptor.iManufacturer != 0)
1047 {
1048 usbh_get_string_descriptor(udev, udev->descriptor.iManufacturer, str_buff, MAX_DESC_BUFF_SIZE);
1049 print_usb_string("Manufactor: ", str_buff);
1050 }
1051 if (udev->descriptor.iProduct != 0)
1052 {
1053 usbh_get_string_descriptor(udev, udev->descriptor.iProduct, str_buff, MAX_DESC_BUFF_SIZE);
1054 print_usb_string("Product: ", str_buff);
1055 }
1056 if (udev->descriptor.iSerialNumber != 0)
1057 {
1058 usbh_get_string_descriptor(udev, udev->descriptor.iSerialNumber, str_buff, MAX_DESC_BUFF_SIZE);
1059 print_usb_string("Serial Number: ", str_buff);
1060 }
1061 usbh_free_mem(str_buff, MAX_DESC_BUFF_SIZE);
1062#endif
1063
1064 /* Always select the first configuration */
1065 ret = usbh_set_configuration(udev, conf->bConfigurationValue);
1066 if (ret < 0)
1067 {
1068 USB_debug("Set configuration %d failed!\n", conf->bConfigurationValue);
1069 free_dev_address(udev->dev_num);
1070 return ret;
1071 }
1072
1073 /* Parse the configuration/interface/endpoint descriptors and find corresponding drivers. */
1074 ret = usbh_parse_configuration(udev, (uint8_t *)conf);
1075 if (ret < 0)
1076 {
1077 USB_debug("Parse configuration %d failed!\n", conf->bConfigurationValue);
1078 free_dev_address(udev->dev_num);
1079 return ret;
1080 }
1081
1082 if (conf->bmAttributes & (1<<5))
1083 {
1084 /* If this configuration supports remote wakeup, enable it. */
1085 if (usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_STD_DEV | REQ_TYPE_TO_DEV,
1086 USB_REQ_SET_FEATURE, 0x01, 0x0000, 0x0000,
1087 NULL, &read_len, 300) < 0)
1088 {
1089 USB_debug("Device does not accept remote wakeup enable command.\n");
1090 }
1091 }
1092
1093 if (g_conn_func)
1094 g_conn_func(udev, 0);
1095
1096 return ret;
1097}
1098
1099int usbh_reset_device(UDEV_T *udev)
1100{
1101 IFACE_T *iface;
1102 DESC_CONF_T *conf;
1103 uint32_t read_len;
1104 int dev_num, ret;
1105
1106 USB_debug("Reset device =>\n");
1107
1109
1110 /*------------------------------------------------------------------------------------*/
1111 /* Disconnect device */
1112 /*------------------------------------------------------------------------------------*/
1113
1114 if (g_disconn_func)
1115 g_disconn_func(udev, 0);
1116
1117 usbh_quit_xfer(udev, &(udev->ep0)); /* Quit control transfer if hw_pipe is not NULL. */
1118
1119 /* Notified all actived interface device driver */
1120 iface = udev->iface_list;
1121 while (iface != NULL)
1122 {
1123 udev->iface_list = iface->next;
1124 iface->driver->disconnect(iface);
1125 usbh_free_mem(iface, sizeof(*iface));
1126 iface = udev->iface_list;
1127 }
1128
1129 /*------------------------------------------------------------------------------------*/
1130 /* Reset device */
1131 /*------------------------------------------------------------------------------------*/
1132
1133 reset_device(udev);
1134
1135 delay_us(100 * 1000);
1136
1137 /*------------------------------------------------------------------------------------*/
1138 /* Set address (use current address) */
1139 /*------------------------------------------------------------------------------------*/
1140
1141 dev_num = udev->dev_num;
1142 udev->dev_num = 0;
1143 /* Issue SET ADDRESS command to set the same device address */
1144 ret = usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_STD_DEV | REQ_TYPE_TO_DEV,
1145 USB_REQ_SET_ADDRESS, dev_num, 0, 0,
1146 NULL, &read_len, 100);
1147 udev->dev_num = dev_num;
1148 if (ret < 0)
1149 return ret;
1150
1151 delay_us(100 * 1000); /* after set address, give 100 ms delay */
1152
1153 /*------------------------------------------------------------------------------------*/
1154 /* Get device descriptor */
1155 /*------------------------------------------------------------------------------------*/
1156
1157 /* Get device descriptor again with new device address */
1158 ret = usbh_get_device_descriptor(udev, &udev->descriptor);
1159 if (ret < 0)
1160 return ret;
1161
1162 /*------------------------------------------------------------------------------------*/
1163 /* Get configuration descriptor */
1164 /*------------------------------------------------------------------------------------*/
1165
1166 conf = (DESC_CONF_T *)udev->cfd_buff; /* using the previously allocated buffer */
1167
1168 /* Get configuration descriptor again with new device address */
1169 ret = usbh_get_config_descriptor(udev, (uint8_t *)conf, MAX_DESC_BUFF_SIZE);
1170 if (ret < 0)
1171 return ret;
1172
1173 /* Always select the first configuration */
1174 ret = usbh_set_configuration(udev, udev->cur_conf);
1175 if (ret < 0)
1176 {
1177 USB_debug("Set configuration %d failed!\n", udev->cur_conf);
1178 return ret;
1179 }
1180
1181 /* Parse the configuration/interface/endpoint descriptors and find corresponding drivers. */
1182 ret = usbh_parse_configuration(udev, (uint8_t *)conf);
1183 if (ret < 0)
1184 {
1185 USB_debug("Parse configuration %d failed!\n", conf->bConfigurationValue);
1186 return ret;
1187 }
1188
1189 /* Enable remote wakeup */
1190 if (usbh_ctrl_xfer(udev, REQ_TYPE_OUT | REQ_TYPE_STD_DEV | REQ_TYPE_TO_DEV,
1191 USB_REQ_SET_FEATURE, 0x01, 0x0000, 0x0000,
1192 NULL, &read_len, 300) < 0)
1193 {
1194 USB_debug("Device not accept remote wakeup enable command.\n");
1195 }
1196
1197 if (g_conn_func)
1198 g_conn_func(udev, 0);
1199
1200 return ret;
1201}
1202
1203void disconnect_device(UDEV_T *udev)
1204{
1205 IFACE_T *iface;
1206
1207 USB_debug("disconnect device...\n");
1208
1209 if (g_disconn_func)
1210 g_disconn_func(udev, 0);
1211
1212 usbh_quit_xfer(udev, &(udev->ep0)); /* Quit control transfer if hw_pipe is not NULL. */
1213
1214 /* Notified all actived interface device driver */
1215 iface = udev->iface_list;
1216 while (iface != NULL)
1217 {
1218 udev->iface_list = iface->next;
1219 iface->driver->disconnect(iface);
1220 usbh_free_mem(iface, sizeof(*iface));
1221 iface = udev->iface_list;
1222 }
1223
1224 /* remove device from global device list */
1225 free_dev_address(udev->dev_num);
1226 free_device(udev);
1227
1228 usbh_memory_used();
1229}
1230
1231#if 0
1232static int check_device(UDEV_T *udev)
1233{
1234 UDEV_T *d;
1235
1236 if (udev == NULL)
1238
1239 //if ((udev->hc_driver != &ohci_driver) && (udev->hc_driver != &ehci_driver))
1240 // return USBH_ERR_INVALID_PARAM;
1241
1242 d = g_udev_list;
1243 while (d)
1244 {
1245 if (d == udev)
1246 return USBH_OK;
1247 d = d->next;
1248 }
1250}
1251#endif
1252
1253EP_INFO_T * usbh_iface_find_ep(IFACE_T *iface, uint8_t ep_addr, uint8_t dir_type)
1254{
1255 ALT_IFACE_T *aif = iface->aif;
1256 int i;
1257
1258 if (ep_addr == 0) /* find the first EP matched with specified direction and type */
1259 {
1260 for (i = 0; i < aif->ifd->bNumEndpoints; i++)
1261 {
1262 if (((aif->ep[i].bEndpointAddress & EP_ADDR_DIR_MASK) == (dir_type & EP_ADDR_DIR_MASK)) &&
1263 ((aif->ep[i].bmAttributes & EP_ATTR_TT_MASK) == (dir_type & EP_ATTR_TT_MASK)))
1264 return &aif->ep[i];
1265 }
1266 }
1267 else /* find the EP with specified endpoint address */
1268 {
1269 for (i = 0; i < aif->ifd->bNumEndpoints; i++)
1270 {
1271 if (aif->ep[i].bEndpointAddress == ep_addr)
1272 return &aif->ep[i];
1273 }
1274 }
1275 return NULL;
1276}
1277
1278void usbh_dump_buff_bytes(uint8_t *buff, int nSize)
1279{
1280 int nIdx, i;
1281
1282 nIdx = 0;
1283 while (nSize > 0)
1284 {
1285 printf("0x%04X ", nIdx);
1286 for (i = 0; i < 16; i++)
1287 printf("%02x ", buff[nIdx + i]);
1288 printf(" ");
1289 for (i = 0; i < 16; i++)
1290 {
1291 if ((buff[nIdx + i] >= 0x20) && (buff[nIdx + i] < 127))
1292 printf("%c", buff[nIdx + i]);
1293 else
1294 printf(".");
1295 nSize--;
1296 }
1297 nIdx += 16;
1298 printf("\n");
1299 }
1300 printf("\n");
1301}
1302
1303void usbh_dump_iface(IFACE_T *iface)
1304{
1305 USB_debug("\n [IFACE info] (0x%x)\n", (int)iface);
1306 USB_debug(" ----------------------------------------------\n");
1307 USB_debug(" udev = 0x%x\n", iface->udev);
1308 USB_debug(" if_num = %d\n", iface->if_num);
1309 USB_debug(" driver = 0x%x\n", (int)iface->driver);
1310 USB_debug(" next = 0x%x\n", (int)iface->next);
1311 usbh_dump_interface_descriptor(iface->aif->ifd);
1312}
1313
1314void usbh_dump_ep_info(EP_INFO_T *ep)
1315{
1316 USB_debug("\n [Endpoint Info] (0x%x)\n", (int)ep);
1317 USB_debug(" ----------------------------------------------\n");
1318 USB_debug(" bEndpointAddress = 0x%02x\n", ep->bEndpointAddress);
1319 USB_debug(" bmAttributes = 0x%02x\n", ep->bmAttributes);
1320 USB_debug(" bInterval = %d\n", ep->bInterval);
1321 USB_debug(" wMaxPacketSize = %d\n", ep->wMaxPacketSize);
1322 USB_debug(" hw_pipe = 0x%x\n", (int)ep->hw_pipe);
1323}
1324
1326
1327
1328/*** (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:133
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:41
void usbh_install_conn_callback(CONN_FUNC *conn_func, CONN_FUNC *disconn_func)
Install device connect and disconnect callback function.
Definition: usb_core.c:104
void usbh_core_init_ex(int ovc_alv)
Initialize M480 USB Host controller and USB stack.
Definition: usb_core.c:91
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:194
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:110