summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMarcus Glocker <mglocker@cvs.openbsd.org>2008-05-24 19:37:35 +0000
committerMarcus Glocker <mglocker@cvs.openbsd.org>2008-05-24 19:37:35 +0000
commitec8b8e37b2177d2b6911ecc80da5c5211d200380 (patch)
treee75a0bea9b7e89835738efd8affa4cead1803068 /sys/dev
parent49a507fbe9895f9d7339d9e4f70a773072da0d09 (diff)
- Enable userland to read(2) video stream from /dev/video.
- Prepare for mmap(2).
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/usb/uvideo.c23
-rw-r--r--sys/dev/usb/uvideo.h7
-rw-r--r--sys/dev/video.c81
-rw-r--r--sys/dev/video_if.h5
-rw-r--r--sys/dev/videovar.h5
5 files changed, 112 insertions, 9 deletions
diff --git a/sys/dev/usb/uvideo.c b/sys/dev/usb/uvideo.c
index 3e3fde7fb23..1ca14d2fdf2 100644
--- a/sys/dev/usb/uvideo.c
+++ b/sys/dev/usb/uvideo.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvideo.c,v 1.16 2008/05/18 09:35:35 mglocker Exp $ */
+/* $OpenBSD: uvideo.c,v 1.17 2008/05/24 19:37:34 mglocker Exp $ */
/*
* Copyright (c) 2008 Robert Nagy <robert@openbsd.org>
@@ -54,7 +54,8 @@ int uvideo_debug = 1;
int uvideo_enable(void *);
void uvideo_disable(void *);
-int uvideo_open(void *, int);
+int uvideo_open(void *, int, int *, uint8_t *, void (*)(void *),
+ void *arg);
int uvideo_close(void *);
int uvideo_match(struct device *, void *, void *);
@@ -197,7 +198,8 @@ uvideo_disable(void *v)
}
int
-uvideo_open(void *addr, int flags)
+uvideo_open(void *addr, int flags, int *size, uint8_t *buffer,
+ void (*intr)(void *), void *arg)
{
struct uvideo_softc *sc = addr;
usbd_status error;
@@ -208,6 +210,12 @@ uvideo_open(void *addr, int flags)
if (sc->sc_dying)
return (EIO);
+ /* pointers to upper layer which we need */
+ sc->sc_uplayer_arg = arg;
+ sc->sc_uplayer_fsize = size;
+ sc->sc_uplayer_fbuffer = buffer;
+ sc->sc_uplayer_intr = intr;
+
/* open video stream pipe */
error = uvideo_vs_open(sc);
if (error != USBD_NORMAL_COMPLETION)
@@ -1161,6 +1169,15 @@ uvideo_vs_decode_stream_header(struct uvideo_softc *sc, uint8_t *frame,
usb_rem_task(sc->sc_udev, &sc->sc_task_write);
usb_add_task(sc->sc_udev, &sc->sc_task_write);
#endif
+ /*
+ * Copy video frame to upper layer buffer and call
+ * upper layer interrupt.
+ */
+ bzero(sc->sc_uplayer_fbuffer, 32000);
+ *sc->sc_uplayer_fsize = fb->offset;
+ bcopy(fb->buf, sc->sc_uplayer_fbuffer, fb->offset);
+ sc->sc_uplayer_intr(sc->sc_uplayer_arg);
+
fb->fragment = 0;
fb->fid = 0;
// fb->offset = 0;
diff --git a/sys/dev/usb/uvideo.h b/sys/dev/usb/uvideo.h
index 8bc8fc006e8..6950f5d76db 100644
--- a/sys/dev/usb/uvideo.h
+++ b/sys/dev/usb/uvideo.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvideo.h,v 1.7 2008/04/20 09:14:05 mglocker Exp $ */
+/* $OpenBSD: uvideo.h,v 1.8 2008/05/24 19:37:34 mglocker Exp $ */
/*
* Copyright (c) 2007 Robert Nagy <robert@openbsd.org>
@@ -393,4 +393,9 @@ struct uvideo_softc {
#define UVIDEO_MAX_VS_NUM 8
struct uvideo_vs_iface *sc_vs_curr;
struct uvideo_vs_iface sc_vs_coll[UVIDEO_MAX_VS_NUM];
+
+ void *sc_uplayer_arg;
+ int *sc_uplayer_fsize;
+ uint8_t *sc_uplayer_fbuffer;
+ void (*sc_uplayer_intr)(void *);
};
diff --git a/sys/dev/video.c b/sys/dev/video.c
index 75a19eaa5f8..a525d1e733f 100644
--- a/sys/dev/video.c
+++ b/sys/dev/video.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: video.c,v 1.1 2008/04/09 19:49:55 robert Exp $ */
+/* $OpenBSD: video.c,v 1.2 2008/05/24 19:37:34 mglocker Exp $ */
/*
* Copyright (c) 2008 Robert Nagy <robert@openbsd.org>
*
@@ -23,6 +23,8 @@
#include <sys/fcntl.h>
#include <sys/device.h>
#include <sys/vnode.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
#include <sys/conf.h>
#include <sys/videoio.h>
@@ -37,6 +39,8 @@ int videodetach(struct device *, int);
int videoactivate(struct device *, enum devact);
int videoprint(void *, const char *);
+void video_intr(void *);
+
struct cfattach video_ca = {
sizeof(struct video_softc), videoprobe, videoattach,
videodetach, videoactivate
@@ -76,8 +80,15 @@ videoopen(dev_t dev, int flags, int fmt, struct proc *p)
sc->hw_if == NULL)
return (ENXIO);
+ sc->sc_fsize = 0;
+ /* XXX find proper size */
+ sc->sc_fbuffer = malloc(32000, M_DEVBUF, M_NOWAIT);
+ if (sc->sc_fbuffer == NULL)
+ return (ENOMEM);
+
if (sc->hw_if->open != NULL)
- return (sc->hw_if->open(sc->hw_hdl, flags));
+ return (sc->hw_if->open(sc->hw_hdl, flags, &sc->sc_fsize,
+ sc->sc_fbuffer, video_intr, sc));
else
return (0);
}
@@ -89,6 +100,9 @@ videoclose(dev_t dev, int flags, int fmt, struct proc *p)
sc = video_cd.cd_devs[VIDEOUNIT(dev)];
+ if (sc->sc_fbuffer != NULL)
+ free(sc->sc_fbuffer, M_DEVBUF);
+
if (sc->hw_if->close != NULL)
return (sc->hw_if->close(sc->hw_hdl));
else
@@ -96,6 +110,41 @@ videoclose(dev_t dev, int flags, int fmt, struct proc *p)
}
int
+videoread(dev_t dev, struct uio *uio, int ioflag)
+{
+ struct video_softc *sc;
+ int unit, error, size;
+
+ unit = VIDEOUNIT(dev);
+ if (unit >= video_cd.cd_ndevs ||
+ (sc = video_cd.cd_devs[unit]) == NULL)
+ return (ENXIO);
+
+ if (sc->sc_dying)
+ return (EIO);
+
+ DPRINTF(("resid=%d\n", uio->uio_resid));
+
+ /* block userland read until a frame is ready */
+ error = tsleep(sc, PWAIT | PCATCH, "vid_rd", 0);
+ if (error)
+ return (error);
+
+ /* move the frame to userland */
+ if (sc->sc_fsize < uio->uio_resid)
+ size = sc->sc_fsize;
+ else
+ size = uio->uio_resid;
+ error = uiomove(sc->sc_fbuffer, size, uio);
+ if (error)
+ return (error);
+
+ DPRINTF(("uiomove successfully done (%d bytes)\n", size));
+
+ return (0);
+}
+
+int
videoioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
{
struct video_softc *sc;
@@ -142,6 +191,25 @@ videoioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
return (error);
}
+paddr_t
+videommap(dev_t dev, off_t off, int prot)
+{
+ struct video_softc *sc;
+ int unit;
+
+ unit = VIDEOUNIT(dev);
+ if (unit >= video_cd.cd_ndevs ||
+ (sc = video_cd.cd_devs[unit]) == NULL)
+ return (ENXIO);
+
+ if (sc->sc_dying)
+ return (EIO);
+
+ /* TODO */
+
+ return (0);
+}
+
/*
* Called from hardware driver. This is where the MI video driver gets
* probed/attached to the hardware driver
@@ -156,6 +224,15 @@ video_attach_mi(struct video_hw_if *rhwp, void *hdlp, struct device *dev)
return (config_found(dev, &arg, videoprint));
}
+void
+video_intr(void *addr)
+{
+ struct video_softc *sc = (struct video_softc *)addr;
+
+ printf("video_intr sc=%p\n", sc);
+ wakeup(sc);
+}
+
int
videoprint(void *aux, const char *pnp)
{
diff --git a/sys/dev/video_if.h b/sys/dev/video_if.h
index 66360fe8614..7ee06b05645 100644
--- a/sys/dev/video_if.h
+++ b/sys/dev/video_if.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: video_if.h,v 1.1 2008/04/09 19:49:55 robert Exp $ */
+/* $OpenBSD: video_if.h,v 1.2 2008/05/24 19:37:34 mglocker Exp $ */
/*
* Copyright (c) 2008 Robert Nagy <robert@openbsd.org>
*
@@ -26,7 +26,8 @@
struct video_hw_if {
/* open hardware */
- int (*open)(void *, int);
+ int (*open)(void *, int, int *, uint8_t *, void (*)(void *),
+ void *);
/* close hardware */
int (*close)(void *);
diff --git a/sys/dev/videovar.h b/sys/dev/videovar.h
index 3b6319cfd28..53999bfe958 100644
--- a/sys/dev/videovar.h
+++ b/sys/dev/videovar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: videovar.h,v 1.1 2008/04/09 19:49:55 robert Exp $ */
+/* $OpenBSD: videovar.h,v 1.2 2008/05/24 19:37:34 mglocker Exp $ */
/*
* Copyright (c) 2008 Robert Nagy <robert@openbsd.org>
*
@@ -24,6 +24,9 @@ struct video_softc {
struct device *sc_dev; /* hardware device struct */
struct video_hw_if *hw_if; /* hardware interface */
char sc_dying; /* device detached */
+
+ int sc_fsize;
+ uint8_t *sc_fbuffer;
};
#endif /* _SYS_DEV_VIDEOVAR_H */