Sun Sep 21 14:13:24 2008 UTC ()
UVC bulk endpoint support, from myself, mjf, and a bottle of vodka. Mostly
works, doesn't handle stream errors properly yet.


(jmcneill)
diff -r1.16 -r1.17 src/sys/dev/usb/uvideo.c

cvs diff -r1.16 -r1.17 src/sys/dev/usb/uvideo.c (expand / switch to unified diff)

--- src/sys/dev/usb/uvideo.c 2008/09/20 21:05:58 1.16
+++ src/sys/dev/usb/uvideo.c 2008/09/21 14:13:24 1.17
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: uvideo.c,v 1.16 2008/09/20 21:05:58 jmcneill Exp $ */ 1/* $NetBSD: uvideo.c,v 1.17 2008/09/21 14:13:24 jmcneill Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2008 Patrick Mahoney 4 * Copyright (c) 2008 Patrick Mahoney
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code was written by Patrick Mahoney (pat@polycrystal.org) as 7 * This code was written by Patrick Mahoney (pat@polycrystal.org) as
8 * part of Google Summer of Code 2008. 8 * part of Google Summer of Code 2008.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -32,64 +32,66 @@ @@ -32,64 +32,66 @@
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE. 36 * POSSIBILITY OF SUCH DAMAGE.
37 */ 37 */
38 38
39/* 39/*
40 * USB video specs: 40 * USB video specs:
41 * http://www.usb.org/developers/devclass_docs/USB_Video_Class_1_1.zip 41 * http://www.usb.org/developers/devclass_docs/USB_Video_Class_1_1.zip
42 */ 42 */
43 43
44#include <sys/cdefs.h> 44#include <sys/cdefs.h>
45__KERNEL_RCSID(0, "$NetBSD: uvideo.c,v 1.16 2008/09/20 21:05:58 jmcneill Exp $"); 45__KERNEL_RCSID(0, "$NetBSD: uvideo.c,v 1.17 2008/09/21 14:13:24 jmcneill Exp $");
46 46
47#ifdef _MODULE 47#ifdef _MODULE
48#include <sys/module.h> 48#include <sys/module.h>
49#endif 49#endif
50 50
51#include <sys/param.h> 51#include <sys/param.h>
52#include <sys/systm.h> 52#include <sys/systm.h>
53#include <sys/kernel.h> 53#include <sys/kernel.h>
54/* #include <sys/malloc.h> */ 54/* #include <sys/malloc.h> */
55#include <sys/kmem.h> 55#include <sys/kmem.h>
56#include <sys/device.h> 56#include <sys/device.h>
57#include <sys/ioctl.h> 57#include <sys/ioctl.h>
58#include <sys/uio.h> 58#include <sys/uio.h>
59#include <sys/tty.h> 59#include <sys/tty.h>
60#include <sys/file.h> 60#include <sys/file.h>
61#include <sys/select.h> 61#include <sys/select.h>
62#include <sys/proc.h> 62#include <sys/proc.h>
63#include <sys/conf.h> 63#include <sys/conf.h>
64#include <sys/vnode.h> 64#include <sys/vnode.h>
65#include <sys/poll.h> 65#include <sys/poll.h>
66#include <sys/queue.h> /* SLIST */ 66#include <sys/queue.h> /* SLIST */
 67#include <sys/kthread.h>
67 68
68#include <sys/videoio.h> 69#include <sys/videoio.h>
69#include <dev/video_if.h> 70#include <dev/video_if.h>
70 71
71#include <dev/usb/usb.h> 72#include <dev/usb/usb.h>
72#include <dev/usb/usbdi.h> 73#include <dev/usb/usbdi.h>
73#include <dev/usb/usbdi_util.h> 74#include <dev/usb/usbdi_util.h>
74#include <dev/usb/usb_quirks.h> 75#include <dev/usb/usb_quirks.h>
75 76
76#include <dev/usb/uvideoreg.h> 77#include <dev/usb/uvideoreg.h>
77 78
78#if !defined(_MODULE) 79#if !defined(_MODULE)
79#include "opt_uvideo.h" 80#include "opt_uvideo.h"
80#endif 81#endif
81 82
82#define UVIDEO_NXFERS 3 83#define UVIDEO_NXFERS 3
 84#define PRI_UVIDEO PRI_BIO
