linux/drivers/media/video/v4l1-compat.c
<<
>>
Prefs
   1/*
   2 *
   3 *      Video for Linux Two
   4 *      Backward Compatibility Layer
   5 *
   6 *      Support subroutines for providing V4L2 drivers with backward
   7 *      compatibility with applications using the old API.
   8 *
   9 *      This program is free software; you can redistribute it and/or
  10 *      modify it under the terms of the GNU General Public License
  11 *      as published by the Free Software Foundation; either version
  12 *      2 of the License, or (at your option) any later version.
  13 *
  14 * Author:      Bill Dirks <bill@thedirks.org>
  15 *              et al.
  16 *
  17 */
  18
  19
  20#include <linux/init.h>
  21#include <linux/module.h>
  22#include <linux/types.h>
  23#include <linux/kernel.h>
  24#include <linux/sched.h>
  25#include <linux/mm.h>
  26#include <linux/fs.h>
  27#include <linux/file.h>
  28#include <linux/string.h>
  29#include <linux/errno.h>
  30#include <linux/slab.h>
  31#include <linux/videodev.h>
  32#include <media/v4l2-common.h>
  33
  34#include <asm/uaccess.h>
  35#include <asm/system.h>
  36#include <asm/pgtable.h>
  37
  38#ifdef CONFIG_KMOD
  39#include <linux/kmod.h>
  40#endif
  41
  42static unsigned int debug  = 0;
  43module_param(debug, int, 0644);
  44MODULE_PARM_DESC(debug,"enable debug messages");
  45MODULE_AUTHOR("Bill Dirks");
  46MODULE_DESCRIPTION("v4l(1) compatibility layer for v4l2 drivers.");
  47MODULE_LICENSE("GPL");
  48
  49#define dprintk(fmt, arg...)    if (debug) \
  50        printk(KERN_DEBUG "v4l1-compat: " fmt , ## arg)
  51
  52/*
  53 *      I O C T L   T R A N S L A T I O N
  54 *
  55 *      From here on down is the code for translating the numerous
  56 *      ioctl commands from the old API to the new API.
  57 */
  58
  59static int
  60get_v4l_control(struct inode            *inode,
  61                struct file             *file,
  62                int                     cid,
  63                v4l2_kioctl             drv)
  64{
  65        struct v4l2_queryctrl   qctrl2;
  66        struct v4l2_control     ctrl2;
  67        int                     err;
  68
  69        qctrl2.id = cid;
  70        err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);
  71        if (err < 0)
  72                dprintk("VIDIOC_QUERYCTRL: %d\n",err);
  73        if (err == 0 &&
  74            !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
  75        {
  76                ctrl2.id = qctrl2.id;
  77                err = drv(inode, file, VIDIOC_G_CTRL, &ctrl2);
  78                if (err < 0) {
  79                        dprintk("VIDIOC_G_CTRL: %d\n",err);
  80                        return 0;
  81                }
  82                return ((ctrl2.value - qctrl2.minimum) * 65535
  83                         + (qctrl2.maximum - qctrl2.minimum) / 2)
  84                        / (qctrl2.maximum - qctrl2.minimum);
  85        }
  86        return 0;
  87}
  88
  89static int
  90set_v4l_control(struct inode            *inode,
  91                struct file             *file,
  92                int                     cid,
  93                int                     value,
  94                v4l2_kioctl             drv)
  95{
  96        struct v4l2_queryctrl   qctrl2;
  97        struct v4l2_control     ctrl2;
  98        int                     err;
  99
 100        qctrl2.id = cid;
 101        err = drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2);
 102        if (err < 0)
 103                dprintk("VIDIOC_QUERYCTRL: %d\n",err);
 104        if (err == 0 &&
 105            !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED) &&
 106            !(qctrl2.flags & V4L2_CTRL_FLAG_GRABBED))
 107        {
 108                if (value < 0)
 109                        value = 0;
 110                if (value > 65535)
 111                        value = 65535;
 112                if (value && qctrl2.type == V4L2_CTRL_TYPE_BOOLEAN)
 113                        value = 65535;
 114                ctrl2.id = qctrl2.id;
 115                ctrl2.value =
 116                        (value * (qctrl2.maximum - qctrl2.minimum)
 117                         + 32767)
 118                        / 65535;
 119                ctrl2.value += qctrl2.minimum;
 120                err = drv(inode, file, VIDIOC_S_CTRL, &ctrl2);
 121                if (err < 0)
 122                        dprintk("VIDIOC_S_CTRL: %d\n",err);
 123        }
 124        return 0;
 125}
 126
 127/* ----------------------------------------------------------------- */
 128
 129const static unsigned int palette2pixelformat[] = {
 130        [VIDEO_PALETTE_GREY]    = V4L2_PIX_FMT_GREY,
 131        [VIDEO_PALETTE_RGB555]  = V4L2_PIX_FMT_RGB555,
 132        [VIDEO_PALETTE_RGB565]  = V4L2_PIX_FMT_RGB565,
 133        [VIDEO_PALETTE_RGB24]   = V4L2_PIX_FMT_BGR24,
 134        [VIDEO_PALETTE_RGB32]   = V4L2_PIX_FMT_BGR32,
 135        /* yuv packed pixel */
 136        [VIDEO_PALETTE_YUYV]    = V4L2_PIX_FMT_YUYV,
 137        [VIDEO_PALETTE_YUV422]  = V4L2_PIX_FMT_YUYV,
 138        [VIDEO_PALETTE_UYVY]    = V4L2_PIX_FMT_UYVY,
 139        /* yuv planar */
 140        [VIDEO_PALETTE_YUV410P] = V4L2_PIX_FMT_YUV410,
 141        [VIDEO_PALETTE_YUV420]  = V4L2_PIX_FMT_YUV420,
 142        [VIDEO_PALETTE_YUV420P] = V4L2_PIX_FMT_YUV420,
 143        [VIDEO_PALETTE_YUV411P] = V4L2_PIX_FMT_YUV411P,
 144        [VIDEO_PALETTE_YUV422P] = V4L2_PIX_FMT_YUV422P,
 145};
 146
 147static unsigned int __pure
 148palette_to_pixelformat(unsigned int palette)
 149{
 150        if (palette < ARRAY_SIZE(palette2pixelformat))
 151                return palette2pixelformat[palette];
 152        else
 153                return 0;
 154}
 155
 156static unsigned int __attribute_const__
 157pixelformat_to_palette(unsigned int pixelformat)
 158{
 159        int     palette = 0;
 160        switch (pixelformat)
 161        {
 162        case V4L2_PIX_FMT_GREY:
 163                palette = VIDEO_PALETTE_GREY;
 164                break;
 165        case V4L2_PIX_FMT_RGB555:
 166                palette = VIDEO_PALETTE_RGB555;
 167                break;
 168        case V4L2_PIX_FMT_RGB565:
 169                palette = VIDEO_PALETTE_RGB565;
 170                break;
 171        case V4L2_PIX_FMT_BGR24:
 172                palette = VIDEO_PALETTE_RGB24;
 173                break;
 174        case V4L2_PIX_FMT_BGR32:
 175                palette = VIDEO_PALETTE_RGB32;
 176                break;
 177        /* yuv packed pixel */
 178        case V4L2_PIX_FMT_YUYV:
 179                palette = VIDEO_PALETTE_YUYV;
 180                break;
 181        case V4L2_PIX_FMT_UYVY:
 182                palette = VIDEO_PALETTE_UYVY;
 183                break;
 184        /* yuv planar */
 185        case V4L2_PIX_FMT_YUV410:
 186                palette = VIDEO_PALETTE_YUV420;
 187                break;
 188        case V4L2_PIX_FMT_YUV420:
 189                palette = VIDEO_PALETTE_YUV420;
 190                break;
 191        case V4L2_PIX_FMT_YUV411P:
 192                palette = VIDEO_PALETTE_YUV411P;
 193                break;
 194        case V4L2_PIX_FMT_YUV422P:
 195                palette = VIDEO_PALETTE_YUV422P;
 196                break;
 197        }
 198        return palette;
 199}
 200
 201/* ----------------------------------------------------------------- */
 202
 203static int poll_one(struct file *file)
 204{
 205        int retval = 1;
 206        poll_table *table;
 207        struct poll_wqueues pwq;
 208
 209        poll_initwait(&pwq);
 210        table = &pwq.pt;
 211        for (;;) {
 212                int mask;
 213                set_current_state(TASK_INTERRUPTIBLE);
 214                mask = file->f_op->poll(file, table);
 215                if (mask & POLLIN)
 216                        break;
 217                table = NULL;
 218                if (signal_pending(current)) {
 219                        retval = -ERESTARTSYS;
 220                        break;
 221                }
 222                schedule();
 223        }
 224        set_current_state(TASK_RUNNING);
 225        poll_freewait(&pwq);
 226        return retval;
 227}
 228
 229static int count_inputs(struct inode         *inode,
 230                        struct file          *file,
 231                        v4l2_kioctl          drv)
 232{
 233        struct v4l2_input input2;
 234        int i;
 235
 236        for (i = 0;; i++) {
 237                memset(&input2,0,sizeof(input2));
 238                input2.index = i;
 239                if (0 != drv(inode,file,VIDIOC_ENUMINPUT, &input2))
 240                        break;
 241        }
 242        return i;
 243}
 244
 245static int check_size(struct inode         *inode,
 246                      struct file          *file,
 247                      v4l2_kioctl          drv,
 248                      int *maxw, int *maxh)
 249{
 250        struct v4l2_fmtdesc desc2;
 251        struct v4l2_format  fmt2;
 252
 253        memset(&desc2,0,sizeof(desc2));
 254        memset(&fmt2,0,sizeof(fmt2));
 255
 256        desc2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 257        if (0 != drv(inode,file,VIDIOC_ENUM_FMT, &desc2))
 258                goto done;
 259
 260        fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 261        fmt2.fmt.pix.width       = 10000;
 262        fmt2.fmt.pix.height      = 10000;
 263        fmt2.fmt.pix.pixelformat = desc2.pixelformat;
 264        if (0 != drv(inode,file,VIDIOC_TRY_FMT, &fmt2))
 265                goto done;
 266
 267        *maxw = fmt2.fmt.pix.width;
 268        *maxh = fmt2.fmt.pix.height;
 269
 270 done:
 271        return 0;
 272}
 273
 274/* ----------------------------------------------------------------- */
 275
 276/*
 277 *      This function is exported.
 278 */
 279int
 280v4l_compat_translate_ioctl(struct inode         *inode,
 281                           struct file          *file,
 282                           int                  cmd,
 283                           void                 *arg,
 284                           v4l2_kioctl          drv)
 285{
 286        struct v4l2_capability  *cap2 = NULL;
 287        struct v4l2_format      *fmt2 = NULL;
 288        enum v4l2_buf_type      captype = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 289
 290        struct v4l2_framebuffer fbuf2;
 291        struct v4l2_input       input2;
 292        struct v4l2_tuner       tun2;
 293        struct v4l2_standard    std2;
 294        struct v4l2_frequency   freq2;
 295        struct v4l2_audio       aud2;
 296        struct v4l2_queryctrl   qctrl2;
 297        struct v4l2_buffer      buf2;
 298        v4l2_std_id             sid;
 299        int i, err = 0;
 300
 301        switch (cmd) {
 302        case VIDIOCGCAP:        /* capability */
 303        {
 304                struct video_capability *cap = arg;
 305
 306                cap2 = kzalloc(sizeof(*cap2),GFP_KERNEL);
 307                memset(cap, 0, sizeof(*cap));
 308                memset(&fbuf2, 0, sizeof(fbuf2));
 309
 310                err = drv(inode, file, VIDIOC_QUERYCAP, cap2);
 311                if (err < 0) {
 312                        dprintk("VIDIOCGCAP / VIDIOC_QUERYCAP: %d\n",err);
 313                        break;
 314                }
 315                if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY) {
 316                        err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
 317                        if (err < 0) {
 318                                dprintk("VIDIOCGCAP / VIDIOC_G_FBUF: %d\n",err);
 319                                memset(&fbuf2, 0, sizeof(fbuf2));
 320                        }
 321                        err = 0;
 322                }
 323
 324                memcpy(cap->name, cap2->card,
 325                       min(sizeof(cap->name), sizeof(cap2->card)));
 326                cap->name[sizeof(cap->name) - 1] = 0;
 327                if (cap2->capabilities & V4L2_CAP_VIDEO_CAPTURE)
 328                        cap->type |= VID_TYPE_CAPTURE;
 329                if (cap2->capabilities & V4L2_CAP_TUNER)
 330                        cap->type |= VID_TYPE_TUNER;
 331                if (cap2->capabilities & V4L2_CAP_VBI_CAPTURE)
 332                        cap->type |= VID_TYPE_TELETEXT;
 333                if (cap2->capabilities & V4L2_CAP_VIDEO_OVERLAY)
 334                        cap->type |= VID_TYPE_OVERLAY;
 335                if (fbuf2.capability & V4L2_FBUF_CAP_LIST_CLIPPING)
 336                        cap->type |= VID_TYPE_CLIPPING;
 337
 338                cap->channels  = count_inputs(inode,file,drv);
 339                check_size(inode,file,drv,
 340                           &cap->maxwidth,&cap->maxheight);
 341                cap->audios    =  0; /* FIXME */
 342                cap->minwidth  = 48; /* FIXME */
 343                cap->minheight = 32; /* FIXME */
 344                break;
 345        }
 346        case VIDIOCGFBUF: /*  get frame buffer  */
 347        {
 348                struct video_buffer     *buffer = arg;
 349
 350                memset(buffer, 0, sizeof(*buffer));
 351                memset(&fbuf2, 0, sizeof(fbuf2));
 352
 353                err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
 354                if (err < 0) {
 355                        dprintk("VIDIOCGFBUF / VIDIOC_G_FBUF: %d\n",err);
 356                        break;
 357                }
 358                buffer->base   = fbuf2.base;
 359                buffer->height = fbuf2.fmt.height;
 360                buffer->width  = fbuf2.fmt.width;
 361
 362                switch (fbuf2.fmt.pixelformat) {
 363                case V4L2_PIX_FMT_RGB332:
 364                        buffer->depth = 8;
 365                        break;
 366                case V4L2_PIX_FMT_RGB555:
 367                        buffer->depth = 15;
 368                        break;
 369                case V4L2_PIX_FMT_RGB565:
 370                        buffer->depth = 16;
 371                        break;
 372                case V4L2_PIX_FMT_BGR24:
 373                        buffer->depth = 24;
 374                        break;
 375                case V4L2_PIX_FMT_BGR32:
 376                        buffer->depth = 32;
 377                        break;
 378                default:
 379                        buffer->depth = 0;
 380                }
 381                if (fbuf2.fmt.bytesperline) {
 382                        buffer->bytesperline = fbuf2.fmt.bytesperline;
 383                        if (!buffer->depth && buffer->width)
 384                                buffer->depth   = ((fbuf2.fmt.bytesperline<<3)
 385                                                  + (buffer->width-1) )
 386                                                  /buffer->width;
 387                } else {
 388                        buffer->bytesperline =
 389                                (buffer->width * buffer->depth + 7) & 7;
 390                        buffer->bytesperline >>= 3;
 391                }
 392                break;
 393        }
 394        case VIDIOCSFBUF: /*  set frame buffer  */
 395        {
 396                struct video_buffer     *buffer = arg;
 397
 398                memset(&fbuf2, 0, sizeof(fbuf2));
 399                fbuf2.base       = buffer->base;
 400                fbuf2.fmt.height = buffer->height;
 401                fbuf2.fmt.width  = buffer->width;
 402                switch (buffer->depth) {
 403                case 8:
 404                        fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB332;
 405                        break;
 406                case 15:
 407                        fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB555;
 408                        break;
 409                case 16:
 410                        fbuf2.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
 411                        break;
 412                case 24:
 413                        fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR24;
 414                        break;
 415                case 32:
 416                        fbuf2.fmt.pixelformat = V4L2_PIX_FMT_BGR32;
 417                        break;
 418                }
 419                fbuf2.fmt.bytesperline = buffer->bytesperline;
 420                err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
 421                if (err < 0)
 422                        dprintk("VIDIOCSFBUF / VIDIOC_S_FBUF: %d\n",err);
 423                break;
 424        }
 425        case VIDIOCGWIN: /*  get window or capture dimensions  */
 426        {
 427                struct video_window     *win = arg;
 428
 429                fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
 430                memset(win,0,sizeof(*win));
 431
 432                fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
 433                err = drv(inode, file, VIDIOC_G_FMT, fmt2);
 434                if (err < 0)
 435                        dprintk("VIDIOCGWIN / VIDIOC_G_WIN: %d\n",err);
 436                if (err == 0) {
 437                        win->x         = fmt2->fmt.win.w.left;
 438                        win->y         = fmt2->fmt.win.w.top;
 439                        win->width     = fmt2->fmt.win.w.width;
 440                        win->height    = fmt2->fmt.win.w.height;
 441                        win->chromakey = fmt2->fmt.win.chromakey;
 442                        win->clips     = NULL;
 443                        win->clipcount = 0;
 444                        break;
 445                }
 446
 447                fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 448                err = drv(inode, file, VIDIOC_G_FMT, fmt2);
 449                if (err < 0) {
 450                        dprintk("VIDIOCGWIN / VIDIOC_G_FMT: %d\n",err);
 451                        break;
 452                }
 453                win->x         = 0;
 454                win->y         = 0;
 455                win->width     = fmt2->fmt.pix.width;
 456                win->height    = fmt2->fmt.pix.height;
 457                win->chromakey = 0;
 458                win->clips     = NULL;
 459                win->clipcount = 0;
 460                break;
 461        }
 462        case VIDIOCSWIN: /*  set window and/or capture dimensions  */
 463        {
 464                struct video_window     *win = arg;
 465                int err1,err2;
 466
 467                fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
 468                fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 469                drv(inode, file, VIDIOC_STREAMOFF, &fmt2->type);
 470                err1 = drv(inode, file, VIDIOC_G_FMT, fmt2);
 471                if (err1 < 0)
 472                        dprintk("VIDIOCSWIN / VIDIOC_G_FMT: %d\n",err);
 473                if (err1 == 0) {
 474                        fmt2->fmt.pix.width  = win->width;
 475                        fmt2->fmt.pix.height = win->height;
 476                        fmt2->fmt.pix.field  = V4L2_FIELD_ANY;
 477                        fmt2->fmt.pix.bytesperline = 0;
 478                        err = drv(inode, file, VIDIOC_S_FMT, fmt2);
 479                        if (err < 0)
 480                                dprintk("VIDIOCSWIN / VIDIOC_S_FMT #1: %d\n",
 481                                        err);
 482                        win->width  = fmt2->fmt.pix.width;
 483                        win->height = fmt2->fmt.pix.height;
 484                }
 485
 486                memset(fmt2,0,sizeof(*fmt2));
 487                fmt2->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
 488                fmt2->fmt.win.w.left    = win->x;
 489                fmt2->fmt.win.w.top     = win->y;
 490                fmt2->fmt.win.w.width   = win->width;
 491                fmt2->fmt.win.w.height  = win->height;
 492                fmt2->fmt.win.chromakey = win->chromakey;
 493                fmt2->fmt.win.clips     = (void __user *)win->clips;
 494                fmt2->fmt.win.clipcount = win->clipcount;
 495                err2 = drv(inode, file, VIDIOC_S_FMT, fmt2);
 496                if (err2 < 0)
 497                        dprintk("VIDIOCSWIN / VIDIOC_S_FMT #2: %d\n",err);
 498
 499                if (err1 != 0 && err2 != 0)
 500                        err = err1;
 501                break;
 502        }
 503        case VIDIOCCAPTURE: /*  turn on/off preview  */
 504        {
 505                int *on = arg;
 506
 507                if (0 == *on) {
 508                        /* dirty hack time.  But v4l1 has no STREAMOFF
 509                         * equivalent in the API, and this one at
 510                         * least comes close ... */
 511                        drv(inode, file, VIDIOC_STREAMOFF, &captype);
 512                }
 513                err = drv(inode, file, VIDIOC_OVERLAY, arg);
 514                if (err < 0)
 515                        dprintk("VIDIOCCAPTURE / VIDIOC_PREVIEW: %d\n",err);
 516                break;
 517        }
 518        case VIDIOCGCHAN: /*  get input information  */
 519        {
 520                struct video_channel    *chan = arg;
 521
 522                memset(&input2,0,sizeof(input2));
 523                input2.index = chan->channel;
 524                err = drv(inode, file, VIDIOC_ENUMINPUT, &input2);
 525                if (err < 0) {
 526                        dprintk("VIDIOCGCHAN / VIDIOC_ENUMINPUT: "
 527                                "channel=%d err=%d\n",chan->channel,err);
 528                        break;
 529                }
 530                chan->channel = input2.index;
 531                memcpy(chan->name, input2.name,
 532                       min(sizeof(chan->name), sizeof(input2.name)));
 533                chan->name[sizeof(chan->name) - 1] = 0;
 534                chan->tuners = (input2.type == V4L2_INPUT_TYPE_TUNER) ? 1 : 0;
 535                chan->flags = (chan->tuners) ? VIDEO_VC_TUNER : 0;
 536                switch (input2.type) {
 537                case V4L2_INPUT_TYPE_TUNER:
 538                        chan->type = VIDEO_TYPE_TV;
 539                        break;
 540                default:
 541                case V4L2_INPUT_TYPE_CAMERA:
 542                        chan->type = VIDEO_TYPE_CAMERA;
 543                        break;
 544                }
 545                chan->norm = 0;
 546                err = drv(inode, file, VIDIOC_G_STD, &sid);
 547                if (err < 0)
 548                        dprintk("VIDIOCGCHAN / VIDIOC_G_STD: %d\n",err);
 549                if (err == 0) {
 550                        if (sid & V4L2_STD_PAL)
 551                                chan->norm = VIDEO_MODE_PAL;
 552                        if (sid & V4L2_STD_NTSC)
 553                                chan->norm = VIDEO_MODE_NTSC;
 554                        if (sid & V4L2_STD_SECAM)
 555                                chan->norm = VIDEO_MODE_SECAM;
 556                }
 557                break;
 558        }
 559        case VIDIOCSCHAN: /*  set input  */
 560        {
 561                struct video_channel *chan = arg;
 562
 563                sid = 0;
 564                err = drv(inode, file, VIDIOC_S_INPUT, &chan->channel);
 565                if (err < 0)
 566                        dprintk("VIDIOCSCHAN / VIDIOC_S_INPUT: %d\n",err);
 567                switch (chan->norm) {
 568                case VIDEO_MODE_PAL:
 569                        sid = V4L2_STD_PAL;
 570                        break;
 571                case VIDEO_MODE_NTSC:
 572                        sid = V4L2_STD_NTSC;
 573                        break;
 574                case VIDEO_MODE_SECAM:
 575                        sid = V4L2_STD_SECAM;
 576                        break;
 577                }
 578                if (0 != sid) {
 579                        err = drv(inode, file, VIDIOC_S_STD, &sid);
 580                        if (err < 0)
 581                                dprintk("VIDIOCSCHAN / VIDIOC_S_STD: %d\n",err);
 582                }
 583                break;
 584        }
 585        case VIDIOCGPICT: /*  get tone controls & partial capture format  */
 586        {
 587                struct video_picture    *pict = arg;
 588
 589                pict->brightness = get_v4l_control(inode, file,
 590                                                   V4L2_CID_BRIGHTNESS,drv);
 591                pict->hue = get_v4l_control(inode, file,
 592                                            V4L2_CID_HUE, drv);
 593                pict->contrast = get_v4l_control(inode, file,
 594                                                 V4L2_CID_CONTRAST, drv);
 595                pict->colour = get_v4l_control(inode, file,
 596                                               V4L2_CID_SATURATION, drv);
 597                pict->whiteness = get_v4l_control(inode, file,
 598                                                  V4L2_CID_WHITENESS, drv);
 599
 600                fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
 601                fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 602                err = drv(inode, file, VIDIOC_G_FMT, fmt2);
 603                if (err < 0) {
 604                        dprintk("VIDIOCGPICT / VIDIOC_G_FMT: %d\n",err);
 605                        break;
 606                }
 607
 608                pict->depth   = ((fmt2->fmt.pix.bytesperline<<3)
 609                                 + (fmt2->fmt.pix.width-1) )
 610                                 /fmt2->fmt.pix.width;
 611                pict->palette = pixelformat_to_palette(
 612                        fmt2->fmt.pix.pixelformat);
 613                break;
 614        }
 615        case VIDIOCSPICT: /*  set tone controls & partial capture format  */
 616        {
 617                struct video_picture    *pict = arg;
 618                int mem_err = 0, ovl_err = 0;
 619
 620                memset(&fbuf2, 0, sizeof(fbuf2));
 621
 622                set_v4l_control(inode, file,
 623                                V4L2_CID_BRIGHTNESS, pict->brightness, drv);
 624                set_v4l_control(inode, file,
 625                                V4L2_CID_HUE, pict->hue, drv);
 626                set_v4l_control(inode, file,
 627                                V4L2_CID_CONTRAST, pict->contrast, drv);
 628                set_v4l_control(inode, file,
 629                                V4L2_CID_SATURATION, pict->colour, drv);
 630                set_v4l_control(inode, file,
 631                                V4L2_CID_WHITENESS, pict->whiteness, drv);
 632                /*
 633                 * V4L1 uses this ioctl to set both memory capture and overlay
 634                 * pixel format, while V4L2 has two different ioctls for this.
 635                 * Some cards may not support one or the other, and may support
 636                 * different pixel formats for memory vs overlay.
 637                 */
 638
 639                fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
 640                fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 641                err = drv(inode, file, VIDIOC_G_FMT, fmt2);
 642                /* If VIDIOC_G_FMT failed, then the driver likely doesn't
 643                   support memory capture.  Trying to set the memory capture
 644                   parameters would be pointless.  */
 645                if (err < 0) {
 646                        dprintk("VIDIOCSPICT / VIDIOC_G_FMT: %d\n",err);
 647                        mem_err = -1000;  /* didn't even try */
 648                } else if (fmt2->fmt.pix.pixelformat !=
 649                         palette_to_pixelformat(pict->palette)) {
 650                        fmt2->fmt.pix.pixelformat = palette_to_pixelformat(
 651                                pict->palette);
 652                        mem_err = drv(inode, file, VIDIOC_S_FMT, fmt2);
 653                        if (mem_err < 0)
 654                                dprintk("VIDIOCSPICT / VIDIOC_S_FMT: %d\n",
 655                                        mem_err);
 656                }
 657
 658                err = drv(inode, file, VIDIOC_G_FBUF, &fbuf2);
 659                /* If VIDIOC_G_FBUF failed, then the driver likely doesn't
 660                   support overlay.  Trying to set the overlay parameters
 661                   would be quite pointless.  */
 662                if (err < 0) {
 663                        dprintk("VIDIOCSPICT / VIDIOC_G_FBUF: %d\n",err);
 664                        ovl_err = -1000;  /* didn't even try */
 665                } else if (fbuf2.fmt.pixelformat !=
 666                         palette_to_pixelformat(pict->palette)) {
 667                        fbuf2.fmt.pixelformat = palette_to_pixelformat(
 668                                pict->palette);
 669                        ovl_err = drv(inode, file, VIDIOC_S_FBUF, &fbuf2);
 670                        if (ovl_err < 0)
 671                                dprintk("VIDIOCSPICT / VIDIOC_S_FBUF: %d\n",
 672                                        ovl_err);
 673                }
 674                if (ovl_err < 0 && mem_err < 0)
 675                        /* ioctl failed, couldn't set either parameter */
 676                        if (mem_err != -1000) {
 677                            err = mem_err;
 678                        } else if (ovl_err == -EPERM) {
 679                            err = 0;
 680                        } else {
 681                            err = ovl_err;
 682                        }
 683                else
 684                        err = 0;
 685                break;
 686        }
 687        case VIDIOCGTUNER: /*  get tuner information  */
 688        {
 689                struct video_tuner      *tun = arg;
 690
 691                memset(&tun2,0,sizeof(tun2));
 692                err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
 693                if (err < 0) {
 694                        dprintk("VIDIOCGTUNER / VIDIOC_G_TUNER: %d\n",err);
 695                        break;
 696                }
 697                memcpy(tun->name, tun2.name,
 698                       min(sizeof(tun->name), sizeof(tun2.name)));
 699                tun->name[sizeof(tun->name) - 1] = 0;
 700                tun->rangelow = tun2.rangelow;
 701                tun->rangehigh = tun2.rangehigh;
 702                tun->flags = 0;
 703                tun->mode = VIDEO_MODE_AUTO;
 704
 705                for (i = 0; i < 64; i++) {
 706                        memset(&std2,0,sizeof(std2));
 707                        std2.index = i;
 708                        if (0 != drv(inode, file, VIDIOC_ENUMSTD, &std2))
 709                                break;
 710                        if (std2.id & V4L2_STD_PAL)
 711                                tun->flags |= VIDEO_TUNER_PAL;
 712                        if (std2.id & V4L2_STD_NTSC)
 713                                tun->flags |= VIDEO_TUNER_NTSC;
 714                        if (std2.id & V4L2_STD_SECAM)
 715                                tun->flags |= VIDEO_TUNER_SECAM;
 716                }
 717
 718                err = drv(inode, file, VIDIOC_G_STD, &sid);
 719                if (err < 0)
 720                        dprintk("VIDIOCGTUNER / VIDIOC_G_STD: %d\n",err);
 721                if (err == 0) {
 722                        if (sid & V4L2_STD_PAL)
 723                                tun->mode = VIDEO_MODE_PAL;
 724                        if (sid & V4L2_STD_NTSC)
 725                                tun->mode = VIDEO_MODE_NTSC;
 726                        if (sid & V4L2_STD_SECAM)
 727                                tun->mode = VIDEO_MODE_SECAM;
 728                }
 729
 730                if (tun2.capability & V4L2_TUNER_CAP_LOW)
 731                        tun->flags |= VIDEO_TUNER_LOW;
 732                if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
 733                        tun->flags |= VIDEO_TUNER_STEREO_ON;
 734                tun->signal = tun2.signal;
 735                break;
 736        }
 737        case VIDIOCSTUNER: /*  select a tuner input  */
 738        {
 739                struct video_tuner      *tun = arg;
 740                struct v4l2_tuner       t;
 741                memset(&t,0,sizeof(t));
 742
 743                t.index=tun->tuner;
 744
 745                err = drv(inode, file, VIDIOC_S_INPUT, &t);
 746                if (err < 0)
 747                        dprintk("VIDIOCSTUNER / VIDIOC_S_INPUT: %d\n",err);
 748
 749                break;
 750        }
 751        case VIDIOCGFREQ: /*  get frequency  */
 752        {
 753                unsigned long *freq = arg;
 754                memset(&freq2,0,sizeof(freq2));
 755
 756                freq2.tuner = 0;
 757                err = drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
 758                if (err < 0)
 759                        dprintk("VIDIOCGFREQ / VIDIOC_G_FREQUENCY: %d\n",err);
 760                if (0 == err)
 761                        *freq = freq2.frequency;
 762                break;
 763        }
 764        case VIDIOCSFREQ: /*  set frequency  */
 765        {
 766                unsigned long *freq = arg;
 767                memset(&freq2,0,sizeof(freq2));
 768
 769                drv(inode, file, VIDIOC_G_FREQUENCY, &freq2);
 770                freq2.frequency = *freq;
 771                err = drv(inode, file, VIDIOC_S_FREQUENCY, &freq2);
 772                if (err < 0)
 773                        dprintk("VIDIOCSFREQ / VIDIOC_S_FREQUENCY: %d\n",err);
 774                break;
 775        }
 776        case VIDIOCGAUDIO: /*  get audio properties/controls  */
 777        {
 778                struct video_audio      *aud = arg;
 779                memset(&aud2,0,sizeof(aud2));
 780
 781                err = drv(inode, file, VIDIOC_G_AUDIO, &aud2);
 782                if (err < 0) {
 783                        dprintk("VIDIOCGAUDIO / VIDIOC_G_AUDIO: %d\n",err);
 784                        break;
 785                }
 786                memcpy(aud->name, aud2.name,
 787                       min(sizeof(aud->name), sizeof(aud2.name)));
 788                aud->name[sizeof(aud->name) - 1] = 0;
 789                aud->audio = aud2.index;
 790                aud->flags = 0;
 791                i = get_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME, drv);
 792                if (i >= 0) {
 793                        aud->volume = i;
 794                        aud->flags |= VIDEO_AUDIO_VOLUME;
 795                }
 796                i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BASS, drv);
 797                if (i >= 0) {
 798                        aud->bass = i;
 799                        aud->flags |= VIDEO_AUDIO_BASS;
 800                }
 801                i = get_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE, drv);
 802                if (i >= 0) {
 803                        aud->treble = i;
 804                        aud->flags |= VIDEO_AUDIO_TREBLE;
 805                }
 806                i = get_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE, drv);
 807                if (i >= 0) {
 808                        aud->balance = i;
 809                        aud->flags |= VIDEO_AUDIO_BALANCE;
 810                }
 811                i = get_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE, drv);
 812                if (i >= 0) {
 813                        if (i)
 814                                aud->flags |= VIDEO_AUDIO_MUTE;
 815                        aud->flags |= VIDEO_AUDIO_MUTABLE;
 816                }
 817                aud->step = 1;
 818                qctrl2.id = V4L2_CID_AUDIO_VOLUME;
 819                if (drv(inode, file, VIDIOC_QUERYCTRL, &qctrl2) == 0 &&
 820                    !(qctrl2.flags & V4L2_CTRL_FLAG_DISABLED))
 821                        aud->step = qctrl2.step;
 822                aud->mode = 0;
 823
 824                memset(&tun2,0,sizeof(tun2));
 825                err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
 826                if (err < 0) {
 827                        dprintk("VIDIOCGAUDIO / VIDIOC_G_TUNER: %d\n",err);
 828                        err = 0;
 829                        break;
 830                }
 831
 832                if (tun2.rxsubchans & V4L2_TUNER_SUB_LANG2)
 833                        aud->mode = VIDEO_SOUND_LANG1 | VIDEO_SOUND_LANG2;
 834                else if (tun2.rxsubchans & V4L2_TUNER_SUB_STEREO)
 835                        aud->mode = VIDEO_SOUND_STEREO;
 836                else if (tun2.rxsubchans & V4L2_TUNER_SUB_MONO)
 837                        aud->mode = VIDEO_SOUND_MONO;
 838                break;
 839        }
 840        case VIDIOCSAUDIO: /*  set audio controls  */
 841        {
 842                struct video_audio      *aud = arg;
 843
 844                memset(&aud2,0,sizeof(aud2));
 845                memset(&tun2,0,sizeof(tun2));
 846
 847                aud2.index = aud->audio;
 848                err = drv(inode, file, VIDIOC_S_AUDIO, &aud2);
 849                if (err < 0) {
 850                        dprintk("VIDIOCSAUDIO / VIDIOC_S_AUDIO: %d\n",err);
 851                        break;
 852                }
 853
 854                set_v4l_control(inode, file, V4L2_CID_AUDIO_VOLUME,
 855                                aud->volume, drv);
 856                set_v4l_control(inode, file, V4L2_CID_AUDIO_BASS,
 857                                aud->bass, drv);
 858                set_v4l_control(inode, file, V4L2_CID_AUDIO_TREBLE,
 859                                aud->treble, drv);
 860                set_v4l_control(inode, file, V4L2_CID_AUDIO_BALANCE,
 861                                aud->balance, drv);
 862                set_v4l_control(inode, file, V4L2_CID_AUDIO_MUTE,
 863                                !!(aud->flags & VIDEO_AUDIO_MUTE), drv);
 864
 865                err = drv(inode, file, VIDIOC_G_TUNER, &tun2);
 866                if (err < 0)
 867                        dprintk("VIDIOCSAUDIO / VIDIOC_G_TUNER: %d\n",err);
 868                if (err == 0) {
 869                        switch (aud->mode) {
 870                        default:
 871                        case VIDEO_SOUND_MONO:
 872                        case VIDEO_SOUND_LANG1:
 873                                tun2.audmode = V4L2_TUNER_MODE_MONO;
 874                                break;
 875                        case VIDEO_SOUND_STEREO:
 876                                tun2.audmode = V4L2_TUNER_MODE_STEREO;
 877                                break;
 878                        case VIDEO_SOUND_LANG2:
 879                                tun2.audmode = V4L2_TUNER_MODE_LANG2;
 880                                break;
 881                        }
 882                        err = drv(inode, file, VIDIOC_S_TUNER, &tun2);
 883                        if (err < 0)
 884                                dprintk("VIDIOCSAUDIO / VIDIOC_S_TUNER: %d\n",err);
 885                }
 886                err = 0;
 887                break;
 888        }
 889        case VIDIOCMCAPTURE: /*  capture a frame  */
 890        {
 891                struct video_mmap       *mm = arg;
 892
 893                fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
 894                memset(&buf2,0,sizeof(buf2));
 895
 896                fmt2->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 897                err = drv(inode, file, VIDIOC_G_FMT, fmt2);
 898                if (err < 0) {
 899                        dprintk("VIDIOCMCAPTURE / VIDIOC_G_FMT: %d\n",err);
 900                        break;
 901                }
 902                if (mm->width   != fmt2->fmt.pix.width  ||
 903                    mm->height  != fmt2->fmt.pix.height ||
 904                    palette_to_pixelformat(mm->format) !=
 905                    fmt2->fmt.pix.pixelformat)
 906                {/* New capture format...  */
 907                        fmt2->fmt.pix.width = mm->width;
 908                        fmt2->fmt.pix.height = mm->height;
 909                        fmt2->fmt.pix.pixelformat =
 910                                palette_to_pixelformat(mm->format);
 911                        fmt2->fmt.pix.field = V4L2_FIELD_ANY;
 912                        fmt2->fmt.pix.bytesperline = 0;
 913                        err = drv(inode, file, VIDIOC_S_FMT, fmt2);
 914                        if (err < 0) {
 915                                dprintk("VIDIOCMCAPTURE / VIDIOC_S_FMT: %d\n",err);
 916                                break;
 917                        }
 918                }
 919                buf2.index = mm->frame;
 920                buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 921                err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
 922                if (err < 0) {
 923                        dprintk("VIDIOCMCAPTURE / VIDIOC_QUERYBUF: %d\n",err);
 924                        break;
 925                }
 926                err = drv(inode, file, VIDIOC_QBUF, &buf2);
 927                if (err < 0) {
 928                        dprintk("VIDIOCMCAPTURE / VIDIOC_QBUF: %d\n",err);
 929                        break;
 930                }
 931                err = drv(inode, file, VIDIOC_STREAMON, &captype);
 932                if (err < 0)
 933                        dprintk("VIDIOCMCAPTURE / VIDIOC_STREAMON: %d\n",err);
 934                break;
 935        }
 936        case VIDIOCSYNC: /*  wait for a frame  */
 937        {
 938                int                     *i = arg;
 939
 940                memset(&buf2,0,sizeof(buf2));
 941                buf2.index = *i;
 942                buf2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 943                err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
 944                if (err < 0) {
 945                        /*  No such buffer */
 946                        dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err);
 947                        break;
 948                }
 949                if (!(buf2.flags & V4L2_BUF_FLAG_MAPPED)) {
 950                        /* Buffer is not mapped  */
 951                        err = -EINVAL;
 952                        break;
 953                }
 954
 955                /* make sure capture actually runs so we don't block forever */
 956                err = drv(inode, file, VIDIOC_STREAMON, &captype);
 957                if (err < 0) {
 958                        dprintk("VIDIOCSYNC / VIDIOC_STREAMON: %d\n",err);
 959                        break;
 960                }
 961
 962                /*  Loop as long as the buffer is queued, but not done  */
 963                while ((buf2.flags &
 964                        (V4L2_BUF_FLAG_QUEUED | V4L2_BUF_FLAG_DONE))
 965                       == V4L2_BUF_FLAG_QUEUED)
 966                {
 967                        err = poll_one(file);
 968                        if (err < 0 ||  /* error or sleep was interrupted  */
 969                            err == 0)   /* timeout? Shouldn't occur.  */
 970                                break;
 971                        err = drv(inode, file, VIDIOC_QUERYBUF, &buf2);
 972                        if (err < 0)
 973                                dprintk("VIDIOCSYNC / VIDIOC_QUERYBUF: %d\n",err);
 974                }
 975                if (!(buf2.flags & V4L2_BUF_FLAG_DONE)) /* not done */
 976                        break;
 977                do {
 978                        err = drv(inode, file, VIDIOC_DQBUF, &buf2);
 979                        if (err < 0)
 980                                dprintk("VIDIOCSYNC / VIDIOC_DQBUF: %d\n",err);
 981                } while (err == 0 && buf2.index != *i);
 982                break;
 983        }
 984
 985        case VIDIOCGVBIFMT: /* query VBI data capture format */
 986        {
 987                struct vbi_format      *fmt = arg;
 988
 989                fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
 990                fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
 991
 992                err = drv(inode, file, VIDIOC_G_FMT, fmt2);
 993                if (err < 0) {
 994                        dprintk("VIDIOCGVBIFMT / VIDIOC_G_FMT: %d\n", err);
 995                        break;
 996                }
 997                if (fmt2->fmt.vbi.sample_format != V4L2_PIX_FMT_GREY) {
 998                        err = -EINVAL;
 999                        break;
1000                }
1001                memset(fmt, 0, sizeof(*fmt));
1002                fmt->samples_per_line = fmt2->fmt.vbi.samples_per_line;
1003                fmt->sampling_rate    = fmt2->fmt.vbi.sampling_rate;
1004                fmt->sample_format    = VIDEO_PALETTE_RAW;
1005                fmt->start[0]         = fmt2->fmt.vbi.start[0];
1006                fmt->count[0]         = fmt2->fmt.vbi.count[0];
1007                fmt->start[1]         = fmt2->fmt.vbi.start[1];
1008                fmt->count[1]         = fmt2->fmt.vbi.count[1];
1009                fmt->flags            = fmt2->fmt.vbi.flags & 0x03;
1010                break;
1011        }
1012        case VIDIOCSVBIFMT:
1013        {
1014                struct vbi_format      *fmt = arg;
1015
1016                if (VIDEO_PALETTE_RAW != fmt->sample_format) {
1017                        err = -EINVAL;
1018                        break;
1019                }
1020
1021                fmt2 = kzalloc(sizeof(*fmt2),GFP_KERNEL);
1022
1023                fmt2->type = V4L2_BUF_TYPE_VBI_CAPTURE;
1024                fmt2->fmt.vbi.samples_per_line = fmt->samples_per_line;
1025                fmt2->fmt.vbi.sampling_rate    = fmt->sampling_rate;
1026                fmt2->fmt.vbi.sample_format    = V4L2_PIX_FMT_GREY;
1027                fmt2->fmt.vbi.start[0]         = fmt->start[0];
1028                fmt2->fmt.vbi.count[0]         = fmt->count[0];
1029                fmt2->fmt.vbi.start[1]         = fmt->start[1];
1030                fmt2->fmt.vbi.count[1]         = fmt->count[1];
1031                fmt2->fmt.vbi.flags            = fmt->flags;
1032                err = drv(inode, file, VIDIOC_TRY_FMT, fmt2);
1033                if (err < 0) {
1034                        dprintk("VIDIOCSVBIFMT / VIDIOC_TRY_FMT: %d\n", err);
1035                        break;
1036                }
1037
1038                if (fmt2->fmt.vbi.samples_per_line != fmt->samples_per_line ||
1039                    fmt2->fmt.vbi.sampling_rate    != fmt->sampling_rate    ||
1040                    fmt2->fmt.vbi.sample_format    != V4L2_PIX_FMT_GREY     ||
1041                    fmt2->fmt.vbi.start[0]         != fmt->start[0]         ||
1042                    fmt2->fmt.vbi.count[0]         != fmt->count[0]         ||
1043                    fmt2->fmt.vbi.start[1]         != fmt->start[1]         ||
1044                    fmt2->fmt.vbi.count[1]         != fmt->count[1]         ||
1045                    fmt2->fmt.vbi.flags            != fmt->flags) {
1046                        err = -EINVAL;
1047                        break;
1048                }
1049                err = drv(inode, file, VIDIOC_S_FMT, fmt2);
1050                if (err < 0)
1051                        dprintk("VIDIOCSVBIFMT / VIDIOC_S_FMT: %d\n", err);
1052                break;
1053        }
1054
1055        default:
1056                err = -ENOIOCTLCMD;
1057                break;
1058        }
1059
1060        kfree(cap2);
1061        kfree(fmt2);
1062        return err;
1063}
1064
1065EXPORT_SYMBOL(v4l_compat_translate_ioctl);
1066
1067/*
1068 * Local variables:
1069 * c-basic-offset: 8
1070 * End:
1071 */
1072