NUC472_NUC442_BSP V3.03.005
The Board Support Package for NUC472/NUC442
usbh_core.c
Go to the documentation of this file.
1/*
2 * drivers/usb/usb.c
3 *
4 * (C) Copyright Linus Torvalds 1999
5 * (C) Copyright Johannes Erdfelt 1999
6 * (C) Copyright Andreas Gal 1999
7 * (C) Copyright Gregory P. Smith 1999
8 * (C) Copyright Deti Fliegl 1999 (new USB architecture)
9 * (C) Copyright Randy Dunlap 2000
10 * (C) Copyright David Brownell 2000 (kernel hotplug, usb_device_id)
11 * (C) Copyright Yggdrasil Computing, Inc. 2000
12 * (usb_device_id matching changes by Adam J. Richter)
13 *
14 * NOTE! This is not actually a driver at all, rather this is
15 * just a collection of helper routines that implement the
16 * generic USB things that the real drivers can use..
17 *
18 * Think of this as a "USB library" rather than anything else.
19 * It should be considered a slave, with no callbacks. Callbacks
20 * are evil.
21 *
22 * $Id: usb.c,v 1.53 2000/01/14 16:19:09 acher Exp $
23 */
24
25/**************************************************************************/
35#include <stdio.h>
36#include <string.h>
37
38#include "NUC472_442.h"
39#include "usbh_core.h"
40#include "usbh_ohci.h"
41
56
57extern USB_DEV_T g_dev_pool[DEV_MAX_NUM];
58extern uint8_t dev_alloc_mark[DEV_MAX_NUM];
59
60static volatile uint32_t g_devmap;
61
62/*
63 * We have a per-interface "registered driver" list.
64 */
65LIST_HEAD(_UsbDriverList);
66LIST_HEAD(_UsbBusList);
67
69
70
78int32_t USBH_RegisterDriver(USB_DRIVER_T *new_driver)
79{
80 /* Add it to the list of known drivers */
81 list_add_tail(&new_driver->driver_list, &_UsbDriverList);
82 return 0;
83}
84
86
87const USB_DEV_ID_T *usb_match_id(USB_DEV_T *dev, USB_IF_DESC_T *intf,
88 const USB_DEV_ID_T *id)
89{
90 /* proc_connectinfo in devio.c may call us with id == NULL. */
91 if (id == NULL)
92 return NULL;
93
94 /*
95 * It is important to check that id->driver_info is nonzero,
96 * since an entry that is all zeroes except for a nonzero
97 * id->driver_info is the way to create an entry that indicates
98 * that the driver want to examine every device and interface.
99 */
100 for (; id->idVendor || id->bDeviceClass || id->bInterfaceClass || id->driver_info; id++)
101 {
102 if ((id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
103 (id->idVendor != dev->descriptor.idVendor))
104 continue;
105
106 if ((id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT) &&
107 (id->idProduct != dev->descriptor.idProduct))
108 continue;
109
110 /* No need to test id->bcdDevice_lo != 0, since 0 is never
111 greater than any unsigned number. */
112 if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO) &&
113 (id->bcdDevice_lo > dev->descriptor.bcdDevice))
114 continue;
115
116 if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI) &&
117 (id->bcdDevice_hi < dev->descriptor.bcdDevice))
118 continue;
119
120 if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS) &&
121 (id->bDeviceClass != dev->descriptor.bDeviceClass))
122 continue;
123
124 if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS) &&
125 (id->bDeviceSubClass!= dev->descriptor.bDeviceSubClass))
126 continue;
127
128 if ((id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL) &&
129 (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
130 continue;
131
132 if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
133 (id->bInterfaceClass != intf->bInterfaceClass))
134 continue;
135
136 if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS) &&
137 (id->bInterfaceSubClass != intf->bInterfaceSubClass))
138 continue;
139
140 if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL) &&
141 (id->bInterfaceProtocol != intf->bInterfaceProtocol))
142 continue;
143 return id;
144 }
145 return NULL;
146}
147
148
149/*
150 * This entry point gets called for each new device.
151 *
152 * We now walk the list of registered USB drivers,
153 * looking for one that will accept this interface.
154 *
155 * "New Style" drivers use a table describing the devices and interfaces
156 * they handle. Those tables are available to user mode tools deciding
157 * whether to load driver modules for a new device.
158 *
159 * The probe return value is changed to be a private pointer. This way
160 * the drivers don't have to dig around in our structures to set the
161 * private pointer if they only need one interface.
162 *
163 * Returns: 0 if a driver accepted the interface, -1 otherwise
164 */
165static int usb_find_interface_driver(USB_DEV_T *dev, USB_IF_DESC_T *intf)
166{
167 USB_LIST_T *tmp;
168 const USB_DEV_ID_T *id;
169 USB_DRIVER_T *driver;
170 int i, found;
171
172 for (tmp = _UsbDriverList.next; tmp != &_UsbDriverList;) /* search through the driver list */
173 {
174 driver = list_entry(tmp, USB_DRIVER_T, driver_list);
175 tmp = tmp->next;
176
177 id = driver->id_table;
178 id = usb_match_id(dev, intf, id);
179 if (id)
180 {
181 if (driver->probe(dev, intf, id) == 0)
182 {
183 /*
184 * Add driver to driver list of this device.
185 */
186 for (found = 0, i = 0; i < dev->driver_cnt; i++)
187 if (dev->driver[i] == driver) found = 1;
188
189 if (!found)
190 {
191 if (dev->driver_cnt >= MAX_DRIVER_PER_DEV)
192 {
193 USB_error("Driver overrun for one device!\n");
194 return USB_ERR_NOMEM;
195 }
196 dev->driver[dev->driver_cnt] = driver;
197 dev->driver_cnt++;
198 USB_debug("Deivce bind driver count %d\n", dev->driver_cnt);
199 return 0;
200 }
201 }
202 }
203 }
204 if (dev->driver_cnt == 0)
205 USB_warning("No matching driver!!\n");
206 return -1;
207}
208
210
219{
220 if (urb && urb->dev)
221 return urb->dev->bus->op->submit_urb(urb);
222 else
223 {
224 return USB_ERR_NODEV;
225 }
226}
227
228
237{
238 if (urb && urb->dev)
239 return urb->dev->bus->op->unlink_urb(urb);
240 else
241 return USB_ERR_NODEV;
242}
243
244
246
247/*-------------------------------------------------------------------*
248 * COMPLETION HANDLERS *
249 *-------------------------------------------------------------------*/
250
251static volatile int _Event_UrbCompleted;
252
253/*-------------------------------------------------------------------*
254 * completion handler for compatibility wrappers (sync control/bulk) *
255 *-------------------------------------------------------------------*/
256static void ctrl_msg_complete(URB_T *urb)
257{
258 _Event_UrbCompleted = 1;
259}
260
261static int get_ctrl_msg_signal()
262{
263 return _Event_UrbCompleted;
264}
265static void clr_ctrl_msg_signal()
266{
267 _Event_UrbCompleted = 0;
268}
269
270
271
272/*-------------------------------------------------------------------*
273 * COMPATIBILITY STUFF *
274 *-------------------------------------------------------------------*/
275/* Starts urb and waits for completion or timeout */
276static int usb_start_wait_urb(URB_T *urb, int timeout, int* actual_length)
277{
278 volatile int t0;
279 int status;
280
281 timeout /= 10000;
282 if (timeout == 0) timeout = 100;
283
284 clr_ctrl_msg_signal();
285
286 status = USBH_SubmitUrb(urb);
287 if (status)
288 return status;
289
290#if 1
291 for (t0 = 0; t0 < 0x100000; t0++)
292 {
293 if (get_ctrl_msg_signal())
294 break;
295 }
296
297 if (t0 >= 0x100000)
299 else
300 urb->status = 0;
301#else
302 t0 = sysGetTicks(TIMER0);
303 while (sysGetTicks(TIMER0) - t0 < timeout)
304 {
305 if (get_ctrl_msg_signal())
306 break;
307 }
308
309 if (sysGetTicks(TIMER0) - t0 >= timeout)
311 else
312 urb->status = 0;
313#endif
314
315 if (urb->status == USB_ERR_INPROGRESS)
316 {
317 /* timeout */
318 USB_warning("usb_control/bulk_msg: timeout\n");
319 USBH_UnlinkUrb(urb); /* remove urb safely */
320 status = USB_ERR_TIMEOUT;
321 }
322 else
323 status = urb->status;
324
325 if (actual_length)
326 *actual_length = urb->actual_length;
327
328 return status;
329}
330
331
332/*-------------------------------------------------------------------*/
333// returns status (negative) or length (positive)
334static int usb_internal_control_msg(USB_DEV_T *usb_dev, uint32_t pipe,
335 DEV_REQ_T *cmd, void *data, int len, int timeout)
336{
337 URB_T urb;
338 int retv;
339 int length;
340
341 FILL_CONTROL_URB(&urb, usb_dev, pipe, (uint8_t*)cmd, data, len, /* build urb */
342 ctrl_msg_complete, 0);
343
344 retv = usb_start_wait_urb(&urb, timeout, &length);
345 if (retv < 0)
346 return retv;
347 else
348 return length;
349}
350
352
353
378int32_t USBH_SendCtrlMsg(USB_DEV_T *dev, uint32_t pipe, uint8_t request,
379 uint8_t requesttype, uint16_t value, uint16_t index, void *data,
380 uint16_t size, int timeout)
381{
382 DEV_REQ_T dr;
383
384 dr.requesttype = requesttype;
385 dr.request = request;
386 dr.value = value;
387 dr.index = index;
388 dr.length = size;
389 return usb_internal_control_msg(dev, pipe, &dr, (uint8_t *)data, size, timeout);
390}
391
392
416int32_t USBH_SendBulkMsg(USB_DEV_T *usb_dev, uint32_t pipe,
417 void *data, int len, int *actual_length, int timeout)
418{
419 URB_T urb;
420
421 FILL_BULK_URB(&urb,usb_dev,pipe,(uint8_t *)data,len, /* build urb */
422 ctrl_msg_complete, 0);
423
424 return usb_start_wait_urb(&urb, timeout, actual_length);
425}
426
428
429int usb_maxpacket(USB_DEV_T *dev, uint32_t pipe, int out)
430{
431 int i;
432 int ep_addr;
433
434 ep_addr = (((pipe) >> 15) & 0xf) | (pipe & 0x80);
435
436 if ((ep_addr == 0) || (ep_addr == 0x80))
437 return dev->ep_list[0].wMaxPacketSize;
438
439 for (i = 0; i < dev->ep_list_cnt; i++)
440 {
441 if ((dev->ep_list[i].cfgno == dev->act_config) &&
442 (dev->ep_list[i].bEndpointAddress == ep_addr))
443 {
444 return dev->ep_list[i].wMaxPacketSize;
445 }
446 }
447 USB_error("usb_maxpacket - endpoint %x not found!!\n", ep_addr);
448 return 64;
449}
450
451
452static int usb_parse_endpoint(USB_DEV_T *dev, int cfg_value, USB_IF_DESC_T *ifp, uint8_t *buffer, int size)
453{
454 USB_EP_DESC_T endpoint;
455 USB_DESC_HDR_T *header;
456 EP_INFO_T *ep_info;
457 int parsed = 0, numskipped;
458
459 header = (USB_DESC_HDR_T *)buffer;
460 memcpy((uint8_t *)&endpoint, buffer, sizeof(USB_EP_DESC_T));
461
462 /* Everything should be fine being passed into here, but we sanity */
463 if (header->bLength > size)
464 {
465 USB_error("Error! - ran out of descriptors parsing");
466 return -1;
467 }
468
469 if (header->bDescriptorType != USB_DT_ENDPOINT)
470 {
471 USB_warning("Warning! - unexpected descriptor 0x%X, expecting endpoint descriptor, type 0x%X",
472 endpoint.bDescriptorType, USB_DT_ENDPOINT);
473 return parsed;
474 }
475
476 if (dev->ep_list_cnt < MAX_ENDPOINTS)
477 {
478 ep_info = &dev->ep_list[dev->ep_list_cnt];
479 ep_info->cfgno = cfg_value;
480 ep_info->ifnum = ifp->bInterfaceNumber;
481 ep_info->altno = ifp->bAlternateSetting;
482 ep_info->bEndpointAddress = endpoint.bEndpointAddress;
483 ep_info->bmAttributes = endpoint.bmAttributes;
484 ep_info->bInterval = endpoint.bInterval;
485 ep_info->wMaxPacketSize = endpoint.wMaxPacketSize;
486 if ((ep_info->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK)
487 {
488 if (ep_info->wMaxPacketSize > 64)
489 {
490 USB_debug("Endpoint %x wMaxPacketSize is %d bytes, force to change as 64 bytes!\n",
491 endpoint.bEndpointAddress, endpoint.wMaxPacketSize);
492 ep_info->wMaxPacketSize = 64;
493 }
494 }
495 dev->ep_list_cnt++;
496 //USB_debug("Add endpoint 0x%x - %d %d %d, max_pkt = %d\n", ep_info->bEndpointAddress, ep_info->cfgno,
497 // ep_info->ifnum, ep_info->altno, ep_info->wMaxPacketSize);
498 }
499 else
500 {
501 USB_error("Too many endpoints!\n");
502 }
503
504 buffer += header->bLength;
505 size -= header->bLength;
506 parsed += header->bLength;
507
508 /* Skip over the rest of the Class Specific or Vendor Specific descriptors */
509 numskipped = 0;
510 while (size >= sizeof(USB_DESC_HDR_T))
511 {
512 header = (USB_DESC_HDR_T *)buffer;
513
514 if (header->bLength < 2)
515 {
516 USB_error("Error! - invalid descriptor length of %d\n", header->bLength);
517 return -1;
518 }
519
520 /* If we find another descriptor which is at or below us */
521 /* in the descriptor heirarchy then we're done */
522 if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
523 (header->bDescriptorType == USB_DT_INTERFACE) ||
524 (header->bDescriptorType == USB_DT_CONFIG) ||
525 (header->bDescriptorType == USB_DT_DEVICE))
526 break;
527 USB_info("skipping descriptor 0x%X\n", header->bDescriptorType);
528 numskipped++;
529
530 buffer += header->bLength;
531 size -= header->bLength;
532 parsed += header->bLength;
533 }
534
535 if (numskipped)
536 USB_warning("Skipped %d class/vendor specific endpoint descriptors\n", numskipped);
537
538 return parsed;
539}
540
541
542static int usb_parse_interface(USB_DEV_T *dev, int cfg_value, uint8_t *buffer, int size)
543{
544 int i, numskipped, retval, parsed = 0;
545 USB_DESC_HDR_T *header;
546 USB_IF_DESC_T ifp;
547
548#ifdef USB_VERBOSE_DEBUG
549 //HexDumpBuffer("usb_parse_interface", (uint8_t *)buffer, size);
550#endif
551
552 while (size > 0)
553 {
554 memcpy((char *)&ifp, buffer, USB_DT_INTERFACE_SIZE);
555
556 /* Skip over the interface */
557 buffer += ifp.bLength;
558 parsed += ifp.bLength;
559 size -= ifp.bLength;
560
561 numskipped = 0;
562
563 /*
564 * Skip over any interface, class or vendor descriptors
565 * ¦b parsing interface descriptors ªº¹Lµ{¤¤, ­Yµo²{ class descriptors
566 * ©̠vendor descriptors, ´Nª½±µ skip ¤§, ¤£°µ parsing
567 */
568 while (size >= sizeof(USB_DESC_HDR_T))
569 {
570 header = (USB_DESC_HDR_T *)buffer;
571
572 if (header->bLength < 2)
573 {
574 USB_error("Invalid descriptor length of %d\n", header->bLength);
575 return -1;
576 }
577
578 /* If we find another descriptor which is at or below */
579 /* us in the descriptor heirarchy then return */
580 if ((header->bDescriptorType == USB_DT_INTERFACE) ||
581 (header->bDescriptorType == USB_DT_ENDPOINT) ||
582 (header->bDescriptorType == USB_DT_CONFIG) ||
583 (header->bDescriptorType == USB_DT_DEVICE))
584 break;
585
586 USB_info("skipping descriptor 0x%X\n", header->bDescriptorType);
587 numskipped++;
588 buffer += header->bLength;
589 parsed += header->bLength;
590 size -= header->bLength;
591 }
592
593 if (numskipped)
594 {
595 USB_warning("skipped %d class/vendor specific interface descriptors\n", numskipped);
596 }
597
598 /* Did we hit an unexpected descriptor? */
599 header = (USB_DESC_HDR_T *)buffer;
600 if ((size >= sizeof(USB_DESC_HDR_T)) &&
601 ((header->bDescriptorType == USB_DT_CONFIG) ||
602 (header->bDescriptorType == USB_DT_DEVICE)))
603 {
604 USB_warning("parsing interface - hit an unexpected descriptor!\n");
605 return parsed;
606 }
607
608 if (ifp.bNumEndpoints > USB_MAXENDPOINTS)
609 {
610 USB_warning("Warning - illegal endpoint number %d\n", ifp.bNumEndpoints);
611 return -1;
612 }
613
614 /* fixed by YCHuang, 2002.03.13, ifp.bNumEndpoints number may be zero */
615 if (ifp.bNumEndpoints > 0)
616 {
617 for (i = 0; i < ifp.bNumEndpoints; i++)
618 {
619 header = (USB_DESC_HDR_T *)buffer;
620 if (header->bLength > size)
621 {
622 USB_error("Error - ran out of descriptors parsing");
623 return -1;
624 }
625
626#ifdef DUMP_DEV_DESCRIPTORS
627 usbh_dump_ep_descriptor((USB_EP_DESC_T *)buffer);
628#endif
629 retval = usb_parse_endpoint(dev, cfg_value, &ifp, buffer, size);
630 if (retval < 0)
631 return retval;
632
633 buffer += retval;
634 parsed += retval;
635 size -= retval;
636 }
637 }
638
639 /* We check to see if it's an alternate to this one */
640 memcpy((char *)&ifp, buffer, USB_DT_INTERFACE_SIZE);
641 if ((size < USB_DT_INTERFACE_SIZE) ||
642 (ifp.bDescriptorType != USB_DT_INTERFACE) || !ifp.bAlternateSetting)
643 return parsed;
644 } /* end of while */
645 return parsed;
646}
647
648
649static int usb_parse_configuration(USB_DEV_T *dev, USB_CONFIG_DESC_T *config, uint8_t *buffer)
650{
651 int i, retval, size;
652 USB_DESC_HDR_T *header;
653
654 memcpy(config, buffer, USB_DT_CONFIG_SIZE);
655 size = config->wTotalLength;
656
657 if (config->bNumInterfaces > USB_MAXINTERFACES)
658 {
659 USB_warning("Warning - too many interfaces\n");
660 return -1;
661 }
662
663 buffer += config->bLength;
664 size -= config->bLength;
665
666 for (i = 0; i < config->bNumInterfaces; i++)
667 {
668 int numskipped;
669
670 /* Skip over the rest of the Class Specific or Vendor */
671 /* Specific descriptors */
672 numskipped = 0;
673 while (size >= sizeof(USB_DESC_HDR_T))
674 {
675 header = (USB_DESC_HDR_T *)buffer;
676
677 if ((header->bLength > size) || (header->bLength < 2))
678 {
679 USB_error("Error - invalid descriptor length of %d\n", header->bLength);
680 return -1;
681 }
682
683 /* If we find another descriptor which is at or below */
684 /* us in the descriptor heirarchy then we're done */
685 if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
686 (header->bDescriptorType == USB_DT_INTERFACE) ||
687 (header->bDescriptorType == USB_DT_CONFIG) ||
688 (header->bDescriptorType == USB_DT_DEVICE))
689 break;
690
691 USB_info("skipping descriptor 0x%X\n", header->bDescriptorType);
692 numskipped++;
693
694 buffer += header->bLength;
695 size -= header->bLength;
696 } /* end of while */
697
698 if (numskipped)
699 {
700 USB_warning("skipped %d class/vendor specific endpoint descriptors\n", numskipped);
701 }
702
703#ifdef DUMP_DEV_DESCRIPTORS
704 usbh_dump_iface_descriptor((USB_IF_DESC_T *)buffer);
705#endif
706
707 retval = usb_parse_interface(dev, config->bConfigurationValue, buffer, size);
708 if (retval < 0)
709 return retval;
710
711 /* probe drivers... */
712 usb_find_interface_driver(dev, (USB_IF_DESC_T *)buffer);
713
714 buffer += retval;
715 size -= retval;
716 }
717 return size;
718}
719
720
721/*
722 * Something got disconnected. Get rid of it, and all of its children.
723 */
724void usbh_disconnect_device(USB_DEV_T **pdev)
725{
726 USB_DEV_T *dev = *pdev;
727 USB_DRIVER_T *driver;
728 int i;
729
730 if (!dev)
731 return;
732
733 *pdev = NULL;
734
735 USB_info("usbh_disconnect_device - USB disconnect on device %d\n", dev->devnum);
736
737 usbh_free_dev_urbs(dev);
738
739 for (i = 0; i < dev->driver_cnt; i++)
740 {
741 driver = dev->driver[i];
742 driver->disconnect(dev);
743 }
744
745 /* Free up all the children.. */
746 for (i = 0; i < USB_MAXCHILDREN; i++)
747 {
748 USB_DEV_T **child = dev->children + i;
749 if (*child)
750 usbh_disconnect_device(child);
751 }
752
753 /* Free the device number and remove the /proc/bus/usb entry */
754 if (dev->devnum > 0)
755 {
756 g_devmap &= ~(1 << dev->devnum);
757 }
758
759 /* Free up the device itself */
760 usbh_free_device(dev);
761
762 usbh_mdelay(5); // let Host Controller got some time to free all
763}
764
765
766/*
767 * Connect a new USB device. This basically just initializes
768 * the USB device information and sets up the topology - it's
769 * up to the low-level driver to reset the port and actually
770 * do the setup (the upper levels don't know how to do that).
771 */
772void usbh_connect_device(USB_DEV_T *dev)
773{
774 int devnum;
775
776 dev->descriptor.bMaxPacketSize0 = 8; /* Start off at 8 bytes */
777
778 for (devnum = 1; devnum < 31; devnum++)
779 {
780 if ((g_devmap & (1 << devnum)) == 0)
781 break;
782 }
783 if (devnum > 31)
784 {
785 USB_error("Serious devnum error!\n");
786 devnum = 31;
787 }
788
789 g_devmap |= (1 << devnum);
790 dev->devnum = devnum;
791}
792
793
794/*
795 * These are the actual routines to send
796 * and receive control messages.
797 */
798
799#define GET_TIMEOUT 1000
800#define SET_TIMEOUT 100
802int usbh_set_address(USB_DEV_T *dev)
803{
804 return USBH_SendCtrlMsg(dev, usb_snddefctrl(dev), USB_REQ_SET_ADDRESS,
805 0, dev->devnum, 0, NULL, 0, HZ * GET_TIMEOUT);
806}
807
809
810
822int32_t USBH_GetDescriptor(USB_DEV_T *dev, uint8_t type, uint8_t index,
823 void *buf, int size)
824{
825 int i = 5;
826 int result = 0;
827
828 memset(buf, 0, size); /* Make sure we parse really received data */
829
830 while (i--)
831 {
832 if ((result = USBH_SendCtrlMsg(dev, usb_rcvctrlpipe(dev, 0),
833 USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
834 (type << 8) + index, 0, buf, size, HZ * GET_TIMEOUT)) > 0 || result == USB_ERR_PIPE)
835 break; /* retry if the returned length was 0; flaky device */
836 }
837 return result;
838}
839
841
842static int usbh_get_string_descriptor(USB_DEV_T *dev, uint16_t langid, uint8_t index,
843 void *buf, int size)
844{
845 return USBH_SendCtrlMsg(dev, usb_rcvctrlpipe(dev, 0),
846 USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
847 (USB_DT_STRING << 8) + index, langid, buf, size, HZ * GET_TIMEOUT);
848}
849
850
852{
853 int ret;
854
855 ret = USBH_GetDescriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, sizeof(dev->descriptor));
856 return ret;
857}
858
859
860int usbh_get_protocol(USB_DEV_T *dev, int ifnum)
861{
862 uint8_t type;
863 int ret;
864
865 if ((ret = USBH_SendCtrlMsg(dev, usb_rcvctrlpipe(dev, 0),
866 USB_REQ_GET_PROTOCOL, USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
867 0, ifnum, &type, 1, HZ * GET_TIMEOUT)) < 0)
868 return ret;
869
870 return type;
871}
872
873
874int usbh_set_protocol(USB_DEV_T *dev, int ifnum, int protocol)
875{
876 return USBH_SendCtrlMsg(dev, usb_sndctrlpipe(dev, 0),
877 USB_REQ_SET_PROTOCOL, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
878 protocol, ifnum, NULL, 0, HZ * SET_TIMEOUT);
879}
880
881
882int usbh_set_idle(USB_DEV_T *dev, int ifnum, int duration, int report_id)
883{
884 return USBH_SendCtrlMsg(dev, usb_sndctrlpipe(dev, 0),
885 USB_REQ_SET_IDLE, USB_TYPE_CLASS | USB_RECIP_INTERFACE,
886 (duration << 8) | report_id, ifnum, NULL, 0, HZ * SET_TIMEOUT);
887}
888
890
891
900int32_t USBH_ClearHalt(USB_DEV_T *dev, int pipe)
901{
902 int result;
903 uint16_t status;
904 int endp;
905
906 endp = usb_pipeendpoint(pipe)|(usb_pipein(pipe)<<7);
907
908 /*
909 if (!usb_endpoint_halted(dev, endp & 0x0f, usb_endpoint_out(endp)))
910 return 0;
911 */
912
913 result = USBH_SendCtrlMsg(dev, usb_sndctrlpipe(dev, 0),
914 USB_REQ_CLEAR_FEATURE, USB_RECIP_ENDPOINT, 0, endp, NULL, 0, HZ * SET_TIMEOUT);
915
916 /* don't clear if failed */
917 if (result < 0)
918 return result;
919
920 result = USBH_SendCtrlMsg(dev, usb_rcvctrlpipe(dev, 0),
921 USB_REQ_GET_STATUS, USB_DIR_IN | USB_RECIP_ENDPOINT, 0, endp,
922 &status, sizeof(status), HZ * SET_TIMEOUT);
923 if (result < 0)
924 return result;
925
926 if (USB_SWAP16(status) & 1)
927 return USB_ERR_PIPE; /* still halted */
928
929 usb_endpoint_running(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe));
930
931 /* toggle is reset on clear */
932
933 usb_settoggle(dev, usb_pipeendpoint(pipe), usb_pipeout(pipe), 0);
934
935 return 0;
936}
937
938
948int32_t USBH_SetInterface(USB_DEV_T *dev, char interface, char alternate)
949{
950 int ret;
951
952 if ((ret = USBH_SendCtrlMsg(dev, usb_sndctrlpipe(dev, 0),
953 USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate,
954 interface, NULL, 0, HZ * 5)) < 0)
955 return ret;
956
957 dev->act_iface = interface;
958 dev->iface_alternate = alternate;
959 dev->toggle[0] = 0; /* 9.1.1.5 says to do this */
960 dev->toggle[1] = 0;
961 return 0;
962}
963
964
973int32_t USBH_SetConfiguration(USB_DEV_T *dev, int configuration)
974{
975 int ret;
976
977 if ((ret = USBH_SendCtrlMsg(dev, usb_sndctrlpipe(dev, 0),
978 USB_REQ_SET_CONFIGURATION, 0, configuration, 0, NULL, 0, HZ * SET_TIMEOUT)) < 0)
979 return ret;
980 dev->act_config = configuration;
981 dev->toggle[0] = 0;
982 dev->toggle[1] = 0;
983 return 0;
984}
985
986
988
989/*
990 * usbh_settle_configuration
991 *
992 * 1. get configuration descriptor
993 * 2. set default configuration
994 * 3. parse configuration
995 * 4. probe USB device drivers by interface
996 */
997static int usbh_settle_configuration(USB_DEV_T *dev)
998{
999 int result;
1000 uint32_t cfgno, length;
1001 uint8_t *buffer;
1002 USB_CONFIG_DESC_T *desc;
1003 uint32_t stack_buff[384];
1004
1005 if (dev->descriptor.bNumConfigurations > USB_MAXCONFIG)
1006 {
1007 USB_warning("Too many configurations\n");
1008 return USB_ERR_INVAL;
1009 }
1010
1011 if (dev->descriptor.bNumConfigurations != 1)
1012 {
1013 USB_warning("This driver does not support multi-configuration devices!\n");
1014 return USB_ERR_INVAL;
1015 }
1016
1017 buffer = (uint8_t *)&stack_buff[0];
1018 desc = (USB_CONFIG_DESC_T *)buffer;
1019
1020 for (cfgno = 0; cfgno < dev->descriptor.bNumConfigurations; cfgno++)
1021 {
1022 /* We grab the first 8 bytes so we know how long the whole */
1023 /* configuration is */
1024 result = USBH_GetDescriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8);
1025 if (result < 8)
1026 {
1027 if (result < 0)
1028 USB_error("Unable to get descriptor\n");
1029 else
1030 {
1031 USB_error("Config descriptor too short (expected %i, got %i)\n", 8, result);
1032 result = USB_ERR_INVAL;
1033 }
1034 goto err;
1035 }
1036
1037 /* Get the full buffer */
1038 length = desc->wTotalLength;
1039
1040 if (length > 384)
1041 {
1042 length = 384;
1043 USB_error("Config descriptor is too large. Read 384 bytes only. This may cause lost of information!\n");
1044 }
1045
1046 /* Now that we know the length, get the whole thing */
1047 result = USBH_GetDescriptor(dev, USB_DT_CONFIG, cfgno, buffer, length);
1048 if (result < 0)
1049 {
1050 USB_error("Couldn't get all of config descriptors\n");
1051 goto err;
1052 }
1053
1054 if (result < length)
1055 {
1056 USB_error("Config descriptor too short (expected %d, got %d)\n", length, result);
1057 result = USB_ERR_INVAL;
1058 goto err;
1059 }
1060
1061 /*
1062 * Set first configuration as the default configuration
1063 */
1064 if (cfgno == 0)
1065 {
1066 result = USBH_SetConfiguration(dev, desc->bConfigurationValue);
1067 if (result)
1068 {
1069 USB_error("Failed to set device %d default configuration (error=%d)\n", dev->devnum, result);
1070 goto err;
1071 }
1072 }
1073
1074#ifdef DUMP_DEV_DESCRIPTORS
1075 usbh_dump_config_descriptor(desc);
1076#endif
1077
1078 result = usb_parse_configuration(dev, desc, buffer);
1079 if (result > 0)
1080 {
1081 USB_warning("Descriptor data left\n");
1082 }
1083 else if (result < 0)
1084 {
1085 USB_warning("usb_parse_configuration error\n");
1086 result = USB_ERR_INVAL;
1087 goto err;
1088 }
1089 }
1090
1091 return 0;
1092
1093err:
1094 dev->descriptor.bNumConfigurations = cfgno;
1095 return result;
1096}
1097
1098/*
1099 * usbh_translate_string:
1100 * returns string length (> 0) or error (< 0)
1101 */
1102int usbh_translate_string(USB_DEV_T *dev, int index, char *buf, int size)
1103{
1104 int err = 0;
1105 uint32_t u, idx;
1106 uint8_t tbuf[256];
1107
1108 if (size == 0 || !buf || !index)
1109 return USB_ERR_INVAL;
1110 buf[0] = 0;
1111
1112 /* get langid for strings if it's not yet known */
1113 if (!dev->have_langid)
1114 {
1115 err = usbh_get_string_descriptor(dev, 0, 0, tbuf, 4);
1116 if (err < 0)
1117 {
1118 USB_error("usbh_translate_string - error getting string descriptor 0 (error=%d)\n", err);
1119 goto errout;
1120 }
1121 else if (tbuf[0] < 4)
1122 {
1123 USB_error("usbh_translate_string - string descriptor 0 too short\n");
1124 err = USB_ERR_INVAL;
1125 goto errout;
1126 }
1127 else
1128 {
1129 dev->have_langid = -1;
1130 dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
1131 /* always use the first langid listed */
1132 USB_info("USB device number %d default language ID 0x%x\n",
1133 dev->devnum, dev->string_langid);
1134 }
1135 }
1136
1137 /* YCHuang, added for W99683, prevent halt */
1138 if ((dev->descriptor.idVendor == 0x416) && (dev->descriptor.idProduct == 0x9683))
1139 {
1140 USB_warning("??? Skip usbh_get_string_descriptor, 255\n");
1141 goto errout;
1142 }
1143
1144
1145 /*
1146 * Just ask for a maximum length string and then take the length
1147 * that was returned.
1148 */
1149 err = usbh_get_string_descriptor(dev, dev->string_langid, index, tbuf, 255);
1150 if (err < 0)
1151 goto errout;
1152
1153 size--; /* leave room for trailing NULL char in output buffer */
1154 for (idx = 0, u = 2; u < err; u += 2)
1155 {
1156 if (idx >= size)
1157 break;
1158 if (tbuf[u+1]) /* high byte */
1159 buf[idx++] = '?'; /* non-ASCII character */
1160 else
1161 buf[idx++] = tbuf[u];
1162 }
1163 buf[idx] = 0;
1164 err = idx;
1165
1166errout:
1167 return err;
1168}
1169
1170
1171
1172/*
1173 * By the time we get here, the device has gotten a new device ID
1174 * and is in the default state. We need to identify the thing and
1175 * get the ball rolling..
1176 *
1177 * Returns 0 for success, != 0 for error.
1178 */
1179int usbh_settle_new_device(USB_DEV_T *dev)
1180{
1181 int err;
1182
1183 USB_info("[USBH] Enter usbh_settle_new_device() ...\n");
1184 /*
1185 * USB v1.1 5.5.3
1186 * We read the first 8 bytes from the device descriptor to get to
1187 * the bMaxPacketSize0 field. Then we set the maximum packet size
1188 * for the control pipe, and retrieve the rest
1189 */
1190 dev->ep_list[0].bEndpointAddress = 0;;
1191 dev->ep_list[0].wMaxPacketSize = 8;
1192 dev->ep_list_cnt = 1;
1193
1194 err = usbh_set_address(dev);
1195 if (err < 0)
1196 {
1197 USB_error("USB device not accepting new address=%d (error=%d)\n", dev->devnum, err);
1198 g_devmap &= ~(1 << dev->devnum);
1199 dev->devnum = -1;
1200 return 1;
1201 }
1202
1203 usbh_mdelay(10); /* Let the SET_ADDRESS settle */
1204
1205 memset((char *)&dev->descriptor, 0, 8);
1206
1207 err = USBH_GetDescriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8);
1208 if (err < 8)
1209 {
1210 USB_debug("USBH_GetDescriptor failed!!\n");
1211 if (err < 0)
1212 USB_error("USB device not responding, giving up (error=%d)\n", err);
1213 else
1214 USB_error("USB device descriptor short read (expected %i, got %i)\n", 8, err);
1215 g_devmap &= ~(1 << dev->devnum);
1216 dev->devnum = -1;
1217 return 1;
1218 }
1219
1220 dev->ep_list[0].wMaxPacketSize = dev->descriptor.bMaxPacketSize0;
1221
1222 err = usbh_get_device_descriptor(dev);
1223 if (err < sizeof(dev->descriptor))
1224 {
1225 if (err < 0)
1226 USB_error("unable to get device descriptor (error=%d)\n", err);
1227 else
1228 USB_error("USB device descriptor short read (expected %i, got %i)\n",
1229 sizeof(dev->descriptor), err);
1230
1231 g_devmap &= ~(1 << dev->devnum);
1232 dev->devnum = -1;
1233 return USB_ERR_INVAL;
1234 }
1235
1236#ifdef DUMP_DEV_DESCRIPTORS
1237 usbh_dump_device_descriptor(&dev->descriptor);
1238#endif
1239
1240 err = usbh_settle_configuration(dev);
1241 if (err < 0)
1242 {
1243 USB_error("Unable to get device %d configuration (error=%d)\n", dev->devnum, err);
1244 g_devmap &= ~(1 << dev->devnum);
1245 dev->devnum = -1;
1246 usbh_free_device(dev);
1247 return 1;
1248 }
1249
1250#ifdef USB_VERBOSE_DEBUG
1251 if (dev->descriptor.iManufacturer)
1252 usbh_print_usb_string(dev, "Manufacturer", dev->descriptor.iManufacturer);
1253 if (dev->descriptor.iProduct)
1254 usbh_print_usb_string(dev, "Product", dev->descriptor.iProduct);
1255 if (dev->descriptor.iSerialNumber)
1256 usbh_print_usb_string(dev, "SerialNumber", dev->descriptor.iSerialNumber);
1257#endif
1258 return 0;
1259}
1260
1262
1263
1270int32_t USBH_Open(void)
1271{
1272 volatile int loop;
1273
1274 //USBH->HcMiscControl |= 0x8; /* over current setting */
1275 USBH->HcMiscControl &= ~0x8; /* over current setting */
1276
1277 usbh_init_memory();
1278
1279 /*
1280 * Init global variables
1281 */
1282 g_devmap = 0;
1283
1284 ENABLE_USB_INT();
1285
1286 usbh_init_hub_driver();
1287
1288#ifdef SUPPORT_HID_CLASS
1289#endif
1290
1291#ifdef SUPPORT_UMAS_CLASS
1292#endif
1293
1294#ifdef SUPPORT_UVC_CLASS
1295#endif
1296
1297#ifdef SUPPORT_UAC_CLASS
1298#endif
1299
1300#ifdef SUPPORT_CDC_CLASS
1301#endif
1302
1303 if (usbh_init_ohci() < 0)
1304 {
1305 USB_debug("OHCI init failed!\n");
1306 return -1;
1307 }
1308
1309 return 0;
1310}
1311
1312
1319int32_t USBH_Close(void)
1320{
1321 DISABLE_USB_INT();
1322
1323 USBH->HcRhStatus = USBH_HcRhStatus_LPS_Msk;
1324
1325 usbh_init_memory();
1326
1327 return 0;
1328}
1329
1336int32_t USBH_Suspend(void)
1337{
1338 int i;
1339 USB_DEV_T *dev;
1340
1341 /* Set feature Device Remote Wakeup to all devices */
1342 for (i = 0; i < DEV_MAX_NUM; i++)
1343 {
1344 if (dev_alloc_mark[i])
1345 {
1346 dev = &g_dev_pool[i];
1347 USBH_SendCtrlMsg(dev, usb_sndctrlpipe(dev, 0),
1348 USB_REQ_SET_FEATURE, 0x00, 0x0001, 0x0000, NULL, 0x0000, HZ * SET_TIMEOUT);
1349 }
1350 }
1351
1352 /* set port suspend if connected */
1353 if (USBH->HcRhPortStatus[0] & 0x1)
1354 USBH->HcRhPortStatus[0] = 0x4;
1355
1356 if (USBH->HcRhPortStatus[1] & 0x1)
1357 USBH->HcRhPortStatus[1] = 0x4;
1358
1359 /* enable Device Remote Wakeup */
1360 USBH->HcRhStatus |= USBH_HcRhStatus_DRWE_Msk;
1361
1362 /* enable USBH RHSC interrupt for system wakeup */
1364
1365 /* set Host Controller enter suspend state */
1366 USBH->HcControl = (USBH->HcControl & ~USBH_HcControl_HCFS_Msk) | (3 << USBH_HcControl_HCFS_Pos);
1367
1368 return 0;
1369}
1370
1371
1378int32_t USBH_Resume(void)
1379{
1380 USBH->HcControl = (USBH->HcControl & ~USBH_HcControl_HCFS_Msk) | (1 << USBH_HcControl_HCFS_Pos);
1381 USBH->HcControl = (USBH->HcControl & ~USBH_HcControl_HCFS_Msk) | (2 << USBH_HcControl_HCFS_Pos);
1382
1383 if (USBH->HcRhPortStatus[0] & 0x4)
1384 USBH->HcRhPortStatus[0] = 0x8;
1385 if (USBH->HcRhPortStatus[1] & 0x4)
1386 USBH->HcRhPortStatus[1] = 0x8;
1387
1388 return 0;
1389}
1390
1391 /* end of group NUC472_442_USBH_EXPORTED_FUNCTIONS */
1393 /* end of group NUC472_442_USBH_Driver */
1395 /* end of group NUC472_442_Device_Driver */
1397
1398/*** (C) COPYRIGHT 2014 Nuvoton Technology Corp. ***/
1399
NUC472/NUC442 peripheral access layer header file. This file contains all the peripheral register's d...
#define USBH_HcRhStatus_DRWE_Msk
Definition: NUC472_442.h:26869
#define USBH_HcInterruptEnable_RD_Msk
Definition: NUC472_442.h:26761
#define USBH_HcRhStatus_LPS_Msk
Definition: NUC472_442.h:26863
#define USBH_HcInterruptEnable_RHSC_Msk
Definition: NUC472_442.h:26767
#define USBH_HcControl_HCFS_Pos
Definition: NUC472_442.h:26718
int usbh_get_device_descriptor(uint8_t *desc_buff)
Get device descriptor from the USB device.
Definition: lw_usbh.c:456
#define USBH
Definition: NUC472_442.h:28818
#define TIMER0
Definition: NUC472_442.h:28837
#define DEV_MAX_NUM
Definition: usbh_config.h:48
#define USB_ERR_TIMEOUT
Definition: usbh_err_code.h:30
#define USB_ERR_NODEV
Definition: usbh_err_code.h:23
#define USB_ERR_INPROGRESS
Definition: usbh_err_code.h:31
#define USB_ERR_INVAL
Definition: usbh_err_code.h:24
#define MAX_ENDPOINTS
Definition: usbh_config.h:53
#define USB_ERR_PIPE
Definition: usbh_err_code.h:25
#define USB_ERR_NOMEM
Definition: usbh_err_code.h:20
#define MAX_DRIVER_PER_DEV
Definition: usbh_config.h:54
int status
Definition: usbh_core.h:543
int32_t USBH_RegisterDriver(USB_DRIVER_T *new_driver)
Register a device driver to USB Host Core driver.
Definition: usbh_core.c:78
int32_t USBH_SendBulkMsg(USB_DEV_T *usb_dev, uint32_t pipe, void *data, int len, int *actual_length, int timeout)
Execute a bulk transfer.
Definition: usbh_core.c:416
int32_t USBH_GetDescriptor(USB_DEV_T *dev, uint8_t type, uint8_t index, void *buf, int size)
Get a descriptor from device.
Definition: usbh_core.c:822
int32_t USBH_Resume(void)
Resume USB Host controller and devices.
Definition: usbh_core.c:1378
int32_t USBH_Close(void)
Disable USB Host controller function.
Definition: usbh_core.c:1319
int32_t USBH_SubmitUrb(URB_T *urb)
Submit an URB to USB core for transfer data.
Definition: usbh_core.c:218
int actual_length
Definition: usbh_core.h:547
int32_t USBH_Suspend(void)
Suspend USB Host Controller and devices.
Definition: usbh_core.c:1336
struct usb_device * dev
Definition: usbh_core.h:541
int32_t USBH_UnlinkUrb(URB_T *urb)
Cancel an URB which has been submit to USB core.
Definition: usbh_core.c:236
int32_t USBH_Open(void)
Open USB Host controller function.
Definition: usbh_core.c:1270
int32_t USBH_SetInterface(USB_DEV_T *dev, char interface, char alternate)
Set USB device interface.
Definition: usbh_core.c:948
int32_t USBH_SendCtrlMsg(USB_DEV_T *dev, uint32_t pipe, uint8_t request, uint8_t requesttype, uint16_t value, uint16_t index, void *data, uint16_t size, int timeout)
Execute a control transfer.
Definition: usbh_core.c:378
USB_BUS_T * bus
Definition: usbh_core.h:679
int32_t USBH_ClearHalt(USB_DEV_T *dev, int pipe)
Clear the halt state of an endpoint.
Definition: usbh_core.c:900
int32_t USBH_SetConfiguration(USB_DEV_T *dev, int configuration)
Select USB device configuration.
Definition: usbh_core.c:973
USB_IF_DESC_T
Definition: usbh_core.h:335
DEV_REQ_T
Definition: usbh_core.h:190
USB_CONFIG_DESC_T
Definition: usbh_core.h:366
HIDDEN_SYMBOLS struct usb_device USB_DEV_T
USB_EP_DESC_T
Definition: usbh_core.h:300
#define NULL
NULL pointer.
Definition: NUC472_442.h:29018
return value
Definition: semihosting.h:98
USB Host core driver header file.