]> git.kernelconcepts.de Git - karo-tx-uboot.git/blobdiff - common/usb.c
Added M5329AFEE and M5329BFEE Platforms
[karo-tx-uboot.git] / common / usb.c
index 1738d950614154374b0a7a72fefe448a0d95920e..0857494b27b974c442b07d96b4f30c46d8d0c54b 100644 (file)
@@ -1,9 +1,19 @@
 /*
- * (C) Copyright 2001
- * Denis Peter, MPL AG Switzerland
  *
  * Most of this source has been derived from the Linux USB
- * project.
+ * project:
+ * (C) Copyright Linus Torvalds 1999
+ * (C) Copyright Johannes Erdfelt 1999-2001
+ * (C) Copyright Andreas Gal 1999
+ * (C) Copyright Gregory P. Smith 1999
+ * (C) Copyright Deti Fliegl 1999 (new USB architecture)
+ * (C) Copyright Randy Dunlap 2000
+ * (C) Copyright David Brownell 2000 (kernel hotplug, usb_device_id)
+ * (C) Copyright Yggdrasil Computing, Inc. 2000
+ *     (usb_device_id matching changes by Adam J. Richter)
+ *
+ * Adapted for U-Boot:
+ * (C) Copyright 2001 Denis Peter, MPL AG Switzerland
  *
  * See file CREDITS for list of people who contributed to this
  * project.
@@ -46,8 +56,7 @@
 #include <405gp_pci.h>
 #endif
 
-
-#undef USB_DEBUG 
+#undef USB_DEBUG
 
 #ifdef USB_DEBUG
 #define        USB_PRINTF(fmt,args...) printf (fmt ,##args)
@@ -63,6 +72,8 @@ static int running;
 static int asynch_allowed;
 static struct devrequest setup_packet;
 
+char usb_started; /* flag for the started/stopped USB status */
+
 /**********************************************************************
  * some forward declerations...
  */
@@ -101,10 +112,12 @@ int usb_init(void)
                printf("scanning bus for devices... ");
                running=1;
                usb_scan_devices();
+               usb_started = 1;
                return 0;
        }
        else {
                printf("Error, couldn't init Lowlevel part\n");
+               usb_started = 0;
                return -1;
        }
 }
@@ -115,6 +128,7 @@ int usb_init(void)
 int usb_stop(void)
 {
        asynch_allowed=1;
+       usb_started = 0;
        usb_hub_reset();
        return usb_lowlevel_stop();
 }
