From: Gerd Knorr Hi, This patch updates the v4l1-compat module. Changes: * use f_op->poll() instead of do_select() * reduce stack usage of the v4l1_translate_ioctl() function. * misc minor fixes here and there. Please apply, Gerd diff -u linux-2.5.69/drivers/media/video/v4l1-compat.c linux/drivers/media/video/v4l1-compat.c 25-akpm/drivers/media/video/v4l1-compat.c | 502 +++++++++++++++--------------- 1 files changed, 259 insertions(+), 243 deletions(-) diff -puN drivers/media/video/v4l1-compat.c~v4l-2 drivers/media/video/v4l1-compat.c --- 25/drivers/media/video/v4l1-compat.c~v4l-2 Mon May 12 15:29:44 2003 +++ 25-akpm/drivers/media/video/v4l1-compat.c Mon May 12 15:29:44 2003 @@ -127,6 +127,8 @@ set_v4l_control(struct inode return 0; } +/* ----------------------------------------------------------------- */ + static int palette2pixelformat[] = { [VIDEO_PALETTE_GREY] = V4L2_PIX_FMT_GREY, [VIDEO_PALETTE_RGB555] = V4L2_PIX_FMT_RGB555, @@ -145,16 +147,16 @@ static int palette2pixelformat[] = { [VIDEO_PALETTE_YUV422P] = V4L2_PIX_FMT_YUV422P, }; -static int -palette_to_pixelformat(int palette) +static unsigned int +palette_to_pixelformat(unsigned int palette) { - if (palette < sizeof(palette2pixelformat)/sizeof(int)) + if (palette < ARRAY_SIZE(palette2pixelformat)) return palette2pixelformat[palette]; else return 0; } -static int +static unsigned int pixelformat_to_palette(int pixelformat) { int palette = 0; @@ -199,66 +201,43 @@ pixelformat_to_palette(int pixelformat) return palette; } -/* Do an 'in' (wait for input) select on a single file descriptor */ -/* This stuff plaigarized from linux/fs/select.c */ -#define __FD_IN(fds, n) (fds->in + n) -#define BIT(i) (1UL << ((i)&(__NFDBITS-1))) -#define SET(i,m) (*(m) |= (i)) -extern int do_select(int n, fd_set_bits *fds, long *timeout); - +/* ----------------------------------------------------------------- */ -static int -simple_select(struct file *file) +static int poll_one(struct file *file) { - fd_set_bits fds; - char *bits; - long timeout; - int i, fd, n, ret, size; - - for (i = 0; i < current->files->max_fds; ++i) - if (file == current->files->fd[i]) - break; - if (i == current->files->max_fds) - return -EINVAL; - fd = i; - n = fd + 1; - - timeout = MAX_SCHEDULE_TIMEOUT; - /* - * We need 6 bitmaps (in/out/ex for both incoming and outgoing), - * since we used fdset we need to allocate memory in units of - * long-words. - */ - ret = -ENOMEM; - size = FDS_BYTES(n); - bits = kmalloc(6 * size, GFP_KERNEL); - if (!bits) - goto out_nofds; - fds.in = (unsigned long *) bits; - fds.out = (unsigned long *) (bits + size); - fds.ex = (unsigned long *) (bits + 2*size); - fds.res_in = (unsigned long *) (bits + 3*size); - fds.res_out = (unsigned long *) (bits + 4*size); - fds.res_ex = (unsigned long *) (bits + 5*size); - - /* All zero except our one file descriptor bit, for input */ - memset(bits, 0, 6 * size); - SET(BIT(fd), __FD_IN((&fds), fd / __NFDBITS)); - - ret = do_select(n, &fds, &timeout); - - if (ret < 0) - goto out; - if (!ret) { - ret = -ERESTARTNOHAND; - if (signal_pending(current)) - goto out; - ret = 0; - } -out: - kfree(bits); -out_nofds: - return ret; + int retval = 1; + poll_table *table; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,48) + poll_table wait_table; + + poll_initwait(&wait_table); + table = &wait_table; +#else + struct poll_wqueues pwq; + + poll_initwait(&pwq); + table = &pwq.pt; +#endif + 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(); + } + current->state = TASK_RUNNING; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,48) + poll_freewait(&wait_table); +#else + poll_freewait(&pwq); +#endif + return retval; } static int count_inputs(struct inode *inode, @@ -306,6 +285,7 @@ static int check_size(struct inode return 0; } +/* ----------------------------------------------------------------- */ /* * This function is exported. @@ -317,26 +297,36 @@ v4l_compat_translate_ioctl(struct inode void *arg, v4l2_kioctl drv) { - int err = -ENOIOCTLCMD; + struct v4l2_capability *cap2 = NULL; + struct v4l2_format *fmt2 = NULL; - switch (cmd) - { + 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; - struct v4l2_capability cap2; - struct v4l2_framebuffer fbuf2; - + + cap2 = kmalloc(sizeof(*cap2),GFP_KERNEL); memset(cap, 0, sizeof(*cap)); - memset(&cap2, 0, sizeof(cap2)); + memset(cap2, 0, sizeof(*cap2)); memset(&fbuf2, 0, sizeof(fbuf2)); - err = drv(inode, file, VIDIOC_QUERYCAP, &cap2); + 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) { + 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); @@ -345,16 +335,16 @@ v4l_compat_translate_ioctl(struct inode err = 0; } - memcpy(cap->name, cap2.card, - min(sizeof(cap->name), sizeof(cap2.card))); + 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) + if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE) cap->type |= VID_TYPE_CAPTURE; - if (cap2.capabilities & V4L2_CAP_TUNER) + if (cap2->capabilities & V4L2_CAP_TUNER) cap->type |= VID_TYPE_TUNER; - if (cap2.capabilities & V4L2_CAP_VBI_CAPTURE) + if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE) cap->type |= VID_TYPE_TELETEXT; - if (cap2.capabilities & V4L2_CAP_VIDEO_OVERLAY) + 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; @@ -370,7 +360,6 @@ v4l_compat_translate_ioctl(struct inode case VIDIOCGFBUF: /* get frame buffer */ { struct video_buffer *buffer = arg; - struct v4l2_framebuffer fbuf2; err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2); if (err < 0) { @@ -412,7 +401,6 @@ v4l_compat_translate_ioctl(struct inode case VIDIOCSFBUF: /* set frame buffer */ { struct video_buffer *buffer = arg; - struct v4l2_framebuffer fbuf2; memset(&fbuf2, 0, sizeof(fbuf2)); fbuf2.base = buffer->base; @@ -444,36 +432,36 @@ v4l_compat_translate_ioctl(struct inode case VIDIOCGWIN: /* get window or capture dimensions */ { struct video_window *win = arg; - struct v4l2_format fmt2; + fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL); memset(win,0,sizeof(*win)); - memset(&fmt2,0,sizeof(fmt2)); + memset(fmt2,0,sizeof(*fmt2)); - fmt2.type = V4L2_BUF_TYPE_VIDEO_OVERLAY; - err = drv(inode, file, VIDIOC_G_FMT, &fmt2); + 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->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); + 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->width = fmt2->fmt.pix.width; + win->height = fmt2->fmt.pix.height; win->chromakey = 0; win->clips = NULL; win->clipcount = 0; @@ -482,37 +470,41 @@ v4l_compat_translate_ioctl(struct inode case VIDIOCSWIN: /* set window and/or capture dimensions */ { struct video_window *win = arg; - struct v4l2_format fmt2; + int err1,err2; - memset(&fmt2,0,sizeof(fmt2)); - fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(inode, file, VIDIOC_G_FMT, &fmt2); - if (err < 0) + fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL); + memset(fmt2,0,sizeof(*fmt2)); + fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + err1 = drv(inode, file, VIDIOC_G_FMT, fmt2); + if (err1 < 0) dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n",err); - if (err == 0) { - fmt2.fmt.pix.width = win->width; - fmt2.fmt.pix.height = win->height; - fmt2.fmt.pix.field = V4L2_FIELD_ANY; - err = drv(inode, file, VIDIOC_S_FMT, &fmt2); + if (err1 == 0) { + fmt2->fmt.pix.width = win->width; + fmt2->fmt.pix.height = win->height; + fmt2->fmt.pix.field = V4L2_FIELD_ANY; + 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; + 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 *)win->clips; - fmt2.fmt.win.clipcount = win->clipcount; - err = drv(inode, file, VIDIOC_S_FMT, &fmt2); - if (err < 0) + 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 *)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 */ @@ -525,8 +517,6 @@ v4l_compat_translate_ioctl(struct inode case VIDIOCGCHAN: /* get input information */ { struct video_channel *chan = arg; - struct v4l2_input input2; - v4l2_std_id sid; memset(&input2,0,sizeof(input2)); input2.index = chan->channel; @@ -568,16 +558,32 @@ v4l_compat_translate_ioctl(struct inode 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; - struct v4l2_format fmt2; pict->brightness = get_v4l_control(inode, file, V4L2_CID_BRIGHTNESS,drv); @@ -590,25 +596,24 @@ v4l_compat_translate_ioctl(struct inode pict->whiteness = get_v4l_control(inode, file, V4L2_CID_WHITENESS, drv); - memset(&fmt2,0,sizeof(fmt2)); - fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(inode, file, VIDIOC_G_FMT, &fmt2); + fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL); + memset(fmt2,0,sizeof(*fmt2)); + 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; } #if 0 /* FIXME */ - pict->depth = fmt2.fmt.pix.depth; + pict->depth = fmt2->fmt.pix.depth; #endif pict->palette = pixelformat_to_palette( - fmt2.fmt.pix.pixelformat); + fmt2->fmt.pix.pixelformat); break; } case VIDIOCSPICT: /* set tone controls & partial capture format */ { struct video_picture *pict = arg; - struct v4l2_format fmt2; - struct v4l2_framebuffer fbuf2; set_v4l_control(inode, file, V4L2_CID_BRIGHTNESS, pict->brightness, drv); @@ -621,16 +626,17 @@ v4l_compat_translate_ioctl(struct inode set_v4l_control(inode, file, V4L2_CID_WHITENESS, pict->whiteness, drv); - memset(&fmt2,0,sizeof(fmt2)); - fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(inode, file, VIDIOC_G_FMT, &fmt2); + fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL); + memset(fmt2,0,sizeof(*fmt2)); + 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 != + if (fmt2->fmt.pix.pixelformat != palette_to_pixelformat(pict->palette)) { - fmt2.fmt.pix.pixelformat = palette_to_pixelformat( + fmt2->fmt.pix.pixelformat = palette_to_pixelformat( pict->palette); - err = drv(inode, file, VIDIOC_S_FMT, &fmt2); + err = drv(inode, file, VIDIOC_S_FMT, fmt2); if (err < 0) dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",err); } @@ -652,8 +658,6 @@ v4l_compat_translate_ioctl(struct inode case VIDIOCGTUNER: /* get tuner information */ { struct video_tuner *tun = arg; - struct v4l2_tuner tun2; - v4l2_std_id sid; memset(&tun2,0,sizeof(tun2)); err = drv(inode, file, VIDIOC_G_TUNER, &tun2); @@ -669,6 +673,19 @@ v4l_compat_translate_ioctl(struct inode 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); @@ -688,21 +705,20 @@ v4l_compat_translate_ioctl(struct inode tun->signal = tun2.signal; break; } -#if 0 /* FIXME */ case VIDIOCSTUNER: /* select a tuner input */ { - int i; - +#if 0 /* FIXME */ err = drv(inode, file, VIDIOC_S_INPUT, &i); if (err < 0) dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err); +#else + err = 0; +#endif break; } -#endif case VIDIOCGFREQ: /* get frequency */ { int *freq = arg; - struct v4l2_frequency freq2; err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); if (err < 0) @@ -714,7 +730,6 @@ v4l_compat_translate_ioctl(struct inode case VIDIOCSFREQ: /* set frequency */ { int *freq = arg; - struct v4l2_frequency freq2; drv(inode, file, VIDIOC_G_FREQUENCY, &freq2); freq2.frequency = *freq; @@ -726,10 +741,6 @@ v4l_compat_translate_ioctl(struct inode case VIDIOCGAUDIO: /* get audio properties/controls */ { struct video_audio *aud = arg; - struct v4l2_audio aud2; - struct v4l2_queryctrl qctrl2; - struct v4l2_tuner tun2; - int v; err = drv(inode, file, VIDIOC_G_AUDIO, &aud2); if (err < 0) { @@ -741,34 +752,29 @@ v4l_compat_translate_ioctl(struct inode aud->name[sizeof(aud->name) - 1] = 0; aud->audio = aud2.index; aud->flags = 0; - v = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv); - if (v >= 0) - { - aud->volume = v; + i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv); + if (i >= 0) { + aud->volume = i; aud->flags |= VIDEO_AUDIO_VOLUME; } - v = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv); - if (v >= 0) - { - aud->bass = v; + i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv); + if (i >= 0) { + aud->bass = i; aud->flags |= VIDEO_AUDIO_BASS; } - v = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv); - if (v >= 0) - { - aud->treble = v; + i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv); + if (i >= 0) { + aud->treble = i; aud->flags |= VIDEO_AUDIO_TREBLE; } - v = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv); - if (v >= 0) - { - aud->balance = v; + i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv); + if (i >= 0) { + aud->balance = i; aud->flags |= VIDEO_AUDIO_BALANCE; } - v = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv); - if (v >= 0) - { - if (v) + 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; } @@ -795,8 +801,6 @@ v4l_compat_translate_ioctl(struct inode case VIDIOCSAUDIO: /* set audio controls */ { struct video_audio *aud = arg; - struct v4l2_audio aud2; - struct v4l2_tuner tun2; memset(&aud2,0,sizeof(aud2)); memset(&tun2,0,sizeof(tun2)); @@ -844,83 +848,36 @@ v4l_compat_translate_ioctl(struct inode break; } #if 0 - case VIDIOCGMBUF: /* get mmap parameters */ - { - struct video_mbuf *mbuf = arg; - struct v4l2_requestbuffers reqbuf2; - struct v4l2_buffer buf2; - struct v4l2_format fmt2, fmt2o; - struct v4l2_capability cap2; - int i; - - /* Set the format to maximum dimensions */ - if ((err = drv(inode, file, VIDIOC_QUERYCAP, &cap2)) < 0) - break; - fmt2o.type = V4L2_BUF_TYPE_CAPTURE; - if ((err = drv(inode, file, VIDIOC_G_FMT, &fmt2o)) < 0) - break; - fmt2 = fmt2o; - fmt2.fmt.pix.width = cap2.maxwidth; - fmt2.fmt.pix.height = cap2.maxheight; - fmt2.fmt.pix.flags |= V4L2_FMT_FLAG_INTERLACED; - if ((err = drv(inode, file, VIDIOC_S_FMT, &fmt2)) < 0) - break; - reqbuf2.count = 2; /* v4l always used two buffers */ - reqbuf2.type = V4L2_BUF_TYPE_CAPTURE | V4L2_BUF_REQ_CONTIG; - err = drv(inode, file, VIDIOC_REQBUFS, &reqbuf2); - if (err < 0 || reqbuf2.count < 2 || reqbuf2.type - != (V4L2_BUF_TYPE_CAPTURE | V4L2_BUF_REQ_CONTIG)) - {/* Driver doesn't support v4l back-compatibility */ - fmt2o.fmt.pix.flags |= V4L2_FMT_FLAG_INTERLACED; - drv(inode, file, VIDIOC_S_FMT, &fmt2o); - reqbuf2.count = 1; - reqbuf2.type = V4L2_BUF_TYPE_CAPTURE; - err = drv(inode, file, VIDIOC_REQBUFS, &reqbuf2); - if (err < 0) - { - err = -EINVAL; - break; - } - printk(KERN_INFO"V4L2: Device \"%s\" doesn't support" - " v4l memory mapping\n", vfl->name); - } - buf2.index = 0; - buf2.type = V4L2_BUF_TYPE_CAPTURE; - err = drv(inode, file, VIDIOC_QUERYBUF, &buf2); - mbuf->size = buf2.length * reqbuf2.count; - mbuf->frames = reqbuf2.count; - memset(mbuf->offsets, 0, sizeof(mbuf->offsets)); - for (i = 0; i < mbuf->frames; ++i) - mbuf->offsets[i] = i * buf2.length; - break; - } + case VIDIOCGMBUF: + /* v4l2 drivers must implement that themself. The + mmap() differences can't be translated fully + transparent, thus there is no point to try that */ #endif case VIDIOCMCAPTURE: /* capture a frame */ { struct video_mmap *mm = arg; - struct v4l2_buffer buf2; - struct v4l2_format fmt2; + fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL); memset(&buf2,0,sizeof(buf2)); - memset(&fmt2,0,sizeof(fmt2)); + memset(fmt2,0,sizeof(*fmt2)); - fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - err = drv(inode, file, VIDIOC_G_FMT, &fmt2); + 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 || + if (mm->width != fmt2->fmt.pix.width || + mm->height != fmt2->fmt.pix.height || palette_to_pixelformat(mm->format) != - fmt2.fmt.pix.pixelformat) + fmt2->fmt.pix.pixelformat) {/* New capture format... */ - fmt2.fmt.pix.width = mm->width; - fmt2.fmt.pix.height = mm->height; - fmt2.fmt.pix.pixelformat = + 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; - err = drv(inode, file, VIDIOC_S_FMT, &fmt2); + fmt2->fmt.pix.field = V4L2_FIELD_ANY; + err = drv(inode, file, VIDIOC_S_FMT, fmt2); if (err < 0) { dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n",err); break; @@ -946,7 +903,6 @@ v4l_compat_translate_ioctl(struct inode case VIDIOCSYNC: /* wait for a frame */ { int *i = arg; - struct v4l2_buffer buf2; buf2.index = *i; buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -967,7 +923,7 @@ v4l_compat_translate_ioctl(struct inode (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE)) == V4L2_BUF_FLAG_QUEUED) { - err = simple_select(file); + err = poll_one(file); if (err < 0 || /* error or sleep was interrupted */ err == 0) /* timeout? Shouldn't occur. */ break; @@ -984,20 +940,80 @@ v4l_compat_translate_ioctl(struct inode } while (err == 0 && buf2.index != *i); break; } - case VIDIOCGUNIT: /* get related device minors */ - /* No translation */ - break; - case VIDIOCGCAPTURE: /* */ - /* No translation, yet... */ - printk(KERN_INFO"v4l1-compat: VIDIOCGCAPTURE not implemented." - " Send patches to bdirks@pacbell.net :-)\n"); - break; - case VIDIOCSCAPTURE: /* */ - /* No translation, yet... */ - printk(KERN_INFO"v4l1-compat: VIDIOCSCAPTURE not implemented." - " Send patches to bdirks@pacbell.net :-)\n"); + + case VIDIOCGVBIFMT: /* query VBI data capture format */ + { + struct vbi_format *fmt = arg; + + fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL); + memset(fmt2, 0, sizeof(*fmt2)); + 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; + } + 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; + + fmt2 = kmalloc(sizeof(*fmt2),GFP_KERNEL); + memset(fmt2, 0, sizeof(*fmt2)); + + 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; } + + if (cap2) + kfree(cap2); + if (fmt2) + kfree(fmt2); return err; } _