summaryrefslogtreecommitdiffstats
path: root/common/usb.c
diff options
context:
space:
mode:
authorRemy Bohmer <linux@bohmer.net>2008-10-10 10:23:21 +0200
committerMarkus Klotzbuecher <mk@denx.de>2008-10-14 16:42:44 +0200
commit48867208444cb2a82e2af9c3249e90b7ed4a1751 (patch)
treef6a05b67058517735a3a3d99b15f993758f1aaf7 /common/usb.c
parente58c41e26cf3c8accd60311be579f452e368e97e (diff)
downloadtalos-obmc-uboot-48867208444cb2a82e2af9c3249e90b7ed4a1751.tar.gz
talos-obmc-uboot-48867208444cb2a82e2af9c3249e90b7ed4a1751.zip
fix USB initialisation procedure
The max packet size is encoded as 0,1,2,3 for 8,16,32,64 bytes. At some places directly 8,16,32,64 was used instead of the encoded value. Made a enum for the options to make this more clear and to help preventing similar errors in the future. After fixing this bug it became clear that another bug existed where the 'pipe' is and-ed with PIPE_* flags, where it should have been 'usb_pipetype(pipe)', or even better usb_pipeint(pipe). Also removed the triple 'get_device_descriptor' sequence, it has no use, and Windows nor Linux behaves that way. There is also a poll going on with a timeout when usb_control_msg() fails. However, the poll is useless, because the flag will never be set on a error, because there is no code that runs in a parallel that can set this flag. Changed this to something more logical. Tested on AT91SAM9261ek and compared the flow on the USB bus to what Linux is doing. There is no difference anymore in the early initialisation sequence. Signed-off-by: Remy Bohmer <linux@bohmer.net> Signed-off-by: Markus Klotzbuecher <mk@denx.de>
Diffstat (limited to 'common/usb.c')
-rw-r--r--common/usb.c56
1 files changed, 28 insertions, 28 deletions
diff --git a/common/usb.c b/common/usb.c
index db65d7db34..7ab5df670b 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -196,15 +196,16 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe,
if (timeout == 0)
return (int)size;
- while (timeout--) {
- if (!((volatile unsigned long)dev->status & USB_ST_NOT_PROC))
- break;
- wait_ms(1);
- }
- if (dev->status == 0)
- return dev->act_len;
- else
+ if (dev->status != 0) {
+ /*
+ * Let's wait a while for the timeout to elapse.
+ * It has no real use, but it keeps the interface happy.
+ */
+ wait_ms(timeout);
return -1;
+ }
+
+ return dev->act_len;
}
/*-------------------------------------------------------------------
@@ -442,14 +443,14 @@ int usb_get_configuration_no(struct usb_device *dev,
config = (struct usb_config_descriptor *)&buffer[0];
- result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 8);
- if (result < 8) {
+ result = usb_get_descriptor(dev, USB_DT_CONFIG, cfgno, buffer, 9);
+ if (result < 9) {
if (result < 0)
printf("unable to get descriptor, error %lX\n",
dev->status);
else
printf("config descriptor too short " \
- "(expected %i, got %i)\n", 8, result);
+ "(expected %i, got %i)\n", 9, result);
return -1;
}
tmp = le16_to_cpu(config->wTotalLength);
@@ -777,7 +778,7 @@ int usb_new_device(struct usb_device *dev)
* 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->maxpacketsize = PACKET_SIZE_8;
dev->epmaxpacketin [0] = 8;
dev->epmaxpacketout[0] = 8;
@@ -788,15 +789,12 @@ int usb_new_device(struct usb_device *dev)
return 1;
}
#else
- /* this is a Windows scheme of initialization sequence, with double
- * 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)
+ /* This is a Windows scheme of initialization sequence, with double
+ * reset of the device (Linux uses the same sequence)
* 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;
struct usb_device_descriptor *desc;
int port = -1;
struct usb_device *parent = dev->parent;
@@ -809,20 +807,22 @@ int usb_new_device(struct usb_device *dev)
desc = (struct usb_device_descriptor *)tmpbuf;
dev->descriptor.bMaxPacketSize0 = 64; /* Start off at 64 bytes */
- dev->maxpacketsize = 64; /* Default to 64 byte max packet size */
+ /* Default to 64 byte max packet size */
+ dev->maxpacketsize = PACKET_SIZE_64;
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) {
- USB_PRINTF("usb_new_device: 64 byte descr\n");
- break;
- }
+
+ err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, desc, 64);
+ if (err < 0) {
+ USB_PRINTF("usb_new_device: usb_get_descriptor() failed\n");
+ return 1;
}
+
dev->descriptor.bMaxPacketSize0 = desc->bMaxPacketSize0;
/* find the port number we're at */
if (parent) {
+ int j;
for (j = 0; j < parent->maxchild; j++) {
if (parent->children[j] == dev) {
@@ -847,10 +847,10 @@ int usb_new_device(struct usb_device *dev)
dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0;
dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
switch (dev->descriptor.bMaxPacketSize0) {
- case 8: dev->maxpacketsize = 0; break;
- case 16: dev->maxpacketsize = 1; break;
- case 32: dev->maxpacketsize = 2; break;
- case 64: dev->maxpacketsize = 3; break;
+ case 8: dev->maxpacketsize = PACKET_SIZE_8; break;
+ case 16: dev->maxpacketsize = PACKET_SIZE_16; break;
+ case 32: dev->maxpacketsize = PACKET_SIZE_32; break;
+ case 64: dev->maxpacketsize = PACKET_SIZE_64; break;
}
dev->devnum = addr;
OpenPOWER on IntegriCloud