@@ -271,56 +285,68 @@ int usb_set_maxpacket(struct usb_device *dev)
 int usb_parse_config(struct usb_device *dev, unsigned char *buffer, int cfgno)
 {
        struct usb_descriptor_header *head;
-       int index,ifno,epno;
-       ifno=-1;
-       epno=-1;
-
-       dev->configno=cfgno;
-       head =(struct usb_descriptor_header *)&buffer[0];
-       if(head->bDescriptorType!=USB_DT_CONFIG) {
-               printf(" ERROR: NOT USB_CONFIG_DESC %x\n",head->bDescriptorType);
+       int index, ifno, epno, curr_if_num;
+       int i;
+       unsigned char *ch;
+
+       ifno = -1;
+       epno = -1;
+       curr_if_num = -1;
+
+       dev->configno = cfgno;
+       head = (struct usb_descriptor_header *) &buffer[0];
+       if(head->bDescriptorType != USB_DT_CONFIG) {
+               printf(" ERROR: NOT USB_CONFIG_DESC %x\n", head->bDescriptorType);
                return -1;
        }
-       memcpy(&dev->config,buffer,buffer[0]);
-       dev->config.wTotalLength=swap_16(dev->config.wTotalLength);
-       dev->config.no_of_if=0;
+       memcpy(&dev->config, buffer, buffer[0]);
+       dev->config.wTotalLength = swap_16(dev->config.wTotalLength);
+       dev->config.no_of_if = 0;
 
-       index=dev->config.bLength;
+       index = dev->config.bLength;
        /* Ok the first entry must be a configuration entry, now process the others */
-       head=(struct usb_descriptor_header *)&buffer[index];
-       while(index+1 < dev->config.wTotalLength) {
+       head = (struct usb_descriptor_header *) &buffer[index];
+       while(index + 1 < dev->config.wTotalLength) {
                switch(head->bDescriptorType) {
                        case USB_DT_INTERFACE:
-                               ifno=dev->config.no_of_if;
-                               dev->config.no_of_if++; /* found an interface desc, increase numbers */
-                               memcpy(&dev->config.if_desc[ifno],&buffer[index],buffer[index]); /* copy new desc */
-                               dev->config.if_desc[ifno].no_of_ep=0;
-
+                               if(((struct usb_interface_descriptor *) &buffer[index])->
+                                       bInterfaceNumber != curr_if_num) {
+                                       /* this is a new interface, copy new desc */
+                                       ifno = dev->config.no_of_if;
+                                       dev->config.no_of_if++;
+                                       memcpy(&dev->config.if_desc[ifno],
+                                               &buffer[index], buffer[index]);
+                                       dev->config.if_desc[ifno].no_of_ep = 0;
+                                       dev->config.if_desc[ifno].num_altsetting = 1;
+                                       curr_if_num = dev->config.if_desc[ifno].bInterfaceNumber;
+                               } else {
+                                       /* found alternate setting for the interface */
+                                       dev->config.if_desc[ifno].num_altsetting++;
+                               }
                                break;
                        case USB_DT_ENDPOINT:
-                               epno=dev->config.if_desc[ifno].no_of_ep;
+                               epno = dev->config.if_desc[ifno].no_of_ep;
                                dev->config.if_desc[ifno].no_of_ep++; /* found an endpoint */
-                               memcpy(&dev->config.if_desc[ifno].ep_desc[epno],&buffer[index],buffer[index]);
-                               dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize
-                                       =swap_16(dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize);
-                               USB_PRINTF("if %d, ep %d\n",ifno,epno);
+                               memcpy(&dev->config.if_desc[ifno].ep_desc[epno],
+                                       &buffer[index], buffer[index]);
+                               dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize =
+                                       swap_16(dev->config.if_desc[ifno].ep_desc[epno].wMaxPacketSize);
+                               USB_PRINTF("if %d, ep %d\n", ifno, epno);
                                break;
                        default:
-                               if(head->bLength==0)
+                               if(head->bLength == 0)
                                        return 1;
-                               USB_PRINTF("unknown Description Type : %x\n",head->bDescriptorType);
+                               USB_PRINTF("unknown Description Type : %x\n", head->bDescriptorType);
                                {
-                                       int i;
-                                       unsigned char *ch;
-                                       ch=(unsigned char *)head;
-                                       for(i=0;i<head->bLength; i++)
-                                               USB_PRINTF("%02X ",*ch++);
+                                       ch = (unsigned char *)head;
+                                       for(i = 0; i < head->bLength; i++)
+                                               USB_PRINTF("%02X ", *ch++);
                                        USB_PRINTF("\n\n\n");
                                }
                                break;
                }
-               index+=head->bLength;
-               head=(struct usb_descriptor_header *)&buffer[index];
+               index += head->bLength;
+               head = (struct usb_descriptor_header *)&buffer[index];
        }
        return 1;
 }
@@ -342,7 +368,7 @@ int usb_clear_halt(struct usb_device *dev, int pipe)
        if (result < 0)
                return result;
 
-       /* 
+       /*
         * NOTE: we do not get status and verify reset was successful
         * as some devices are reported to lock up upon this check..
         */
@@ -434,6 +460,14 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
                printf("selecting invalid interface %d", interface);
                return -1;
        }
+       /*
+        * We should return now for devices with only one alternate setting.
+        * According to 9.4.10 of the Universal Serial Bus Specification Revision 2.0
+        * such devices can return with a STALL. This results in some USB sticks
+        * timeouting during initialization and then being unusable in U-Boot.
+        */
+       if (if_face->num_altsetting == 1)
+               return 0;
 
        if ((ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
            USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, alternate,
@@ -517,13 +551,13 @@ int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char
                /* some devices are flaky */
                result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
                        USB_REQ_GET_DESCRIPTOR, USB_DIR_IN,
-                       (USB_DT_STRING << 8) + index, langid, buf, size, 
+                       (USB_DT_STRING << 8) + index, langid, buf, size,
                        USB_CNTL_TIMEOUT);
 
                if (result > 0)
                        break;
-       }       
-                               
+       }
+
        return result;
 }
 
@@ -572,7 +606,7 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid,
        }
 
        if (rc < 2)
-               rc = -1; 
+               rc = -1;
 
        return rc;
 }
@@ -721,10 +755,10 @@ int usb_new_device(struct usb_device *dev)
                }
        }
        dev->descriptor.bMaxPacketSize0 = desc->bMaxPacketSize0;
-       
+
        /* find the port number we're at */
        if (parent) {
-       
+
                for (j = 0; j < parent->maxchild; j++) {
                        if (parent->children[j] == dev) {
                                port = j;
@@ -958,7 +992,7 @@ static int hub_port_reset(struct usb_device *dev, int port,
                        return -1;
 
                if (portstatus & USB_PORT_STAT_ENABLE) {
-                       
+
                        break;
                }