summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRemy Bohmer <linux@bohmer.net>2008-09-16 14:55:44 +0200
committerMarkus Klotzbuecher <mk@denx.de>2008-09-17 15:41:21 +0200
commitc9e8436b10cca53fca4904ecbadcd6231ad72c38 (patch)
tree82c0b1610d3cd0057c65ac3a2a0bdbfa7b0a5cfa
parent6f5794a6f78b313231256958fd73673c6aacc116 (diff)
downloadu-boot-imx-c9e8436b10cca53fca4904ecbadcd6231ad72c38.zip
u-boot-imx-c9e8436b10cca53fca4904ecbadcd6231ad72c38.tar.gz
u-boot-imx-c9e8436b10cca53fca4904ecbadcd6231ad72c38.tar.bz2
USB layer of U-Boot causes USB protocol errors while using USB memory sticks
There are several differences between Linux, Windows and U-boot for initialising the USB devices. While analysing the behaviour of U-boot it turned out that U-boot does things really different, and some are wrong (compared to the USB standard). This patch fixes some errors: * The NEW_init procedure that was already in the code is good, while the old procedure is wrong. See code comments for more info. * On a Control request the data returned by the device can be more than 8 bytes, while the host limits it to 8 bytes. This caused the host to generate a DataOverrun error. This results in a lot of USB sticks not being recognised, and the transmission ended frequently with a CTL:TIMEOUT Error. * Added a flag CONFIG_LEGACY_USB_INIT_SEQ to allow users to use the old init procedure. Signed-off-by: Remy Bohmer <linux@bohmer.net> Signed-off-by: Markus Klotzbuecher <mk@denx.de>
-rw-r--r--common/usb.c50
1 files changed, 30 insertions, 20 deletions
diff --git a/common/usb.c b/common/usb.c
index be81aaf..db65d7d 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -80,7 +80,8 @@ void usb_scan_devices(void);
int usb_hub_probe(struct usb_device *dev, int ifnum);
void usb_hub_reset(void);
-
+static int hub_port_reset(struct usb_device *dev, int port,
+ unsigned short *portstat);
/***********************************************************************
* wait_ms
@@ -765,20 +766,34 @@ int usb_new_device(struct usb_device *dev)
int tmp;
unsigned char tmpbuf[USB_BUFSIZ];
- dev->descriptor.bMaxPacketSize0 = 8; /* Start off at 8 bytes */
- dev->maxpacketsize = 0; /* Default to 8 byte max packet size */
- dev->epmaxpacketin [0] = 8;
- dev->epmaxpacketout[0] = 8;
-
/* We still haven't set the Address yet */
addr = dev->devnum;
dev->devnum = 0;
-#undef NEW_INIT_SEQ
-#ifdef NEW_INIT_SEQ
+#ifdef CONFIG_LEGACY_USB_INIT_SEQ
+ /* this is the old and known way of initializing devices, it is
+ * different than what Windows and Linux are doing. Windows and Linux
+ * both retrieve 64 bytes while reading the device descriptor
+ * Several USB stick devices report ERR: CTL_TIMEOUT, caused by an
+ * invalid header while reading 8 bytes as device descriptor. */
+ dev->descriptor.bMaxPacketSize0 = 8; /* Start off at 8 bytes */
+ dev->maxpacketsize = 0; /* Default to 8 byte max packet size */
+ dev->epmaxpacketin [0] = 8;
+ dev->epmaxpacketout[0] = 8;
+
+ err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8);
+ if (err < 8) {
+ printf("\n USB device not responding, " \
+ "giving up (status=%lX)\n",dev->status);
+ return 1;
+ }
+#else
/* this is a Windows scheme of initialization sequence, with double
- * reset of the device. Some equipment is said to work only with such
- * init sequence; this patch is based on the work by Alan Stern:
+ * reset of the device (Linux uses the same sequence, but without double
+ * reset. This double reset is not considered harmful and matches the
+ * Windows behaviour)
+ * Some equipment is said to work only with such init sequence; this
+ * patch is based on the work by Alan Stern:
* http://sourceforge.net/mailarchive/forum.php?thread_id=5729457&forum_id=5398
*/
int j;
@@ -790,10 +805,13 @@ int usb_new_device(struct usb_device *dev)
/* send 64-byte GET-DEVICE-DESCRIPTOR request. Since the descriptor is
* only 18 bytes long, this will terminate with a short packet. But if
* the maxpacket size is 8 or 16 the device may be waiting to transmit
- * some more. */
+ * some more, or keeps on retransmitting the 8 byte header. */
desc = (struct usb_device_descriptor *)tmpbuf;
- desc->bMaxPacketSize0 = 0;
+ dev->descriptor.bMaxPacketSize0 = 64; /* Start off at 64 bytes */
+ dev->maxpacketsize = 64; /* Default to 64 byte max packet size */
+ dev->epmaxpacketin [0] = 64;
+ dev->epmaxpacketout[0] = 64;
for (j = 0; j < 3; ++j) {
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, 64);
if (err < 0) {
@@ -824,14 +842,6 @@ int usb_new_device(struct usb_device *dev)
return 1;
}
}
-#else
- /* and this is the old and known way of initializing devices */
- err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8);
- if (err < 8) {
- printf("\n USB device not responding, " \
- "giving up (status=%lX)\n", dev->status);
- return 1;
- }
#endif
dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0;