diff options
-rw-r--r-- | sys/conf/files | 7 | ||||
-rw-r--r-- | sys/dev/usb/files.usb | 7 | ||||
-rw-r--r-- | sys/dev/usb/uvideo.c | 1118 | ||||
-rw-r--r-- | sys/dev/usb/uvideo.h | 382 | ||||
-rw-r--r-- | sys/dev/video.c | 199 | ||||
-rw-r--r-- | sys/dev/video_if.h | 49 | ||||
-rw-r--r-- | sys/dev/videovar.h | 29 | ||||
-rw-r--r-- | sys/sys/conf.h | 10 | ||||
-rw-r--r-- | sys/sys/videoio.h | 1516 |
9 files changed, 3314 insertions, 3 deletions
diff --git a/sys/conf/files b/sys/conf/files index f40bef8b826..9c45d640adf 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -1,4 +1,4 @@ -# $OpenBSD: files,v 1.426 2008/03/16 19:42:57 otto Exp $ +# $OpenBSD: files,v 1.427 2008/04/09 19:49:55 robert Exp $ # $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 @@ -20,6 +20,7 @@ define radiobus {} define i2cbus {} define gpiobus {} define onewirebus {} +define video {} # filesystem firmware loading attribute define firmload @@ -34,6 +35,9 @@ define lm700x define tc921x define pt2254a +device video +attach video at video + # audio and midi devices, attaches to audio hardware driver device audio attach audio at audio @@ -619,6 +623,7 @@ file dev/raidframe/rf_stripelocks.c raid needs-flag file dev/raidframe/rf_strutils.c raid needs-flag file dev/raidframe/rf_threadstuff.c raid needs-flag file dev/raidframe/rf_utils.c raid needs-flag +file dev/video.c video needs-flag file isofs/cd9660/cd9660_bmap.c cd9660 file isofs/cd9660/cd9660_lookup.c cd9660 file isofs/cd9660/cd9660_node.c cd9660 diff --git a/sys/dev/usb/files.usb b/sys/dev/usb/files.usb index 3345d0adb27..098a116d5dd 100644 --- a/sys/dev/usb/files.usb +++ b/sys/dev/usb/files.usb @@ -1,4 +1,4 @@ -# $OpenBSD: files.usb,v 1.75 2007/12/16 18:10:46 deraadt Exp $ +# $OpenBSD: files.usb,v 1.76 2008/04/09 19:49:55 robert Exp $ # $NetBSD: files.usb,v 1.16 2000/02/14 20:29:54 augustss Exp $ # # Config file and device description for machine-independent USB code. @@ -34,6 +34,11 @@ device uaudio: audio, auconv, mulaw attach uaudio at uhub file dev/usb/uaudio.c uaudio +# Video devices +device uvideo: video +attach uvideo at uhub +file dev/usb/uvideo.c uvideo + # MIDI devices device umidi: midibus attach umidi at uhub diff --git a/sys/dev/usb/uvideo.c b/sys/dev/usb/uvideo.c new file mode 100644 index 00000000000..3f2f537f911 --- /dev/null +++ b/sys/dev/usb/uvideo.c @@ -0,0 +1,1118 @@ +/* + * Copyright (c) 2008 Robert Nagy <robert@openbsd.org> + * Copyright (c) 2008 Marcus Glocker <mglocker@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/malloc.h> +#include <sys/device.h> +#include <sys/ioctl.h> +#include <sys/tty.h> +#include <sys/file.h> +#include <sys/reboot.h> +#include <sys/selinfo.h> +#include <sys/proc.h> +#include <sys/namei.h> +#include <sys/vnode.h> +#include <sys/lock.h> +#include <sys/stat.h> +#include <sys/device.h> +#include <sys/poll.h> + +#include <dev/usb/usb.h> +#include <dev/usb/usbdi.h> +#include <dev/usb/usbdi_util.h> +#include <dev/usb/usbdevs.h> +#include <dev/usb/uvideo.h> + +#include <dev/video_if.h> + +#define UVIDEO_DEBUG + +#ifdef UVIDEO_DEBUG +int uvideo_debug = 1; +#define DPRINTF(l, x...) do { if ((l) <= uvideo_debug) printf(x); } while (0) +#else +#define DPRINTF(l, x...) +#endif + +int uvideo_enable(void *); +void uvideo_disable(void *); + +int uvideo_open(void *, int); +int uvideo_close(void *); + +int uvideo_find_vs_if(struct uvideo_softc *, + struct usb_attach_arg *, usb_config_descriptor_t *); +usbd_status uvideo_vs_alloc(struct uvideo_softc *); +usbd_status uvideo_vs_open(struct uvideo_softc *); +void uvideo_vs_start(struct uvideo_softc *); +void uvideo_vs_cb(usbd_xfer_handle, usbd_private_handle, + usbd_status); +int uvideo_vs_set_probe(struct uvideo_softc *, uint8_t *); +int uvideo_vs_get_probe(struct uvideo_softc *, uint8_t *); +int uvideo_vs_set_probe_commit(struct uvideo_softc *, uint8_t *); + +int uvideo_vs_decode_stream_header(struct uvideo_softc *, + uint8_t *, int); + +void uvideo_dump_desc_all(struct uvideo_softc *); +void uvideo_dump_desc_vcheader(struct uvideo_softc *, + const usb_descriptor_t *); +void uvideo_dump_desc_input(struct uvideo_softc *, + const usb_descriptor_t *); +void uvideo_dump_desc_output(struct uvideo_softc *, + const usb_descriptor_t *); +void uvideo_dump_desc_endpoint(struct uvideo_softc *, + const usb_descriptor_t *); +void uvideo_dump_desc_interface(struct uvideo_softc *, + const usb_descriptor_t *); +void uvideo_dump_desc_config(struct uvideo_softc *, + const usb_descriptor_t *); +void uvideo_dump_desc_cs_endpoint(struct uvideo_softc *, + const usb_descriptor_t *); +void uvideo_dump_desc_colorformat(struct uvideo_softc *, + const usb_descriptor_t *); +void uvideo_dump_desc_frame_mjpeg(struct uvideo_softc *, + const usb_descriptor_t *); +void uvideo_dump_desc_format_mjpeg(struct uvideo_softc *, + const usb_descriptor_t *); + +int uvideo_debug_file_open(struct uvideo_softc *); +void uvideo_debug_file_write_sample(void *); + +void uvideo_hexdump(void *, int); + +int uvideo_match(struct device *, void *, void *); +void uvideo_attach(struct device *, struct device *, void *); +int uvideo_detach(struct device *, int); +int uvideo_activate(struct device *, enum devact); + +int uvideo_querycap(void *, struct v4l2_capability *); +int uvideo_s_fmt(void *, struct v4l2_format *); +int uvideo_g_fmt(void *, struct v4l2_format *); +int uvideo_reqbufs(void *, struct v4l2_requestbuffers *); + +#define DEVNAME(_s) ((_s)->sc_dev.dv_xname) + +const struct cfattach uvideo_ca = { + sizeof(struct uvideo_softc), + uvideo_match, + uvideo_attach, + uvideo_detach, + uvideo_activate, +}; + +struct cfdriver uvideo_cd = { + NULL, + "uvideo", + DV_DULL +}; + +usbd_status +uvideo_usb_request(struct uvideo_softc * sc, u_int8_t type, u_int8_t request, + u_int16_t value, u_int16_t index, u_int16_t length, u_int8_t * data); + +struct video_hw_if uvideo_hw_if = { + uvideo_open, /* open */ + uvideo_close, /* close */ + uvideo_querycap, /* VIDIOC_QUERYCAP */ + uvideo_s_fmt, /* VIDIOC_S_FMT */ + uvideo_g_fmt, /* VIDIOC_G_FMT */ + uvideo_reqbufs, /* VIDIOC_REQBUFS */ + NULL, /* VIDIOC_QBUF */ + NULL /* VIDIOC_DQBUF */ +}; + +int +uvideo_match(struct device * parent, void *match, void *aux) +{ + struct usb_attach_arg *uaa = aux; + usb_interface_descriptor_t *id; + + if (uaa->iface == NULL) + return (UMATCH_NONE); + + id = usbd_get_interface_descriptor(uaa->iface); + if (id == NULL) + return (UMATCH_NONE); + + if (id->bInterfaceClass == UICLASS_VIDEO && + id->bInterfaceSubClass == UISUBCLASS_VIDEOCONTROL) + return (UMATCH_VENDOR_PRODUCT_CONF_IFACE); + + return (UMATCH_NONE); +} + +void +uvideo_attach(struct device * parent, struct device * self, void *aux) +{ + struct uvideo_softc *sc = (struct uvideo_softc *) self; + struct usb_attach_arg *uaa = aux; + usb_config_descriptor_t *cdesc; + usbd_status err; + uint8_t probe_data[34]; + struct uvideo_sample_buffer *fb = &sc->sc_sample_buffer; + + sc->sc_udev = uaa->device; + + /* get the config descriptor */ + cdesc = usbd_get_config_descriptor(sc->sc_udev); + if (cdesc == NULL) { + printf("%s: failed to get configuration descriptor\n", + DEVNAME(sc)); + return; + } + + uvideo_dump_desc_all(sc); + + if (uvideo_vs_set_probe(sc, probe_data)) + return; + if (uvideo_vs_get_probe(sc, probe_data)) + return; + if (uvideo_vs_set_probe_commit(sc, probe_data)) + return; + + uvideo_find_vs_if(sc, uaa, cdesc); + + err = uvideo_vs_alloc(sc); + if (err != USBD_NORMAL_COMPLETION) + return; + + err = uvideo_vs_open(sc); + if (err != USBD_NORMAL_COMPLETION) + return; + + fb->buf = malloc(32000, M_TEMP, M_NOWAIT); + + uvideo_debug_file_open(sc); + usb_init_task(&sc->sc_task_write, uvideo_debug_file_write_sample, sc); + + uvideo_vs_start(sc); + + usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev, &sc->sc_dev); + + DPRINTF(1, "uvideo_attach: doing video_attach_mi\n"); + sc->sc_videodev = video_attach_mi(&uvideo_hw_if, sc, &sc->sc_dev); +} + +int +uvideo_detach(struct device * self, int flags) +{ + struct uvideo_softc *sc = (struct uvideo_softc *) self; + int rv = 0; + + sc->sc_dying = 1; + + if (sc->sc_videodev != NULL) + rv = config_detach(sc->sc_videodev, flags); + + usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev, &sc->sc_dev); + + return (rv); +} + +int +uvideo_activate(struct device * self, enum devact act) +{ + struct uvideo_softc *sc = (struct uvideo_softc *) self; + int rv = 0; + + DPRINTF(1, "uvideo_activate: sc=%p\n", sc); + + switch (act) { + case DVACT_ACTIVATE: + break; + case DVACT_DEACTIVATE: + if (sc->sc_videodev != NULL) + config_deactivate(sc->sc_videodev); + sc->sc_dying = 1; + break; + } + return (rv); +} + +int +uvideo_enable(void *v) +{ + struct uvideo_softc *sc = v; + + DPRINTF(1, "%s: uvideo_enable sc=%p\n", DEVNAME(sc), sc); + + if (sc->sc_dying) + return (EIO); + + if (sc->sc_enabled) + return (EBUSY); + + + sc->sc_enabled = 1; + + return (0); +} + +void +uvideo_disable(void *v) +{ + struct uvideo_softc *sc = v; + + DPRINTF(1, "%s: uvideo_disable sc=%p\n", DEVNAME(sc), sc); + + if (!sc->sc_enabled) { + printf("uvideo_disable: already disabled!\n"); + return; + } + sc->sc_enabled = 0; +} + +int +uvideo_open(void *addr, int flags) +{ + struct uvideo_softc *sc = addr; + + DPRINTF(1, "uvideo_open: sc=%p\n", sc); + + if (sc->sc_dying) + return (EIO); + + return (0); +} + +int +uvideo_close(void *addr) +{ + struct uvideo_softc *sc = addr; + + DPRINTF(1, "uvideo_close: sc=%p\n", sc); + + return (0); +} + +int +uvideo_find_vs_if(struct uvideo_softc *sc, struct usb_attach_arg *uaa, + usb_config_descriptor_t *cdesc) +{ + struct uvideo_stream_if *si = &sc->sc_curr_strm; + usb_interface_descriptor_t *id; + usb_endpoint_descriptor_t *ed; + int i, numalts; + + printf("%s: nifaces=%d\n", DEVNAME(sc), uaa->nifaces); + + for (i = 0; i < uaa->nifaces; i++) { + if (uaa->ifaces[i] == NULL) + continue; + + id = usbd_get_interface_descriptor(uaa->ifaces[i]); + if (id == NULL) + continue; + printf("%s: bInterfaceNumber=%d, bAlternateSetting=%d, ", + DEVNAME(sc), + id->bInterfaceNumber, id->bAlternateSetting); + + numalts = usbd_get_no_alts(cdesc, id->bInterfaceNumber); + printf("numalts=%d\n", numalts); + + if (id->bInterfaceNumber == 1) { /* XXX baInterfaceNr */ + si->in_ifaceh = uaa->ifaces[i]; + si->numalts = numalts; + } + + ed = usbd_interface2endpoint_descriptor(uaa->ifaces[i], i); + if (ed == NULL) { + printf("%s: no endpoint descriptor for iface %d\n", + DEVNAME(sc), i); + continue; + } + printf("%s: bEndpointAddress=0x%02x\n", + DEVNAME(sc), ed->bEndpointAddress); + } + + for (i = 0; i < si->numalts; i++) { + if (usbd_set_interface(si->in_ifaceh, i)) { + printf("%s: could not set alt iface %d\n", + DEVNAME(sc), i); + return (1); + } + + ed = usbd_interface2endpoint_descriptor(si->in_ifaceh, 0); + if (ed == NULL) { + printf("%s: no endpoint descriptor for VS iface\n", + DEVNAME(sc)); + continue; + } + printf("%s: VS iface alt iface bEndpointAddress=0x%02x, " + "wMaxPacketSize=%d\n", + DEVNAME(sc), + ed->bEndpointAddress, + UGETW(ed->wMaxPacketSize)); + + si->endpoint = ed->bEndpointAddress; + } + + return (0); +} + +usbd_status +uvideo_vs_alloc(struct uvideo_softc *sc) +{ + struct uvideo_stream_if *si = &sc->sc_curr_strm; + + DPRINTF(1, "%s: %s\n", DEVNAME(sc), __func__); + + si->sc = sc; + + si->xfer = usbd_alloc_xfer(sc->sc_udev); + if (si->xfer == NULL) { + printf("%s: could not allocate VideoStream xfer!\n", + DEVNAME(sc)); + return (USBD_NOMEM); + } + + si->buf = usbd_alloc_buffer(si->xfer, 384 * UVIDEO_NFRAMES); + if (si->buf == NULL) { + printf("%s: could not allocate VideoStream buffer!\n", + DEVNAME(sc)); + return (USBD_NOMEM); + } + + return (USBD_NORMAL_COMPLETION); +} + +usbd_status +uvideo_vs_open(struct uvideo_softc *sc) +{ + struct uvideo_stream_if *si = &sc->sc_curr_strm; + usb_endpoint_descriptor_t *ed; + usbd_status err; + + DPRINTF(1, "%s: %s\n", DEVNAME(sc), __func__); + + err = usbd_set_interface(si->in_ifaceh, 2); + if (err != 0) { + printf("%s: could not set alternate interface!\n", + DEVNAME(sc)); + return (err); + } + + ed = usbd_interface2endpoint_descriptor(si->in_ifaceh, 0); + if (ed == NULL) { + printf("%s: no endpoint descriptor for VS iface\n", + DEVNAME(sc)); + return (USBD_NOMEM); + } + printf("%s: open pipe for bEndpointAddress=0x%02x (0x%02x), " + "wMaxPacketSize=%d\n", + DEVNAME(sc), + ed->bEndpointAddress, + si->endpoint, + UGETW(ed->wMaxPacketSize)); + + err = usbd_open_pipe(si->in_ifaceh, si->endpoint, USBD_EXCLUSIVE_USE, + &si->in_pipeh); + if (err) { + printf("%s: could not open VS pipe: %s\n", + DEVNAME(sc), usbd_errstr(err)); + return (err); + } + + return (USBD_NORMAL_COMPLETION); +} + +void +uvideo_vs_start(struct uvideo_softc *sc) +{ + struct uvideo_stream_if *si = &sc->sc_curr_strm; + int i; + + DPRINTF(2, "%s: %s\n", DEVNAME(sc), __func__); + + for (i = 0; i < UVIDEO_NFRAMES; i++) + si->size[i] = 384; + + bzero(si->buf, 384 * UVIDEO_NFRAMES); + + usbd_setup_isoc_xfer( + si->xfer, + si->in_pipeh, + si, + si->size, + UVIDEO_NFRAMES, + USBD_NO_COPY | USBD_SHORT_XFER_OK, + uvideo_vs_cb); + + (void)usbd_transfer(si->xfer); +} + +void +uvideo_vs_cb(usbd_xfer_handle xfer, usbd_private_handle priv, + usbd_status status) +{ + struct uvideo_stream_if *sc_curr_strm = priv; + struct uvideo_softc *sc = sc_curr_strm->sc; + int len, i, frame_size; + uint8_t *frame; + + DPRINTF(2, "%s: %s\n", DEVNAME(sc), __func__); + + if (status != USBD_NORMAL_COMPLETION) { + printf("%s: %s: %s\n", DEVNAME(sc), __func__, + usbd_errstr(status)); + return; + } + usbd_get_xfer_status(xfer, NULL, NULL, &len, NULL); + + DPRINTF(2, "%s: *** buffer len = %d\n", DEVNAME(sc), len); + if (len == 0) + goto skip; + + for (i = 0; i < UVIDEO_NFRAMES; i++) { + frame = sc_curr_strm->buf + (i * 384); + frame_size = sc_curr_strm->size[i]; + + if (frame_size == 0) + /* frame is empty */ + continue; + + uvideo_vs_decode_stream_header(sc, frame, frame_size); + } + +skip: /* setup new transfer */ + uvideo_vs_start(sc); +} + +int +uvideo_vs_set_probe(struct uvideo_softc *sc, uint8_t *probe_data) +{ + usb_device_request_t req; + usbd_status err; + uint16_t tmp; + struct usb_video_probe_commit *pc; + + req.bmRequestType = UVIDEO_SET_IF; + req.bRequest = SET_CUR; + tmp = VS_PROBE_CONTROL; + tmp = tmp << 8; + USETW(req.wValue, tmp); + USETW(req.wIndex, 1); + USETW(req.wLength, 26); + + bzero(probe_data, sizeof(probe_data)); + pc = (struct usb_video_probe_commit *)probe_data; + USETW(pc->bmHint, 8); + //USETW(pc->bmHint, 1); + pc->bFormatIndex = 1; + pc->bFrameIndex = 1; + + err = usbd_do_request(sc->sc_udev, &req, probe_data); + if (err) { + printf("%s: could not send SET request: %s\n", + DEVNAME(sc), usbd_errstr(err)); + return (-1); + } + + DPRINTF(1, "%s: SET probe control request successfully\n", + DEVNAME(sc)); + + return (0); +} + +int +uvideo_vs_get_probe(struct uvideo_softc *sc, uint8_t *probe_data) +{ + usb_device_request_t req; + usbd_status err; + uint16_t tmp; + struct usb_video_probe_commit *pc; + + req.bmRequestType = UVIDEO_GET_IF; + req.bRequest = GET_CUR; + tmp = VS_PROBE_CONTROL; + tmp = tmp << 8; + USETW(req.wValue, tmp); + USETW(req.wIndex, 1); + USETW(req.wLength, 26); + + bzero(probe_data, sizeof(probe_data)); + pc = (struct usb_video_probe_commit *)probe_data; + + err = usbd_do_request(sc->sc_udev, &req, probe_data); + if (err) { + printf("%s: could not send GET request: %s\n", + DEVNAME(sc), usbd_errstr(err)); + return (-1); + } + + DPRINTF(1, "%s: GET probe control request successfully\n", + DEVNAME(sc)); + + DPRINTF(1, "bmHint=0x%02x\n", UGETW(pc->bmHint)); + DPRINTF(1, "bFormatIndex=0x%02x\n", pc->bFormatIndex); + DPRINTF(1, "bFrameIndex=0x%02x\n", pc->bFrameIndex); + DPRINTF(1, "dwFrameInterval=%d (ns)\n", UGETDW(pc->dwFrameInterval)); + DPRINTF(1, "wKeyFrameRate=%d\n", UGETW(pc->wKeyFrameRate)); + DPRINTF(1, "wPFrameRate=0x%d\n", UGETW(pc->wPFrameRate)); + DPRINTF(1, "wCompQuality=0x%d\n", UGETW(pc->wCompQuality)); + DPRINTF(1, "wCompWindowSize=0x%04x\n", UGETW(pc->wCompWindowSize)); + DPRINTF(1, "wDelay=%d (ms)\n", UGETW(pc->wDelay)); + DPRINTF(1, "dwMaxVideoFrameSize=%d (bytes)\n", + UGETDW(pc->dwMaxVideoFrameSize)); + DPRINTF(1, "dwMaxPayloadTransferSize=%d (bytes)\n", + UGETDW(pc->dwMaxPayloadTransferSize)); + + return (0); +} + +int +uvideo_vs_set_probe_commit(struct uvideo_softc *sc, uint8_t *probe_data) +{ + usb_device_request_t req; + usbd_status err; + uint16_t tmp; + + req.bmRequestType = UVIDEO_SET_IF; + req.bRequest = SET_CUR; + tmp = VS_COMMIT_CONTROL; + tmp = tmp << 8; + USETW(req.wValue, tmp); + USETW(req.wIndex, 1); + USETW(req.wLength, 26); + + err = usbd_do_request(sc->sc_udev, &req, probe_data); + if (err) { + printf("%s: could not send SET commit request: %s\n", + DEVNAME(sc), usbd_errstr(err)); + return (-1); + } + + DPRINTF(1, "%s: SET probe commit request successfully\n", + DEVNAME(sc)); + + return (0); +} + +int +uvideo_vs_decode_stream_header(struct uvideo_softc *sc, uint8_t *frame, + int frame_size) +{ + struct uvideo_sample_buffer *fb = &sc->sc_sample_buffer; + int header_len, header_flags, fragment_len; + + if (frame_size < 2) + /* frame too small to contain a valid stream header */ + return (-1); + + header_len = frame[0]; + header_flags = frame[1]; + + DPRINTF(2, "%s: header_len = %d\n", DEVNAME(sc), header_len); + + if (header_len != 12) + /* frame header is 12 bytes long */ + return (-1); + if (header_len == frame_size && !(header_flags & UVIDEO_STREAM_EOF)) { + /* stream header without payload and no EOF */ + return (-1); + } + + + DPRINTF(2, "%s: frame_size = %d\n", DEVNAME(sc), frame_size); + + if (header_flags & UVIDEO_STREAM_FID) { + DPRINTF(2, "%s: %s: FID ON (0x%02x)\n", + DEVNAME(sc), __func__, + header_flags & UVIDEO_STREAM_FID); + } else { + DPRINTF(2, "%s: %s: FID OFF (0x%02x)\n", + DEVNAME(sc), __func__, + header_flags & UVIDEO_STREAM_FID); + } + + if (fb->fragment == 0) { + /* first fragment for a sample */ + fb->fragment = 1; + fb->fid = header_flags & UVIDEO_STREAM_FID; + fb->offset = 0; + } else { + /* continues fragment for a sample, check consistency */ + if (fb->fid != (header_flags & UVIDEO_STREAM_FID)) { + DPRINTF(1, "%s: %s: wrong FID, ignore last sample!\n", + DEVNAME(sc), __func__); + fb->fragment = 1; + fb->fid = header_flags & UVIDEO_STREAM_FID; + fb->offset = 0; + } + } + + /* save sample fragment */ + fragment_len = frame_size - header_len; + bcopy(frame + header_len, fb->buf + fb->offset, fragment_len); + fb->offset += fragment_len; + + if (header_flags & UVIDEO_STREAM_EOF) { + /* got a full sample */ + DPRINTF(2, "%s: %s: EOF (sample size = %d bytes)\n", + DEVNAME(sc), __func__, fb->offset); +#ifdef UVIDEO_DEBUG + /* do the file write in process context */ + usb_rem_task(sc->sc_udev, &sc->sc_task_write); + usb_add_task(sc->sc_udev, &sc->sc_task_write); +#endif + fb->fragment = 0; + fb->fid = 0; +// fb->offset = 0; + } + + return (0); +} + +int +uvideo_querycap(void *v, struct v4l2_capability * caps) +{ + struct uvideo_softc *sc = v; + + bzero(caps, sizeof(caps)); + strlcpy(caps->driver, DEVNAME(sc), + sizeof(caps->driver)); + strncpy(caps->card, "Generic USB video class device", + sizeof(caps->card)); + strncpy(caps->bus_info, "usb", sizeof(caps->bus_info)); + + caps->version = 1; + caps->capabilities = V4L2_CAP_VIDEO_CAPTURE + | V4L2_CAP_STREAMING + | V4L2_CAP_READWRITE; + + return (0); +} + +int +uvideo_s_fmt(void *v, struct v4l2_format * fmt) +{ + if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return (EINVAL); + + return (0); +} + +int +uvideo_g_fmt(void *v, struct v4l2_format * fmt) +{ + if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) + return (EINVAL); + + return (0); +} + +int +uvideo_reqbufs(void *v, struct v4l2_requestbuffers * rb) +{ + return (0); +} + +void +uvideo_dump_desc_all(struct uvideo_softc *sc) +{ + usbd_desc_iter_t iter; + const usb_descriptor_t *desc; + + usb_desc_iter_init(sc->sc_udev, &iter); + desc = usb_desc_iter_next(&iter); + while (desc) { + printf("bLength=%d\n", desc->bLength); + printf("bDescriptorType=0x%02x", desc->bDescriptorType); + + switch (desc->bDescriptorType) { + case UDESC_CS_INTERFACE: + printf(" (CS_INTERFACE)\n"); + + switch (desc->bDescriptorSubtype) { + case UDESCSUB_VC_HEADER: + printf("bDescriptorSubtype=0x%02x", + desc->bDescriptorSubtype); + printf(" (UDESCSUB_VC_HEADER)\n"); + if (desc->bLength == 13) { + printf("|\n"); + uvideo_dump_desc_vcheader(sc, desc); + } + break; + case UDESCSUB_VC_INPUT_TERMINAL: + printf("bDescriptorSubtype=0x%02x", + desc->bDescriptorSubtype); + printf(" (UDESCSUB_VC_INPUT_TERMINAL)\n"); + printf("|\n"); + uvideo_dump_desc_input(sc, desc); + break; + case UDESCSUB_VC_OUTPUT_TERMINAL: + printf("bDescriptorSubtype=0x%02x", + desc->bDescriptorSubtype); + printf(" (UDESCSUB_VC_OUTPUT)\n"); + printf("|\n"); + uvideo_dump_desc_output(sc, desc); + break; + case UDESCSUB_VC_SELECTOR_UNIT: + printf("bDescriptorSubtype=0x%02x", + desc->bDescriptorSubtype); + printf(" (UDESCSUB_VC_SELECTOR_UNIT)\n"); + /* TODO */ + break; + case UDESCSUB_VC_PROCESSING_UNIT: + printf("bDescriptorSubtype=0x%02x", + desc->bDescriptorSubtype); + printf(" (UDESCSUB_VC_PROCESSING_UNIT)\n"); + /* TODO */ + break; + case UDESCSUB_VC_EXTENSION_UNIT: + printf("bDescriptorSubtype=0x%02x", + desc->bDescriptorSubtype); + if (desc->bLength == 11) { + printf(" (UDESCSUB_VS_FORMAT_MJPEG)\n"); + printf("|\n"); + uvideo_dump_desc_format_mjpeg(sc, desc); + } else { + printf(" (UDESCSUB_VC_EXTENSION_UNIT)\n"); + /* TODO */ + } + break; + case UDESCSUB_VS_FRAME_MJPEG: + printf("bDescriptorSubtype=0x%02x", + desc->bDescriptorSubtype); + printf(" (UDESCSUB_VS_FRAME_MJPEG)\n"); + if (desc->bLength > 26) { + printf("|\n"); + uvideo_dump_desc_frame_mjpeg(sc, desc); + } + break; + case UDESCSUB_VS_COLORFORMAT: + printf("bDescriptorSubtype=0x%02x", + desc->bDescriptorSubtype); + printf(" (UDESCSUB_VS_COLORFORMAT)\n"); + printf("|\n"); + uvideo_dump_desc_colorformat(sc, desc); + break; + } + + break; + case UDESC_CS_ENDPOINT: + printf(" (UDESC_CS_ENDPOINT)\n"); + + switch (desc->bDescriptorSubtype) { + case EP_INTERRUPT: + printf("bDescriptorSubtype=0x%02x", + desc->bDescriptorSubtype); + printf(" (EP_INTERRUPT)\n"); + printf("|\n"); + uvideo_dump_desc_cs_endpoint(sc, desc); + break; + case EP_GENERAL: + printf("bDescriptorSubtype=0x%02x", + desc->bDescriptorSubtype); + printf(" (EP_GENERAL)\n"); + printf("|\n"); + uvideo_dump_desc_cs_endpoint(sc, desc); + break; + } + + break; + case UDESC_CONFIG: + printf(" (UDESC_CONFIG)\n"); + printf("|\n"); + uvideo_dump_desc_config(sc, desc); + break; + case UDESC_ENDPOINT: + printf(" (UDESC_ENDPOINT)\n"); + printf("|\n"); + uvideo_dump_desc_endpoint(sc, desc); + break; + case UDESC_INTERFACE: + printf(" (UDESC_INTERFACE)\n"); + printf("|\n"); + uvideo_dump_desc_interface(sc, desc); + break; + default: + printf(" (unknown)\n"); + break; + } + + printf("\n"); + + desc = usb_desc_iter_next(&iter); + } + +} + +void +uvideo_dump_desc_vcheader(struct uvideo_softc *sc, + const usb_descriptor_t *desc) +{ + struct usb_video_header_desc *d; + + d = (struct usb_video_header_desc *)(uint8_t *)desc; + + printf("bLength=%d\n", d->bLength); + printf("bDescriptorType=0x%02x\n", d->bDescriptorType); + printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype); + printf("bcdUVC=0x%04x\n", UGETW(d->bcdUVC)); + printf("wTotalLength=%d\n", UGETW(d->wTotalLength)); + printf("dwClockFrequency=%d\n", UGETDW(d->dwClockFrequency)); + printf("bInCollection=0x%02x\n", d->bInCollection); + printf("baInterfaceNr=0x%02x\n", d->baInterfaceNr); +} + +void +uvideo_dump_desc_input(struct uvideo_softc *sc, + const usb_descriptor_t *desc) +{ + struct usb_video_input_terminal_desc *d; + + d = (struct usb_video_input_terminal_desc *)(uint8_t *)desc; + + printf("bLength=%d\n", d->bLength); + printf("bDescriptorType=0x%02x\n", d->bDescriptorType); + printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype); + printf("bTerminalID=0x%02x\n", d->bTerminalID); + printf("wTerminalType=0x%04x\n", UGETW(d->wTerminalType)); + printf("bAssocTerminal=0x%02x\n", d->bAssocTerminal); + printf("iTerminal=0x%02x\n", d->iTerminal); +} + +void +uvideo_dump_desc_output(struct uvideo_softc *sc, + const usb_descriptor_t *desc) +{ + struct usb_video_output_terminal_desc *d; + + d = (struct usb_video_output_terminal_desc *)(uint8_t *)desc; + + printf("bLength=%d\n", d->bLength); + printf("bDescriptorType=0x%02x\n", d->bDescriptorType); + printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype); + printf("bTerminalID=0x%02x\n", d->bTerminalID); + printf("bAssocTerminal=0x%02x\n", d->bAssocTerminal); + printf("bSourceID=0x%02x\n", d->bSourceID); + printf("iTerminal=0x%02x\n", d->iTerminal); + +} + +void +uvideo_dump_desc_endpoint(struct uvideo_softc *sc, + const usb_descriptor_t *desc) +{ + usb_endpoint_descriptor_t *d; + + d = (usb_endpoint_descriptor_t *)(uint8_t *)desc; + + printf("bLength=%d\n", d->bLength); + printf("bDescriptorType=0x%02x\n", d->bDescriptorType); + printf("bEndpointAddress=0x%02x", d->bEndpointAddress); + if (UE_GET_DIR(d->bEndpointAddress) == UE_DIR_IN) + printf(" (IN)\n"); + if (UE_GET_DIR(d->bEndpointAddress) == UE_DIR_OUT) + printf(" (OUT)\n"); + printf("bmAttributes=0x%02x", d->bmAttributes); + if (UE_GET_XFERTYPE(d->bmAttributes) == UE_ISOCHRONOUS) { + printf(" (UE_ISOCHRONOUS,"); + if (UE_GET_ISO_TYPE(d->bmAttributes) == UE_ISO_ASYNC) + printf(" UE_ISO_ASYNC)\n"); + if (UE_GET_ISO_TYPE(d->bmAttributes) == UE_ISO_ADAPT) + printf(" UE_ISO_ADAPT)\n"); + if (UE_GET_ISO_TYPE(d->bmAttributes) == UE_ISO_SYNC) + printf(" UE_ISO_SYNC)\n"); + } + if (UE_GET_XFERTYPE(d->bmAttributes) == UE_CONTROL) + printf(" (UE_CONTROL)\n"); + if (UE_GET_XFERTYPE(d->bmAttributes) == UE_BULK) + printf(" (UE_BULK)\n"); + if (UE_GET_XFERTYPE(d->bmAttributes) == UE_INTERRUPT) + printf(" (UE_INTERRUPT)\n"); + printf("wMaxPacketsize=%d\n", UGETW(d->wMaxPacketSize)); + printf("bInterval=0x%02x\n", d->bInterval); +} + +void +uvideo_dump_desc_interface(struct uvideo_softc *sc, + const usb_descriptor_t *desc) +{ + usb_interface_descriptor_t *d; + + d = (usb_interface_descriptor_t *)(uint8_t *)desc; + + printf("bLength=%d\n", d->bLength); + printf("bDescriptorType=0x%02x\n", d->bDescriptorType); + printf("bInterfaceNumber=0x%02x\n", d->bInterfaceNumber); + printf("bAlternateSetting=0x%02x\n", d->bAlternateSetting); + printf("bNumEndpoints=%d\n", d->bNumEndpoints); + printf("bInterfaceClass=0x%02x\n", d->bInterfaceClass); + printf("bInterfaceSubClass=0x%02x\n", d->bInterfaceSubClass); + printf("bInterfaceProtocol=0x%02x\n", d->bInterfaceProtocol); + printf("iInterface=0x%02x\n", d->iInterface); +} + +void +uvideo_dump_desc_config(struct uvideo_softc *sc, + const usb_descriptor_t *desc) +{ + usb_config_descriptor_t *d; + + d = (usb_config_descriptor_t *)(uint8_t *)desc; + + printf("bLength=%d\n", d->bLength); + printf("bDescriptorType=0x%02x\n", d->bDescriptorType); + printf("wTotalLength=0x%02x\n", d->wTotalLength); + printf("bNumInterface=0x%02x\n", d->bNumInterface); + printf("bConfigurationValue=0x%02x\n", d->bConfigurationValue); + printf("iConfiguration=0x%02x\n", d->iConfiguration); + printf("bmAttributes=0x%02x\n", d->bmAttributes); + printf("bMaxPower=0x%02x\n", d->bMaxPower); +} + +void +uvideo_dump_desc_cs_endpoint(struct uvideo_softc *sc, + const usb_descriptor_t *desc) +{ + struct usb_video_vc_endpoint_desc *d; + + d = (struct usb_video_vc_endpoint_desc *)(uint8_t *)desc; + + printf("bLength=%d\n", d->bLength); + printf("bDescriptorType=0x%02x\n", d->bDescriptorType); + printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype); + printf("wMaxTransferSize=%d\n", UGETW(d->wMaxTransferSize)); +} + +void +uvideo_dump_desc_colorformat(struct uvideo_softc *sc, + const usb_descriptor_t *desc) +{ + struct usb_video_color_matching_descr *d; + + d = (struct usb_video_color_matching_descr *)(uint8_t *)desc; + + printf("bLength=%d\n", d->bLength); + printf("bDescriptorType=0x%02x\n", d->bDescriptorType); + printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype); + printf("bColorPrimaries=0x%02x\n", d->bColorPrimaries); + printf("bTransferCharacteristics=0x%02x\n", + d->bTransferCharacteristics); + printf("bMatrixCoefficients=0x%02x\n", d->bMatrixCoefficients); +} + +void +uvideo_dump_desc_frame_mjpeg(struct uvideo_softc *sc, + const usb_descriptor_t *desc) +{ + struct usb_video_frame_descriptor *d; + + d = (struct usb_video_frame_descriptor *)(uint8_t *)desc; + + printf("bLength=%d\n", d->bLength); + printf("bDescriptorType=0x%02x\n", d->bDescriptorType); + printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype); + printf("bFrameIndex=0x%02x\n", d->bFrameIndex); + printf("bmCapabilities=0x%02x\n", d->bmCapabilities); + printf("wWidth=0x%d\n", UGETW(d->wWidth)); + printf("wHeight=0x%d\n", UGETW(d->wHeight)); + printf("dwMinBitRate=0x%08x\n", UGETDW(d->dwMaxBitRate)); + printf("dwMaxVideoFrameBufferSize=0x%08x\n", + UGETDW(d->dwMaxVideoFrameBufferSize)); + printf("dwDefaultFrameInterval=0x%d\n", + UGETDW(d->dwDefaultFrameInterval)); + printf("bFrameIntervalType=0x%02x\n", d->bFrameIntervalType); +} + +void +uvideo_dump_desc_format_mjpeg(struct uvideo_softc *sc, + const usb_descriptor_t *desc) +{ + struct usb_video_format_mjpeg_descriptor *d; + + d = (struct usb_video_format_mjpeg_descriptor *)(uint8_t *)desc; + + printf("bLength=%d\n", d->bLength); + printf("bDescriptorType=0x%02x\n", d->bDescriptorType); + printf("bDescriptorSubtype=0x%02x\n", d->bDescriptorSubtype); + printf("bFormatIndex=0x%02x\n", d->bFormatIndex); + printf("bNumFrameDescriptors=0x%02x\n", d->bNumFrameDescriptors); + printf("bmFlags=0x%02x\n", d->bmFlags); + printf("bDefaultFrameIndex=0x%02x\n", d->bDefaultFrameIndex); + printf("bAspectRatioX=0x%02x\n", d->bAspectRatioX); + printf("bAspectRatioY=0x%02x\n", d->bAspectRatioY); + printf("bmInterlaceFlags=0x%02x\n", d->bmInterlaceFlags); + printf("bCopyProtect=0x%02x\n", d->bCopyProtect); +} + +int +uvideo_debug_file_open(struct uvideo_softc *sc) +{ + struct proc *p = curproc; + struct nameidata nd; + char name[] = "/uvideo.mjpeg"; + int error; + + NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p); + error = vn_open(&nd, O_CREAT | FWRITE | O_NOFOLLOW, S_IRUSR | S_IWUSR); + if (error) { + return (-1); + } + + sc->sc_vp = nd.ni_vp; + VOP_UNLOCK(sc->sc_vp, 0, p); + if (nd.ni_vp->v_type != VREG) { + vn_close(nd.ni_vp, FWRITE, p->p_ucred, p); + return (-1); + } + + DPRINTF(1, "%s: %s: created debug file %s\n", + DEVNAME(sc), __func__, name); + + return (0); +} + +void +uvideo_debug_file_write_sample(void *arg) +{ + struct uvideo_softc *sc = arg; + struct uvideo_sample_buffer *sb = &sc->sc_sample_buffer; + struct proc *p = curproc; + int error; + + if (sc->sc_vp == NULL) { + printf("%s: %s: no file open!\n", DEVNAME(sc)); + return; + } + + error = vn_rdwr(UIO_WRITE, sc->sc_vp, sb->buf, sb->offset, (off_t)0, + UIO_SYSSPACE, IO_APPEND|IO_UNIT, p->p_ucred, NULL, p); + + if (error) + DPRINTF(1, "vn_rdwr error!\n"); +} + +void +uvideo_hexdump(void *buf, int len) +{ + int i; + + for (i = 0; i < len; i++) { + if (i % 16 == 0) + printf("%s%5i:", i ? "\n" : "", i); + if (i % 4 == 0) + printf(" "); + printf("%02x", (int)*((u_char *)buf + i)); + } + printf("\n"); +} diff --git a/sys/dev/usb/uvideo.h b/sys/dev/usb/uvideo.h new file mode 100644 index 00000000000..74420766623 --- /dev/null +++ b/sys/dev/usb/uvideo.h @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2007 Robert Nagy <robert@openbsd.org> + * Copyright (c) 2008 Marcus Glocker <mglocker@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/videoio.h> + +/* + * USB Video Class + */ +/* Table A-7: Video Class-Specific Endpoint Descriptor Subtypes */ +#define EP_UNDEFINED 0x00 +#define EP_GENERAL 0x01 +#define EP_ENDPOINT 0x02 +#define EP_INTERRUPT 0x03 + +/* Table A-5: Video Class-Specific VC Interface Descriptor Subtypes */ +#define UDESCSUB_VC_DESCRIPTOR_UNDEFINED 0x00 +#define UDESCSUB_VC_HEADER 0x01 +#define UDESCSUB_VC_INPUT_TERMINAL 0x02 +#define UDESCSUB_VC_OUTPUT_TERMINAL 0x03 +#define UDESCSUB_VC_SELECTOR_UNIT 0x04 +#define UDESCSUB_VC_PROCESSING_UNIT 0x05 +#define UDESCSUB_VC_EXTENSION_UNIT 0x06 + +/* Table A-6: Video Class-Specific VS Interface Descriptor Subtypes */ +#define UDESCSUB_VS_UNDEFINED 0x00 +#define UDESCSUB_VS_INPUT_HEADER 0x01 +#define UDESCSUB_VS_OUTPUT_HEADER 0x02 +#define UDESCSUB_VS_STILL_IMAGE_FRAME 0x03 +#define UDESCSUB_VS_FORMAT_UNCOMPRESSED 0x04 +#define UDESCSUB_VS_FRAME_UNCOMPRESSED 0x05 +#define UDESCSUB_VS_FORMAT_MJPEG 0x06 +#define UDESCSUB_VS_FRAME_MJPEG 0x07 +#define UDESCSUB_VS_FORMAT_MPEG2TS 0x0a +#define UDESCSUB_VS_FORMAT_DV 0x0c +#define UDESCSUB_VS_COLORFORMAT 0x0d +#define UDESCSUB_VS_FORMAT_FRAME_BASED 0x10 +#define UDESCSUB_VS_FRAME_FRAME_BASED 0x11 +#define UDESCSUB_VS_FORMAT_STREAM_BASED 0x12 + +/* Table A-8: Video Class-Specific Request Codes */ +#define RC_UNDEFINED 0x00 +#define SET_CUR 0x01 +#define GET_CUR 0x81 +#define GET_MIN 0x82 +#define GET_MAX 0x83 +#define GET_RES 0x84 +#define GET_LEN 0x85 +#define GET_INFO 0x86 +#define GET_DEF 0x87 + +/* Table A-9: Video Control Interface Control Selectors */ +#define VC_CONTROL_UNDEFINED 0x00 +#define VC_VIDEO_POWER_MODE_CONTROL 0x01 +#define VC_REQUEST_ERROR_CODE_CONTROL 0x02 + +/* Table A-11: Selector Unit Control Selectors */ +#define SU_CONTROL_UNDEFINED 0x00 +#define SU_INPUT_SELECT_CONTROL 0x01 + +/* Table A-12: Camera Terminal Control Selectors */ +#define CT_CONTROL_UNDEFINED 0x00 +#define CT_SCANNING_MODE_CONTROL 0x01 +#define CT_AE_MODE_CONTROL 0x02 +#define CT_AE_PRIORITY_CONTROL 0x03 +#define CT_EXPOSURE_TIME_ABSOLUTE_CONTROL 0x04 +#define CT_EXPOSURE_TIME_RELATIVE_CONTROL 0x05 +#define CT_FOCUS_ABSOLUTE_CONTROL 0x06 +#define CT_FOCUS_RELATIVE_CONTROL 0x07 +#define CT_FOCUS_AUTO_CONTROL 0x08 +#define CT_IRIS_ABSOLUTE_CONTROL 0x09 +#define CT_IRIS_RELATIVE_CONTROL 0x0a +#define CT_ZOOM_ABSOLUTE_CONTROL 0x0b +#define CT_ZOOM_RELATIVE_CONTROL 0x0c +#define CT_PANTILT_ABSOLUTE_CONTROL 0x0d +#define CT_PANTILT_RELATIVE_CONTROL 0x0e +#define CT_ROLL_ABSOLUTE_CONTROL 0x0f +#define CT_ROLL_RELATIVE_CONTROL 0x10 +#define CT_PRIVACY_CONTROL 0x11 + +/* Table A-13: Processing Unit Control Selectors */ +#define PU_CONTROL_UNDEFINED 0x00 +#define PU_BACKLIGHT_COMPENSATION_CONTROL 0x01 +#define PU_BRIGHTNESS_CONTROL 0x02 +#define PU_CONTRAST_CONTROL 0x03 +#define PU_GAIN_CONTROL 0x04 +#define PU_POWER_LINE_FREQUENCY_CONTROL 0x05 +#define PU_HUE_CONTROL 0x06 +#define PU_SATURATION_CONTROL 0x07 +#define PU_SHARPNESS_CONTROL 0x08 +#define PU_GAMMA_CONTROL 0x09 +#define PU_WHITE_BALANCE_TEMPERATURE_CONTROL 0x0a +#define PU_WHITE_BALANCE_TEMPERATURE_AUTO_CONTROL 0x0b +#define PU_WHITE_BALANCE_COMPONENT_CONTROL 0x0c +#define PU_WHITE_BALANCE_COMPONENT_AUTO_CONTROL 0x0d +#define PU_DIGITAL_MULTIPLIER_CONTROL 0x0e +#define PU_DIGITAL_MULTIPLIER_LIMIT_CONTROL 0x0f +#define PU_HUE_AUTO_CONTROL 0x10 +#define PU_ANALOG_VIDEO_STANDARD_CONTROL 0x11 +#define PU_ANALOG_LOCK_STATUS_CONTROL 0x12 + +/* Table A-15: VideoStreaming Interface Control Selectors */ +#define VS_CONTROL_UNDEFINED 0x00 +#define VS_PROBE_CONTROL 0x01 +#define VS_COMMIT_CONTROL 0x02 +#define VS_STILL_PROBE_CONTROL 0x03 +#define VS_STILL_COMMIT_CONTROL 0x04 +#define VS_STILL_IMAGE_TRIGGER_CONTROL 0x05 +#define VS_STREAM_ERROR_CODE_CONTROL 0x06 +#define VS_GENERATE_KEY_FRAME_CONTROL 0x07 +#define VS_UPDATE_FRAME_SEGMENT_CONTROL 0x08 +#define VS_SYNC_DELAY_CONTROL 0x09 + +/* probe commit bmRequests */ +#define UVIDEO_SET_IF 0x21 +#define UVIDEO_GET_IF 0xa1 +#define UVIDEO_SET_EP 0x22 +#define UVIDEO_GET_EP 0xa2 + +/* Table B-1: USB Terminal Types */ +#define TT_VENDOR_SPECIFIC 0x0100 +#define TT_STREAMING 0x0101 + +/* Table B-2: Input Terminal Types */ +#define ITT_VENDOR_SPECIFIC 0x0200 +#define ITT_CAMERA 0x0201 +#define ITT_MEDIA_TRANSPORT_INPUT 0x0202 + +/* Table B-3: Output Terminal Types */ +#define OTT_VENDOR_SPECIFIC 0x0300 +#define OTT_DISPLAY 0x0301 +#define OTT_MEDIA_TRANSPORT_OUTPUT 0x0302 + +/* Table B-4: External Terminal Types */ +#define EXTERNAL_VENDOR_SPECIFIC 0x0400 +#define COMPOSITE_CONNECTOR 0x0401 +#define SVIDEO_CONNECTOR 0x0402 +#define COMPONENT_CONNECTOR 0x0403 + +/* Table 3-3: VC Interface Header Descriptor */ +struct usb_video_header_descriptor { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uWord bcdUVC; + uWord wTotalLength; + uDWord dwClockFrequency; /* XXX deprecated */ + uByte bInCollection; +}; + +struct usb_video_control { + struct usb_video_header_descriptor *descr; + uByte *baInterfaceNr; +}; + +struct usb_video_header_desc { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uWord bcdUVC; + uWord wTotalLength; + uDWord dwClockFrequency; /* XXX deprecated */ + uByte bInCollection; + uByte baInterfaceNr; +}; + +/* Table 3-4: Input Terminal Descriptor */ +struct usb_video_input_terminal_desc { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uByte bTerminalID; + uWord wTerminalType; + uByte bAssocTerminal; + uByte iTerminal; +}; + +/* Table 3-5: Output Terminal Descriptor */ +struct usb_video_output_terminal_desc { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uByte bTerminalID; + uWord wTerminalType; + uByte bAssocTerminal; + uByte bSourceID; + uByte iTerminal; +}; + +/* Table 3-6: Camera Terminal Descriptor */ +struct usb_video_camera_terminal_desc { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uByte bTerminalID; + uWord wTerminalType; + uByte bAssocTerminal; + uByte iTerminal; + uWord wObjectiveFocalLengthMin; + uWord wObjectiveFocalLengthMax; + uWord wOcularFocalLength; + uByte bControlSize; + uByte *bmControls; /* XXX */ +}; + +/* Table 3-11: VC Endpoint Descriptor */ +struct usb_video_vc_endpoint_desc { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uWord wMaxTransferSize; +}; + +/* Table 3-18: Color Matching Descriptor */ +struct usb_video_color_matching_descr { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uByte bColorPrimaries; + uByte bTransferCharacteristics; + uByte bMatrixCoefficients; +} __packed; + +/* Table 4-47: Video Probe and Commit Controls */ +struct usb_video_probe_commit { + uByte bmHint[2]; + uByte bFormatIndex; + uByte bFrameIndex; + uByte dwFrameInterval[4]; + uByte wKeyFrameRate[2]; + uByte wPFrameRate[2]; + uByte wCompQuality[2]; + uByte wCompWindowSize[2]; + uByte wDelay[2]; + uByte dwMaxVideoFrameSize[4]; + uByte dwMaxPayloadTransferSize[4]; + uByte wClockFrequency[4]; + uByte bmFramingInfo; + uByte bPreferedVersion; + uByte bMinVersion; + uByte bMaxVersion; +} __packed; + +/* + * USB Video Payload Uncompressed + */ +/* Table 2-1: Compression Formats */ +#define UVIDEO_FORMAT_GUID_YUY2 { \ + 0x59, 0x55, 0x59, 0x32, 0x00, 0x00, 0x10, 0x00, \ + 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } + +#define UVIDEO_FORMAT_GUID_NV12 { \ + 0x4e, 0x56, 0x31, 0x32, 0x00, 0x00, 0x10, 0x00, \ + 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } + +/* + * USB Video Payload MJPEG + */ +/* Table 2-1: Stream Header Format for the Motion-JPEG */ +#define UVIDEO_STREAM_FID (1 << 0) +#define UVIDEO_STREAM_EOF (1 << 1) +#define UVIDEO_STREAM_PTS (1 << 2) +#define UVIDEO_STREAM_SCR (1 << 3) +#define UVIDEO_STREAM_RES (1 << 4) +#define UVIDEO_STREAM_STI (1 << 5) +#define UVIDEO_STREAM_ERR (1 << 6) +#define UVIDEO_STREAM_EOH (1 << 7) + +/* Table 3-1: Motion-JPEG Video Format Descriptor */ +struct usb_video_format_mjpeg_descriptor { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uByte bFormatIndex; + uByte bNumFrameDescriptors; + uByte bmFlags; + uByte bDefaultFrameIndex; + uByte bAspectRatioX; + uByte bAspectRatioY; + uByte bmInterlaceFlags; + uByte bCopyProtect; +} __packed; + +/* Table 3-2: Motion-JPEG Video Frame Descriptor */ +struct usb_video_frame_descriptor { + uByte bLength; + uByte bDescriptorType; + uByte bDescriptorSubtype; + uByte bFrameIndex; + uByte bmCapabilities; + uWord wWidth; + uWord wHeight; + uDWord dwMinBitRate; + uDWord dwMaxBitRate; + uDWord dwMaxVideoFrameBufferSize; + uWord dwDefaultFrameInterval; + uByte bFrameIntervalType; +} __packed; + +/* + * Driver specific private definitions. + */ +#define UVIDEO_NFRAMES 10 /* XXX calculate right value */ + +struct uvideo_stream_if { + struct uvideo_softc *sc; + usbd_xfer_handle xfer; + void *buf; + int busy; + int numalts; + usbd_interface_handle in_ifaceh; + usbd_pipe_handle in_pipeh; + int endpoint; + u_int16_t size[UVIDEO_NFRAMES]; + + u_int8_t fmtgrp_cnt; + + usbd_interface_handle ifaceh; + usbd_interface_handle *if_descr; + int curr_alt; + u_int32_t max_isoc_payload; + + char start_polling; + char fid; +}; + +struct uvideo_sample_buffer { + int fragment; + uint8_t fid; + int offset; + uint8_t *buf; +}; + +struct uvideo_softc { + struct device sc_dev; + usbd_device_handle sc_udev; + usbd_interface_handle sc_iface; + int sc_iface_number; + int sc_product; + int sc_vendor; + + int sc_intr_number; + usbd_pipe_handle sc_intr_pipe; + u_char *sc_ibuf; + int sc_isize; + int sc_vc_iface; + + struct device *sc_videodev; + + struct vs_info *sc_alts; + int sc_nalts; + int sc_nullalt; + int sc_video_rev; + int sc_enabled; + int sc_dying; + int sc_mode; + + u_int16_t uvc_version; + u_int32_t clock_frequency; + u_int32_t quirks; + + struct uvideo_sample_buffer sc_sample_buffer; + + struct vnode *sc_vp; + struct usb_task sc_task_write; + + struct usb_video_control *sc_vc_header; + struct uvideo_stream_if sc_curr_strm; +}; diff --git a/sys/dev/video.c b/sys/dev/video.c new file mode 100644 index 00000000000..75a19eaa5f8 --- /dev/null +++ b/sys/dev/video.c @@ -0,0 +1,199 @@ +/* $OpenBSD: video.c,v 1.1 2008/04/09 19:49:55 robert Exp $ */ +/* + * Copyright (c) 2008 Robert Nagy <robert@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/proc.h> +#include <sys/errno.h> +#include <sys/ioctl.h> +#include <sys/fcntl.h> +#include <sys/device.h> +#include <sys/vnode.h> +#include <sys/conf.h> +#include <sys/videoio.h> + +#include <dev/video_if.h> +#include <dev/videovar.h> + +#define DPRINTF(x) do { printf x; } while (0) + +int videoprobe(struct device *, void *, void *); +void videoattach(struct device *, struct device *, void *); +int videodetach(struct device *, int); +int videoactivate(struct device *, enum devact); +int videoprint(void *, const char *); + +struct cfattach video_ca = { + sizeof(struct video_softc), videoprobe, videoattach, + videodetach, videoactivate +}; + +struct cfdriver video_cd = { + NULL, "video", DV_DULL +}; + +int +videoprobe(struct device *parent, void *match, void *aux) +{ + return (1); +} + +void +videoattach(struct device *parent, struct device *self, void *aux) +{ + struct video_softc *sc = (void *) self; + struct video_attach_args *sa = aux; + + printf("\n"); + sc->hw_if = sa->hwif; + sc->hw_hdl = sa->hdl; + sc->sc_dev = parent; +} + +int +videoopen(dev_t dev, int flags, int fmt, struct proc *p) +{ + int unit; + struct video_softc *sc; + + unit = VIDEOUNIT(dev); + if (unit >= video_cd.cd_ndevs || + (sc = video_cd.cd_devs[unit]) == NULL || + sc->hw_if == NULL) + return (ENXIO); + + if (sc->hw_if->open != NULL) + return (sc->hw_if->open(sc->hw_hdl, flags)); + else + return (0); +} + +int +videoclose(dev_t dev, int flags, int fmt, struct proc *p) +{ + struct video_softc *sc; + + sc = video_cd.cd_devs[VIDEOUNIT(dev)]; + + if (sc->hw_if->close != NULL) + return (sc->hw_if->close(sc->hw_hdl)); + else + return (0); +} + +int +videoioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p) +{ + struct video_softc *sc; + int unit, error; + + unit = VIDEOUNIT(dev); + if (unit >= video_cd.cd_ndevs || + (sc = video_cd.cd_devs[unit]) == NULL || sc->hw_if == NULL) + return (ENXIO); + + DPRINTF(("video_ioctl(%d, '%c', %d)\n", + IOCPARM_LEN(cmd), IOCGROUP(cmd), cmd & 0xff)); + + error = EOPNOTSUPP; + switch (cmd) { + case VIDIOC_QUERYCAP: + if (sc->hw_if->querycap) + error = (sc->hw_if->querycap)(sc->hw_hdl, + (struct v4l2_capability *)data); + break; + case VIDIOC_S_FMT: + if (!(flags & FWRITE)) + return (EACCES); + if (sc->hw_if->s_fmt) + error = (sc->hw_if->s_fmt)(sc->hw_hdl, + (struct v4l2_format *)data); + break; + case VIDIOC_G_FMT: + if (sc->hw_if->g_fmt) + error = (sc->hw_if->g_fmt)(sc->hw_hdl, + (struct v4l2_format *)data); + break; + case VIDIOC_REQBUFS: + if (sc->hw_if->reqbufs) + error = (sc->hw_if->reqbufs)(sc->hw_hdl, + (struct v4l2_requestbuffers *)data); + break; + case VIDIOC_QUERYBUF: + case VIDIOC_QBUF: + default: + error = (ENOTTY); + } + + return (error); +} + +/* + * Called from hardware driver. This is where the MI video driver gets + * probed/attached to the hardware driver + */ +struct device * +video_attach_mi(struct video_hw_if *rhwp, void *hdlp, struct device *dev) +{ + struct video_attach_args arg; + + arg.hwif = rhwp; + arg.hdl = hdlp; + return (config_found(dev, &arg, videoprint)); +} + +int +videoprint(void *aux, const char *pnp) +{ + if (pnp != NULL) + printf("video at %s", pnp); + return (UNCONF); +} + +int +videodetach(struct device *self, int flags) +{ + /*struct video_softc *sc = (struct video_softc *)self;*/ + int maj, mn; + + /* locate the major number */ + for (maj = 0; maj < nchrdev; maj++) + if (cdevsw[maj].d_open == videoopen) + break; + + /* Nuke the vnodes for any open instances (calls close). */ + mn = self->dv_unit; + vdevgone(maj, mn, mn, VCHR); + + return (0); +} + +int +videoactivate(struct device *self, enum devact act) +{ + struct video_softc *sc = (struct video_softc *)self; + + switch (act) { + case DVACT_ACTIVATE: + break; + + case DVACT_DEACTIVATE: + sc->sc_dying = 1; + break; + } + return (0); +} diff --git a/sys/dev/video_if.h b/sys/dev/video_if.h new file mode 100644 index 00000000000..66360fe8614 --- /dev/null +++ b/sys/dev/video_if.h @@ -0,0 +1,49 @@ +/* $OpenBSD: video_if.h,v 1.1 2008/04/09 19:49:55 robert Exp $ */ +/* + * Copyright (c) 2008 Robert Nagy <robert@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_DEV_VIDEO_IF_H +#define _SYS_DEV_VIDEO_IF_H + +/* + * Generic interface to hardware driver + */ + +#define VIDEOUNIT(x) (minor(x)) + +struct video_hw_if { + /* open hardware */ + int (*open)(void *, int); + + /* close hardware */ + int (*close)(void *); + + int (*querycap)(void *, struct v4l2_capability *); + int (*s_fmt)(void *, struct v4l2_format *); + int (*g_fmt)(void *, struct v4l2_format *); + int (*reqbufs)(void *, struct v4l2_requestbuffers *); + int (*qbuf)(void *, struct v4l2_buffer *); + int (*dqbuf)(void *, struct v4l2_buffer *); +}; + +struct video_attach_args { + void *hwif; + void *hdl; +}; + +struct device *video_attach_mi(struct video_hw_if *, void *, struct device *); + +#endif /* _SYS_DEV_VIDEO_IF_H */ diff --git a/sys/dev/videovar.h b/sys/dev/videovar.h new file mode 100644 index 00000000000..3b6319cfd28 --- /dev/null +++ b/sys/dev/videovar.h @@ -0,0 +1,29 @@ +/* $OpenBSD: videovar.h,v 1.1 2008/04/09 19:49:55 robert Exp $ */ +/* + * Copyright (c) 2008 Robert Nagy <robert@openbsd.org> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SYS_DEV_VIDEOVAR_H +#define _SYS_DEV_VIDEOVAR_H + +struct video_softc { + struct device dev; + void *hw_hdl; /* hardware driver handle */ + struct device *sc_dev; /* hardware device struct */ + struct video_hw_if *hw_if; /* hardware interface */ + char sc_dying; /* device detached */ +}; + +#endif /* _SYS_DEV_VIDEOVAR_H */ diff --git a/sys/sys/conf.h b/sys/sys/conf.h index 60e32073ea1..8fe773508a3 100644 --- a/sys/sys/conf.h +++ b/sys/sys/conf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.h,v 1.86 2008/04/08 14:31:54 claudio Exp $ */ +/* $OpenBSD: conf.h,v 1.87 2008/04/09 19:49:55 robert Exp $ */ /* $NetBSD: conf.h,v 1.33 1996/05/03 20:03:32 christos Exp $ */ /*- @@ -450,6 +450,13 @@ void randomattach(void); (dev_type_stop((*))) enodev, 0, (dev_type_poll((*))) enodev, \ (dev_type_mmap((*))) enodev } +/* open, close, ioctl */ +#define cdev_video_init(c,n) { \ + dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ + (dev_type_write((*))) enodev, dev_init(c,n,ioctl), \ + (dev_type_stop((*))) enodev, 0, (dev_type_poll((*))) enodev, \ + (dev_type_mmap((*))) enodev } + /* open, close, write, ioctl */ #define cdev_spkr_init(c,n) { \ dev_init(c,n,open), dev_init(c,n,close), (dev_type_read((*))) enodev, \ @@ -587,6 +594,7 @@ cdev_decl(audio); cdev_decl(midi); cdev_decl(sequencer); cdev_decl(radio); +cdev_decl(video); cdev_decl(cn); bdev_decl(sw); diff --git a/sys/sys/videoio.h b/sys/sys/videoio.h new file mode 100644 index 00000000000..be9c9c0bfc4 --- /dev/null +++ b/sys/sys/videoio.h @@ -0,0 +1,1516 @@ +/* $OpenBSD: videoio.h,v 1.1 2008/04/09 19:49:55 robert Exp $ */ +/* + * Video for Linux Two header file + * + * Copyright (C) 1999-2007 the contributors + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * Alternatively you can redistribute this file under the terms of the + * BSD license as stated below: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. The names of its contributors may not be used to endorse or promote + * products derived from this software without specific prior written + * permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Header file for v4l or V4L2 drivers and applications + * with public API. + * All kernel-specific stuff were moved to media/v4l2-dev.h, so + * no #if __KERNEL tests are allowed here + * + * See http://linuxtv.org for more info + * + * Author: Bill Dirks <bill@thedirks.org> + * Justin Schoeman + * Hans Verkuil <hverkuil@xs4all.nl> + * et al. + */ + +#ifndef _SYS_VIDEOIO_H_ +#define _SYS_VIDEOIO_H_ +#include <sys/time.h> +#include <sys/types.h> + +#ifndef __user +#define __user +#endif + +#ifndef __u8 +typedef u_int8_t __u8; +#endif +#ifndef __u16 +typedef u_int16_t __u16; +#endif +#ifndef __u32 +typedef u_int32_t __u32; +#endif +#ifndef __u64 +typedef u_int64_t __u64; +#endif +#ifndef __s32 +typedef int32_t __s32; +#endif +#ifndef __s64 +typedef int64_t __s64; +#endif + + +/* + * Common stuff for both V4L1 and V4L2 + */ +#define VIDEO_MAX_FRAME 32 + +#define VID_TYPE_CAPTURE 1 /* Can capture */ +#define VID_TYPE_TUNER 2 /* Can tune */ +#define VID_TYPE_TELETEXT 4 /* Does teletext */ +#define VID_TYPE_OVERLAY 8 /* Overlay onto frame buffer */ +#define VID_TYPE_CHROMAKEY 16 /* Overlay by chromakey */ +#define VID_TYPE_CLIPPING 32 /* Can clip */ +#define VID_TYPE_FRAMERAM 64 /* Uses the frame buffer memory */ +#define VID_TYPE_SCALES 128 /* Scalable */ +#define VID_TYPE_MONOCHROME 256 /* Monochrome only */ +#define VID_TYPE_SUBCAPTURE 512 /* Can capture subareas of the image */ +#define VID_TYPE_MPEG_DECODER 1024 /* Can decode MPEG streams */ +#define VID_TYPE_MPEG_ENCODER 2048 /* Can encode MPEG streams */ +#define VID_TYPE_MJPEG_DECODER 4096 /* Can decode MJPEG streams */ +#define VID_TYPE_MJPEG_ENCODER 8192 /* Can encode MJPEG streams */ + +/* + * M I S C E L L A N E O U S + */ + +/* Four-character-code (FOURCC) */ +#define v4l2_fourcc(a,b,c,d)\ + (((__u32)(a)<<0)|((__u32)(b)<<8)|((__u32)(c)<<16)|((__u32)(d)<<24)) + +/* + * E N U M S + */ +enum v4l2_field { + V4L2_FIELD_ANY = 0, /* driver can choose from none, top, bottom, + * interlaced depending on whatever it thinks + * is approximate ... */ + V4L2_FIELD_NONE = 1, /* this device has no fields ... */ + V4L2_FIELD_TOP = 2, /* top field only */ + V4L2_FIELD_BOTTOM = 3, /* bottom field only */ + V4L2_FIELD_INTERLACED = 4, /* both fields interlaced */ + V4L2_FIELD_SEQ_TB = 5, /* both fields sequential into one buffer, + * top-bottom order */ + V4L2_FIELD_SEQ_BT = 6, /* same as above + bottom-top order */ + V4L2_FIELD_ALTERNATE = 7, /* both fields alternating into + * separate buffers */ + V4L2_FIELD_INTERLACED_TB = 8, /* both fields interlaced, top field + * first and the top field is + * transmitted first */ + V4L2_FIELD_INTERLACED_BT = 9, /* both fields interlaced, top field + * first and the bottom field is + * transmitted first */ +}; +#define V4L2_FIELD_HAS_TOP(field) \ + ((field) == V4L2_FIELD_TOP ||\ + (field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_INTERLACED_TB ||\ + (field) == V4L2_FIELD_INTERLACED_BT ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) +#define V4L2_FIELD_HAS_BOTTOM(field) \ + ((field) == V4L2_FIELD_BOTTOM ||\ + (field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_INTERLACED_TB ||\ + (field) == V4L2_FIELD_INTERLACED_BT ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) +#define V4L2_FIELD_HAS_BOTH(field) \ + ((field) == V4L2_FIELD_INTERLACED ||\ + (field) == V4L2_FIELD_INTERLACED_TB ||\ + (field) == V4L2_FIELD_INTERLACED_BT ||\ + (field) == V4L2_FIELD_SEQ_TB ||\ + (field) == V4L2_FIELD_SEQ_BT) + +enum v4l2_buf_type { + V4L2_BUF_TYPE_VIDEO_CAPTURE = 1, + V4L2_BUF_TYPE_VIDEO_OUTPUT = 2, + V4L2_BUF_TYPE_VIDEO_OVERLAY = 3, + V4L2_BUF_TYPE_VBI_CAPTURE = 4, + V4L2_BUF_TYPE_VBI_OUTPUT = 5, + V4L2_BUF_TYPE_SLICED_VBI_CAPTURE = 6, + V4L2_BUF_TYPE_SLICED_VBI_OUTPUT = 7, +#if 1 /* KEEP */ + /* Experimental */ + V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8, +#endif + V4L2_BUF_TYPE_PRIVATE = 0x80, +}; + +enum v4l2_ctrl_type { + V4L2_CTRL_TYPE_INTEGER = 1, + V4L2_CTRL_TYPE_BOOLEAN = 2, + V4L2_CTRL_TYPE_MENU = 3, + V4L2_CTRL_TYPE_BUTTON = 4, + V4L2_CTRL_TYPE_INTEGER64 = 5, + V4L2_CTRL_TYPE_CTRL_CLASS = 6, +}; + +enum v4l2_tuner_type { + V4L2_TUNER_RADIO = 1, + V4L2_TUNER_ANALOG_TV = 2, + V4L2_TUNER_DIGITAL_TV = 3, +}; + +enum v4l2_memory { + V4L2_MEMORY_MMAP = 1, + V4L2_MEMORY_USERPTR = 2, + V4L2_MEMORY_OVERLAY = 3, +}; + +/* see also http://vektor.theorem.ca/graphics/ycbcr/ */ +enum v4l2_colorspace { + /* ITU-R 601 -- broadcast NTSC/PAL */ + V4L2_COLORSPACE_SMPTE170M = 1, + + /* 1125-Line (US) HDTV */ + V4L2_COLORSPACE_SMPTE240M = 2, + + /* HD and modern captures. */ + V4L2_COLORSPACE_REC709 = 3, + + /* broken BT878 extents (601, luma range 16-253 instead of 16-235) */ + V4L2_COLORSPACE_BT878 = 4, + + /* These should be useful. Assume 601 extents. */ + V4L2_COLORSPACE_470_SYSTEM_M = 5, + V4L2_COLORSPACE_470_SYSTEM_BG = 6, + + /* + * I know there will be cameras that send this. So, this is + * unspecified chromaticities and full 0-255 on each of the Y'CbCr + * components + */ + V4L2_COLORSPACE_JPEG = 7, + + /* For RGB colourspaces, this is probably a good start. */ + V4L2_COLORSPACE_SRGB = 8, +}; + +enum v4l2_priority { + V4L2_PRIORITY_UNSET = 0,/* not initialized */ + V4L2_PRIORITY_BACKGROUND = 1, + V4L2_PRIORITY_INTERACTIVE = 2, + V4L2_PRIORITY_RECORD = 3, + V4L2_PRIORITY_DEFAULT = V4L2_PRIORITY_INTERACTIVE, +}; + +struct v4l2_rect { + __s32 left; + __s32 top; + __s32 width; + __s32 height; +}; + +struct v4l2_fract { + __u32 numerator; + __u32 denominator; +}; + +/* + * D R I V E R C A P A B I L I T I E S + */ +struct v4l2_capability { + __u8 driver[16]; /* i.e.ie; "bttv" */ + __u8 card[32]; /* i.e.ie; "Hauppauge WinTV" */ + __u8 bus_info[32]; /* "PCI:" + pci_name(pci_dev) */ + __u32 version;/* should use KERNEL_VERSION() */ + __u32 capabilities; /* Device capabilities */ + __u32 reserved[4]; +}; + +/* Values for 'capabilities' field */ +#define V4L2_CAP_VIDEO_CAPTURE 0x00000001 /* Is a video capture + * device */ +#define V4L2_CAP_VIDEO_OUTPUT 0x00000002 /* Is a video output + * device */ +#define V4L2_CAP_VIDEO_OVERLAY 0x00000004 /* Can do video overlay */ +#define V4L2_CAP_VBI_CAPTURE 0x00000010 /* Is a raw VBI capture + * device */ +#define V4L2_CAP_VBI_OUTPUT 0x00000020 /* Is a raw VBI output + * device */ +#define V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040 /* Is a sliced VBI + * capture device */ +#define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* Is a sliced VBI + * output device */ +#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */ +#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY 0x00000200 /* Can do video output + * overlay */ + +#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */ +#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */ +#define V4L2_CAP_RADIO 0x00040000 /* is a radio device */ + +#define V4L2_CAP_READWRITE 0x01000000 /* read/write + * systemcalls */ +#define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */ +#define V4L2_CAP_STREAMING 0x04000000 /* streaming I/O ioctls */ + +/* + * V I D E O I M A G E F O R M A T + */ +struct v4l2_pix_format { + __u32 width; + __u32 height; + __u32 pixelformat; + enum v4l2_field field; + __u32 bytesperline; /* for padding, zero if unused */ + __u32 sizeimage; + enum v4l2_colorspace colorspace; + __u32 priv; /* private data, depends on pixelformat */ +}; + +/* Pixel format FOURCC depth Description */ +#define V4L2_PIX_FMT_RGB332 v4l2_fourcc('R','G','B','1') /* 8 RGB-3-3-2 */ +#define V4L2_PIX_FMT_RGB444 v4l2_fourcc('R','4','4','4') /* 16 xxxxrrrr ggggbbbb */ +#define V4L2_PIX_FMT_RGB555 v4l2_fourcc('R','G','B','O') /* 16 RGB-5-5-5 */ +#define V4L2_PIX_FMT_RGB565 v4l2_fourcc('R','G','B','P') /* 16 RGB-5-6-5 */ +#define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R','G','B','Q') /* 16 RGB-5-5-5 BE */ +#define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R','G','B','R') /* 16 RGB-5-6-5 BE */ +#define V4L2_PIX_FMT_BGR24 v4l2_fourcc('B','G','R','3') /* 24 BGR-8-8-8 */ +#define V4L2_PIX_FMT_RGB24 v4l2_fourcc('R','G','B','3') /* 24 RGB-8-8-8 */ +#define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B','G','R','4') /* 32 BGR-8-8-8-8 */ +#define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R','G','B','4') /* 32 RGB-8-8-8-8 */ +#define V4L2_PIX_FMT_GREY v4l2_fourcc('G','R','E','Y') /* 8 Greyscale */ +#define V4L2_PIX_FMT_PAL8 v4l2_fourcc('P','A','L','8') /* 8 8-bit palette */ +#define V4L2_PIX_FMT_YVU410 v4l2_fourcc('Y','V','U','9') /* 9 YVU 4:1:0 */ +#define V4L2_PIX_FMT_YVU420 v4l2_fourcc('Y','V','1','2') /* 12 YVU 4:2:0 */ +#define V4L2_PIX_FMT_YUYV v4l2_fourcc('Y','U','Y','V') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_UYVY v4l2_fourcc('U','Y','V','Y') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_YUV422P v4l2_fourcc('4','2','2','P') /* 16 YVU422 planar */ +#define V4L2_PIX_FMT_YUV411P v4l2_fourcc('4','1','1','P') /* 16 YVU411 planar */ +#define V4L2_PIX_FMT_Y41P v4l2_fourcc('Y','4','1','P') /* 12 YUV 4:1:1 */ +#define V4L2_PIX_FMT_YUV444 v4l2_fourcc('Y','4','4','4') /* 16 xxxxyyyy uuuuvvvv */ +#define V4L2_PIX_FMT_YUV555 v4l2_fourcc('Y','U','V','O') /* 16 YUV-5-5-5 */ +#define V4L2_PIX_FMT_YUV565 v4l2_fourcc('Y','U','V','P') /* 16 YUV-5-6-5 */ +#define V4L2_PIX_FMT_YUV32 v4l2_fourcc('Y','U','V','4') /* 32 YUV-8-8-8-8 */ + +/* two planes -- one Y, one Cr + Cb interleaved */ +#define V4L2_PIX_FMT_NV12 v4l2_fourcc('N','V','1','2') /* 12 Y/CbCr 4:2:0 */ +#define V4L2_PIX_FMT_NV21 v4l2_fourcc('N','V','2','1') /* 12 Y/CrCb 4:2:0 */ + +/* The following formats are not defined in the V4L2 specification */ +#define V4L2_PIX_FMT_YUV410 v4l2_fourcc('Y','U','V','9') /* 9 YUV 4:1:0 */ +#define V4L2_PIX_FMT_YUV420 v4l2_fourcc('Y','U','1','2') /* 12 YUV 4:2:0 */ +#define V4L2_PIX_FMT_YYUV v4l2_fourcc('Y','Y','U','V') /* 16 YUV 4:2:2 */ +#define V4L2_PIX_FMT_HI240 v4l2_fourcc('H','I','2','4') /* 8 8-bit color */ +#define V4L2_PIX_FMT_HM12 v4l2_fourcc('H','M','1','2') /* 8 YUV 4:2:0 16x16 + * macroblocks */ + +/* see http://www.siliconimaging.com/RGB%20Bayer.htm */ +#define V4L2_PIX_FMT_SBGGR8 v4l2_fourcc('B','A','8','1') /* 8 BGBG.. GRGR.. */ + +/* compressed formats */ +#define V4L2_PIX_FMT_MJPEG v4l2_fourcc('M','J','P','G') /* Motion-JPEG */ +#define V4L2_PIX_FMT_JPEG v4l2_fourcc('J','P','E','G') /* JFIF JPEG */ +#define V4L2_PIX_FMT_DV v4l2_fourcc('d','v','s','d') /* 1394 */ +#define V4L2_PIX_FMT_MPEG v4l2_fourcc('M','P','E','G') /* MPEG-1/2/4 */ + +/* Vendor-specific formats */ +#define V4L2_PIX_FMT_WNVA v4l2_fourcc('W','N','V','A') /* Winnov hw compress */ +#define V4L2_PIX_FMT_SN9C10X v4l2_fourcc('S','9','1','0') /* SN9C10x compression */ +#define V4L2_PIX_FMT_PWC1 v4l2_fourcc('P','W','C','1') /* pwc older webcam */ +#define V4L2_PIX_FMT_PWC2 v4l2_fourcc('P','W','C','2') /* pwc newer webcam */ +#define V4L2_PIX_FMT_ET61X251 v4l2_fourcc('E','6','2','5') /* ET61X251 compression */ + +/* + * F O R M A T E N U M E R A T I O N + */ +struct v4l2_fmtdesc { + __u32 index; /* Format number */ + enum v4l2_buf_type type;/* buffer type */ + __u32 flags; + __u8 description[32]; /* Description string */ + __u32 pixelformat; /* Format fourcc */ + __u32 reserved[4]; +}; + +#define V4L2_FMT_FLAG_COMPRESSED 0x0001 + +#if 1 /* KEEP */ +/* Experimental Frame Size and frame rate enumeration */ +/* + * F R A M E S I Z E E N U M E R A T I O N + */ +enum v4l2_frmsizetypes { + V4L2_FRMSIZE_TYPE_DISCRETE = 1, + V4L2_FRMSIZE_TYPE_CONTINUOUS = 2, + V4L2_FRMSIZE_TYPE_STEPWISE = 3, +}; + +struct v4l2_frmsize_discrete { + __u32 width; /* Frame width [pixel] */ + __u32 height; /* Frame height [pixel] */ +}; + +struct v4l2_frmsize_stepwise { + __u32 min_width; /* Minimum frame width [pixel] */ + __u32 max_width; /* Maximum frame width [pixel] */ + __u32 step_width; /* Frame width step size [pixel] */ + __u32 min_height; /* Minimum frame height [pixel] */ + __u32 max_height; /* Maximum frame height [pixel] */ + __u32 step_height; /* Frame height step size [pixel] */ +}; + +struct v4l2_frmsizeenum { + __u32 index; /* Frame size number */ + __u32 pixel_format; /* Pixel format */ + __u32 type; /* Frame size type the device supports. */ + + union { /* Frame size */ + struct v4l2_frmsize_discrete discrete; + struct v4l2_frmsize_stepwise stepwise; + }; + + __u32 reserved[2]; /* Reserved space for future use */ +}; + +/* + * F R A M E R A T E E N U M E R A T I O N + */ +enum v4l2_frmivaltypes { + V4L2_FRMIVAL_TYPE_DISCRETE = 1, + V4L2_FRMIVAL_TYPE_CONTINUOUS = 2, + V4L2_FRMIVAL_TYPE_STEPWISE = 3, +}; + +struct v4l2_frmival_stepwise { + struct v4l2_fract min; /* Minimum frame interval [s] */ + struct v4l2_fract max; /* Maximum frame interval [s] */ + struct v4l2_fract step; /* Frame interval step size [s] */ +}; + +struct v4l2_frmivalenum { + __u32 index; /* Frame format index */ + __u32 pixel_format; /* Pixel format */ + __u32 width; /* Frame width */ + __u32 height; /* Frame height */ + __u32 type; /* Frame interval type the device supports. */ + + union { /* Frame interval */ + struct v4l2_fract discrete; + struct v4l2_frmival_stepwise stepwise; + }; + + __u32 reserved[2]; /* Reserved space for future use */ +}; +#endif + +/* + * T I M E C O D E + */ +struct v4l2_timecode { + __u32 type; + __u32 flags; + __u8 frames; + __u8 seconds; + __u8 minutes; + __u8 hours; + __u8 userbits[4]; +}; + +/* Type */ +#define V4L2_TC_TYPE_24FPS 1 +#define V4L2_TC_TYPE_25FPS 2 +#define V4L2_TC_TYPE_30FPS 3 +#define V4L2_TC_TYPE_50FPS 4 +#define V4L2_TC_TYPE_60FPS 5 + +/* Flags */ +#define V4L2_TC_FLAG_DROPFRAME 0x0001 /* "drop-frame" mode */ +#define V4L2_TC_FLAG_COLORFRAME 0x0002 +#define V4L2_TC_USERBITS_field 0x000C +#define V4L2_TC_USERBITS_USERDEFINED 0x0000 +#define V4L2_TC_USERBITS_8BITCHARS 0x0008 +/* The above is based on SMPTE timecodes */ + +#ifdef __KERNEL__ +/* + * M P E G C O M P R E S S I O N P A R A M E T E R S + * + * ### WARNING: This experimental MPEG compression API is obsolete. + * ### It is replaced by the MPEG controls API. + * ### This old API will disappear in the near future! + * + */ +enum v4l2_bitrate_mode { + V4L2_BITRATE_NONE = 0, /* not specified */ + V4L2_BITRATE_CBR, /* constant bitrate */ + V4L2_BITRATE_VBR, /* variable bitrate */ +}; +struct v4l2_bitrate { + /* rates are specified in kbit/sec */ + enum v4l2_bitrate_mode mode; + __u32 min; + __u32 target; /* use this one for CBR */ + __u32 max; +}; + +enum v4l2_mpeg_streamtype { + V4L2_MPEG_SS_1, /* MPEG-1 system stream */ + V4L2_MPEG_PS_2, /* MPEG-2 program stream */ + V4L2_MPEG_TS_2, /* MPEG-2 transport stream */ + V4L2_MPEG_PS_DVD, /* MPEG-2 program stream with DVD header + * fixups */ +}; +enum v4l2_mpeg_audiotype { + V4L2_MPEG_AU_2_I, /* MPEG-2 layer 1 */ + V4L2_MPEG_AU_2_II, /* MPEG-2 layer 2 */ + V4L2_MPEG_AU_2_III, /* MPEG-2 layer 3 */ + V4L2_MPEG_AC3, /* AC3 */ + V4L2_MPEG_LPCM, /* LPCM */ +}; +enum v4l2_mpeg_videotype { + V4L2_MPEG_VI_1, /* MPEG-1 */ + V4L2_MPEG_VI_2, /* MPEG-2 */ +}; +enum v4l2_mpeg_aspectratio { + V4L2_MPEG_ASPECT_SQUARE = 1, /* square pixel */ + V4L2_MPEG_ASPECT_4_3 = 2, /* 4 : 3 */ + V4L2_MPEG_ASPECT_16_9 = 3, /* 16 : 9 */ + V4L2_MPEG_ASPECT_1_221 = 4, /* 1 : 2,21 */ +}; + +struct v4l2_mpeg_compression { + /* general */ + enum v4l2_mpeg_streamtype st_type; + struct v4l2_bitrate st_bitrate; + + /* transport streams */ + __u16 ts_pid_pmt; + __u16 ts_pid_audio; + __u16 ts_pid_video; + __u16 ts_pid_pcr; + + /* program stream */ + __u16 ps_size; + __u16 reserved_1; /* align */ + + /* audio */ + enum v4l2_mpeg_audiotype au_type; + struct v4l2_bitrate au_bitrate; + __u32 au_sample_rate; + __u8 au_pesid; + __u8 reserved_2[3]; /* align */ + + /* video */ + enum v4l2_mpeg_videotype vi_type; + enum v4l2_mpeg_aspectratio vi_aspect_ratio; + struct v4l2_bitrate vi_bitrate; + __u32 vi_frame_rate; + __u16 vi_frames_per_gop; + __u16 vi_bframes_count; + __u8 vi_pesid; + __u8 reserved_3[3]; /* align */ + + /* misc flags */ + __u32 closed_gops:1; + __u32 pulldown:1; + __u32 reserved_4:30; /* align */ + + /* I don't expect the above being perfect yet ;) */ + __u32 reserved_5[8]; +}; +#endif + +struct v4l2_jpegcompression { + int quality; + + int APPn; /* Number of APP segment to be written, must + * be 0..15 */ + int APP_len;/* Length of data in JPEG APPn segment */ + char APP_data[60]; /* Data in the JPEG APPn segment. */ + + int COM_len;/* Length of data in JPEG COM segment */ + char COM_data[60]; /* Data in JPEG COM segment */ + + __u32 jpeg_markers; /* Which markers should go into the + * JPEG output. Unless you exactly + * know what you do, leave them + * untouched. Inluding less markers + * will make the resulting code + * smaller, but there will be fewer + * aplications which can read it. The + * presence of the APP and COM marker + * is influenced by APP_len and + * COM_len ONLY, not by this + * property! */ + +#define V4L2_JPEG_MARKER_DHT (1<<3) /* Define Huffman Tables */ +#define V4L2_JPEG_MARKER_DQT (1<<4) /* Define Quantization Tables */ +#define V4L2_JPEG_MARKER_DRI (1<<5) /* Define Restart Interval */ +#define V4L2_JPEG_MARKER_COM (1<<6) /* Comment segment */ +#define V4L2_JPEG_MARKER_APP (1<<7) /* App segment, driver will allways + * use APP0 */ +}; + +/* + * M E M O R Y - M A P P I N G B U F F E R S + */ +struct v4l2_requestbuffers { + __u32 count; + enum v4l2_buf_type type; + enum v4l2_memory memory; + __u32 reserved[2]; +}; + +struct v4l2_buffer { + __u32 index; + enum v4l2_buf_type type; + __u32 bytesused; + __u32 flags; + enum v4l2_field field; + struct timeval timestamp; + struct v4l2_timecode timecode; + __u32 sequence; + + /* memory location */ + enum v4l2_memory memory; + union { + __u32 offset; + unsigned long userptr; + } m; + __u32 length; + __u32 input; + __u32 reserved; +}; + +/* Flags for 'flags' field */ +#define V4L2_BUF_FLAG_MAPPED 0x0001 /* Buffer is mapped (flag) */ +#define V4L2_BUF_FLAG_QUEUED 0x0002 /* Buffer is queued for processing */ +#define V4L2_BUF_FLAG_DONE 0x0004 /* Buffer is ready */ +#define V4L2_BUF_FLAG_KEYFRAME 0x0008 /* Image is a keyframe (I-frame) */ +#define V4L2_BUF_FLAG_PFRAME 0x0010 /* Image is a P-frame */ +#define V4L2_BUF_FLAG_BFRAME 0x0020 /* Image is a B-frame */ +#define V4L2_BUF_FLAG_TIMECODE 0x0100 /* timecode field is valid */ +#define V4L2_BUF_FLAG_INPUT 0x0200 /* input field is valid */ + +/* + * O V E R L A Y P R E V I E W + */ +struct v4l2_framebuffer { + __u32 capability; + __u32 flags; + /* + * FIXME: in theory we should pass something like PCI device + memory + * region + offset instead of some physical address + */ + void *base; + struct v4l2_pix_format fmt; +}; +/* Flags for the 'capability' field. Read only */ +#define V4L2_FBUF_CAP_EXTERNOVERLAY 0x0001 +#define V4L2_FBUF_CAP_CHROMAKEY 0x0002 +#define V4L2_FBUF_CAP_LIST_CLIPPING 0x0004 +#define V4L2_FBUF_CAP_BITMAP_CLIPPING 0x0008 +#define V4L2_FBUF_CAP_LOCAL_ALPHA 0x0010 +#define V4L2_FBUF_CAP_GLOBAL_ALPHA 0x0020 +#define V4L2_FBUF_CAP_LOCAL_INV_ALPHA 0x0040 +/* Flags for the 'flags' field. */ +#define V4L2_FBUF_FLAG_PRIMARY 0x0001 +#define V4L2_FBUF_FLAG_OVERLAY 0x0002 +#define V4L2_FBUF_FLAG_CHROMAKEY 0x0004 +#define V4L2_FBUF_FLAG_LOCAL_ALPHA 0x0008 +#define V4L2_FBUF_FLAG_GLOBAL_ALPHA 0x0010 +#define V4L2_FBUF_FLAG_LOCAL_INV_ALPHA 0x0020 + +struct v4l2_clip { + struct v4l2_rect c; + struct v4l2_clip __user *next; +}; + +struct v4l2_window { + struct v4l2_rect w; + enum v4l2_field field; + __u32 chromakey; + struct v4l2_clip __user *clips; + __u32 clipcount; + void __user *bitmap; + __u8 global_alpha; +}; + +/* + * C A P T U R E P A R A M E T E R S + */ +struct v4l2_captureparm { + __u32 capability; /* Supported modes */ + __u32 capturemode; /* Current mode */ + struct v4l2_fract timeperframe; /* Time per frame in .1us units */ + __u32 extendedmode; /* Driver-specific extensions */ + __u32 readbuffers; /* # of buffers for read */ + __u32 reserved[4]; +}; + +/* Flags for 'capability' and 'capturemode' fields */ +#define V4L2_MODE_HIGHQUALITY 0x0001 /* High quality imaging mode */ +#define V4L2_CAP_TIMEPERFRAME 0x1000 /* timeperframe field is supported */ + +struct v4l2_outputparm { + __u32 capability; /* Supported modes */ + __u32 outputmode; /* Current mode */ + struct v4l2_fract timeperframe; /* Time per frame in seconds */ + __u32 extendedmode; /* Driver-specific extensions */ + __u32 writebuffers; /* # of buffers for write */ + __u32 reserved[4]; +}; + +/* + * I N P U T I M A G E C R O P P I N G + */ +struct v4l2_cropcap { + enum v4l2_buf_type type; + struct v4l2_rect bounds; + struct v4l2_rect defrect; + struct v4l2_fract pixelaspect; +}; + +struct v4l2_crop { + enum v4l2_buf_type type; + struct v4l2_rect c; +}; + +/* + * A N A L O G V I D E O S T A N D A R D + */ + +typedef __u64 v4l2_std_id; + +/* one bit for each */ +#define V4L2_STD_PAL_B ((v4l2_std_id)0x00000001) +#define V4L2_STD_PAL_B1 ((v4l2_std_id)0x00000002) +#define V4L2_STD_PAL_G ((v4l2_std_id)0x00000004) +#define V4L2_STD_PAL_H ((v4l2_std_id)0x00000008) +#define V4L2_STD_PAL_I ((v4l2_std_id)0x00000010) +#define V4L2_STD_PAL_D ((v4l2_std_id)0x00000020) +#define V4L2_STD_PAL_D1 ((v4l2_std_id)0x00000040) +#define V4L2_STD_PAL_K ((v4l2_std_id)0x00000080) + +#define V4L2_STD_PAL_M ((v4l2_std_id)0x00000100) +#define V4L2_STD_PAL_N ((v4l2_std_id)0x00000200) +#define V4L2_STD_PAL_Nc ((v4l2_std_id)0x00000400) +#define V4L2_STD_PAL_60 ((v4l2_std_id)0x00000800) + +#define V4L2_STD_NTSC_M ((v4l2_std_id)0x00001000) +#define V4L2_STD_NTSC_M_JP ((v4l2_std_id)0x00002000) +#define V4L2_STD_NTSC_443 ((v4l2_std_id)0x00004000) +#define V4L2_STD_NTSC_M_KR ((v4l2_std_id)0x00008000) + +#define V4L2_STD_SECAM_B ((v4l2_std_id)0x00010000) +#define V4L2_STD_SECAM_D ((v4l2_std_id)0x00020000) +#define V4L2_STD_SECAM_G ((v4l2_std_id)0x00040000) +#define V4L2_STD_SECAM_H ((v4l2_std_id)0x00080000) +#define V4L2_STD_SECAM_K ((v4l2_std_id)0x00100000) +#define V4L2_STD_SECAM_K1 ((v4l2_std_id)0x00200000) +#define V4L2_STD_SECAM_L ((v4l2_std_id)0x00400000) +#define V4L2_STD_SECAM_LC ((v4l2_std_id)0x00800000) + +/* ATSC/HDTV */ +#define V4L2_STD_ATSC_8_VSB ((v4l2_std_id)0x01000000) +#define V4L2_STD_ATSC_16_VSB ((v4l2_std_id)0x02000000) + +/* + * FIXME: Although std_id is 64 bits, there is an issue on PPC32 architecture + * that makes switch(__u64) to break. So, there's a hack on v4l2-common.c + * rounding this value to 32 bits. As, currently, the max value is for + * V4L2_STD_ATSC_16_VSB (30 bits wide), it should work fine. However, if + * needed to add more than two standards, v4l2-common.c should be fixed. + */ + +/* some merged standards */ +#define V4L2_STD_MN (V4L2_STD_PAL_M|V4L2_STD_PAL_N|V4L2_STD_PAL_Nc|V4L2_STD_NTSC) +#define V4L2_STD_B (V4L2_STD_PAL_B|V4L2_STD_PAL_B1|V4L2_STD_SECAM_B) +#define V4L2_STD_GH (V4L2_STD_PAL_G|V4L2_STD_PAL_H|V4L2_STD_SECAM_G|V4L2_STD_SECAM_H) +#define V4L2_STD_DK (V4L2_STD_PAL_DK|V4L2_STD_SECAM_DK) + +/* some common needed stuff */ +#define V4L2_STD_PAL_BG (V4L2_STD_PAL_B |\ + V4L2_STD_PAL_B1 |\ + V4L2_STD_PAL_G) +#define V4L2_STD_PAL_DK (V4L2_STD_PAL_D |\ + V4L2_STD_PAL_D1 |\ + V4L2_STD_PAL_K) +#define V4L2_STD_PAL (V4L2_STD_PAL_BG |\ + V4L2_STD_PAL_DK |\ + V4L2_STD_PAL_H |\ + V4L2_STD_PAL_I) +#define V4L2_STD_NTSC (V4L2_STD_NTSC_M |\ + V4L2_STD_NTSC_M_JP |\ + V4L2_STD_NTSC_M_KR) +#define V4L2_STD_SECAM_DK (V4L2_STD_SECAM_D |\ + V4L2_STD_SECAM_K |\ + V4L2_STD_SECAM_K1) +#define V4L2_STD_SECAM (V4L2_STD_SECAM_B |\ + V4L2_STD_SECAM_G |\ + V4L2_STD_SECAM_H |\ + V4L2_STD_SECAM_DK |\ + V4L2_STD_SECAM_L |\ + V4L2_STD_SECAM_LC) + +#define V4L2_STD_525_60 (V4L2_STD_PAL_M |\ + V4L2_STD_PAL_60 |\ + V4L2_STD_NTSC |\ + V4L2_STD_NTSC_443) +#define V4L2_STD_625_50 (V4L2_STD_PAL |\ + V4L2_STD_PAL_N |\ + V4L2_STD_PAL_Nc |\ + V4L2_STD_SECAM) +#define V4L2_STD_ATSC (V4L2_STD_ATSC_8_VSB |\ + V4L2_STD_ATSC_16_VSB) + +#define V4L2_STD_UNKNOWN 0 +#define V4L2_STD_ALL (V4L2_STD_525_60 |\ + V4L2_STD_625_50) + +struct v4l2_standard { + __u32 index; + v4l2_std_id id; + __u8 name[24]; + struct v4l2_fract frameperiod; /* Frames, not fields */ + __u32 framelines; + __u32 reserved[4]; +}; + +/* + * V I D E O I N P U T S + */ +struct v4l2_input { + __u32 index; /* Which input */ + __u8 name[32]; /* Label */ + __u32 type; /* Type of input */ + __u32 audioset; /* Associated audios (bitfield) */ + __u32 tuner; /* Associated tuner */ + v4l2_std_id std; + __u32 status; + __u32 reserved[4]; +}; + +/* Values for the 'type' field */ +#define V4L2_INPUT_TYPE_TUNER 1 +#define V4L2_INPUT_TYPE_CAMERA 2 + +/* field 'status' - general */ +#define V4L2_IN_ST_NO_POWER 0x00000001 /* Attached device is off */ +#define V4L2_IN_ST_NO_SIGNAL 0x00000002 +#define V4L2_IN_ST_NO_COLOR 0x00000004 + +/* field 'status' - analog */ +#define V4L2_IN_ST_NO_H_LOCK 0x00000100 /* No horizontal sync lock */ +#define V4L2_IN_ST_COLOR_KILL 0x00000200 /* Color killer is active */ + +/* field 'status' - digital */ +#define V4L2_IN_ST_NO_SYNC 0x00010000 /* No synchronization lock */ +#define V4L2_IN_ST_NO_EQU 0x00020000 /* No equalizer lock */ +#define V4L2_IN_ST_NO_CARRIER 0x00040000 /* Carrier recovery failed */ + +/* field 'status' - VCR and set-top box */ +#define V4L2_IN_ST_MACROVISION 0x01000000 /* Macrovision detected */ +#define V4L2_IN_ST_NO_ACCESS 0x02000000 /* Conditional access denied */ +#define V4L2_IN_ST_VTR 0x04000000 /* VTR time constant */ + +/* + * V I D E O O U T P U T S + */ +struct v4l2_output { + __u32 index; /* Which output */ + __u8 name[32]; /* Label */ + __u32 type; /* Type of output */ + __u32 audioset; /* Associated audios (bitfield) */ + __u32 modulator; /* Associated modulator */ + v4l2_std_id std; + __u32 reserved[4]; +}; +/* Values for the 'type' field */ +#define V4L2_OUTPUT_TYPE_MODULATOR 1 +#define V4L2_OUTPUT_TYPE_ANALOG 2 +#define V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY 3 + +/* + * C O N T R O L S + */ +struct v4l2_control { + __u32 id; + __s32 value; +}; + +struct v4l2_ext_control { + __u32 id; + __u32 reserved2[2]; + union { + __s32 value; + __s64 value64; + void *reserved; + }; +} __attribute__((packed)); + +struct v4l2_ext_controls { + __u32 ctrl_class; + __u32 count; + __u32 error_idx; + __u32 reserved[2]; + struct v4l2_ext_control *controls; +}; + +/* Values for ctrl_class field */ +#define V4L2_CTRL_CLASS_USER 0x00980000 /* Old-style 'user' controls */ +#define V4L2_CTRL_CLASS_MPEG 0x00990000 /* MPEG-compression controls */ + +#define V4L2_CTRL_ID_MASK (0x0fffffff) +#define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL) +#define V4L2_CTRL_DRIVER_PRIV(id) (((id) & 0xffff) >= 0x1000) + +/* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */ +struct v4l2_queryctrl { + __u32 id; + enum v4l2_ctrl_type type; + __u8 name[32]; /* Whatever */ + __s32 minimum;/* Note signedness */ + __s32 maximum; + __s32 step; + __s32 default_value; + __u32 flags; + __u32 reserved[2]; +}; + +/* Used in the VIDIOC_QUERYMENU ioctl for querying menu items */ +struct v4l2_querymenu { + __u32 id; + __u32 index; + __u8 name[32]; /* Whatever */ + __u32 reserved; +}; + +/* Control flags */ +#define V4L2_CTRL_FLAG_DISABLED 0x0001 +#define V4L2_CTRL_FLAG_GRABBED 0x0002 +#define V4L2_CTRL_FLAG_READ_ONLY 0x0004 +#define V4L2_CTRL_FLAG_UPDATE 0x0008 +#define V4L2_CTRL_FLAG_INACTIVE 0x0010 +#define V4L2_CTRL_FLAG_SLIDER 0x0020 + +/* Query flag, to be ORed with the control ID */ +#define V4L2_CTRL_FLAG_NEXT_CTRL 0x80000000 + +/* User-class control IDs defined by V4L2 */ +#define V4L2_CID_BASE (V4L2_CTRL_CLASS_USER | 0x900) +#define V4L2_CID_USER_BASE V4L2_CID_BASE +/* IDs reserved for driver specific controls */ +#define V4L2_CID_PRIVATE_BASE 0x08000000 + +#define V4L2_CID_USER_CLASS (V4L2_CTRL_CLASS_USER | 1) +#define V4L2_CID_BRIGHTNESS (V4L2_CID_BASE+0) +#define V4L2_CID_CONTRAST (V4L2_CID_BASE+1) +#define V4L2_CID_SATURATION (V4L2_CID_BASE+2) +#define V4L2_CID_HUE (V4L2_CID_BASE+3) +#define V4L2_CID_AUDIO_VOLUME (V4L2_CID_BASE+5) +#define V4L2_CID_AUDIO_BALANCE (V4L2_CID_BASE+6) +#define V4L2_CID_AUDIO_BASS (V4L2_CID_BASE+7) +#define V4L2_CID_AUDIO_TREBLE (V4L2_CID_BASE+8) +#define V4L2_CID_AUDIO_MUTE (V4L2_CID_BASE+9) +#define V4L2_CID_AUDIO_LOUDNESS (V4L2_CID_BASE+10) +#define V4L2_CID_BLACK_LEVEL (V4L2_CID_BASE+11) +#define V4L2_CID_AUTO_WHITE_BALANCE (V4L2_CID_BASE+12) +#define V4L2_CID_DO_WHITE_BALANCE (V4L2_CID_BASE+13) +#define V4L2_CID_RED_BALANCE (V4L2_CID_BASE+14) +#define V4L2_CID_BLUE_BALANCE (V4L2_CID_BASE+15) +#define V4L2_CID_GAMMA (V4L2_CID_BASE+16) +#define V4L2_CID_WHITENESS (V4L2_CID_GAMMA) /* ? Not sure */ +#define V4L2_CID_EXPOSURE (V4L2_CID_BASE+17) +#define V4L2_CID_AUTOGAIN (V4L2_CID_BASE+18) +#define V4L2_CID_GAIN (V4L2_CID_BASE+19) +#define V4L2_CID_HFLIP (V4L2_CID_BASE+20) +#define V4L2_CID_VFLIP (V4L2_CID_BASE+21) +#define V4L2_CID_HCENTER (V4L2_CID_BASE+22) +#define V4L2_CID_VCENTER (V4L2_CID_BASE+23) +#define V4L2_CID_LASTP1 (V4L2_CID_BASE+24) /* last CID + 1 */ + +/* MPEG-class control IDs defined by V4L2 */ +#define V4L2_CID_MPEG_BASE (V4L2_CTRL_CLASS_MPEG | 0x900) +#define V4L2_CID_MPEG_CLASS (V4L2_CTRL_CLASS_MPEG | 1) + +/* MPEG streams */ +#define V4L2_CID_MPEG_STREAM_TYPE (V4L2_CID_MPEG_BASE+0) +enum v4l2_mpeg_stream_type { + V4L2_MPEG_STREAM_TYPE_MPEG2_PS = 0, /* MPEG-2 program stream */ + V4L2_MPEG_STREAM_TYPE_MPEG2_TS = 1, /* MPEG-2 transport stream */ + V4L2_MPEG_STREAM_TYPE_MPEG1_SS = 2, /* MPEG-1 system stream */ + V4L2_MPEG_STREAM_TYPE_MPEG2_DVD = 3, /* MPEG-2 DVD-compatible + * stream */ + V4L2_MPEG_STREAM_TYPE_MPEG1_VCD = 4, /* MPEG-1 VCD-compatible + * stream */ + V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD = 5, /* MPEG-2 SVCD-compatible + * stream */ +}; +#define V4L2_CID_MPEG_STREAM_PID_PMT (V4L2_CID_MPEG_BASE+1) +#define V4L2_CID_MPEG_STREAM_PID_AUDIO (V4L2_CID_MPEG_BASE+2) +#define V4L2_CID_MPEG_STREAM_PID_VIDEO (V4L2_CID_MPEG_BASE+3) +#define V4L2_CID_MPEG_STREAM_PID_PCR (V4L2_CID_MPEG_BASE+4) +#define V4L2_CID_MPEG_STREAM_PES_ID_AUDIO (V4L2_CID_MPEG_BASE+5) +#define V4L2_CID_MPEG_STREAM_PES_ID_VIDEO (V4L2_CID_MPEG_BASE+6) +#define V4L2_CID_MPEG_STREAM_VBI_FMT (V4L2_CID_MPEG_BASE+7) +enum v4l2_mpeg_stream_vbi_fmt { + V4L2_MPEG_STREAM_VBI_FMT_NONE = 0, /* No VBI in the MPEG stream */ + V4L2_MPEG_STREAM_VBI_FMT_IVTV = 1, /* VBI in private packets, + * IVTV format */ +}; + +/* MPEG audio */ +#define V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ (V4L2_CID_MPEG_BASE+100) +enum v4l2_mpeg_audio_sampling_freq { + V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100 = 0, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000 = 1, + V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000 = 2, +}; +#define V4L2_CID_MPEG_AUDIO_ENCODING (V4L2_CID_MPEG_BASE+101) +enum v4l2_mpeg_audio_encoding { + V4L2_MPEG_AUDIO_ENCODING_LAYER_1 = 0, + V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1, + V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2, +}; +#define V4L2_CID_MPEG_AUDIO_L1_BITRATE (V4L2_CID_MPEG_BASE+102) +enum v4l2_mpeg_audio_l1_bitrate { + V4L2_MPEG_AUDIO_L1_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_L1_BITRATE_64K = 1, + V4L2_MPEG_AUDIO_L1_BITRATE_96K = 2, + V4L2_MPEG_AUDIO_L1_BITRATE_128K = 3, + V4L2_MPEG_AUDIO_L1_BITRATE_160K = 4, + V4L2_MPEG_AUDIO_L1_BITRATE_192K = 5, + V4L2_MPEG_AUDIO_L1_BITRATE_224K = 6, + V4L2_MPEG_AUDIO_L1_BITRATE_256K = 7, + V4L2_MPEG_AUDIO_L1_BITRATE_288K = 8, + V4L2_MPEG_AUDIO_L1_BITRATE_320K = 9, + V4L2_MPEG_AUDIO_L1_BITRATE_352K = 10, + V4L2_MPEG_AUDIO_L1_BITRATE_384K = 11, + V4L2_MPEG_AUDIO_L1_BITRATE_416K = 12, + V4L2_MPEG_AUDIO_L1_BITRATE_448K = 13, +}; +#define V4L2_CID_MPEG_AUDIO_L2_BITRATE (V4L2_CID_MPEG_BASE+103) +enum v4l2_mpeg_audio_l2_bitrate { + V4L2_MPEG_AUDIO_L2_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_L2_BITRATE_48K = 1, + V4L2_MPEG_AUDIO_L2_BITRATE_56K = 2, + V4L2_MPEG_AUDIO_L2_BITRATE_64K = 3, + V4L2_MPEG_AUDIO_L2_BITRATE_80K = 4, + V4L2_MPEG_AUDIO_L2_BITRATE_96K = 5, + V4L2_MPEG_AUDIO_L2_BITRATE_112K = 6, + V4L2_MPEG_AUDIO_L2_BITRATE_128K = 7, + V4L2_MPEG_AUDIO_L2_BITRATE_160K = 8, + V4L2_MPEG_AUDIO_L2_BITRATE_192K = 9, + V4L2_MPEG_AUDIO_L2_BITRATE_224K = 10, + V4L2_MPEG_AUDIO_L2_BITRATE_256K = 11, + V4L2_MPEG_AUDIO_L2_BITRATE_320K = 12, + V4L2_MPEG_AUDIO_L2_BITRATE_384K = 13, +}; +#define V4L2_CID_MPEG_AUDIO_L3_BITRATE (V4L2_CID_MPEG_BASE+104) +enum v4l2_mpeg_audio_l3_bitrate { + V4L2_MPEG_AUDIO_L3_BITRATE_32K = 0, + V4L2_MPEG_AUDIO_L3_BITRATE_40K = 1, + V4L2_MPEG_AUDIO_L3_BITRATE_48K = 2, + V4L2_MPEG_AUDIO_L3_BITRATE_56K = 3, + V4L2_MPEG_AUDIO_L3_BITRATE_64K = 4, + V4L2_MPEG_AUDIO_L3_BITRATE_80K = 5, + V4L2_MPEG_AUDIO_L3_BITRATE_96K = 6, + V4L2_MPEG_AUDIO_L3_BITRATE_112K = 7, + V4L2_MPEG_AUDIO_L3_BITRATE_128K = 8, + V4L2_MPEG_AUDIO_L3_BITRATE_160K = 9, + V4L2_MPEG_AUDIO_L3_BITRATE_192K = 10, + V4L2_MPEG_AUDIO_L3_BITRATE_224K = 11, + V4L2_MPEG_AUDIO_L3_BITRATE_256K = 12, + V4L2_MPEG_AUDIO_L3_BITRATE_320K = 13, +}; +#define V4L2_CID_MPEG_AUDIO_MODE (V4L2_CID_MPEG_BASE+105) +enum v4l2_mpeg_audio_mode { + V4L2_MPEG_AUDIO_MODE_STEREO = 0, + V4L2_MPEG_AUDIO_MODE_JOINT_STEREO = 1, + V4L2_MPEG_AUDIO_MODE_DUAL = 2, + V4L2_MPEG_AUDIO_MODE_MONO = 3, +}; +#define V4L2_CID_MPEG_AUDIO_MODE_EXTENSION (V4L2_CID_MPEG_BASE+106) +enum v4l2_mpeg_audio_mode_extension { + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4 = 0, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_8 = 1, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_12 = 2, + V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16 = 3, +}; +#define V4L2_CID_MPEG_AUDIO_EMPHASIS (V4L2_CID_MPEG_BASE+107) +enum v4l2_mpeg_audio_emphasis { + V4L2_MPEG_AUDIO_EMPHASIS_NONE = 0, + V4L2_MPEG_AUDIO_EMPHASIS_50_DIV_15_uS = 1, + V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17 = 2, +}; +#define V4L2_CID_MPEG_AUDIO_CRC (V4L2_CID_MPEG_BASE+108) +enum v4l2_mpeg_audio_crc { + V4L2_MPEG_AUDIO_CRC_NONE = 0, + V4L2_MPEG_AUDIO_CRC_CRC16 = 1, +}; +#define V4L2_CID_MPEG_AUDIO_MUTE (V4L2_CID_MPEG_BASE+109) + +/* MPEG video */ +#define V4L2_CID_MPEG_VIDEO_ENCODING (V4L2_CID_MPEG_BASE+200) +enum v4l2_mpeg_video_encoding { + V4L2_MPEG_VIDEO_ENCODING_MPEG_1 = 0, + V4L2_MPEG_VIDEO_ENCODING_MPEG_2 = 1, +}; +#define V4L2_CID_MPEG_VIDEO_ASPECT (V4L2_CID_MPEG_BASE+201) +enum v4l2_mpeg_video_aspect { + V4L2_MPEG_VIDEO_ASPECT_1x1 = 0, + V4L2_MPEG_VIDEO_ASPECT_4x3 = 1, + V4L2_MPEG_VIDEO_ASPECT_16x9 = 2, + V4L2_MPEG_VIDEO_ASPECT_221x100 = 3, +}; +#define V4L2_CID_MPEG_VIDEO_B_FRAMES (V4L2_CID_MPEG_BASE+202) +#define V4L2_CID_MPEG_VIDEO_GOP_SIZE (V4L2_CID_MPEG_BASE+203) +#define V4L2_CID_MPEG_VIDEO_GOP_CLOSURE (V4L2_CID_MPEG_BASE+204) +#define V4L2_CID_MPEG_VIDEO_PULLDOWN (V4L2_CID_MPEG_BASE+205) +#define V4L2_CID_MPEG_VIDEO_BITRATE_MODE (V4L2_CID_MPEG_BASE+206) +enum v4l2_mpeg_video_bitrate_mode { + V4L2_MPEG_VIDEO_BITRATE_MODE_VBR = 0, + V4L2_MPEG_VIDEO_BITRATE_MODE_CBR = 1, +}; +#define V4L2_CID_MPEG_VIDEO_BITRATE (V4L2_CID_MPEG_BASE+207) +#define V4L2_CID_MPEG_VIDEO_BITRATE_PEAK (V4L2_CID_MPEG_BASE+208) +#define V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION (V4L2_CID_MPEG_BASE+209) +#define V4L2_CID_MPEG_VIDEO_MUTE (V4L2_CID_MPEG_BASE+210) +#define V4L2_CID_MPEG_VIDEO_MUTE_YUV (V4L2_CID_MPEG_BASE+211) + +/* MPEG-class control IDs specific to the CX2584x driver as defined by V4L2 */ +#define V4L2_CID_MPEG_CX2341X_BASE (V4L2_CTRL_CLASS_MPEG | 0x1000) +#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE (V4L2_CID_MPEG_CX2341X_BASE+0) +enum v4l2_mpeg_cx2341x_video_spatial_filter_mode { + V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL = 0, + V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO = 1, +}; +#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER (V4L2_CID_MPEG_CX2341X_BASE+1) +#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+2) +enum v4l2_mpeg_cx2341x_video_luma_spatial_filter_type { + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF = 0, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR = 1, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_VERT = 2, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_HV_SEPARABLE = 3, + V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE = 4, +}; +#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+3) +enum v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type { + V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF = 0, + V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR = 1, +}; +#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE (V4L2_CID_MPEG_CX2341X_BASE+4) +enum v4l2_mpeg_cx2341x_video_temporal_filter_mode { + V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL = 0, + V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO = 1, +}; +#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER (V4L2_CID_MPEG_CX2341X_BASE+5) +#define V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE (V4L2_CID_MPEG_CX2341X_BASE+6) +enum v4l2_mpeg_cx2341x_video_median_filter_type { + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF = 0, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR = 1, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_VERT = 2, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR_VERT = 3, + V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG = 4, +}; +#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM (V4L2_CID_MPEG_CX2341X_BASE+7) +#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP (V4L2_CID_MPEG_CX2341X_BASE+8) +#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM (V4L2_CID_MPEG_CX2341X_BASE+9) +#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP (V4L2_CID_MPEG_CX2341X_BASE+10) +#define V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS (V4L2_CID_MPEG_CX2341X_BASE+11) + +/* + * T U N I N G + */ +struct v4l2_tuner { + __u32 index; + __u8 name[32]; + enum v4l2_tuner_type type; + __u32 capability; + __u32 rangelow; + __u32 rangehigh; + __u32 rxsubchans; + __u32 audmode; + __s32 signal; + __s32 afc; + __u32 reserved[4]; +}; + +struct v4l2_modulator { + __u32 index; + __u8 name[32]; + __u32 capability; + __u32 rangelow; + __u32 rangehigh; + __u32 txsubchans; + __u32 reserved[4]; +}; + +/* Flags for the 'capability' field */ +#define V4L2_TUNER_CAP_LOW 0x0001 +#define V4L2_TUNER_CAP_NORM 0x0002 +#define V4L2_TUNER_CAP_STEREO 0x0010 +#define V4L2_TUNER_CAP_LANG2 0x0020 +#define V4L2_TUNER_CAP_SAP 0x0020 +#define V4L2_TUNER_CAP_LANG1 0x0040 + +/* Flags for the 'rxsubchans' field */ +#define V4L2_TUNER_SUB_MONO 0x0001 +#define V4L2_TUNER_SUB_STEREO 0x0002 +#define V4L2_TUNER_SUB_LANG2 0x0004 +#define V4L2_TUNER_SUB_SAP 0x0004 +#define V4L2_TUNER_SUB_LANG1 0x0008 + +/* Values for the 'audmode' field */ +#define V4L2_TUNER_MODE_MONO 0x0000 +#define V4L2_TUNER_MODE_STEREO 0x0001 +#define V4L2_TUNER_MODE_LANG2 0x0002 +#define V4L2_TUNER_MODE_SAP 0x0002 +#define V4L2_TUNER_MODE_LANG1 0x0003 +#define V4L2_TUNER_MODE_LANG1_LANG2 0x0004 + +struct v4l2_frequency { + __u32 tuner; + enum v4l2_tuner_type type; + __u32 frequency; + __u32 reserved[8]; +}; + +/* + * A U D I O + */ +struct v4l2_audio { + __u32 index; + __u8 name[32]; + __u32 capability; + __u32 mode; + __u32 reserved[2]; +}; + +/* Flags for the 'capability' field */ +#define V4L2_AUDCAP_STEREO 0x00001 +#define V4L2_AUDCAP_AVL 0x00002 + +/* Flags for the 'mode' field */ +#define V4L2_AUDMODE_AVL 0x00001 + +struct v4l2_audioout { + __u32 index; + __u8 name[32]; + __u32 capability; + __u32 mode; + __u32 reserved[2]; +}; + +/* + * M P E G S E R V I C E S + * + * NOTE: EXPERIMENTAL API + */ +#if 1 /* KEEP */ +#define V4L2_ENC_IDX_FRAME_I (0) +#define V4L2_ENC_IDX_FRAME_P (1) +#define V4L2_ENC_IDX_FRAME_B (2) +#define V4L2_ENC_IDX_FRAME_MASK (0xf) + +struct v4l2_enc_idx_entry { + __u64 offset; + __u64 pts; + __u32 length; + __u32 flags; + __u32 reserved[2]; +}; + +#define V4L2_ENC_IDX_ENTRIES (64) +struct v4l2_enc_idx { + __u32 entries; + __u32 entries_cap; + __u32 reserved[4]; + struct v4l2_enc_idx_entry entry[V4L2_ENC_IDX_ENTRIES]; +}; + + +#define V4L2_ENC_CMD_START (0) +#define V4L2_ENC_CMD_STOP (1) +#define V4L2_ENC_CMD_PAUSE (2) +#define V4L2_ENC_CMD_RESUME (3) + +/* Flags for V4L2_ENC_CMD_STOP */ +#define V4L2_ENC_CMD_STOP_AT_GOP_END (1 << 0) + +struct v4l2_encoder_cmd { + __u32 cmd; + __u32 flags; + union { + struct { + __u32 data[8]; + } raw; + }; +}; + +#endif + + +/* + * D A T A S E R V I C E S ( V B I ) + * + * Data services API by Michael Schimek + */ + +/* Raw VBI */ +struct v4l2_vbi_format { + __u32 sampling_rate; /* in 1 Hz */ + __u32 offset; + __u32 samples_per_line; + __u32 sample_format; /* V4L2_PIX_FMT_* */ + __s32 start[2]; + __u32 count[2]; + __u32 flags; /* V4L2_VBI_* */ + __u32 reserved[2]; /* must be zero */ +}; + +/* VBI flags */ +#define V4L2_VBI_UNSYNC (1<< 0) +#define V4L2_VBI_INTERLACED (1<< 1) + +/* + * Sliced VBI + * + * This implements is a proposal V4L2 API to allow SLICED VBI required for some + * hardware encoders. It should change without notice in the definitive + * implementation. + */ + +struct v4l2_sliced_vbi_format { + __u16 service_set; + /* + * service_lines[0][...] specifies lines 0-23 (1-23 used) of the + * first field service_lines[1][...] specifies lines 0-23 (1-23 used) + * of the second field (equals frame lines 313-336 for 625 line video + * standards, 263-286 for 525 line standards) + */ + __u16 service_lines[2][24]; + __u32 io_size; + __u32 reserved[2]; /* must be zero */ +}; + +/* + * Teletext World System Teletext (WST), defined on ITU-R BT.653-2 + */ +#define V4L2_SLICED_TELETEXT_B (0x0001) +/* Video Program System, defined on ETS 300 231 */ +#define V4L2_SLICED_VPS (0x0400) +/* Closed Caption, defined on EIA-608 */ +#define V4L2_SLICED_CAPTION_525 (0x1000) +/* Wide Screen System, defined on ITU-R BT1119.1 */ +#define V4L2_SLICED_WSS_625 (0x4000) + +#define V4L2_SLICED_VBI_525 (V4L2_SLICED_CAPTION_525) +#define V4L2_SLICED_VBI_625 (V4L2_SLICED_TELETEXT_B | V4L2_SLICED_VPS | V4L2_SLICED_WSS_625) + +struct v4l2_sliced_vbi_cap { + __u16 service_set; + /* + * service_lines[0][...] specifies lines 0-23 (1-23 used) of the + * first field service_lines[1][...] specifies lines 0-23 (1-23 used) + * of the second field (equals frame lines 313-336 for 625 line video + * standards, 263-286 for 525 line standards) + */ + __u16 service_lines[2][24]; + enum v4l2_buf_type type; + __u32 reserved[3]; /* must be 0 */ +}; + +struct v4l2_sliced_vbi_data { + __u32 id; + __u32 field; /* 0: first field, 1: second field */ + __u32 line; /* 1-23 */ + __u32 reserved; /* must be 0 */ + __u8 data[48]; +}; + +/* + * A G G R E G A T E S T R U C T U R E S + */ + +/* + * Stream data format + */ +struct v4l2_format { + enum v4l2_buf_type type; + union { + struct v4l2_pix_format pix; + //V4L2_BUF_TYPE_VIDEO_CAPTURE + struct v4l2_window win; + //V4L2_BUF_TYPE_VIDEO_OVERLAY + struct v4l2_vbi_format vbi; + //V4L2_BUF_TYPE_VBI_CAPTURE + struct v4l2_sliced_vbi_format sliced; + //V4L2_BUF_TYPE_SLICED_VBI_CAPTURE + __u8 raw_data[200]; + //user - defined + } fmt; +}; + + +/* + * Stream type-dependent parameters + */ +struct v4l2_streamparm { + enum v4l2_buf_type type; + union { + struct v4l2_captureparm capture; + struct v4l2_outputparm output; + __u8 raw_data[200]; /* user-defined */ + } parm; +}; + +/* + * A D V A N C E D D E B U G G I N G + * + * NOTE: EXPERIMENTAL API + */ + +/* VIDIOC_DBG_G_REGISTER and VIDIOC_DBG_S_REGISTER */ + +#define V4L2_CHIP_MATCH_HOST 0 /* Match against chip ID on host (0 + * for the host) */ +#define V4L2_CHIP_MATCH_I2C_DRIVER 1 /* Match against I2C driver ID */ +#define V4L2_CHIP_MATCH_I2C_ADDR 2 /* Match against I2C 7-bit address */ + +struct v4l2_register { + __u32 match_type; /* Match type */ + __u32 match_chip; /* Match this chip, meaning + * determined by match_type */ + __u64 reg; + __u64 val; +}; + +/* VIDIOC_G_CHIP_IDENT */ +struct v4l2_chip_ident { + __u32 match_type; /* Match type */ + __u32 match_chip; /* Match this chip, meaning + * determined by match_type */ + __u32 ident; /* chip identifier as specified in + * <media/v4l2-chip-ident.h> */ + __u32 revision; /* chip revision, chip specific */ +}; + +/* + * I O C T L C O D E S F O R V I D E O D E V I C E S + * + */ +#define VIDIOC_QUERYCAP _IOR ('V', 0, struct v4l2_capability) +#define VIDIOC_RESERVED _IO ('V', 1) +#define VIDIOC_ENUM_FMT _IOWR ('V', 2, struct v4l2_fmtdesc) +#define VIDIOC_G_FMT _IOWR ('V', 4, struct v4l2_format) +#define VIDIOC_S_FMT _IOWR ('V', 5, struct v4l2_format) +#ifdef __KERNEL__ +#define VIDIOC_G_MPEGCOMP _IOR ('V', 6, struct v4l2_mpeg_compression) +#define VIDIOC_S_MPEGCOMP _IOW ('V', 7, struct v4l2_mpeg_compression) +#endif +#define VIDIOC_REQBUFS _IOWR ('V', 8, struct v4l2_requestbuffers) +#define VIDIOC_QUERYBUF _IOWR ('V', 9, struct v4l2_buffer) +#define VIDIOC_G_FBUF _IOR ('V', 10, struct v4l2_framebuffer) +#define VIDIOC_S_FBUF _IOW ('V', 11, struct v4l2_framebuffer) +#define VIDIOC_OVERLAY _IOW ('V', 14, int) +#define VIDIOC_QBUF _IOWR ('V', 15, struct v4l2_buffer) +#define VIDIOC_DQBUF _IOWR ('V', 17, struct v4l2_buffer) +#define VIDIOC_STREAMON _IOW ('V', 18, int) +#define VIDIOC_STREAMOFF _IOW ('V', 19, int) +#define VIDIOC_G_PARM _IOWR ('V', 21, struct v4l2_streamparm) +#define VIDIOC_S_PARM _IOWR ('V', 22, struct v4l2_streamparm) +#define VIDIOC_G_STD _IOR ('V', 23, v4l2_std_id) +#define VIDIOC_S_STD _IOW ('V', 24, v4l2_std_id) +#define VIDIOC_ENUMSTD _IOWR ('V', 25, struct v4l2_standard) +#define VIDIOC_ENUMINPUT _IOWR ('V', 26, struct v4l2_input) +#define VIDIOC_G_CTRL _IOWR ('V', 27, struct v4l2_control) +#define VIDIOC_S_CTRL _IOWR ('V', 28, struct v4l2_control) +#define VIDIOC_G_TUNER _IOWR ('V', 29, struct v4l2_tuner) +#define VIDIOC_S_TUNER _IOW ('V', 30, struct v4l2_tuner) +#define VIDIOC_G_AUDIO _IOR ('V', 33, struct v4l2_audio) +#define VIDIOC_S_AUDIO _IOW ('V', 34, struct v4l2_audio) +#define VIDIOC_QUERYCTRL _IOWR ('V', 36, struct v4l2_queryctrl) +#define VIDIOC_QUERYMENU _IOWR ('V', 37, struct v4l2_querymenu) +#define VIDIOC_G_INPUT _IOR ('V', 38, int) +#define VIDIOC_S_INPUT _IOWR ('V', 39, int) +#define VIDIOC_G_OUTPUT _IOR ('V', 46, int) +#define VIDIOC_S_OUTPUT _IOWR ('V', 47, int) +#define VIDIOC_ENUMOUTPUT _IOWR ('V', 48, struct v4l2_output) +#define VIDIOC_G_AUDOUT _IOR ('V', 49, struct v4l2_audioout) +#define VIDIOC_S_AUDOUT _IOW ('V', 50, struct v4l2_audioout) +#define VIDIOC_G_MODULATOR _IOWR ('V', 54, struct v4l2_modulator) +#define VIDIOC_S_MODULATOR _IOW ('V', 55, struct v4l2_modulator) +#define VIDIOC_G_FREQUENCY _IOWR ('V', 56, struct v4l2_frequency) +#define VIDIOC_S_FREQUENCY _IOW ('V', 57, struct v4l2_frequency) +#define VIDIOC_CROPCAP _IOWR ('V', 58, struct v4l2_cropcap) +#define VIDIOC_G_CROP _IOWR ('V', 59, struct v4l2_crop) +#define VIDIOC_S_CROP _IOW ('V', 60, struct v4l2_crop) +#define VIDIOC_G_JPEGCOMP _IOR ('V', 61, struct v4l2_jpegcompression) +#define VIDIOC_S_JPEGCOMP _IOW ('V', 62, struct v4l2_jpegcompression) +#define VIDIOC_QUERYSTD _IOR ('V', 63, v4l2_std_id) +#define VIDIOC_TRY_FMT _IOWR ('V', 64, struct v4l2_format) +#define VIDIOC_ENUMAUDIO _IOWR ('V', 65, struct v4l2_audio) +#define VIDIOC_ENUMAUDOUT _IOWR ('V', 66, struct v4l2_audioout) +#define VIDIOC_G_PRIORITY _IOR ('V', 67, enum v4l2_priority) +#define VIDIOC_S_PRIORITY _IOW ('V', 68, enum v4l2_priority) +#define VIDIOC_G_SLICED_VBI_CAP _IOWR ('V', 69, struct v4l2_sliced_vbi_cap) +#define VIDIOC_LOG_STATUS _IO ('V', 70) +#define VIDIOC_G_EXT_CTRLS _IOWR ('V', 71, struct v4l2_ext_controls) +#define VIDIOC_S_EXT_CTRLS _IOWR ('V', 72, struct v4l2_ext_controls) +#define VIDIOC_TRY_EXT_CTRLS _IOWR ('V', 73, struct v4l2_ext_controls) +#if 1 /* KEEP */ +#define VIDIOC_ENUM_FRAMESIZES _IOWR ('V', 74, struct v4l2_frmsizeenum) +#define VIDIOC_ENUM_FRAMEINTERVALS _IOWR ('V', 75, struct v4l2_frmivalenum) +#define VIDIOC_G_ENC_INDEX _IOR ('V', 76, struct v4l2_enc_idx) +#define VIDIOC_ENCODER_CMD _IOWR ('V', 77, struct v4l2_encoder_cmd) +#define VIDIOC_TRY_ENCODER_CMD _IOWR ('V', 78, struct v4l2_encoder_cmd) + +/* Experimental, only implemented if CONFIG_VIDEO_ADV_DEBUG is defined */ +#define VIDIOC_DBG_S_REGISTER _IOW ('V', 79, struct v4l2_register) +#define VIDIOC_DBG_G_REGISTER _IOWR ('V', 80, struct v4l2_register) + +#define VIDIOC_G_CHIP_IDENT _IOWR ('V', 81, struct v4l2_chip_ident) +#endif + +#ifdef __OLD_VIDIOC_ +/* for compatibility, will go away some day */ +#define VIDIOC_OVERLAY_OLD _IOWR ('V', 14, int) +#define VIDIOC_S_PARM_OLD _IOW ('V', 22, struct v4l2_streamparm) +#define VIDIOC_S_CTRL_OLD _IOW ('V', 28, struct v4l2_control) +#define VIDIOC_G_AUDIO_OLD _IOWR ('V', 33, struct v4l2_audio) +#define VIDIOC_G_AUDOUT_OLD _IOWR ('V', 49, struct v4l2_audioout) +#define VIDIOC_CROPCAP_OLD _IOR ('V', 58, struct v4l2_cropcap) +#endif + +#define BASE_VIDIOC_PRIVATE 192 /* 192-255 are private */ + +#endif /* _SYS_VIDEOIO_H */ |