On Fri, 7 May 2004, Zariel Skotlex wrote: > Ok... I finally managed to snatch my brother's pc for testing (it > already had Gentoo-Linux installed, but was outdated for a month or > so). After upgrading the kernel to 2.6.5 and rebooting and bringing > the pc here to connect it to the cable modem and blah blah blah, I got > this: > > //------------------------------------------------------- > uhci_hcd 0000:00:11.2: port 1 portsc 0093 > hub 1-0:1.0: port 1, status 101, change 1, 12 Mb/s > hub 1-0:1.0: debounce: port 1: delay 100ms stable 4 status 0x101 > usb 1-1: new full speed USB device using address 3 > usb 1-1: new device strings: Mfr=1, Product=2, SerialNumber=3 > uhci_hcd 0000:00:11.2: uhci_result_control: failed with status 500000 > [cf5c5240] link (0f5c51e2) element (0f7ba0c0) > Element != First TD > 0: [cf7ba040] link (0f7ba0c0) e3 Length=7 MaxLen=7 DT0 EndPt=0 > Dev=3, PID=2d(SETUP) (buf=0f29efe0) > 1: [cf7ba0c0] link (0f7ba100) e3 Stalled Babble Length=3 MaxLen=3 > DT1 EndPt=0 Dev=3, PID=69(IN) (buf=0e6fac80) > 2: [cf7ba100] link (00000001) e3 IOC Active Length=0 MaxLen=7ff DT1 > EndPt=0 Dev=3, PID=e1(OUT) (buf=00000000) > > drivers/usb/core/message.c: error getting string descriptor 0 > (error=-75) > usb 1-1: control timeout on ep0in
This means that when the PC asked for the first 4 bytes of string descriptor 0, the cable modem sent back more than 4 bytes. That's a definite error, and the device probably would not pass USB certification. Trying to read string descriptors from devices is a problem. The length of a string descriptor is stored in its first 2 bytes, so a natural approach is to read just that much (to learn the length) and then read the whole thing. Some devices, like your cable modem, won't cooperate with this scheme. Since the maximum possible descriptor length is 255 bytes, another approach is to try asking for that much and let the device send as much as it's got -- but other devices won't cooperate with that scheme. There's no universal solution. > So it appears that afterall, the problem is in the cable modem <-> > driver communication. The message still tells me the error is while > getting the string descriptor, so I suppose the problem is not > critical (well, it does works using the CDCEther on 2.4, afterall). My Critical is as critical does. While failure to retrieve string descriptor 0 won't hurt very much, the particular mode of failure might be important. For example, in the log above there was a "babble" error -- the device tried to send more data than it had been asked for. As it happens, VIA's UHCI controllers have a bug that causes them to stop functioning when they receive a packet longer than expected! Although you didn't show any more of the log, if you had persisted you would have found that _nothing_ you plugged into that USB port thereafter would work until you either reloaded the UHCI driver or rebooted. > brother's pc USB host controller info is: > > //------------------------------------------------------- > 00:11.2 USB Controller: VIA Technologies, Inc. USB (rev 23) (prog-if > 00 [UHCI]) > Subsystem: VIA Technologies, Inc. (Wrong ID) USB Controller > Flags: bus master, medium devsel, latency 32, IRQ 5 > I/O ports at dc00 [size=32] > Capabilities: [80] Power Management version 2 > > 00:11.3 USB Controller: VIA Technologies, Inc. USB (rev 23) (prog-if > 00 [UHCI]) > Subsystem: VIA Technologies, Inc. (Wrong ID) USB Controller > Flags: bus master, medium devsel, latency 32, IRQ 5 > I/O ports at e000 [size=32] > Capabilities: [80] Power Management version 2 > //------------------------------------------------------- > > So.. now what? It looks like the communication between the uhci driver > and the modem does not goes well at all and the modem just "breaks" > down (I mean... something in the modem was changed since the next time > I load the CDCEther driver the cable-modem does not gets detected > until I re-insert the module). I am wondering if indeed some pin of my > cable modem was damaged (well if you consider it stopped working after > an accidental unplug, but I can't SEE how would that affect the pins > on the cable modem's end when the cable that was unplugged was the one > connected to the pc, and I already changed it... maybe it WAS a > coincidence afterall). If it was a damaged pin you probably wouldn't be able to communicate at all. This sounds more like a firmware change (if it ever used to work with 2.6) or a firmware bug (if it never worked with 2.6). > ...so anything else I need to test? I don't think changing the > cable-modem would be much of an option (my cable company probably > would grumble if I ask to change it) Just for kicks, try applying this patch on both computers and send the relevant debugging logs. My hope is that this will avoid the "babble" errors and allow things to proceed, even if reading the descriptors fails. Of course, if something else is also wrong with the cable modem, this won't help. Alan Stern ===== drivers/usb/core/message.c 1.82 vs edited ===== --- 1.82/drivers/usb/core/message.c Thu Apr 15 08:28:25 2004 +++ edited/drivers/usb/core/message.c Fri May 7 14:45:56 2004 @@ -1241,6 +1241,68 @@ return ret; } +static int usb_control_msg2(struct usb_device *dev, unsigned int pipe, + int request, int requesttype, int value, int index, + void *data, int size, int timeout) +{ + struct usb_ctrlrequest *dr = kmalloc(sizeof(struct usb_ctrlrequest), + GFP_NOIO); + int maxpacket, i; + int ret; + + if (!dr) + return -ENOMEM; + + dr->bRequestType= requesttype; + dr->bRequest = request; + dr->wValue = cpu_to_le16p(&value); + dr->wIndex = cpu_to_le16p(&index); + dr->wLength = cpu_to_le16p(&size); + + maxpacket = min((int) dev->epmaxpacketin[0], 64); + i = size % maxpacket; + if (i > 0) + size += maxpacket - i; + + ret = usb_internal_control_msg(dev, pipe, dr, data, size, timeout); + printk(KERN_DEBUG "%s: result = %d\n", __FUNCTION__, ret); + + kfree(dr); + return ret; +} + +static int usb_get_descriptor2(struct usb_device *dev, int type, int index, + void *buf, int size) +{ + int i = 5; + int result; + + memset(buf,0,size); // Make sure we parse really received data + + while (i--) { + /* retry on length 0 or stall; some devices are flakey */ + if ((result = usb_control_msg2(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, + (type << 8) + index, 0, buf, size, + HZ * USB_CTRL_GET_TIMEOUT)) > 0 + || result != -EPIPE) + break; + + dev_dbg (&dev->dev, "RETRY descriptor, result %d\n", result); + result = -ENOMSG; + } + return result; +} + +static int usb_get_string2(struct usb_device *dev, int langid, int index, + void *buf, int size) +{ + return usb_control_msg2(dev, usb_rcvctrlpipe(dev, 0), + USB_REQ_GET_DESCRIPTOR, USB_DIR_IN, + (USB_DT_STRING << 8) + index, langid, buf, size, + HZ * USB_CTRL_GET_TIMEOUT); +} + /** * usb_string - returns ISO 8859-1 version of a string descriptor * @dev: the device whose string descriptor is being retrieved @@ -1280,7 +1342,7 @@ /* get langid for strings if it's not yet known */ if (!dev->have_langid) { - err = usb_get_descriptor(dev, USB_DT_STRING, 0, tbuf, 4); + err = usb_get_descriptor2(dev, USB_DT_STRING, 0, tbuf, 4); if (err < 0) { dev_err (&dev->dev, "string descriptor 0 read error: %d\n", @@ -1303,7 +1365,7 @@ * ask for the length of the string */ - err = usb_get_string(dev, dev->string_langid, index, tbuf, 2); + err = usb_get_string2(dev, dev->string_langid, index, tbuf, 2); if (err == -EPIPE) { dev_dbg(&dev->dev, "RETRY string %d read/%d\n", index, 2); err = usb_get_string(dev, dev->string_langid, index, tbuf, 2); ------------------------------------------------------- This SF.Net email is sponsored by Sleepycat Software Learn developer strategies Cisco, Motorola, Ericsson & Lucent use to deliver higher performing products faster, at low TCO. http://www.sleepycat.com/telcomwpreg.php?From=osdnemail3 _______________________________________________ [EMAIL PROTECTED] To unsubscribe, use the last form field at: https://lists.sourceforge.net/lists/listinfo/linux-usb-devel