Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/usb Enable UVC-style headers and use them to help de...



details:   https://anonhg.NetBSD.org/src/rev/589232e8e83e
branches:  trunk
changeset: 747147:589232e8e83e
user:      jmcneill <jmcneill%NetBSD.org@localhost>
date:      Fri Sep 04 11:26:54 2009 +0000

description:
Enable UVC-style headers and use them to help detect stream errors.

diffstat:

 sys/dev/usb/pseye.c |  92 ++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 64 insertions(+), 28 deletions(-)

diffs (165 lines):

diff -r 19e92da6b31f -r 589232e8e83e sys/dev/usb/pseye.c
--- a/sys/dev/usb/pseye.c       Fri Sep 04 10:54:44 2009 +0000
+++ b/sys/dev/usb/pseye.c       Fri Sep 04 11:26:54 2009 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: pseye.c,v 1.12 2009/08/19 13:38:51 jmcneill Exp $ */
+/* $NetBSD: pseye.c,v 1.13 2009/09/04 11:26:54 jmcneill Exp $ */
 
 /*-
  * Copyright (c) 2008 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pseye.c,v 1.12 2009/08/19 13:38:51 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pseye.c,v 1.13 2009/09/04 11:26:54 jmcneill Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -58,13 +58,15 @@
 #include <dev/usb/usbdi.h>
 #include <dev/usb/usbdi_util.h>
 #include <dev/usb/usbdevs.h>
+#include <dev/usb/uvideoreg.h>
 
 #include <dev/video_if.h>
 
 #define PRI_PSEYE      PRI_BIO
 
-/* Bulk-in buffer length */
-#define PSEYE_BULKIN_BUFLEN    (640 * 480 * 2)
+/* Bulk-in buffer length -- make room for payload + UVC headers */
+#define PSEYE_BULKIN_BUFLEN    ((640 * 480 * 2) + 4096)
+#define PSEYE_BULKIN_BLKLEN    2048
 
 /* SCCB/sensor interface */
 #define PSEYE_SCCB_ADDRESS     0xf1
@@ -119,7 +121,8 @@
 static int     pseye_init_pipes(struct pseye_softc *);
 static int     pseye_close_pipes(struct pseye_softc *);
 
-static usbd_status     pseye_get_frame(struct pseye_softc *);
+static usbd_status     pseye_get_frame(struct pseye_softc *, uint32_t *);
+static void    pseye_submit_payload(struct pseye_softc *, uint32_t);
 
 /* video(9) API */
 static int             pseye_open(void *, int);
@@ -351,9 +354,6 @@
        pseye_setregv(sc, 0xe2, 0x00);
        pseye_setregv(sc, 0xe7, 0x3e);
 
-       pseye_setreg(sc, 0x1c, 0x0a);
-       pseye_setreg(sc, 0x1d, 0x22);
-       pseye_setreg(sc, 0x1d, 0x06);
        pseye_setregv(sc, 0x96, 0x00);
 
        pseye_setreg(sc, 0x97, 0x20);
@@ -380,11 +380,15 @@
 
        pseye_setreg(sc, 0x1c, 0x00);
        pseye_setreg(sc, 0x1d, 0x40);
-       pseye_setreg(sc, 0x1d, 0x02);
+       pseye_setreg(sc, 0x1d, 0x02);   /* payload size 0x0200 * 4 == 2048 */
+       pseye_setreg(sc, 0x1d, 0x00);
+       pseye_setreg(sc, 0x1d, 0x02);   /* frame size 0x025800 * 4 == 614400 */
+       pseye_setreg(sc, 0x1d, 0x58);
        pseye_setreg(sc, 0x1d, 0x00);
-       pseye_setreg(sc, 0x1d, 0x02);
-       pseye_setreg(sc, 0x1d, 0x57);
-       pseye_setreg(sc, 0x1d, 0xff);
+
+       pseye_setreg(sc, 0x1c, 0x0a);
+       pseye_setreg(sc, 0x1d, 0x08);   /* enable UVC header */
+       pseye_setreg(sc, 0x1d, 0x0e);
 
        pseye_setregv(sc, 0x8d, 0x1c);
        pseye_setregv(sc, 0x8e, 0x80);
@@ -610,16 +614,14 @@
 }
 
 static usbd_status
-pseye_get_frame(struct pseye_softc *sc)
+pseye_get_frame(struct pseye_softc *sc, uint32_t *plen)
 {
-       uint32_t len = sc->sc_bulkin_bufferlen;
-
        if (sc->sc_dying)
                return USBD_IOERROR;
 
        return usbd_bulk_transfer(sc->sc_bulkin_xfer, sc->sc_bulkin_pipe,
-           USBD_SHORT_XFER_OK|USBD_NO_COPY, 50,
-           sc->sc_bulkin_buffer, &len, "pseyerb");
+           USBD_SHORT_XFER_OK|USBD_NO_COPY, 1000,
+           sc->sc_bulkin_buffer, plen, "pseyerb");
 }
 
 static int
@@ -658,23 +660,57 @@
 }
 
 static void
+pseye_submit_payload(struct pseye_softc *sc, uint32_t tlen)
+{
+       struct video_payload payload;
+       uvideo_payload_header_t *uvchdr;
+       uint8_t *buf = sc->sc_bulkin_buffer;
+       uint32_t len;
+       uint32_t brem = (640*480*2);
+
+       while (brem > 0 && tlen > 0) {
+               len = min(tlen, PSEYE_BULKIN_BLKLEN);
+               if (len < UVIDEO_PAYLOAD_HEADER_SIZE) {
+                       printf("pseye_submit_payload: len=%u\n", len);
+                       return;
+               }
+
+               uvchdr = (uvideo_payload_header_t *)buf;
+               if (uvchdr->bHeaderLength != UVIDEO_PAYLOAD_HEADER_SIZE)
+                       goto next;
+               if (uvchdr->bHeaderLength == len &&
+                   !(uvchdr->bmHeaderInfo & UV_END_OF_FRAME))
+                       goto next;
+               if (uvchdr->bmHeaderInfo & UV_ERROR)
+                       return;
+               if ((uvchdr->bmHeaderInfo & UV_PRES_TIME) == 0)
+                       goto next;
+
+               payload.data = buf + uvchdr->bHeaderLength;
+               payload.size = min(brem, len - uvchdr->bHeaderLength);
+               payload.frameno = UGETDW(&buf[2]);
+               payload.end_of_frame = uvchdr->bmHeaderInfo & UV_END_OF_FRAME;
+               video_submit_payload(sc->sc_videodev, &payload);
+
+next:
+               tlen -= len;
+               buf += len;
+               brem -= payload.size;
+       }
+}
+
+static void
 pseye_transfer_thread(void *opaque)
 {
        struct pseye_softc *sc = opaque;
+       uint32_t len;
        int error;
-       struct video_payload payload;
-
-       payload.frameno = 0;
 
        while (sc->sc_running) {
-               error = pseye_get_frame(sc);
-               if (error == USBD_NORMAL_COMPLETION) {
-                       payload.data = sc->sc_bulkin_buffer;
-                       payload.size = sc->sc_bulkin_bufferlen;
-                       payload.frameno = (payload.frameno + 1) & 1;
-                       payload.end_of_frame = 1;
-                       video_submit_payload(sc->sc_videodev, &payload);
-               }
+               len = sc->sc_bulkin_bufferlen;
+               error = pseye_get_frame(sc, &len);
+               if (error == USBD_NORMAL_COMPLETION)
+                       pseye_submit_payload(sc, len);
        }
 
        mutex_enter(&sc->sc_mtx);



Home | Main Index | Thread Index | Old Index