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 #include #include /* SLIST */ +#include #include #include @@ -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;