Index: sys/dev/usb/uvideo.c
===================================================================
RCS file: /cvsroot/src/sys/dev/usb/uvideo.c,v
retrieving revision 1.8
diff -u -u -r1.8 uvideo.c
--- sys/dev/usb/uvideo.c	18 Sep 2008 17:47:09 -0000	1.8
+++ sys/dev/usb/uvideo.c	20 Sep 2008 16:02:19 -0000
@@ -64,6 +64,7 @@
 #include <sys/vnode.h>
 #include <sys/poll.h>
 #include <sys/queue.h>	/* SLIST */
+#include <sys/kthread.h>
 
 #include <sys/videoio.h>
 #include <dev/video_if.h>
@@ -78,6 +79,7 @@
 #include "opt_uvideo.h"
 
 #define UVIDEO_NXFERS	3
+#define PRI_UVIDEO	PRI_BIO
 
 /* #define UVIDEO_DISABLE_MJPEG */
 
@@ -669,6 +671,58 @@
 	return rv;
 }
 
+static usbd_status
+uvideo_stream_recv_bulk_start(struct uvideo_stream *vs)
+{
+	struct uvideo_softc *sc = vs->vs_parent;
+	struct uvideo_bulk_xfer *bx = &vs->vs_xfer.bulk;
+	const uvideo_payload_header_t *hdr;
+	int error, frameno;
+	struct video_payload payload;
+	uint32_t len = bx->bx_buflen;
+
+	frameno = -1;
+
+	printf("uvideo_stream_recv_bulk_start");
+	for (;;) {
+		error = usbd_bulk_transfer(bx->bx_xfer, bx->bx_pipe,
+			    USBD_SHORT_XFER_OK|USBD_NO_COPY, 50000,
+			    bx->bx_buffer, &len, "uvideorb");
+		if (len >= sizeof(uvideo_payload_header_t) &&
+		    error == USBD_NORMAL_COMPLETION) {
+
+			hdr = (const uvideo_payload_header_t *)&bx->bx_buffer;
+			if (hdr->bHeaderLength == 0)
+				continue;
+
+			payload.data = bx->bx_buffer + hdr->bHeaderLength;
+			payload.size = bx->bx_buflen - hdr->bHeaderLength;
+			payload.frameno = hdr->bmHeaderInfo & UV_FRAME_ID;
+			payload.end_of_frame =
+			    hdr->bmHeaderInfo & UV_END_OF_FRAME;
+			
+			if (frameno == -1)
+				frameno = payload.frameno;
+
+			video_submit_payload(sc->sc_videodev, &payload);
+			
+			/* 
+			 * The payload can only be smaller than
+			 * bx_buflen on the last payload. If this is the
+			 * last one then we are done.
+			 */
+			if (len < bx->bx_buflen)
+				break;
+
+			if (frameno != payload.frameno ||
+			    payload.end_of_frame)
+				break;
+		} else
+			break;
+	}
+	return error;
+}
+
 /* Search the stream list for a stream matching the interface number.
  * This is an O(n) search, but most devices should have only one or at
  * most two streams. */
@@ -1068,7 +1122,13 @@
 					bx->bx_endpt =
 					    GET(usb_endpoint_descriptor_t,
 						desc, bEndpointAddress);
+					bx->bx_buflen = 
+					    UGETW(GET(usb_endpoint_descriptor_t,
+						desc, wMaxPacketSize));
+					printf("wMaxPacketSize = %d\n", bx->bx_buflen);
+
 				}
+				
 			} else if (xfer_type == UE_ISOCHRONOUS) {
 				ix = &vs->vs_xfer.isoc;
 				for (i = 0; i < UVIDEO_NXFERS; i++) {
@@ -1345,14 +1405,42 @@
 	uint32_t vframe_len;	/* rough bytes per video frame */
 	uint32_t uframe_len;	/* bytes per usb frame (TODO: or microframe?) */
 	uint32_t nframes;	/* number of usb frames (TODO: or microframs?) */
-	int i;
+	int i, ret;
 
 	struct uvideo_alternate *alt, *alt_maybe;
 	usbd_status err;
 
 	switch (vs->vs_xfer_type) {
 	case UE_BULK:
+		ret = 0;
 		bx = &vs->vs_xfer.bulk;
+		err = usbd_open_pipe(vs->vs_iface, bx->bx_endpt,
+				     USBD_EXCLUSIVE_USE, &bx->bx_pipe);
+		if (err != USBD_NORMAL_COMPLETION) {
+			DPRINTF(("uvideo: error opening pipe: %s (%d)\n",
+				 usbd_errstr(err), err));
+			return EIO;
+		}
+
+		bx->bx_xfer = usbd_alloc_xfer(sc->sc_udev);
+		if (bx->bx_xfer == NULL) {
+			DPRINTF(("uvideo: failed to alloc xfer: %s"
+			 " (%d)\n",
+			 usbd_errstr(err), err));
+			return ENOMEM;
+		}
+
+		bx->bx_buffer = usbd_alloc_buffer(bx->bx_xfer,
+				    bx->bx_buflen);
+		if (bx->bx_xfer == NULL) {
+			DPRINTF(("uvideo: failed to alloc buf: %s"
+			 " (%d)\n",
+			 usbd_errstr(err), err));
+			return ENOMEM;
+		}
+
+		uvideo_stream_recv_bulk_start(vs);
+
 		return 0;
 	case UE_ISOCHRONOUS:
 		ix = &vs->vs_xfer.isoc;
@@ -1481,6 +1569,8 @@
 	switch (vs->vs_xfer_type) {
 	case UE_BULK:
 		bx = &vs->vs_xfer.bulk;
+
+		/* TODO: Free resources */
 		return 0;
 	case UE_ISOCHRONOUS:
 		ix = &vs->vs_xfer.isoc;
