Subject: kern/25959: umct(4) fails to locate the bulkin endpoint descriptor
To: None <gnats-bugs@gnats.NetBSD.org>
From: None <rumble@ephemeral.org>
List: netbsd-bugs
Date: 06/17/2004 20:20:41
>Number:         25959
>Category:       kern
>Synopsis:       umct(4) fails to utilise the proper endpoint descriptor
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    kern-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Fri Jun 18 00:22:00 UTC 2004
>Closed-Date:
>Last-Modified:
>Originator:     Steve Rumble
>Release:        NetBSD 2.0_BETA
>Organization:
	
>Environment:
	
	
System: NetBSD t23.ephemeral.org 2.0_BETA NetBSD 2.0_BETA (T23) #10: Sun Jun 13 17:53:30 EDT 2004 rumble@t23.ephemeral.org:/usr/src/sys/arch/i386/compile/T23 i386
Architecture: i386
Machine: i386
>Description:
umct(4) has a workaround for a hardware bug that tags the bulkin
interface descriptor as an interrupt descriptor. In order to
differentiate the interrupt descriptor from the actual bulkin
one, it simply assumes a certain order during enumeration. This
fails on my belkin f5u109 adapter and produces the odd behaviour
of accomodating successful transmits, but no receive capability.

>How-To-Repeat:
Apparently the majority of devices follow the expected
enumeration sequence and do not run into this issue. If your
MCT-based usb serial adapter can transmit, but not receive, this
could be the problem.

>Fix:
The attached patch uses FreeBSD's logic to identify the interrupt
descriptor based on its packet size. I'm not knowledgable enough
about USB to determine if there is a better method, nor whether
one may ever encounter an interrupt descriptor that doesn't have
a 0x2 wMaxPacketSize.

This patch should apply cleanly to -current and 2.0 (and perhaps
earlier code). If committed, a pullup to 2-0 and perhaps 1-6
would be in order.

Index: umct.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/umct.c,v
retrieving revision 1.12
diff -u -r1.12 umct.c
--- umct.c	10 Nov 2003 08:58:39 -0000	1.12
+++ umct.c	7 Jun 2004 01:07:14 -0000
@@ -180,7 +180,7 @@
 	char devinfo[1024];
 	char *devname = USBDEVNAME(sc->sc_dev);
 	usbd_status err;
-	int i, found;
+	int i;
 	struct ucom_attach_args uca;
 
         usbd_devinfo(dev, 0, devinfo);
@@ -230,7 +230,6 @@
 
 	id = usbd_get_interface_descriptor(sc->sc_iface);
 	sc->sc_iface_number = id->bInterfaceNumber;
-	found = 0;
 
 	for (i = 0; i < id->bNumEndpoints; i++) {
 		ed = usbd_interface2endpoint_descriptor(sc->sc_iface, i);
@@ -241,11 +240,15 @@
 			USB_ATTACH_ERROR_RETURN;
 		}
 
+		/*
+		 * The Bulkin endpoint is marked as an interrupt. Since
+		 * we can't rely on the endpoint descriptor order, we'll
+		 * check the wMaxPacketSize field to differentiate.
+		 */
 		if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN &&
 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_INTERRUPT &&
-		    found == 0) {
+		    UGETW(ed->wMaxPacketSize) != 0x2) {
 			uca.bulkin = ed->bEndpointAddress;
-			found = 1;
 		} else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT &&
 		    UE_GET_XFERTYPE(ed->bmAttributes) == UE_BULK) {
 			uca.bulkout = ed->bEndpointAddress;
>Release-Note:
>Audit-Trail:
>Unformatted: