diff options
author | Marcus Glocker <mglocker@cvs.openbsd.org> | 2008-05-24 19:37:35 +0000 |
---|---|---|
committer | Marcus Glocker <mglocker@cvs.openbsd.org> | 2008-05-24 19:37:35 +0000 |
commit | ec8b8e37b2177d2b6911ecc80da5c5211d200380 (patch) | |
tree | e75a0bea9b7e89835738efd8affa4cead1803068 /sys/dev | |
parent | 49a507fbe9895f9d7339d9e4f70a773072da0d09 (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.c | 23 | ||||
-rw-r--r-- | sys/dev/usb/uvideo.h | 7 | ||||
-rw-r--r-- | sys/dev/video.c | 81 | ||||
-rw-r--r-- | sys/dev/video_if.h | 5 | ||||
-rw-r--r-- | sys/dev/videovar.h | 5 |
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 */ |