On Thu, 7 Oct 2004, Til Schubbe wrote: > * On 06.10. Alan Stern muttered: > > > Have you tried using that patch with 2.6.7? You can download > > the patch from > > > > http://marc.theaimsgroup.com/?l=linux-usb-devel&m=109069796003168&w=2 > > debian:/etc # lsusb > Bus 004 Device 001: ID 0000:0000 > Bus 003 Device 001: ID 0000:0000 > Bus 002 Device 003: ID 054c:00c0 Sony Corp. > Bus 002 Device 001: ID 0000:0000 > Bus 001 Device 001: ID 0000:0000 > > :-) > > > But syslog says 'uhci_result_control: failed with status ...':
As you should expect, because the patch uses the regular Linux-style initialization first and only falls back to the Microsoft-style initialization if it has to. So the 2.6.7 version of the patch works but the 2.6.8.1 version fails... Well, looking through the new patch I see two mistakes. One is unimportant but the other could be crucial. Below is an updated version of the patch. It contains both the original 2.6.8.1 patch (with the mistakes fixed) and the extra little diagnostic patch. Apply this to a vanilla kernel and see if it works better this time. Alan Stern --- 2.6.8.1/drivers/usb/core/hub.c.orig 2004-10-04 15:39:26.000000000 -0400 +++ 2.6.8.1/drivers/usb/core/hub.c 2004-10-07 14:10:32.000000000 -0400 @@ -1127,7 +1127,7 @@ #define PORT_RESET_TRIES 5 #define SET_ADDRESS_TRIES 2 #define GET_DESCRIPTOR_TRIES 2 -#define SET_CONFIG_TRIES 2 +#define SET_CONFIG_TRIES 4 #define HUB_ROOT_RESET_TIME 50 /* times are in msec */ #define HUB_SHORT_RESET_TIME 10 @@ -1352,7 +1352,8 @@ * pointers, it's not necessary to lock the device. */ static int -hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port) +hub_port_init (struct usb_device *hdev, struct usb_device *udev, int port, + int get_descriptor_first) { static DECLARE_MUTEX(usb_address0_sem); @@ -1387,6 +1388,7 @@ dev_dbg(&udev->dev, "device reset changed speed!\n"); goto fail; } + oldspeed = udev->speed; /* USB 2.0 section 5.5.3 talks about ep0 maxpacket ... * it's fixed size except for full speed devices. @@ -1396,19 +1398,18 @@ 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. + /* to determine the ep0 maxpacket size, try to read + * the device descriptor to get bMaxPacketSize0 and + * then correct our initial guess. */ - // FALLTHROUGH + i = 64; + break; case USB_SPEED_LOW: /* fixed at 8 */ i = 8; break; default: goto fail; } - udev->epmaxpacketin [0] = i; - udev->epmaxpacketout[0] = i; dev_info (&udev->dev, "%s %s speed USB device using address %d\n", @@ -1433,17 +1434,65 @@ udev->tt = &hub->tt; udev->ttport = port + 1; } + + /* Clear out any stale HC state pertaining to device 0 endpoint 0 */ + j = udev->devnum; + udev->devnum = 0; + usb_disable_endpoint(udev, 0 + USB_DIR_IN); + usb_disable_endpoint(udev, 0 + USB_DIR_OUT); + udev->devnum = j; + udev->epmaxpacketin [0] = i; + udev->epmaxpacketout[0] = i; + usb_endpoint_running(udev, 0, 0); + usb_endpoint_running(udev, 0, 1); /* Why interleave GET_DESCRIPTOR and SET_ADDRESS this way? * Because device hardware and firmware is sometimes buggy in * this area, and this is how Linux has done it for ages. * Change it cautiously. * - * NOTE: Windows gets the descriptor first, seemingly to help - * work around device bugs like "can't use addresses with bit 3 - * set in certain configurations". Yes, really. + * NOTE: For full-speed devices, if get_descriptor_first + * is set we will start by issuing a 64-byte GET_DESCRIPTOR + * request. This is what Windows does, so it may help with some + * non-standards-compliant devices. Otherwise we start with + * SET_ADDRESS and then try to read the first 8 bytes of the + * device descriptor to get the ep0 maxpacket value. */ - for (i = 0; i < GET_DESCRIPTOR_TRIES; ++i) { + for (i = 0; i < GET_DESCRIPTOR_TRIES; (++i, msleep(100))) { + if (get_descriptor_first) { + struct usb_device_descriptor *buf; + + buf = kmalloc(64, GFP_NOIO); + if (!buf) { + retval = -ENOMEM; + continue; + } + memset(buf, 0, 64); + j = usb_control_msg(udev, + /* Address 0 */ + (PIPE_CONTROL << 30) | USB_DIR_IN, + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, + USB_DT_DEVICE << 8, 0, + buf, 64, + HZ * USB_CTRL_GET_TIMEOUT); +printk(KERN_INFO "Init get-descr: %d, maxpacket %d\n", +j, buf->bMaxPacketSize0); + udev->descriptor = *buf; + kfree(buf); + + retval = hub_port_reset(hdev, port, udev, delay); + if (retval < 0) /* error or disconnect */ + goto fail; + if (oldspeed != udev->speed) { + retval = -ENODEV; + goto fail; + } + if (udev->descriptor.bMaxPacketSize0 < 8) { + retval = -EMSGSIZE; + continue; + } + } + for (j = 0; j < SET_ADDRESS_TRIES; ++j) { retval = hub_set_address(udev); if (retval >= 0) @@ -1462,10 +1511,12 @@ * - read ep0 maxpacket even for high and low speed, */ msleep(10); - retval = usb_get_device_descriptor(udev, 8); + if (get_descriptor_first) + retval = 8; + else + retval = usb_get_device_descriptor(udev, 8); if (retval >= 8) break; - msleep(100); } if (retval != 8) { dev_err(&udev->dev, "device descriptor read/%s, error %d\n", @@ -1645,7 +1696,7 @@ } /* reset and get descriptor */ - status = hub_port_init(hdev, udev, port); + status = hub_port_init(hdev, udev, port, (i < 2)); if (status < 0) goto loop; @@ -2060,7 +2111,7 @@ { struct usb_device *parent = udev->parent; struct usb_device_descriptor descriptor = udev->descriptor; - int i, ret, port = -1; + int i, ret = 0, port = -1; struct usb_hub *hub; if (udev->state == USB_STATE_NOTATTACHED || @@ -2092,7 +2143,11 @@ return -ENOENT; } - ret = hub_port_init(parent, udev, port); + for (i = 0; i < SET_CONFIG_TRIES; ++i) { + ret = hub_port_init(parent, udev, port, (i >= 2)); + if (ret >= 0) + break; + } if (ret < 0) goto re_enumerate; ------------------------------------------------------- This SF.net email is sponsored by: IT Product Guide on ITManagersJournal Use IT products in your business? Tell us what you think of them. Give us Your Opinions, Get Free ThinkGeek Gift Certificates! Click to find out more http://productguide.itmanagersjournal.com/guidepromo.tmpl _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-users