ChangeSet 1.808.2.11, 2002/10/23 11:27:20-07:00, [EMAIL PROTECTED]

[PATCH] ehci enumerating full speed devices

The EHCI driver was never adjusting the full speed maximum packet size up
(when enumerating through a transaction translating hub).  This broke the
enumeration of some devices (maxpacket != 8) pretty early.

This patch updates EHCI to fix the bug, and does minor cleanup to usbcore
logic that figures out ep0 maxpacket.  I left the partial read in for all
speeds, even though only full speed needs it.


diff -Nru a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
--- a/drivers/usb/core/usb.c    Mon Oct 28 13:54:54 2002
+++ b/drivers/usb/core/usb.c    Mon Oct 28 13:54:54 2002
@@ -942,12 +942,27 @@
        int i;
        int j;
 
-       /* USB v1.1 5.5.3 */
-       /* We read the first 8 bytes from the device descriptor to get to */
-       /*  the bMaxPacketSize0 field. Then we set the maximum packet size */
-       /*  for the control pipe, and retrieve the rest */
-       dev->epmaxpacketin [0] = 8;
-       dev->epmaxpacketout[0] = 8;
+       /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ...
+        * it's fixed size except for full speed devices.
+        */
+       switch (dev->speed) {
+       case USB_SPEED_HIGH:            /* fixed at 64 */
+               i = 64;
+               break;
+       case USB_SPEED_FULL:            /* 8, 16, 32, or 64 */
+               /* to determine the ep0 maxpacket size, read the first 8
+                * bytes from the device descriptor to get bMaxPacketSize0;
+                * then correct our initial (small) guess.
+                */
+               // FALLTHROUGH
+       case USB_SPEED_LOW:             /* fixed at 8 */
+               i = 8;
+               break;
+       default:
+               return -EINVAL;
+       }
+       dev->epmaxpacketin [0] = i;
+       dev->epmaxpacketout[0] = i;
 
        for (i = 0; i < NEW_DEVICE_RETRYS; ++i) {
 
@@ -967,6 +982,7 @@
 
                wait_ms(10);    /* Let the SET_ADDRESS settle */
 
+               /* high and low speed devices don't need this... */
                err = usb_get_descriptor(dev, USB_DT_DEVICE, 0, &dev->descriptor, 8);
                if (err >= 8)
                        break;
@@ -982,8 +998,10 @@
                dev->devnum = -1;
                return 1;
        }
-       dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0;
-       dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
+       if (dev->speed == USB_SPEED_FULL) {
+               dev->epmaxpacketin [0] = dev->descriptor.bMaxPacketSize0;
+               dev->epmaxpacketout[0] = dev->descriptor.bMaxPacketSize0;
+       }
 
        err = usb_get_device_descriptor(dev);
        if (err < (signed)sizeof(dev->descriptor)) {
diff -Nru a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c
--- a/drivers/usb/host/ehci-q.c Mon Oct 28 13:54:54 2002
+++ b/drivers/usb/host/ehci-q.c Mon Oct 28 13:54:54 2002
@@ -778,10 +778,26 @@
                        qtd = list_entry (qtd_list->next, struct ehci_qtd,
                                        qtd_list);
 
-               /* maybe patch the qh used for set_address */
-               if (unlikely (epnum == 0
-                               && le32_to_cpu (qh->hw_info1 & 0x7f) == 0))
-                       qh->hw_info1 |= cpu_to_le32 (usb_pipedevice(urb->pipe));
+               /* control qh may need patching after enumeration */
+               if (unlikely (epnum == 0)) {
+                       /* set_address changes the address */
+                       if (le32_to_cpu (qh->hw_info1 & 0x7f) == 0)
+                               qh->hw_info1 |= cpu_to_le32 (
+                                               usb_pipedevice (urb->pipe));
+
+                       /* for full speed, ep0 maxpacket can grow */
+                       else if (!(qh->hw_info1 & cpu_to_le32 (0x3 << 12))) {
+                               u32     info, max;
+
+                               info = le32_to_cpu (qh->hw_info1);
+                               max = urb->dev->descriptor.bMaxPacketSize0;
+                               if (max > (0x07ff & (info >> 16))) {
+                                       info &= ~(0x07ff << 16);
+                                       info |= max << 16;
+                                       qh->hw_info1 = cpu_to_le32 (info);
+                               }
+                       }
+               }
 
                /* append to tds already queued to this qh? */
                if (unlikely (!list_empty (&qh->qtd_list) && qtd)) {


-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to