83 85
84/* #define UVIDEO_DISABLE_MJPEG */ 86/* #define UVIDEO_DISABLE_MJPEG */
85 87
86#ifdef UVIDEO_DEBUG 88#ifdef UVIDEO_DEBUG
87#define DPRINTF(x) do { if (uvideodebug) logprintf x; } while (0) 89#define DPRINTF(x) do { if (uvideodebug) logprintf x; } while (0)
88#define DPRINTFN(n,x) do { if (uvideodebug>(n)) logprintf x; } while (0) 90#define DPRINTFN(n,x) do { if (uvideodebug>(n)) logprintf x; } while (0)
89int uvideodebug = 20; 91int uvideodebug = 20;
90#else 92#else
91#define DPRINTF(x) 93#define DPRINTF(x)
92#define DPRINTFN(n,x) 94#define DPRINTFN(n,x)
93#endif 95#endif
94 96
95typedef enum { 97typedef enum {
@@ -191,27 +193,29 @@ struct uvideo_isoc_xfer { @@ -191,27 +193,29 @@ struct uvideo_isoc_xfer {
191 struct uvideo_isoc ix_i[UVIDEO_NXFERS]; 193 struct uvideo_isoc ix_i[UVIDEO_NXFERS];
192 uint32_t ix_nframes; 194 uint32_t ix_nframes;
193 uint32_t ix_uframe_len; 195 uint32_t ix_uframe_len;
194 196
195 struct altlist ix_altlist; 197 struct altlist ix_altlist;
196}; 198};
197 199
198struct uvideo_bulk_xfer { 200struct uvideo_bulk_xfer {
199 uint8_t bx_endpt; 201 uint8_t bx_endpt;
200 usbd_pipe_handle bx_pipe; 202 usbd_pipe_handle bx_pipe;
201 usbd_xfer_handle bx_xfer; 203 usbd_xfer_handle bx_xfer;
202 uint8_t *bx_buffer; 204 uint8_t *bx_buffer;
203 int bx_buflen; 205 int bx_buflen;
204 int bx_datalen; 206 bool bx_running;
 207 kcondvar_t bx_cv;
 208 kmutex_t bx_lock;
205}; 209};
206 210
207struct uvideo_stream { 211struct uvideo_stream {
208 struct uvideo_softc *vs_parent; 212 struct uvideo_softc *vs_parent;
209 usbd_interface_handle vs_iface; 213 usbd_interface_handle vs_iface;
210 uint8_t vs_ifaceno; 214 uint8_t vs_ifaceno;
211 uint8_t vs_subtype; /* input or output */ 215 uint8_t vs_subtype; /* input or output */
212 uint16_t vs_probelen; /* length of probe and 216 uint16_t vs_probelen; /* length of probe and
213 * commit data; varies 217 * commit data; varies
214 * depending on version 218 * depending on version
215 * of spec. */ 219 * of spec. */
216 struct uvideo_format_list vs_formats; 220 struct uvideo_format_list vs_formats;
217 struct uvideo_pixel_format_list vs_pixel_formats; 221 struct uvideo_pixel_format_list vs_pixel_formats;
@@ -323,31 +327,34 @@ static usbd_status uvideo_stream_init( @@ -323,31 +327,34 @@ static usbd_status uvideo_stream_init(
323 uint8_t idx); 327 uint8_t idx);
324static usbd_status uvideo_stream_init_desc( 328static usbd_status uvideo_stream_init_desc(
325 struct uvideo_stream *, 329 struct uvideo_stream *,
326 const usb_interface_descriptor_t *ifdesc, 330 const usb_interface_descriptor_t *ifdesc,
327 usbd_desc_iter_t *iter); 331 usbd_desc_iter_t *iter);
328static usbd_status uvideo_stream_init_frame_based_format( 332static usbd_status uvideo_stream_init_frame_based_format(
329 struct uvideo_stream *, 333 struct uvideo_stream *,
330 const uvideo_descriptor_t *, 334 const uvideo_descriptor_t *,
331 usbd_desc_iter_t *); 335 usbd_desc_iter_t *);
332static void uvideo_stream_free(struct uvideo_stream *); 336static void uvideo_stream_free(struct uvideo_stream *);
333 337
334static int uvideo_stream_start_xfer(struct uvideo_stream *); 338static int uvideo_stream_start_xfer(struct uvideo_stream *);
335static int uvideo_stream_stop_xfer(struct uvideo_stream *); 339static int uvideo_stream_stop_xfer(struct uvideo_stream *);
 340static usbd_status uvideo_stream_recv_process(struct uvideo_stream *,
 341 uint8_t *, uint32_t);
336static usbd_status uvideo_stream_recv_isoc_start(struct uvideo_stream *); 342static usbd_status uvideo_stream_recv_isoc_start(struct uvideo_stream *);
337static usbd_status uvideo_stream_recv_isoc_start1(struct uvideo_isoc *); 343static usbd_status uvideo_stream_recv_isoc_start1(struct uvideo_isoc *);
338static void uvideo_stream_recv_isoc_complete(usbd_xfer_handle, 344static void uvideo_stream_recv_isoc_complete(usbd_xfer_handle,
339 usbd_private_handle, 345 usbd_private_handle,
340 usbd_status); 346 usbd_status);
 347static void uvideo_stream_recv_bulk_transfer(void *);
341 348
342/* format probe and commit */ 349/* format probe and commit */
343#define uvideo_stream_probe(vs, act, data) \ 350#define uvideo_stream_probe(vs, act, data) \
344 (uvideo_stream_probe_and_commit((vs), (act), \ 351 (uvideo_stream_probe_and_commit((vs), (act), \
345 UVIDEO_VS_PROBE_CONTROL, (data))) 352 UVIDEO_VS_PROBE_CONTROL, (data)))
346#define uvideo_stream_commit(vs, act, data) \ 353#define uvideo_stream_commit(vs, act, data) \
347 (uvideo_stream_probe_and_commit((vs), (act), \ 354 (uvideo_stream_probe_and_commit((vs), (act), \
348 UVIDEO_VS_COMMIT_CONTROL, (data))) 355 UVIDEO_VS_COMMIT_CONTROL, (data)))
349static usbd_status uvideo_stream_probe_and_commit(struct uvideo_stream *, 356static usbd_status uvideo_stream_probe_and_commit(struct uvideo_stream *,
350 uint8_t, uint8_t, 357 uint8_t, uint8_t,
351 void *); 358 void *);
352static void uvideo_init_probe_data(uvideo_probe_and_commit_data_t *); 359static void uvideo_init_probe_data(uvideo_probe_and_commit_data_t *);
353 360
@@ -1079,48 +1086,60 @@ uvideo_stream_init(struct uvideo_stream  @@ -1079,48 +1086,60 @@ uvideo_stream_init(struct uvideo_stream
1079 * interface descriptor, modifying the iterator. This may be called 1086 * interface descriptor, modifying the iterator. This may be called
1080 * multiple times because there may be several alternate interfaces 1087 * multiple times because there may be several alternate interfaces
1081 * associated with the same interface number. */ 1088 * associated with the same interface number. */
1082static usbd_status 1089static usbd_status
1083uvideo_stream_init_desc(struct uvideo_stream *vs, 1090uvideo_stream_init_desc(struct uvideo_stream *vs,
1084 const usb_interface_descriptor_t *ifdesc, 1091 const usb_interface_descriptor_t *ifdesc,
1085 usbd_desc_iter_t *iter) 1092 usbd_desc_iter_t *iter)
1086{ 1093{
1087 const usb_descriptor_t *desc; 1094 const usb_descriptor_t *desc;
1088 const uvideo_descriptor_t *uvdesc; 1095 const uvideo_descriptor_t *uvdesc;
1089 struct uvideo_bulk_xfer *bx; 1096 struct uvideo_bulk_xfer *bx;
1090 struct uvideo_isoc_xfer *ix; 1097 struct uvideo_isoc_xfer *ix;
1091 struct uvideo_alternate *alt; 1098 struct uvideo_alternate *alt;
1092 uint8_t xfer_type; 1099 uint8_t xfer_type, xfer_dir;
 1100 uint8_t bmAttributes, bEndpointAddress;
1093 int i; 1101 int i;
1094 1102
1095 /* Iterate until the next interface descriptor. All 1103 /* Iterate until the next interface descriptor. All
1096 * descriptors until then belong to this streaming 1104 * descriptors until then belong to this streaming
1097 * interface. */ 1105 * interface. */
1098 while ((desc = usb_desc_iter_next_non_interface(iter)) != NULL) { 1106 while ((desc = usb_desc_iter_next_non_interface(iter)) != NULL) {
1099 uvdesc = (const uvideo_descriptor_t *)desc; 1107 uvdesc = (const uvideo_descriptor_t *)desc;
1100  1108
1101 switch (uvdesc->bDescriptorType) { 1109 switch (uvdesc->bDescriptorType) {
1102 case UDESC_ENDPOINT: 1110 case UDESC_ENDPOINT:
1103 xfer_type = UE_GET_XFERTYPE(GET(usb_endpoint_descriptor_t, 1111 bmAttributes = GET(usb_endpoint_descriptor_t,
1104 desc, bmAttributes)); 1112 desc, bmAttributes);
1105 if (xfer_type == UE_BULK) { 1113 bEndpointAddress = GET(usb_endpoint_descriptor_t,
 1114 desc, bEndpointAddress);
 1115 xfer_type = UE_GET_XFERTYPE(bmAttributes);
 1116 xfer_dir = UE_GET_DIR(bEndpointAddress);
 1117 if (xfer_type == UE_BULK && xfer_dir == UE_DIR_IN) {
1106 bx = &vs->vs_xfer.bulk; 1118 bx = &vs->vs_xfer.bulk;
1107 if (vs->vs_xfer_type == 0) { 1119 if (vs->vs_xfer_type == 0) {
1108 DPRINTFN(15, ("uvideo_attach: " 1120 DPRINTFN(15, ("uvideo_attach: "
1109 "BULK stream *\n")); 1121 "BULK stream *\n"));
1110 vs->vs_xfer_type = UE_BULK; 1122 vs->vs_xfer_type = UE_BULK;
1111 bx->bx_endpt = 1123 bx->bx_endpt = bEndpointAddress;
1112 GET(usb_endpoint_descriptor_t, 1124 DPRINTF(("uvideo_attach: BULK "
1113 desc, bEndpointAddress); 1125 "endpoint %x\n",
 1126 bx->bx_endpt));
 1127 bx->bx_running = false;
 1128 cv_init(&bx->bx_cv,
 1129 device_xname(vs->vs_parent->sc_dev)
 1130 );
 1131 mutex_init(&bx->bx_lock,
 1132 MUTEX_DEFAULT, IPL_NONE);
1114 } 1133 }
1115 } else if (xfer_type == UE_ISOCHRONOUS) { 1134 } else if (xfer_type == UE_ISOCHRONOUS) {
1116 ix = &vs->vs_xfer.isoc; 1135 ix = &vs->vs_xfer.isoc;
1117 for (i = 0; i < UVIDEO_NXFERS; i++) { 1136 for (i = 0; i < UVIDEO_NXFERS; i++) {
1118 ix->ix_i[i].i_ix = ix; 1137 ix->ix_i[i].i_ix = ix;
1119 ix->ix_i[i].i_vs = vs; 1138 ix->ix_i[i].i_vs = vs;
1120 } 1139 }
1121 if (vs->vs_xfer_type == 0) { 1140 if (vs->vs_xfer_type == 0) {
1122 DPRINTFN(15, ("uvideo_attach: " 1141 DPRINTFN(15, ("uvideo_attach: "
1123 "ISOC stream *\n")); 1142 "ISOC stream *\n"));
1124 SLIST_INIT(&ix->ix_altlist); 1143 SLIST_INIT(&ix->ix_altlist);
1125 vs->vs_xfer_type = UE_ISOCHRONOUS; 1144 vs->vs_xfer_type = UE_ISOCHRONOUS;
1126 ix->ix_endpt = 1145 ix->ix_endpt =
@@ -1421,34 +1440,81 @@ uvideo_stream_init_frame_based_format(st @@ -1421,34 +1440,81 @@ uvideo_stream_init_frame_based_format(st
1421  1440
1422 return USBD_NORMAL_COMPLETION; 1441 return USBD_NORMAL_COMPLETION;
1423} 1442}
1424 1443
1425static int 1444static int
1426uvideo_stream_start_xfer(struct uvideo_stream *vs) 1445uvideo_stream_start_xfer(struct uvideo_stream *vs)
1427{ 1446{
1428 struct uvideo_softc *sc = vs->vs_parent; 1447 struct uvideo_softc *sc = vs->vs_parent;
1429 struct uvideo_bulk_xfer *bx; 1448 struct uvideo_bulk_xfer *bx;
1430 struct uvideo_isoc_xfer *ix; 1449 struct uvideo_isoc_xfer *ix;
1431 uint32_t vframe_len; /* rough bytes per video frame */ 1450 uint32_t vframe_len; /* rough bytes per video frame */
1432 uint32_t uframe_len; /* bytes per usb frame (TODO: or microframe?) */ 1451 uint32_t uframe_len; /* bytes per usb frame (TODO: or microframe?) */
1433 uint32_t nframes; /* number of usb frames (TODO: or microframs?) */ 1452 uint32_t nframes; /* number of usb frames (TODO: or microframs?) */
1434 int i; 1453 int i, ret;
1435 1454
1436 struct uvideo_alternate *alt, *alt_maybe; 1455 struct uvideo_alternate *alt, *alt_maybe;
1437 usbd_status err; 1456 usbd_status err;
1438 1457
1439 switch (vs->vs_xfer_type) { 1458 switch (vs->vs_xfer_type) {
1440 case UE_BULK: 1459 case UE_BULK:
 1460 ret = 0;
1441 bx = &vs->vs_xfer.bulk; 1461 bx = &vs->vs_xfer.bulk;
 1462
 1463 bx->bx_xfer = usbd_alloc_xfer(sc->sc_udev);
 1464 if (bx->bx_xfer == NULL) {
 1465 DPRINTF(("uvideo: couldn't allocate xfer\n"));
 1466 return ENOMEM;
 1467 }
 1468 DPRINTF(("uvideo: xfer %p\n", bx->bx_xfer));
 1469
 1470 bx->bx_buflen = vs->vs_max_payload_size;
 1471
 1472 DPRINTF(("uvideo: allocating %u byte buffer\n", bx->bx_buflen));
 1473 bx->bx_buffer = usbd_alloc_buffer(bx->bx_xfer, bx->bx_buflen);
 1474 if (bx->bx_buffer == NULL) {
 1475 DPRINTF(("uvideo: couldn't allocate buffer\n"));
 1476 return ENOMEM;
 1477 }
 1478
 1479 err = usbd_open_pipe(vs->vs_iface, bx->bx_endpt, 0,
 1480 &bx->bx_pipe);
 1481 if (err != USBD_NORMAL_COMPLETION) {
 1482 DPRINTF(("uvideo: error opening pipe: %s (%d)\n",
 1483 usbd_errstr(err), err));
 1484 return EIO;
 1485 }
 1486 DPRINTF(("uvideo: pipe %p\n", bx->bx_pipe));
 1487
 1488 mutex_enter(&bx->bx_lock);
 1489 if (bx->bx_running == false) {
 1490 bx->bx_running = true;
 1491 ret = kthread_create(PRI_UVIDEO, 0, NULL,
 1492 uvideo_stream_recv_bulk_transfer, vs,
 1493 NULL, device_xname(sc->sc_dev));
 1494 if (ret) {
 1495 DPRINTF(("uvideo: couldn't create kthread:"
 1496 " %d\n", err));
 1497 bx->bx_running = false;
 1498 mutex_exit(&bx->bx_lock);
 1499 return err;
 1500 }
 1501 } else
 1502 aprint_error_dev(sc->sc_dev,
 1503 "transfer already in progress\n");
 1504 mutex_exit(&bx->bx_lock);
 1505
 1506 DPRINTF(("uvideo: thread created\n"));
 1507
1442 return 0; 1508 return 0;
1443 case UE_ISOCHRONOUS: 1509 case UE_ISOCHRONOUS:
1444 ix = &vs->vs_xfer.isoc; 1510 ix = &vs->vs_xfer.isoc;
1445 1511
1446 /* Choose an alternate interface most suitable for 1512 /* Choose an alternate interface most suitable for
1447 * this format. Choose the smallest size that can 1513 * this format. Choose the smallest size that can
1448 * contain max_payload_size. 1514 * contain max_payload_size.
1449 * 1515 *
1450 * It is assumed that the list is sorted in descending 1516 * It is assumed that the list is sorted in descending
1451 * order from largest to smallest packet size. 1517 * order from largest to smallest packet size.
1452 * 1518 *
1453 * TODO: what should the strategy be for choosing an 1519 * TODO: what should the strategy be for choosing an
1454 * alt interface? 1520 * alt interface?
@@ -1549,26 +1615,51 @@ uvideo_stream_start_xfer(struct uvideo_s @@ -1549,26 +1615,51 @@ uvideo_stream_start_xfer(struct uvideo_s
1549} 1615}
1550 1616
1551static int 1617static int
1552uvideo_stream_stop_xfer(struct uvideo_stream *vs) 1618uvideo_stream_stop_xfer(struct uvideo_stream *vs)
1553{ 1619{
1554 struct uvideo_bulk_xfer *bx; 1620 struct uvideo_bulk_xfer *bx;
1555 struct uvideo_isoc_xfer *ix; 1621 struct uvideo_isoc_xfer *ix;
1556 usbd_status err; 1622 usbd_status err;
1557 int i; 1623 int i;
1558 1624
1559 switch (vs->vs_xfer_type) { 1625 switch (vs->vs_xfer_type) {
1560 case UE_BULK: 1626 case UE_BULK:
1561 bx = &vs->vs_xfer.bulk; 1627 bx = &vs->vs_xfer.bulk;
 1628
 1629 DPRINTF(("uvideo_stream_stop_xfer: UE_BULK: "
 1630 "waiting for thread to complete\n"));
 1631 mutex_enter(&bx->bx_lock);
 1632 if (bx->bx_running == true) {
 1633 bx->bx_running = false;
 1634 cv_wait_sig(&bx->bx_cv, &bx->bx_lock);
 1635 }
 1636 mutex_exit(&bx->bx_lock);
 1637
 1638 DPRINTF(("uvideo_stream_stop_xfer: UE_BULK: cleaning up\n"));
 1639
 1640 if (bx->bx_pipe) {
 1641 usbd_abort_pipe(bx->bx_pipe);
 1642 usbd_close_pipe(bx->bx_pipe);
 1643 bx->bx_pipe = NULL;
 1644 }
 1645
 1646 if (bx->bx_xfer) {
 1647 usbd_free_xfer(bx->bx_xfer);
 1648 bx->bx_xfer = NULL;
 1649 }
 1650
 1651 DPRINTF(("uvideo_stream_stop_xfer: UE_BULK: done\n"));
 1652
1562 return 0; 1653 return 0;
1563 case UE_ISOCHRONOUS: 1654 case UE_ISOCHRONOUS:
1564 ix = &vs->vs_xfer.isoc; 1655 ix = &vs->vs_xfer.isoc;
1565 if (ix->ix_pipe != NULL) { 1656 if (ix->ix_pipe != NULL) {
1566 usbd_abort_pipe(ix->ix_pipe); 1657 usbd_abort_pipe(ix->ix_pipe);
1567 usbd_close_pipe(ix->ix_pipe); 1658 usbd_close_pipe(ix->ix_pipe);
1568 ix->ix_pipe = NULL; 1659 ix->ix_pipe = NULL;
1569 } 1660 }
1570 1661
1571 for (i = 0; i < UVIDEO_NXFERS; i++) { 1662 for (i = 0; i < UVIDEO_NXFERS; i++) {
1572 struct uvideo_isoc *isoc = &ix->ix_i[i]; 1663 struct uvideo_isoc *isoc = &ix->ix_i[i];
1573 if (isoc->i_xfer != NULL) { 1664 if (isoc->i_xfer != NULL) {
1574 usbd_free_buffer(isoc->i_xfer); 1665 usbd_free_buffer(isoc->i_xfer);
@@ -1637,40 +1728,72 @@ uvideo_stream_recv_isoc_start1(struct uv @@ -1637,40 +1728,72 @@ uvideo_stream_recv_isoc_start1(struct uv
1637 ix->ix_nframes, 1728 ix->ix_nframes,
1638 USBD_NO_COPY | USBD_SHORT_XFER_OK, 1729 USBD_NO_COPY | USBD_SHORT_XFER_OK,
1639 uvideo_stream_recv_isoc_complete); 1730 uvideo_stream_recv_isoc_complete);
1640 1731
1641 err = usbd_transfer(isoc->i_xfer); 1732 err = usbd_transfer(isoc->i_xfer);
1642 if (err != USBD_IN_PROGRESS) { 1733 if (err != USBD_IN_PROGRESS) {
1643 DPRINTF(("uvideo_stream_recv_start: " 1734 DPRINTF(("uvideo_stream_recv_start: "
1644 "usbd_transfer status=%s (%d)\n", 1735 "usbd_transfer status=%s (%d)\n",
1645 usbd_errstr(err), err)); 1736 usbd_errstr(err), err));
1646 } 1737 }
1647 return err; 1738 return err;
1648} 1739}
1649 1740
 1741static usbd_status
 1742uvideo_stream_recv_process(struct uvideo_stream *vs, uint8_t *buf, uint32_t len)
 1743{
 1744 uvideo_payload_header_t *hdr;
 1745 struct video_payload payload;
 1746
 1747 if (len < sizeof(uvideo_payload_header_t)) {
 1748 DPRINTF(("uvideo_stream_recv_process: len %d < payload hdr\n",
 1749 len));
 1750 return USBD_SHORT_XFER;
 1751 }
 1752
 1753 hdr = (uvideo_payload_header_t *)buf;
 1754
 1755#if 0
 1756 if (hdr->bHeaderLength != UVIDEO_PAYLOAD_HEADER_SIZE)
 1757 return USBD_INVAL;
 1758#endif
 1759 if (hdr->bHeaderLength == len && !(hdr->bmHeaderInfo & UV_END_OF_FRAME))
 1760 return USBD_INVAL;
 1761 if (hdr->bmHeaderInfo & UV_ERROR)
 1762 return USBD_IOERROR;
 1763
 1764 payload.data = buf + hdr->bHeaderLength;
 1765 payload.size = len - hdr->bHeaderLength;
 1766 payload.frameno = hdr->bmHeaderInfo & UV_FRAME_ID;
 1767 payload.end_of_frame = hdr->bmHeaderInfo & UV_END_OF_FRAME;
 1768
 1769 video_submit_payload(vs->vs_parent->sc_videodev, &payload);
 1770
 1771 return USBD_NORMAL_COMPLETION;
 1772}
 1773
1650/* Callback on completion of usb isoc transfer */ 1774/* Callback on completion of usb isoc transfer */
1651static void 1775static void
1652uvideo_stream_recv_isoc_complete(usbd_xfer_handle xfer, 1776uvideo_stream_recv_isoc_complete(usbd_xfer_handle xfer,
1653 usbd_private_handle priv, 1777 usbd_private_handle priv,
1654 usbd_status status) 1778 usbd_status status)
1655{ 1779{
1656 struct uvideo_stream *vs; 1780 struct uvideo_stream *vs;
1657 struct uvideo_isoc_xfer *ix; 1781 struct uvideo_isoc_xfer *ix;
1658 struct uvideo_isoc *isoc; 1782 struct uvideo_isoc *isoc;
1659 int i; 1783 int i;
1660 uint32_t count; 1784 uint32_t count;
1661 const uvideo_payload_header_t *hdr; 1785 const uvideo_payload_header_t *hdr;
1662 uint8_t *buf; 1786 uint8_t *buf;
1663 struct video_payload payload; 
1664 1787
1665 isoc = priv; 1788 isoc = priv;
1666 vs = isoc->i_vs; 1789 vs = isoc->i_vs;
1667 ix = isoc->i_ix; 1790 ix = isoc->i_ix;
1668 1791
1669 if (status != USBD_NORMAL_COMPLETION) { 1792 if (status != USBD_NORMAL_COMPLETION) {
1670 DPRINTF(("uvideo_stream_recv_isoc_complete: status=%s (%d)\n", 1793 DPRINTF(("uvideo_stream_recv_isoc_complete: status=%s (%d)\n",
1671 usbd_errstr(status), status)); 1794 usbd_errstr(status), status));
1672  1795
1673 if (status == USBD_STALLED) 1796 if (status == USBD_STALLED)
1674 usbd_clear_endpoint_stall_async(ix->ix_pipe); 1797 usbd_clear_endpoint_stall_async(ix->ix_pipe);
1675 else 1798 else
1676 return; 1799 return;
@@ -1678,57 +1801,76 @@ uvideo_stream_recv_isoc_complete(usbd_xf @@ -1678,57 +1801,76 @@ uvideo_stream_recv_isoc_complete(usbd_xf
1678 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL); 1801 usbd_get_xfer_status(xfer, NULL, NULL, &count, NULL);
1679 1802
1680 if (count == 0) { 1803 if (count == 0) {
1681 /* DPRINTF(("uvideo: zero length transfer\n")); */ 1804 /* DPRINTF(("uvideo: zero length transfer\n")); */
1682 goto next; 1805 goto next;
1683 } 1806 }
1684  1807
1685 hdr = (const uvideo_payload_header_t *)isoc->i_buf; 1808 hdr = (const uvideo_payload_header_t *)isoc->i_buf;
1686  1809
1687 for (i = 0, buf = isoc->i_buf; 1810 for (i = 0, buf = isoc->i_buf;
1688 i < ix->ix_nframes; 1811 i < ix->ix_nframes;
1689 ++i, buf += ix->ix_uframe_len) 1812 ++i, buf += ix->ix_uframe_len)
1690 { 1813 {
1691 if (isoc->i_frlengths[i] < 1814 status = uvideo_stream_recv_process(vs, buf,
1692 sizeof(uvideo_payload_header_t)) 1815 isoc->i_frlengths[i]);
1693 continue; 1816 if (status == USBD_IOERROR)
1694  
1695 hdr = (uvideo_payload_header_t *)buf; 
1696 if (hdr->bHeaderLength != UVIDEO_PAYLOAD_HEADER_SIZE) 
1697 continue; 
1698 if (hdr->bHeaderLength == isoc->i_frlengths[i] && 
1699 !(hdr->bmHeaderInfo & UV_END_OF_FRAME)) 
1700 continue; 
1701 if (hdr->bmHeaderInfo & UV_ERROR) { 
1702 DPRINTF(("uvideo: stream error\n")); 
1703 break; 1817 break;
1704 } 
1705 
1706 payload.data = buf + hdr->bHeaderLength; 
1707 payload.size = isoc->i_frlengths[i] - 
1708 hdr->bHeaderLength; 
1709 payload.frameno = hdr->bmHeaderInfo & UV_FRAME_ID; 
1710 payload.end_of_frame = 
1711 hdr->bmHeaderInfo & UV_END_OF_FRAME; 
1712  
1713 video_submit_payload(vs->vs_parent->sc_videodev, 
1714 &payload); 
1715 } 1818 }
1716 } 1819 }
1717 1820
1718next: 1821next:
1719 uvideo_stream_recv_isoc_start1(isoc); 1822 uvideo_stream_recv_isoc_start1(isoc);
1720} 1823}
1721 1824
 1825static void
 1826uvideo_stream_recv_bulk_transfer(void *addr)
 1827{
 1828 struct uvideo_stream *vs = addr;
 1829 struct uvideo_softc *sc = vs->vs_parent;
 1830 struct uvideo_bulk_xfer *bx = &vs->vs_xfer.bulk;
 1831 usbd_status err;
 1832 uint32_t len;
 1833
 1834 DPRINTF(("uvideo_stream_recv_bulk_transfer: "
 1835 "vs %p sc %p bx %p buffer %p\n", vs, sc, bx, bx->bx_buffer));
 1836
 1837 while (bx->bx_running) {
 1838 len = bx->bx_buflen;
 1839 err = usbd_bulk_transfer(bx->bx_xfer, bx->bx_pipe,
 1840 USBD_SHORT_XFER_OK /* | USBD_NO_COPY */, 500,
 1841 bx->bx_buffer, &len, "uvideorb");
 1842
 1843 if (len == 0)
 1844 DPRINTF(("uvideo_stream_recv_bulk_transfer: 0 len\n"));
 1845
 1846 if (err == USBD_NORMAL_COMPLETION) {
 1847 uvideo_stream_recv_process(vs, bx->bx_buffer, len);
 1848 } else {
 1849 DPRINTF(("uvideo_stream_recv_bulk_transfer: %s\n",
 1850 usbd_errstr(err)));
 1851 }
 1852 }
 1853
 1854 DPRINTF(("uvideo_stream_recv_bulk_transfer: notify complete\n"));
 1855
 1856 mutex_enter(&bx->bx_lock);
 1857 cv_broadcast(&bx->bx_cv);
 1858 mutex_exit(&bx->bx_lock);
 1859
 1860 DPRINTF(("uvideo_stream_recv_bulk_transfer: return\n"));
 1861
 1862 kthread_exit(0);
 1863}
1722 1864
1723/* 1865/*
1724 * uvideo_open - probe and commit video format and start receiving 1866 * uvideo_open - probe and commit video format and start receiving
1725 * video data 1867 * video data
1726 */ 1868 */
1727static int 1869static int
1728uvideo_open(void *addr, int flags) 1870uvideo_open(void *addr, int flags)
1729{ 1871{
1730 struct uvideo_softc *sc; 1872 struct uvideo_softc *sc;
1731 struct uvideo_stream *vs; 1873 struct uvideo_stream *vs;
1732 struct video_format fmt; 1874 struct video_format fmt;
1733 1875
1734 sc = addr; 1876 sc = addr;