1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021 |
- /*
- *
- * Video for Linux Two
- * Backward Compatibility Layer
- *
- * Support subroutines for providing V4L2 drivers with backward
- * compatibility with applications using the old API.
- *
- * 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.
- *
- * Author: Bill Dirks <bdirks@pacbell.net>
- * et al.
- *
- */
- #include <linux/config.h>
- #include <linux/init.h>
- #include <linux/module.h>
- #include <linux/moduleparam.h>
- #include <linux/types.h>
- #include <linux/kernel.h>
- #include <linux/sched.h>
- #include <linux/smp_lock.h>
- #include <linux/mm.h>
- #include <linux/fs.h>
- #include <linux/file.h>
- #include <linux/string.h>
- #include <linux/errno.h>
- #include <linux/slab.h>
- #include <linux/videodev.h>
- #include <asm/uaccess.h>
- #include <asm/system.h>
- #include <asm/pgtable.h>
- #ifdef CONFIG_KMOD
- #include <linux/kmod.h>
- #endif
- static unsigned int debug = 0;
- module_param(debug, int, 0644);
- MODULE_PARM_DESC(debug,"enable debug messages");
- MODULE_AUTHOR("Bill Dirks");
- MODULE_DESCRIPTION("v4l(1) compatibility layer for v4l2 drivers.");
- MODULE_LICENSE("GPL");
- #define dprintk(fmt, arg...) if (debug) \
- printk(KERN_DEBUG "v4l1-compat: " fmt , ## arg)
- /*
- * I O C T L T R A N S L A T I O N
- *
- * From here on down is the code for translating the numerous
- * ioctl commands from the old API to the new API.
- */
- static int
- get_v4l_control(struct inode *inode,
- struct file *file,
- int cid,
- v4l2_kioctl drv)
- {
- struct v4l2_queryctrl qctrl2;
- struct v4l2_control ctrl2;
- int err;
- qctrl2.id = cid;
- err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);
- if (err < 0)
- dprintk("VIDIOC_QUERYCTRL: %d\n",err);
- if (err == 0 &&
- !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
- {
- ctrl2.id = qctrl2.id;
- err = drv(inode, file, VIDIOC_G_CTRL, &ctrl2);
- if (err < 0) {
- dprintk("VIDIOC_G_CTRL: %d\n",err);
- return 0;
- }
- return ((ctrl2.value - qctrl2.minimum) * 65535
- + (qctrl2.maximum - qctrl2.minimum) / 2)
- / (qctrl2.maximum - qctrl2.minimum);
- }
- return 0;
- }
- static int
- set_v4l_control(struct inode *inode,
- struct file *file,
- int cid,
- int value,
- v4l2_kioctl drv)
- {
- struct v4l2_queryctrl qctrl2;
- struct v4l2_control ctrl2;
- int err;
- qctrl2.id = cid;
- err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);
- if (err < 0)
- dprintk("VIDIOC_QUERYCTRL: %d\n",err);
- if (err == 0 &&
- !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED) &&
- !(qctrl2.flags & V4L2_CTRL_FLAG_GRABBED))
- {
- if (value < 0)
- value = 0;
- if (value > 65535)
- value = 65535;
- if (value && qctrl2.type == V4L2_CTRL_TYPE_BOOLEAN)
- value = 65535;
- ctrl2.id = qctrl2.id;
- ctrl2.value =
- (value * (qctrl2.maximum - qctrl2.minimum)
- + 32767)
- / 65535;
- ctrl2.value += qctrl2.minimum;
- err = drv(inode, file, VIDIOC_S_CTRL, &ctrl2);
- if (err < 0)
- dprintk("VIDIOC_S_CTRL: %d\n",err);
- }
- return 0;
- }
- /* ----------------------------------------------------------------- */
- static int palette2pixelformat[] = {
- [VIDEO_PALETTE_GREY] = V4L2_PIX_FMT_GREY,
- [VIDEO_PALETTE_RGB555] = V4L2_PIX_FMT_RGB555,
- [VIDEO_PALETTE_RGB565] = V4L2_PIX_FMT_RGB565,
- [VIDEO_PALETTE_RGB24] = V4L2_PIX_FMT_BGR24,
- [VIDEO_PALETTE_RGB32] = V4L2_PIX_FMT_BGR32,
- /* yuv packed pixel */
- [VIDEO_PALETTE_YUYV] = V4L2_PIX_FMT_YUYV,
- [VIDEO_PALETTE_YUV422] = V4L2_PIX_FMT_YUYV,
- [VIDEO_PALETTE_UYVY] = V4L2_PIX_FMT_UYVY,
- /* yuv planar */
- [VIDEO_PALETTE_YUV410P] = V4L2_PIX_FMT_YUV410,
- [VIDEO_PALETTE_YUV420] = V4L2_PIX_FMT_YUV420,
- [VIDEO_PALETTE_YUV420P] = V4L2_PIX_FMT_YUV420,
- [VIDEO_PALETTE_YUV411P] = V4L2_PIX_FMT_YUV411P,
- [VIDEO_PALETTE_YUV422P] = V4L2_PIX_FMT_YUV422P,
- };
- static unsigned int
- palette_to_pixelformat(unsigned int palette)
- {
- if (palette < ARRAY_SIZE(palette2pixelformat))
- return palette2pixelformat[palette];
- else
- return 0;
- }
- static unsigned int
- pixelformat_to_palette(int pixelformat)
- {
- int palette = 0;
- switch (pixelformat)
- {
- case V4L2_PIX_FMT_GREY:
- palette = VIDEO_PALETTE_GREY;
- break;
- case V4L2_PIX_FMT_RGB555:
- palette = VIDEO_PALETTE_RGB555;
- break;
- case V4L2_PIX_FMT_RGB565:
- palette = VIDEO_PALETTE_RGB565;
- break;
- case V4L2_PIX_FMT_BGR24:
- palette = VIDEO_PALETTE_RGB24;
- break;
- case V4L2_PIX_FMT_BGR32:
- palette = VIDEO_PALETTE_RGB32;
- break;
- /* yuv packed pixel */
- case V4L2_PIX_FMT_YUYV:
- palette = VIDEO_PALETTE_YUYV;
- break;
- case V4L2_PIX_FMT_UYVY:
- palette = VIDEO_PALETTE_UYVY;
- break;
- /* yuv planar */
- case V4L2_PIX_FMT_YUV410:
- palette = VIDEO_PALETTE_YUV420;
- break;
- case V4L2_PIX_FMT_YUV420:
- palette = VIDEO_PALETTE_YUV420;
- break;
- case V4L2_PIX_FMT_YUV411P:
- palette = VIDEO_PALETTE_YUV411P;
- break;
- case V4L2_PIX_FMT_YUV422P:
- palette = VIDEO_PALETTE_YUV422P;
- break;
- }
- return palette;
- }
- /* ----------------------------------------------------------------- */
- static int poll_one(struct file *file)
- {
- int retval = 1;
- poll_table *table;
- struct poll_wqueues pwq;
- poll_initwait(&pwq);
- table = &pwq.pt;
- for (;;) {
- int mask;
- set_current_state(TASK_INTERRUPTIBLE);
- mask = file->f_op->poll(file, table);
- if (mask & POLLIN)
- break;
- table = NULL;
- if (signal_pending(current)) {
- retval = -ERESTARTSYS;
- break;
- }
- schedule();
- }
- set_current_state(TASK_RUNNING);
- poll_freewait(&pwq);
- return retval;
- }
- static int count_inputs(struct inode *inode,
- struct file *file,
- v4l2_kioctl drv)
- {
- struct v4l2_input input2;
- int i;
- for (i = 0;; i++) {
- memset(&input2,0,sizeof(input2));
- input2.index = i;
- if (0 != drv(inode,file,VIDIOC_ENUMINPUT, &input2))
- break;
- }
- return i;
- }
- static int check_size(struct inode *inode,
- struct file *file,
- v4l2_kioctl drv,
- int *maxw, int *maxh)
- {
- struct v4l2_fmtdesc desc2;
- struct v4l2_format fmt2;
- memset(&desc2,0,sizeof(desc2));
- memset(&fmt2,0,sizeof(fmt2));
- desc2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- if (0 != drv(inode,file,VIDIOC_ENUM_FMT, &desc2))
- goto done;
- fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- fmt2.fmt.pix.width = 10000;
- fmt2.fmt.pix.height = 10000;
- fmt2.fmt.pix.pixelformat = desc2.pixelformat;
- if (0 != drv(inode,file,VIDIOC_TRY_FMT, &fmt2))
- goto done;
- *maxw = fmt2.fmt.pix.width;
- *maxh = fmt2.fmt.pix.height;
- done:
- return 0;
- }
- /* ----------------------------------------------------------------- */
- /*
- * This function is exported.
- */
- int
- v4l_compat_translate_ioctl(struct inode *inode,
- struct file *file,
- int cmd,
- void *arg,
- v4l2_kioctl drv)
- {
- struct v4l2_capability *cap2 = NULL;
- struct v4l2_format *fmt2 = NULL;
- enum v4l2_buf_type captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- struct v4l2_framebuffer fbuf2;
- struct v4l2_input input2;
- struct v4l2_tuner tun2;
- struct v4l2_standard std2;
- struct v4l2_frequency freq2;
- struct v4l2_audio aud2;
- struct v4l2_queryctrl qctrl2;
- struct v4l2_buffer buf2;
- v4l2_std_id sid;
- int i, err = 0;
- switch (cmd) {
- case VIDIOCGCAP: /* capability */
- {
- struct video_capability *cap = arg;
- cap2 = kzalloc(sizeof(*cap2),GFP_KERNEL);
- memset(cap, 0, sizeof(*cap));
- memset(&fbuf2, 0, sizeof(fbuf2));
- err = drv(inode, file, VIDIOC_QUERYCAP, cap2);
- if (err < 0) {
- dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n",err);
- break;
- }
- if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {
- err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
- if (err < 0) {
- dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n",err);
- memset(&fbuf2, 0, sizeof(fbuf2));
- }
- err = 0;
- }
- memcpy(cap->name, cap2->card,
- min(sizeof(cap->name), sizeof(cap2->card)));
- cap->name[sizeof(cap->name) - 1] = 0;
- if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE)
- cap->type |= VID_TYPE_CAPTURE;
- if (cap2->capabilities & V4L2_CAP_TUNER)
- cap->type |= VID_TYPE_TUNER;
- if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE)
- cap->type |= VID_TYPE_TELETEXT;
- if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY)
- cap->type |= VID_TYPE_OVERLAY;
- if (fbuf2.capability & V4L2_FBUF_CAP_LIST_CLIPPING)
- cap->type |= VID_TYPE_CLIPPING;
- cap->channels = count_inputs(inode,file,drv);
- check_size(inode,file,drv,
- &cap->maxwidth,&cap->maxheight);
- cap->audios = 0; /* FIXME */
- cap->minwidth = 48; /* FIXME */
- cap->minheight = 32; /* FIXME */
- break;
- }
- case VIDIOCGFBUF: /* get frame buffer */
- {
- struct video_buffer *buffer = arg;
- err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
- if (err < 0) {
- dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n",err);
- break;
- }
- buffer->base = fbuf2.base;
- buffer->height = fbuf2.fmt.height;
- buffer->width = fbuf2.fmt.width;
- switch (fbuf2.fmt.pixelformat) {
- case V4L2_PIX_FMT_RGB332:
- buffer->depth = 8;
- break;
- case V4L2_PIX_FMT_RGB555:
- buffer->depth = 15;
- break;
- case V4L2_PIX_FMT_RGB565:
- buffer->depth = 16;
- break;
- case V4L2_PIX_FMT_BGR24:
- buffer->depth = 24;
- break;
- case V4L2_PIX_FMT_BGR32:
- buffer->depth = 32;
- break;
- default:
- buffer->depth = 0;
- }
- if (0 != fbuf2.fmt.bytesperline)
- buffer->bytesperline = fbuf2.fmt.bytesperline;
- else {
- buffer->bytesperline =
- (buffer->width * buffer->depth + 7) & 7;
- buffer->bytesperline >>= 3;
- }
- break;
- }
- case VIDIOCSFBUF: /* set frame buffer */
- {
- struct video_buffer *buffer = arg;
- memset(&fbuf2, 0, sizeof(fbuf2));
- fbuf2.base = buffer->base;
- fbuf2.fmt.height = buffer->height;
- fbuf2.fmt.width = buffer->width;
- switch (buffer->depth) {
- case 8:
- fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB332;
- break;
- case 15:
- fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB555;
- break;
- case 16:
- fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
- break;
- case 24:
- fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR24;
- break;
- case 32:
- fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR32;
- break;
- }
- fbuf2.fmt.bytesperline = buffer->bytesperline;
- err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
- if (err < 0)
- dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n",err);
- break;
- }
- case VIDIOCGWIN: /* get window or capture dimensions */
- {
- struct video_window *win = arg;
- fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
- memset(win,0,sizeof(*win));
- fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
- err = drv(inode, file, VIDIOC_G_FMT, fmt2);
- if (err < 0)
- dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n",err);
- if (err == 0) {
- win->x = fmt2->fmt.win.w.left;
- win->y = fmt2->fmt.win.w.top;
- win->width = fmt2->fmt.win.w.width;
- win->height = fmt2->fmt.win.w.height;
- win->chromakey = fmt2->fmt.win.chromakey;
- win->clips = NULL;
- win->clipcount = 0;
- break;
- }
- fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_G_FMT, fmt2);
- if (err < 0) {
- dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n",err);
- break;
- }
- win->x = 0;
- win->y = 0;
- win->width = fmt2->fmt.pix.width;
- win->height = fmt2->fmt.pix.height;
- win->chromakey = 0;
- win->clips = NULL;
- win->clipcount = 0;
- break;
- }
- case VIDIOCSWIN: /* set window and/or capture dimensions */
- {
- struct video_window *win = arg;
- int err1,err2;
- fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
- fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- drv(inode, file, VIDIOC_STREAMOFF, &fmt2->type);
- err1 = drv(inode, file, VIDIOC_G_FMT, fmt2);
- if (err1 < 0)
- dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n",err);
- if (err1 == 0) {
- fmt2->fmt.pix.width = win->width;
- fmt2->fmt.pix.height = win->height;
- fmt2->fmt.pix.field = V4L2_FIELD_ANY;
- fmt2->fmt.pix.bytesperline = 0;
- err = drv(inode, file, VIDIOC_S_FMT, fmt2);
- if (err < 0)
- dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n",
- err);
- win->width = fmt2->fmt.pix.width;
- win->height = fmt2->fmt.pix.height;
- }
- memset(fmt2,0,sizeof(*fmt2));
- fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
- fmt2->fmt.win.w.left = win->x;
- fmt2->fmt.win.w.top = win->y;
- fmt2->fmt.win.w.width = win->width;
- fmt2->fmt.win.w.height = win->height;
- fmt2->fmt.win.chromakey = win->chromakey;
- fmt2->fmt.win.clips = (void __user *)win->clips;
- fmt2->fmt.win.clipcount = win->clipcount;
- err2 = drv(inode, file, VIDIOC_S_FMT, fmt2);
- if (err2 < 0)
- dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n",err);
- if (err1 != 0 && err2 != 0)
- err = err1;
- break;
- }
- case VIDIOCCAPTURE: /* turn on/off preview */
- {
- int *on = arg;
- if (0 == *on) {
- /* dirty hack time. But v4l1 has no STREAMOFF
- * equivalent in the API, and this one at
- * least comes close ... */
- drv(inode, file, VIDIOC_STREAMOFF, &captype);
- }
- err = drv(inode, file, VIDIOC_OVERLAY, arg);
- if (err < 0)
- dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n",err);
- break;
- }
- case VIDIOCGCHAN: /* get input information */
- {
- struct video_channel *chan = arg;
- memset(&input2,0,sizeof(input2));
- input2.index = chan->channel;
- err = drv(inode, file, VIDIOC_ENUMINPUT, &input2);
- if (err < 0) {
- dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: "
- "channel=%d err=%d\n",chan->channel,err);
- break;
- }
- chan->channel = input2.index;
- memcpy(chan->name, input2.name,
- min(sizeof(chan->name), sizeof(input2.name)));
- chan->name[sizeof(chan->name) - 1] = 0;
- chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0;
- chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0;
- switch (input2.type) {
- case V4L2_INPUT_TYPE_TUNER:
- chan->type = VIDEO_TYPE_TV;
- break;
- default:
- case V4L2_INPUT_TYPE_CAMERA:
- chan->type = VIDEO_TYPE_CAMERA;
- break;
- }
- chan->norm = 0;
- err = drv(inode, file, VIDIOC_G_STD, &sid);
- if (err < 0)
- dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n",err);
- if (err == 0) {
- if (sid & V4L2_STD_PAL)
- chan->norm = VIDEO_MODE_PAL;
- if (sid & V4L2_STD_NTSC)
- chan->norm = VIDEO_MODE_NTSC;
- if (sid & V4L2_STD_SECAM)
- chan->norm = VIDEO_MODE_SECAM;
- }
- break;
- }
- case VIDIOCSCHAN: /* set input */
- {
- struct video_channel *chan = arg;
- sid = 0;
- err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel);
- if (err < 0)
- dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n",err);
- switch (chan->norm) {
- case VIDEO_MODE_PAL:
- sid = V4L2_STD_PAL;
- break;
- case VIDEO_MODE_NTSC:
- sid = V4L2_STD_NTSC;
- break;
- case VIDEO_MODE_SECAM:
- sid = V4L2_STD_SECAM;
- break;
- }
- if (0 != sid) {
- err = drv(inode, file, VIDIOC_S_STD, &sid);
- if (err < 0)
- dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n",err);
- }
- break;
- }
- case VIDIOCGPICT: /* get tone controls & partial capture format */
- {
- struct video_picture *pict = arg;
- pict->brightness = get_v4l_control(inode, file,
- V4L2_CID_BRIGHTNESS,drv);
- pict->hue = get_v4l_control(inode, file,
- V4L2_CID_HUE, drv);
- pict->contrast = get_v4l_control(inode, file,
- V4L2_CID_CONTRAST, drv);
- pict->colour = get_v4l_control(inode, file,
- V4L2_CID_SATURATION, drv);
- pict->whiteness = get_v4l_control(inode, file,
- V4L2_CID_WHITENESS, drv);
- fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
- fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_G_FMT, fmt2);
- if (err < 0) {
- dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n",err);
- break;
- }
- pict->palette = pixelformat_to_palette(
- fmt2->fmt.pix.pixelformat);
- break;
- }
- case VIDIOCSPICT: /* set tone controls & partial capture format */
- {
- struct video_picture *pict = arg;
- set_v4l_control(inode, file,
- V4L2_CID_BRIGHTNESS, pict->brightness, drv);
- set_v4l_control(inode, file,
- V4L2_CID_HUE, pict->hue, drv);
- set_v4l_control(inode, file,
- V4L2_CID_CONTRAST, pict->contrast, drv);
- set_v4l_control(inode, file,
- V4L2_CID_SATURATION, pict->colour, drv);
- set_v4l_control(inode, file,
- V4L2_CID_WHITENESS, pict->whiteness, drv);
- fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
- fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_G_FMT, fmt2);
- if (err < 0)
- dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n",err);
- if (fmt2->fmt.pix.pixelformat !=
- palette_to_pixelformat(pict->palette)) {
- fmt2->fmt.pix.pixelformat = palette_to_pixelformat(
- pict->palette);
- err = drv(inode, file, VIDIOC_S_FMT, fmt2);
- if (err < 0)
- dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",err);
- }
- err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
- if (err < 0)
- dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n",err);
- if (fbuf2.fmt.pixelformat !=
- palette_to_pixelformat(pict->palette)) {
- fbuf2.fmt.pixelformat = palette_to_pixelformat(
- pict->palette);
- err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
- if (err < 0)
- dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",err);
- err = 0; /* likely fails for non-root */
- }
- break;
- }
- case VIDIOCGTUNER: /* get tuner information */
- {
- struct video_tuner *tun = arg;
- memset(&tun2,0,sizeof(tun2));
- err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
- if (err < 0) {
- dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n",err);
- break;
- }
- memcpy(tun->name, tun2.name,
- min(sizeof(tun->name), sizeof(tun2.name)));
- tun->name[sizeof(tun->name) - 1] = 0;
- tun->rangelow = tun2.rangelow;
- tun->rangehigh = tun2.rangehigh;
- tun->flags = 0;
- tun->mode = VIDEO_MODE_AUTO;
- for (i = 0; i < 64; i++) {
- memset(&std2,0,sizeof(std2));
- std2.index = i;
- if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2))
- break;
- if (std2.id & V4L2_STD_PAL)
- tun->flags |= VIDEO_TUNER_PAL;
- if (std2.id & V4L2_STD_NTSC)
- tun->flags |= VIDEO_TUNER_NTSC;
- if (std2.id & V4L2_STD_SECAM)
- tun->flags |= VIDEO_TUNER_SECAM;
- }
- err = drv(inode, file, VIDIOC_G_STD, &sid);
- if (err < 0)
- dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n",err);
- if (err == 0) {
- if (sid & V4L2_STD_PAL)
- tun->mode = VIDEO_MODE_PAL;
- if (sid & V4L2_STD_NTSC)
- tun->mode = VIDEO_MODE_NTSC;
- if (sid & V4L2_STD_SECAM)
- tun->mode = VIDEO_MODE_SECAM;
- }
- if (tun2.capability & V4L2_TUNER_CAP_LOW)
- tun->flags |= VIDEO_TUNER_LOW;
- if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
- tun->flags |= VIDEO_TUNER_STEREO_ON;
- tun->signal = tun2.signal;
- break;
- }
- case VIDIOCSTUNER: /* select a tuner input */
- {
- err = 0;
- break;
- }
- case VIDIOCGFREQ: /* get frequency */
- {
- unsigned long *freq = arg;
- freq2.tuner = 0;
- err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
- if (err < 0)
- dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n",err);
- if (0 == err)
- *freq = freq2.frequency;
- break;
- }
- case VIDIOCSFREQ: /* set frequency */
- {
- unsigned long *freq = arg;
- freq2.tuner = 0;
- drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
- freq2.frequency = *freq;
- err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2);
- if (err < 0)
- dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n",err);
- break;
- }
- case VIDIOCGAUDIO: /* get audio properties/controls */
- {
- struct video_audio *aud = arg;
- err = drv(inode, file, VIDIOC_G_AUDIO, &aud2);
- if (err < 0) {
- dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n",err);
- break;
- }
- memcpy(aud->name, aud2.name,
- min(sizeof(aud->name), sizeof(aud2.name)));
- aud->name[sizeof(aud->name) - 1] = 0;
- aud->audio = aud2.index;
- aud->flags = 0;
- i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv);
- if (i >= 0) {
- aud->volume = i;
- aud->flags |= VIDEO_AUDIO_VOLUME;
- }
- i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv);
- if (i >= 0) {
- aud->bass = i;
- aud->flags |= VIDEO_AUDIO_BASS;
- }
- i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv);
- if (i >= 0) {
- aud->treble = i;
- aud->flags |= VIDEO_AUDIO_TREBLE;
- }
- i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv);
- if (i >= 0) {
- aud->balance = i;
- aud->flags |= VIDEO_AUDIO_BALANCE;
- }
- i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv);
- if (i >= 0) {
- if (i)
- aud->flags |= VIDEO_AUDIO_MUTE;
- aud->flags |= VIDEO_AUDIO_MUTABLE;
- }
- aud->step = 1;
- qctrl2.id = V4L2_CID_AUDIO_VOLUME;
- if (drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 &&
- !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
- aud->step = qctrl2.step;
- aud->mode = 0;
- memset(&tun2,0,sizeof(tun2));
- err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
- if (err < 0) {
- dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n",err);
- err = 0;
- break;
- }
- if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2)
- aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
- else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
- aud->mode = VIDEO_SOUND_STEREO;
- else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO)
- aud->mode = VIDEO_SOUND_MONO;
- break;
- }
- case VIDIOCSAUDIO: /* set audio controls */
- {
- struct video_audio *aud = arg;
- memset(&aud2,0,sizeof(aud2));
- memset(&tun2,0,sizeof(tun2));
- aud2.index = aud->audio;
- err = drv(inode, file, VIDIOC_S_AUDIO, &aud2);
- if (err < 0) {
- dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n",err);
- break;
- }
- set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME,
- aud->volume, drv);
- set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS,
- aud->bass, drv);
- set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE,
- aud->treble, drv);
- set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE,
- aud->balance, drv);
- set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE,
- !!(aud->flags & VIDEO_AUDIO_MUTE), drv);
- err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
- if (err < 0)
- dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n",err);
- if (err == 0) {
- switch (aud->mode) {
- default:
- case VIDEO_SOUND_MONO:
- case VIDEO_SOUND_LANG1:
- tun2.audmode = V4L2_TUNER_MODE_MONO;
- break;
- case VIDEO_SOUND_STEREO:
- tun2.audmode = V4L2_TUNER_MODE_STEREO;
- break;
- case VIDEO_SOUND_LANG2:
- tun2.audmode = V4L2_TUNER_MODE_LANG2;
- break;
- }
- err = drv(inode, file, VIDIOC_S_TUNER, &tun2);
- if (err < 0)
- dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n",err);
- }
- err = 0;
- break;
- }
- case VIDIOCMCAPTURE: /* capture a frame */
- {
- struct video_mmap *mm = arg;
- fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
- memset(&buf2,0,sizeof(buf2));
- fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_G_FMT, fmt2);
- if (err < 0) {
- dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n",err);
- break;
- }
- if (mm->width != fmt2->fmt.pix.width ||
- mm->height != fmt2->fmt.pix.height ||
- palette_to_pixelformat(mm->format) !=
- fmt2->fmt.pix.pixelformat)
- {/* New capture format... */
- fmt2->fmt.pix.width = mm->width;
- fmt2->fmt.pix.height = mm->height;
- fmt2->fmt.pix.pixelformat =
- palette_to_pixelformat(mm->format);
- fmt2->fmt.pix.field = V4L2_FIELD_ANY;
- fmt2->fmt.pix.bytesperline = 0;
- err = drv(inode, file, VIDIOC_S_FMT, fmt2);
- if (err < 0) {
- dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n",err);
- break;
- }
- }
- buf2.index = mm->frame;
- buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
- if (err < 0) {
- dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n",err);
- break;
- }
- err = drv(inode, file, VIDIOC_QBUF, &buf2);
- if (err < 0) {
- dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n",err);
- break;
- }
- err = drv(inode, file, VIDIOC_STREAMON, &captype);
- if (err < 0)
- dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n",err);
- break;
- }
- case VIDIOCSYNC: /* wait for a frame */
- {
- int *i = arg;
- buf2.index = *i;
- buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
- if (err < 0) {
- /* No such buffer */
- dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err);
- break;
- }
- if (!(buf2.flags & V4L2_BUF_FLAG_MAPPED)) {
- /* Buffer is not mapped */
- err = -EINVAL;
- break;
- }
- /* make sure capture actually runs so we don't block forever */
- err = drv(inode, file, VIDIOC_STREAMON, &captype);
- if (err < 0) {
- dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n",err);
- break;
- }
- /* Loop as long as the buffer is queued, but not done */
- while ((buf2.flags &
- (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))
- == V4L2_BUF_FLAG_QUEUED)
- {
- err = poll_one(file);
- if (err < 0 || /* error or sleep was interrupted */
- err == 0) /* timeout? Shouldn't occur. */
- break;
- err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
- if (err < 0)
- dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err);
- }
- if (!(buf2.flags & V4L2_BUF_FLAG_DONE)) /* not done */
- break;
- do {
- err = drv(inode, file, VIDIOC_DQBUF, &buf2);
- if (err < 0)
- dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n",err);
- } while (err == 0 && buf2.index != *i);
- break;
- }
- case VIDIOCGVBIFMT: /* query VBI data capture format */
- {
- struct vbi_format *fmt = arg;
- fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
- fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
- err = drv(inode, file, VIDIOC_G_FMT, fmt2);
- if (err < 0) {
- dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
- break;
- }
- if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) {
- err = -EINVAL;
- break;
- }
- memset(fmt, 0, sizeof(*fmt));
- fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line;
- fmt->sampling_rate = fmt2->fmt.vbi.sampling_rate;
- fmt->sample_format = VIDEO_PALETTE_RAW;
- fmt->start[0] = fmt2->fmt.vbi.start[0];
- fmt->count[0] = fmt2->fmt.vbi.count[0];
- fmt->start[1] = fmt2->fmt.vbi.start[1];
- fmt->count[1] = fmt2->fmt.vbi.count[1];
- fmt->flags = fmt2->fmt.vbi.flags & 0x03;
- break;
- }
- case VIDIOCSVBIFMT:
- {
- struct vbi_format *fmt = arg;
- if (VIDEO_PALETTE_RAW != fmt->sample_format) {
- err = -EINVAL;
- break;
- }
- fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
- fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
- fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line;
- fmt2->fmt.vbi.sampling_rate = fmt->sampling_rate;
- fmt2->fmt.vbi.sample_format = V4L2_PIX_FMT_GREY;
- fmt2->fmt.vbi.start[0] = fmt->start[0];
- fmt2->fmt.vbi.count[0] = fmt->count[0];
- fmt2->fmt.vbi.start[1] = fmt->start[1];
- fmt2->fmt.vbi.count[1] = fmt->count[1];
- fmt2->fmt.vbi.flags = fmt->flags;
- err = drv(inode, file, VIDIOC_TRY_FMT, fmt2);
- if (err < 0) {
- dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err);
- break;
- }
- if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line ||
- fmt2->fmt.vbi.sampling_rate != fmt->sampling_rate ||
- fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY ||
- fmt2->fmt.vbi.start[0] != fmt->start[0] ||
- fmt2->fmt.vbi.count[0] != fmt->count[0] ||
- fmt2->fmt.vbi.start[1] != fmt->start[1] ||
- fmt2->fmt.vbi.count[1] != fmt->count[1] ||
- fmt2->fmt.vbi.flags != fmt->flags) {
- err = -EINVAL;
- break;
- }
- err = drv(inode, file, VIDIOC_S_FMT, fmt2);
- if (err < 0)
- dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err);
- break;
- }
- default:
- err = -ENOIOCTLCMD;
- break;
- }
- kfree(cap2);
- kfree(fmt2);
- return err;
- }
- EXPORT_SYMBOL(v4l_compat_translate_ioctl);
- /*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
|