Index: sys/dev/usb/uftdi.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/uftdi.c,v
retrieving revision 1.51
diff -p -u -r1.51 uftdi.c
--- sys/dev/usb/uftdi.c	11 Feb 2012 05:27:55 -0000	1.51
+++ sys/dev/usb/uftdi.c	11 Aug 2012 06:38:28 -0000
@@ -49,6 +49,7 @@ __KERNEL_RCSID(0, "$NetBSD: uftdi.c,v 1.
 
 #include <dev/usb/uftdireg.h>
 
+#define UFTDI_DEBUG 1
 #ifdef UFTDI_DEBUG
 #define DPRINTF(x)	if (uftdidebug) printf x
 #define DPRINTFN(n,x)	if (uftdidebug>(n)) printf x
@@ -69,6 +70,9 @@ int uftdidebug = 0;
 #define UFTDIIBUFSIZE 64
 #define UFTDIOBUFSIZE 64
 
+#define	UFTDI_MAX_IBUFSIZE	512
+#define	UFTDI_MAX_OBUFSIZE	256
+
 struct uftdi_softc {
 	device_t		sc_dev;		/* base device */
 	usbd_device_handle	sc_udev;	/* device */
@@ -254,6 +258,7 @@ uftdi_attach(device_t parent, device_t s
 		sc->sc_iface[idx] = iface;
 
 		uca.bulkin = uca.bulkout = -1;
+		uca.ibufsize = uca.obufsize = 0;
 		for (i = 0; i < id->bNumEndpoints; i++) {
 			int addr, dir, attr;
 			ed = usbd_interface2endpoint_descriptor(iface, i);
@@ -267,11 +272,24 @@ uftdi_attach(device_t parent, device_t s
 			addr = ed->bEndpointAddress;
 			dir = UE_GET_DIR(ed->bEndpointAddress);
 			attr = ed->bmAttributes & UE_XFERTYPE;
-			if (dir == UE_DIR_IN && attr == UE_BULK)
+			DPRINTF(("uftdi: wMaxPacketSize=%x\n",
+				(unsigned)UGETW(ed->wMaxPacketSize)));
+			if (dir == UE_DIR_IN && attr == UE_BULK) {
 				uca.bulkin = addr;
-			else if (dir == UE_DIR_OUT && attr == UE_BULK)
+				uca.ibufsize = UGETW(ed->wMaxPacketSize);
+				if (uca.ibufsize >= UFTDI_MAX_IBUFSIZE)
+					uca.ibufsize = UFTDI_MAX_IBUFSIZE;
+			} else if (dir == UE_DIR_OUT && attr == UE_BULK) {
 				uca.bulkout = addr;
-			else {
+				uca.obufsize = UGETW(ed->wMaxPacketSize)
+				    - sc->sc_hdrlen;
+				if (uca.obufsize >= UFTDI_MAX_OBUFSIZE)
+					uca.obufsize = UFTDI_MAX_OBUFSIZE;
+				/* Limit length if we have a 6-bit header.  */
+				if ((sc->sc_hdrlen > 0) &&
+				    (uca.obufsize > UFTDIOBUFSIZE))
+					uca.obufsize = UFTDIOBUFSIZE;
+			} else {
 				aprint_error_dev(self,
 				    "unexpected endpoint\n");
 				goto bad;
@@ -290,9 +308,11 @@ uftdi_attach(device_t parent, device_t s
 
 		uca.portno = FTDI_PIT_SIOA + idx;
 		/* bulkin, bulkout set above */
-		uca.ibufsize = UFTDIIBUFSIZE;
-		uca.obufsize = UFTDIOBUFSIZE - sc->sc_hdrlen;
-		uca.ibufsizepad = UFTDIIBUFSIZE;
+		if (uca.ibufsize == 0)
+			uca.ibufsize = UFTDIIBUFSIZE;
+		uca.ibufsizepad = uca.ibufsize;
+		if (uca.obufsize == 0)
+			uca.obufsize = UFTDIOBUFSIZE - sc->sc_hdrlen;
 		uca.opkthdrlen = sc->sc_hdrlen;
 		uca.device = dev;
 		uca.iface = iface;
@@ -300,7 +320,9 @@ uftdi_attach(device_t parent, device_t s
 		uca.arg = sc;
 		uca.info = NULL;
 
-		DPRINTF(("uftdi: in=0x%x out=0x%x\n", uca.bulkin, uca.bulkout));
+		DPRINTF(("uftdi: in=0x%x out=0x%x isize=0x%x osize=0x%x\n",
+			uca.bulkin, uca.bulkout,
+			uca.ibufsize, uca.obufsize));
 		sc->sc_subdev[idx] = config_found_sm_loc(self, "ucombus", NULL,
 		    &uca, ucomprint, ucomsubmatch);
 	}