linux/drivers/media/video/compat_ioctl32.c
<<
>>
Prefs
   1/*
   2 * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
   3 *      Separated from fs stuff by Arnd Bergmann <arnd@arndb.de>
   4 *
   5 * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
   6 * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
   7 * Copyright (C) 2001,2002  Andi Kleen, SuSE Labs
   8 * Copyright (C) 2003       Pavel Machek (pavel@suse.cz)
   9 * Copyright (C) 2005       Philippe De Muyter (phdm@macqel.be)
  10 *
  11 * These routines maintain argument size conversion between 32bit and 64bit
  12 * ioctls.
  13 */
  14
  15#include <linux/compat.h>
  16#include <linux/videodev.h>
  17#include <linux/videodev2.h>
  18#include <linux/module.h>
  19#include <linux/smp_lock.h>
  20#include <media/v4l2-common.h>
  21
  22#ifdef CONFIG_COMPAT
  23
  24#ifdef CONFIG_VIDEO_V4L1_COMPAT
  25struct video_tuner32 {
  26        compat_int_t tuner;
  27        char name[32];
  28        compat_ulong_t rangelow, rangehigh;
  29        u32 flags;      /* It is really u32 in videodev.h */
  30        u16 mode, signal;
  31};
  32
  33static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
  34{
  35        if(!access_ok(VERIFY_READ, up, sizeof(struct video_tuner32)) ||
  36                get_user(kp->tuner, &up->tuner) ||
  37                copy_from_user(kp->name, up->name, 32) ||
  38                get_user(kp->rangelow, &up->rangelow) ||
  39                get_user(kp->rangehigh, &up->rangehigh) ||
  40                get_user(kp->flags, &up->flags) ||
  41                get_user(kp->mode, &up->mode) ||
  42                get_user(kp->signal, &up->signal))
  43                return -EFAULT;
  44        return 0;
  45}
  46
  47static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
  48{
  49        if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_tuner32)) ||
  50                put_user(kp->tuner, &up->tuner) ||
  51                copy_to_user(up->name, kp->name, 32) ||
  52                put_user(kp->rangelow, &up->rangelow) ||
  53                put_user(kp->rangehigh, &up->rangehigh) ||
  54                put_user(kp->flags, &up->flags) ||
  55                put_user(kp->mode, &up->mode) ||
  56                put_user(kp->signal, &up->signal))
  57                        return -EFAULT;
  58        return 0;
  59}
  60
  61
  62struct video_buffer32 {
  63        compat_caddr_t base;
  64        compat_int_t height, width, depth, bytesperline;
  65};
  66
  67static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up)
  68{
  69        u32 tmp;
  70
  71        if (!access_ok(VERIFY_READ, up, sizeof(struct video_buffer32)) ||
  72                get_user(tmp, &up->base) ||
  73                get_user(kp->height, &up->height) ||
  74                get_user(kp->width, &up->width) ||
  75                get_user(kp->depth, &up->depth) ||
  76                get_user(kp->bytesperline, &up->bytesperline))
  77                        return -EFAULT;
  78
  79        /* This is actually a physical address stored
  80         * as a void pointer.
  81         */
  82        kp->base = (void *)(unsigned long) tmp;
  83
  84        return 0;
  85}
  86
  87static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up)
  88{
  89        u32 tmp = (u32)((unsigned long)kp->base);
  90
  91        if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_buffer32)) ||
  92                put_user(tmp, &up->base) ||
  93                put_user(kp->height, &up->height) ||
  94                put_user(kp->width, &up->width) ||
  95                put_user(kp->depth, &up->depth) ||
  96                put_user(kp->bytesperline, &up->bytesperline))
  97                        return -EFAULT;
  98        return 0;
  99}
 100
 101struct video_clip32 {
 102        s32 x, y, width, height;        /* Its really s32 in videodev.h */
 103        compat_caddr_t next;
 104};
 105
 106struct video_window32 {
 107        u32 x, y, width, height, chromakey, flags;
 108        compat_caddr_t clips;
 109        compat_int_t clipcount;
 110};
 111#endif
 112
 113static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 114{
 115        int ret = -ENOIOCTLCMD;
 116
 117        if (file->f_op->unlocked_ioctl)
 118                ret = file->f_op->unlocked_ioctl(file, cmd, arg);
 119        else if (file->f_op->ioctl) {
 120                lock_kernel();
 121                ret = file->f_op->ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
 122                unlock_kernel();
 123        }
 124
 125        return ret;
 126}
 127
 128
 129#ifdef CONFIG_VIDEO_V4L1_COMPAT
 130/* You get back everything except the clips... */
 131static int put_video_window32(struct video_window *kp, struct video_window32 __user *up)
 132{
 133        if(!access_ok(VERIFY_WRITE, up, sizeof(struct video_window32)) ||
 134                put_user(kp->x, &up->x) ||
 135                put_user(kp->y, &up->y) ||
 136                put_user(kp->width, &up->width) ||
 137                put_user(kp->height, &up->height) ||
 138                put_user(kp->chromakey, &up->chromakey) ||
 139                put_user(kp->flags, &up->flags) ||
 140                put_user(kp->clipcount, &up->clipcount))
 141                        return -EFAULT;
 142        return 0;
 143}
 144#endif
 145
 146struct v4l2_clip32
 147{
 148        struct v4l2_rect        c;
 149        compat_caddr_t          next;
 150};
 151
 152struct v4l2_window32
 153{
 154        struct v4l2_rect        w;
 155        enum v4l2_field         field;
 156        __u32                   chromakey;
 157        compat_caddr_t          clips; /* actually struct v4l2_clip32 * */
 158        __u32                   clipcount;
 159        compat_caddr_t          bitmap;
 160};
 161
 162static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
 163{
 164        if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
 165                copy_from_user(&kp->w, &up->w, sizeof(up->w)) ||
 166                get_user(kp->field, &up->field) ||
 167                get_user(kp->chromakey, &up->chromakey) ||
 168                get_user(kp->clipcount, &up->clipcount))
 169                        return -EFAULT;
 170        if (kp->clipcount > 2048)
 171                return -EINVAL;
 172        if (kp->clipcount) {
 173                struct v4l2_clip32 __user *uclips;
 174                struct v4l2_clip __user *kclips;
 175                int n = kp->clipcount;
 176                compat_caddr_t p;
 177
 178                if (get_user(p, &up->clips))
 179                        return -EFAULT;
 180                uclips = compat_ptr(p);
 181                kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
 182                kp->clips = kclips;
 183                while (--n >= 0) {
 184                        if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
 185                                return -EFAULT;
 186                        if (put_user(n ? kclips + 1 : NULL, &kclips->next))
 187                                return -EFAULT;
 188                        uclips += 1;
 189                        kclips += 1;
 190                }
 191        } else
 192                kp->clips = NULL;
 193        return 0;
 194}
 195
 196static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
 197{
 198        if (copy_to_user(&up->w, &kp->w, sizeof(up->w)) ||
 199                put_user(kp->field, &up->field) ||
 200                put_user(kp->chromakey, &up->chromakey) ||
 201                put_user(kp->clipcount, &up->clipcount))
 202                        return -EFAULT;
 203        return 0;
 204}
 205
 206static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
 207{
 208        if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
 209                return -EFAULT;
 210        return 0;
 211}
 212
 213static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
 214{
 215        if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
 216                return -EFAULT;
 217        return 0;
 218}
 219
 220static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
 221{
 222        if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
 223                return -EFAULT;
 224        return 0;
 225}
 226
 227static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
 228{
 229        if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
 230                return -EFAULT;
 231        return 0;
 232}
 233
 234struct v4l2_format32
 235{
 236        enum v4l2_buf_type type;
 237        union
 238        {
 239                struct v4l2_pix_format  pix;  // V4L2_BUF_TYPE_VIDEO_CAPTURE
 240                struct v4l2_window32    win;  // V4L2_BUF_TYPE_VIDEO_OVERLAY
 241                struct v4l2_vbi_format  vbi;  // V4L2_BUF_TYPE_VBI_CAPTURE
 242                __u8    raw_data[200];        // user-defined
 243        } fmt;
 244};
 245
 246static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
 247{
 248        if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
 249                        get_user(kp->type, &up->type))
 250                        return -EFAULT;
 251        switch (kp->type) {
 252        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 253                return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
 254        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 255                return get_v4l2_window32(&kp->fmt.win, &up->fmt.win);
 256        case V4L2_BUF_TYPE_VBI_CAPTURE:
 257                return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
 258        default:
 259                printk("compat_ioctl : unexpected VIDIOC_FMT type %d\n",
 260                                                                kp->type);
 261                return -ENXIO;
 262        }
 263}
 264
 265static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
 266{
 267        if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
 268                put_user(kp->type, &up->type))
 269                return -EFAULT;
 270        switch (kp->type) {
 271        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 272                return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
 273        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 274                return put_v4l2_window32(&kp->fmt.win, &up->fmt.win);
 275        case V4L2_BUF_TYPE_VBI_CAPTURE:
 276                return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
 277        default:
 278                return -ENXIO;
 279        }
 280}
 281
 282static inline int get_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up)
 283{
 284        if (copy_from_user(kp, up, sizeof(struct v4l2_standard)))
 285                return -EFAULT;
 286        return 0;
 287
 288}
 289
 290static inline int put_v4l2_standard(struct v4l2_standard *kp, struct v4l2_standard __user *up)
 291{
 292        if (copy_to_user(up, kp, sizeof(struct v4l2_standard)))
 293                return -EFAULT;
 294        return 0;
 295}
 296
 297struct v4l2_standard32
 298{
 299        __u32                index;
 300        __u32                id[2]; /* __u64 would get the alignment wrong */
 301        __u8                 name[24];
 302        struct v4l2_fract    frameperiod; /* Frames, not fields */
 303        __u32                framelines;
 304        __u32                reserved[4];
 305};
 306
 307static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
 308{
 309        /* other fields are not set by the user, nor used by the driver */
 310        if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
 311                get_user(kp->index, &up->index))
 312                return -EFAULT;
 313        return 0;
 314}
 315
 316static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
 317{
 318        if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
 319                put_user(kp->index, &up->index) ||
 320                copy_to_user(up->id, &kp->id, sizeof(__u64)) ||
 321                copy_to_user(up->name, kp->name, 24) ||
 322                copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) ||
 323                put_user(kp->framelines, &up->framelines) ||
 324                copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
 325                        return -EFAULT;
 326        return 0;
 327}
 328
 329static inline int get_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up)
 330{
 331        if (copy_from_user(kp, up, sizeof(struct v4l2_tuner)))
 332                return -EFAULT;
 333        return 0;
 334
 335}
 336
 337static inline int put_v4l2_tuner(struct v4l2_tuner *kp, struct v4l2_tuner __user *up)
 338{
 339        if (copy_to_user(up, kp, sizeof(struct v4l2_tuner)))
 340                return -EFAULT;
 341        return 0;
 342}
 343
 344struct v4l2_buffer32
 345{
 346        __u32                   index;
 347        enum v4l2_buf_type      type;
 348        __u32                   bytesused;
 349        __u32                   flags;
 350        enum v4l2_field         field;
 351        struct compat_timeval   timestamp;
 352        struct v4l2_timecode    timecode;
 353        __u32                   sequence;
 354
 355        /* memory location */
 356        enum v4l2_memory        memory;
 357        union {
 358                __u32           offset;
 359                compat_long_t   userptr;
 360        } m;
 361        __u32                   length;
 362        __u32                   input;
 363        __u32                   reserved;
 364};
 365
 366static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
 367{
 368
 369        if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) ||
 370                get_user(kp->index, &up->index) ||
 371                get_user(kp->type, &up->type) ||
 372                get_user(kp->flags, &up->flags) ||
 373                get_user(kp->memory, &up->memory) ||
 374                get_user(kp->input, &up->input))
 375                        return -EFAULT;
 376        switch(kp->memory) {
 377        case V4L2_MEMORY_MMAP:
 378                break;
 379        case V4L2_MEMORY_USERPTR:
 380                {
 381                compat_long_t tmp;
 382
 383                if (get_user(kp->length, &up->length) ||
 384                    get_user(tmp, &up->m.userptr))
 385                        return -EFAULT;
 386
 387                kp->m.userptr = (unsigned long)compat_ptr(tmp);
 388                }
 389                break;
 390        case V4L2_MEMORY_OVERLAY:
 391                if(get_user(kp->m.offset, &up->m.offset))
 392                        return -EFAULT;
 393                break;
 394        }
 395        return 0;
 396}
 397
 398static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
 399{
 400        if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) ||
 401                put_user(kp->index, &up->index) ||
 402                put_user(kp->type, &up->type) ||
 403                put_user(kp->flags, &up->flags) ||
 404                put_user(kp->memory, &up->memory) ||
 405                put_user(kp->input, &up->input))
 406                        return -EFAULT;
 407        switch(kp->memory) {
 408        case V4L2_MEMORY_MMAP:
 409                if (put_user(kp->length, &up->length) ||
 410                        put_user(kp->m.offset, &up->m.offset))
 411                        return -EFAULT;
 412                break;
 413        case V4L2_MEMORY_USERPTR:
 414                if (put_user(kp->length, &up->length) ||
 415                        put_user(kp->m.userptr, &up->m.userptr))
 416                        return -EFAULT;
 417                break;
 418        case V4L2_MEMORY_OVERLAY:
 419                if (put_user(kp->m.offset, &up->m.offset))
 420                        return -EFAULT;
 421                break;
 422        }
 423        if (put_user(kp->bytesused, &up->bytesused) ||
 424                put_user(kp->field, &up->field) ||
 425                put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
 426                put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) ||
 427                copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) ||
 428                put_user(kp->sequence, &up->sequence) ||
 429                put_user(kp->reserved, &up->reserved))
 430                        return -EFAULT;
 431        return 0;
 432}
 433
 434struct v4l2_framebuffer32
 435{
 436        __u32                   capability;
 437        __u32                   flags;
 438        compat_caddr_t          base;
 439        struct v4l2_pix_format  fmt;
 440};
 441
 442static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
 443{
 444        u32 tmp;
 445
 446        if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
 447                get_user(tmp, &up->base) ||
 448                get_user(kp->capability, &up->capability) ||
 449                get_user(kp->flags, &up->flags))
 450                        return -EFAULT;
 451        kp->base = compat_ptr(tmp);
 452        get_v4l2_pix_format(&kp->fmt, &up->fmt);
 453        return 0;
 454}
 455
 456static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
 457{
 458        u32 tmp = (u32)((unsigned long)kp->base);
 459
 460        if(!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
 461                put_user(tmp, &up->base) ||
 462                put_user(kp->capability, &up->capability) ||
 463                put_user(kp->flags, &up->flags))
 464                        return -EFAULT;
 465        put_v4l2_pix_format(&kp->fmt, &up->fmt);
 466        return 0;
 467}
 468
 469static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up)
 470{
 471        if (copy_from_user(kp, up, sizeof(struct v4l2_input) - 4))
 472                return -EFAULT;
 473        return 0;
 474}
 475
 476static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input __user *up)
 477{
 478        if (copy_to_user(up, kp, sizeof(struct v4l2_input) - 4))
 479                return -EFAULT;
 480        return 0;
 481}
 482
 483static inline int get_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up)
 484{
 485        if (copy_from_user(kp, up, sizeof(struct v4l2_input)))
 486                return -EFAULT;
 487        return 0;
 488}
 489
 490static inline int put_v4l2_input(struct v4l2_input *kp, struct v4l2_input __user *up)
 491{
 492        if (copy_to_user(up, kp, sizeof(struct v4l2_input)))
 493                return -EFAULT;
 494        return 0;
 495}
 496
 497#ifdef CONFIG_VIDEO_V4L1_COMPAT
 498struct video_code32
 499{
 500        char            loadwhat[16];   /* name or tag of file being passed */
 501        compat_int_t    datasize;
 502        unsigned char   *data;
 503};
 504
 505static inline int microcode32(struct video_code *kp, struct video_code32 __user *up)
 506{
 507        if(!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) ||
 508                copy_from_user(kp->loadwhat, up->loadwhat, sizeof (up->loadwhat)) ||
 509                get_user(kp->datasize, &up->datasize) ||
 510                copy_from_user(kp->data, up->data, up->datasize))
 511                        return -EFAULT;
 512        return 0;
 513}
 514
 515#define VIDIOCGTUNER32          _IOWR('v',4, struct video_tuner32)
 516#define VIDIOCSTUNER32          _IOW('v',5, struct video_tuner32)
 517#define VIDIOCGWIN32            _IOR('v',9, struct video_window32)
 518#define VIDIOCSWIN32            _IOW('v',10, struct video_window32)
 519#define VIDIOCGFBUF32           _IOR('v',11, struct video_buffer32)
 520#define VIDIOCSFBUF32           _IOW('v',12, struct video_buffer32)
 521#define VIDIOCGFREQ32           _IOR('v',14, u32)
 522#define VIDIOCSFREQ32           _IOW('v',15, u32)
 523#define VIDIOCSMICROCODE32      _IOW('v',27, struct video_code32)
 524
 525#endif
 526
 527/* VIDIOC_ENUMINPUT32 is VIDIOC_ENUMINPUT minus 4 bytes of padding alignement */
 528#define VIDIOC_ENUMINPUT32      VIDIOC_ENUMINPUT - _IOC(0, 0, 0, 4)
 529#define VIDIOC_G_FMT32          _IOWR ('V',  4, struct v4l2_format32)
 530#define VIDIOC_S_FMT32          _IOWR ('V',  5, struct v4l2_format32)
 531#define VIDIOC_QUERYBUF32       _IOWR ('V',  9, struct v4l2_buffer32)
 532#define VIDIOC_G_FBUF32         _IOR  ('V', 10, struct v4l2_framebuffer32)
 533#define VIDIOC_S_FBUF32         _IOW  ('V', 11, struct v4l2_framebuffer32)
 534/* VIDIOC_OVERLAY is now _IOW, but was _IOWR */
 535#define VIDIOC_OVERLAY32        _IOWR ('V', 14, compat_int_t)
 536#define VIDIOC_QBUF32           _IOWR ('V', 15, struct v4l2_buffer32)
 537#define VIDIOC_DQBUF32          _IOWR ('V', 17, struct v4l2_buffer32)
 538#define VIDIOC_STREAMON32       _IOW  ('V', 18, compat_int_t)
 539#define VIDIOC_STREAMOFF32      _IOW  ('V', 19, compat_int_t)
 540#define VIDIOC_ENUMSTD32        _IOWR ('V', 25, struct v4l2_standard32)
 541/* VIDIOC_S_CTRL is now _IOWR, but was _IOW */
 542#define VIDIOC_S_CTRL32         _IOW  ('V', 28, struct v4l2_control)
 543#define VIDIOC_G_INPUT32        _IOR  ('V', 38, compat_int_t)
 544#define VIDIOC_S_INPUT32        _IOWR ('V', 39, compat_int_t)
 545#define VIDIOC_TRY_FMT32        _IOWR ('V', 64, struct v4l2_format32)
 546
 547#ifdef CONFIG_VIDEO_V4L1_COMPAT
 548enum {
 549        MaxClips = (~0U-sizeof(struct video_window))/sizeof(struct video_clip)
 550};
 551
 552static int do_set_window(struct file *file, unsigned int cmd, unsigned long arg)
 553{
 554        struct video_window32 __user *up = compat_ptr(arg);
 555        struct video_window __user *vw;
 556        struct video_clip __user *p;
 557        int nclips;
 558        u32 n;
 559
 560        if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32)))
 561                return -EFAULT;
 562
 563        if (get_user(nclips, &up->clipcount))
 564                return -EFAULT;
 565
 566        /* Peculiar interface... */
 567        if (nclips < 0)
 568                nclips = VIDEO_CLIPMAP_SIZE;
 569
 570        if (nclips > MaxClips)
 571                return -ENOMEM;
 572
 573        vw = compat_alloc_user_space(sizeof(struct video_window) +
 574                                    nclips * sizeof(struct video_clip));
 575
 576        p = nclips ? (struct video_clip __user *)(vw + 1) : NULL;
 577
 578        if (get_user(n, &up->x) || put_user(n, &vw->x) ||
 579            get_user(n, &up->y) || put_user(n, &vw->y) ||
 580            get_user(n, &up->width) || put_user(n, &vw->width) ||
 581            get_user(n, &up->height) || put_user(n, &vw->height) ||
 582            get_user(n, &up->chromakey) || put_user(n, &vw->chromakey) ||
 583            get_user(n, &up->flags) || put_user(n, &vw->flags) ||
 584            get_user(n, &up->clipcount) || put_user(n, &vw->clipcount) ||
 585            get_user(n, &up->clips) || put_user(p, &vw->clips))
 586                return -EFAULT;
 587
 588        if (nclips) {
 589                struct video_clip32 __user *u = compat_ptr(n);
 590                int i;
 591                if (!u)
 592                        return -EINVAL;
 593                for (i = 0; i < nclips; i++, u++, p++) {
 594                        s32 v;
 595                        if (!access_ok(VERIFY_READ, u, sizeof(struct video_clip32)) ||
 596                            !access_ok(VERIFY_WRITE, p, sizeof(struct video_clip32)) ||
 597                            get_user(v, &u->x) ||
 598                            put_user(v, &p->x) ||
 599                            get_user(v, &u->y) ||
 600                            put_user(v, &p->y) ||
 601                            get_user(v, &u->width) ||
 602                            put_user(v, &p->width) ||
 603                            get_user(v, &u->height) ||
 604                            put_user(v, &p->height) ||
 605                            put_user(NULL, &p->next))
 606                                return -EFAULT;
 607                }
 608        }
 609
 610        return native_ioctl(file, VIDIOCSWIN, (unsigned long)vw);
 611}
 612#endif
 613
 614static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 615{
 616        union {
 617#ifdef CONFIG_VIDEO_V4L1_COMPAT
 618                struct video_tuner vt;
 619                struct video_buffer vb;
 620                struct video_window vw;
 621                struct video_code vc;
 622                struct video_audio va;
 623#endif
 624                struct v4l2_format v2f;
 625                struct v4l2_buffer v2b;
 626                struct v4l2_framebuffer v2fb;
 627                struct v4l2_standard v2s;
 628                struct v4l2_input v2i;
 629                struct v4l2_tuner v2t;
 630                unsigned long vx;
 631        } karg;
 632        void __user *up = compat_ptr(arg);
 633        int compatible_arg = 1;
 634        int err = 0;
 635        int realcmd = cmd;
 636
 637        /* First, convert the command. */
 638        switch(cmd) {
 639#ifdef CONFIG_VIDEO_V4L1_COMPAT
 640        case VIDIOCGTUNER32: realcmd = cmd = VIDIOCGTUNER; break;
 641        case VIDIOCSTUNER32: realcmd = cmd = VIDIOCSTUNER; break;
 642        case VIDIOCGWIN32: realcmd = cmd = VIDIOCGWIN; break;
 643        case VIDIOCGFBUF32: realcmd = cmd = VIDIOCGFBUF; break;
 644        case VIDIOCSFBUF32: realcmd = cmd = VIDIOCSFBUF; break;
 645        case VIDIOCGFREQ32: realcmd = cmd = VIDIOCGFREQ; break;
 646        case VIDIOCSFREQ32: realcmd = cmd = VIDIOCSFREQ; break;
 647        case VIDIOCSMICROCODE32: realcmd = cmd = VIDIOCSMICROCODE; break;
 648#endif
 649        case VIDIOC_G_FMT32: realcmd = cmd = VIDIOC_G_FMT; break;
 650        case VIDIOC_S_FMT32: realcmd = cmd = VIDIOC_S_FMT; break;
 651        case VIDIOC_QUERYBUF32: realcmd = cmd = VIDIOC_QUERYBUF; break;
 652        case VIDIOC_QBUF32: realcmd = cmd = VIDIOC_QBUF; break;
 653        case VIDIOC_DQBUF32: realcmd = cmd = VIDIOC_DQBUF; break;
 654        case VIDIOC_STREAMON32: realcmd = cmd = VIDIOC_STREAMON; break;
 655        case VIDIOC_STREAMOFF32: realcmd = cmd = VIDIOC_STREAMOFF; break;
 656        case VIDIOC_G_FBUF32: realcmd = cmd = VIDIOC_G_FBUF; break;
 657        case VIDIOC_S_FBUF32: realcmd = cmd = VIDIOC_S_FBUF; break;
 658        case VIDIOC_OVERLAY32: realcmd = cmd = VIDIOC_OVERLAY; break;
 659        case VIDIOC_ENUMSTD32: realcmd = VIDIOC_ENUMSTD; break;
 660        case VIDIOC_ENUMINPUT32: realcmd = VIDIOC_ENUMINPUT; break;
 661        case VIDIOC_S_CTRL32: realcmd = cmd = VIDIOC_S_CTRL; break;
 662        case VIDIOC_G_INPUT32: realcmd = cmd = VIDIOC_G_INPUT; break;
 663        case VIDIOC_S_INPUT32: realcmd = cmd = VIDIOC_S_INPUT; break;
 664        case VIDIOC_TRY_FMT32: realcmd = cmd = VIDIOC_TRY_FMT; break;
 665        };
 666
 667        switch(cmd) {
 668#ifdef CONFIG_VIDEO_V4L1_COMPAT
 669        case VIDIOCSTUNER:
 670        case VIDIOCGTUNER:
 671                err = get_video_tuner32(&karg.vt, up);
 672                compatible_arg = 0;
 673
 674                break;
 675
 676        case VIDIOCSFBUF:
 677                err = get_video_buffer32(&karg.vb, up);
 678                compatible_arg = 0;
 679                break;
 680
 681
 682        case VIDIOCSFREQ:
 683#endif
 684        case VIDIOC_S_INPUT:
 685        case VIDIOC_OVERLAY:
 686        case VIDIOC_STREAMON:
 687        case VIDIOC_STREAMOFF:
 688                err = get_user(karg.vx, (u32 __user *)up);
 689                compatible_arg = 1;
 690                break;
 691
 692        case VIDIOC_S_FBUF:
 693                err = get_v4l2_framebuffer32(&karg.v2fb, up);
 694                compatible_arg = 0;
 695                break;
 696
 697        case VIDIOC_G_FMT:
 698        case VIDIOC_S_FMT:
 699        case VIDIOC_TRY_FMT:
 700                err = get_v4l2_format32(&karg.v2f, up);
 701                compatible_arg = 0;
 702                break;
 703
 704        case VIDIOC_QUERYBUF:
 705        case VIDIOC_QBUF:
 706        case VIDIOC_DQBUF:
 707                err = get_v4l2_buffer32(&karg.v2b, up);
 708                compatible_arg = 0;
 709                break;
 710
 711        case VIDIOC_ENUMSTD:
 712                err = get_v4l2_standard(&karg.v2s, up);
 713                compatible_arg = 0;
 714                break;
 715
 716        case VIDIOC_ENUMSTD32:
 717                err = get_v4l2_standard32(&karg.v2s, up);
 718                compatible_arg = 0;
 719                break;
 720
 721        case VIDIOC_ENUMINPUT:
 722                err = get_v4l2_input(&karg.v2i, up);
 723                compatible_arg = 0;
 724                break;
 725
 726        case VIDIOC_ENUMINPUT32:
 727                err = get_v4l2_input32(&karg.v2i, up);
 728                compatible_arg = 0;
 729                break;
 730
 731        case VIDIOC_G_TUNER:
 732        case VIDIOC_S_TUNER:
 733                err = get_v4l2_tuner(&karg.v2t, up);
 734                compatible_arg = 0;
 735                break;
 736
 737#ifdef CONFIG_VIDEO_V4L1_COMPAT
 738        case VIDIOCGWIN:
 739        case VIDIOCGFBUF:
 740        case VIDIOCGFREQ:
 741#endif
 742        case VIDIOC_G_FBUF:
 743        case VIDIOC_G_INPUT:
 744                compatible_arg = 0;
 745                break;
 746#ifdef CONFIG_VIDEO_V4L1_COMPAT
 747        case VIDIOCSMICROCODE:
 748                err = microcode32(&karg.vc, up);
 749                compatible_arg = 0;
 750                break;
 751#endif
 752        };
 753        if(err)
 754                goto out;
 755
 756        if(compatible_arg)
 757                err = native_ioctl(file, realcmd, (unsigned long)up);
 758        else {
 759                mm_segment_t old_fs = get_fs();
 760
 761                set_fs(KERNEL_DS);
 762                err = native_ioctl(file, realcmd, (unsigned long) &karg);
 763                set_fs(old_fs);
 764        }
 765        if(err == 0) {
 766                switch(cmd) {
 767#ifdef CONFIG_VIDEO_V4L1_COMPAT
 768                case VIDIOCGTUNER:
 769                        err = put_video_tuner32(&karg.vt, up);
 770                        break;
 771
 772                case VIDIOCGWIN:
 773                        err = put_video_window32(&karg.vw, up);
 774                        break;
 775
 776                case VIDIOCGFBUF:
 777                        err = put_video_buffer32(&karg.vb, up);
 778                        break;
 779
 780#endif
 781                case VIDIOC_G_FBUF:
 782                        err = put_v4l2_framebuffer32(&karg.v2fb, up);
 783                        break;
 784
 785                case VIDIOC_G_FMT:
 786                case VIDIOC_S_FMT:
 787                case VIDIOC_TRY_FMT:
 788                        err = put_v4l2_format32(&karg.v2f, up);
 789                        break;
 790
 791                case VIDIOC_QUERYBUF:
 792                case VIDIOC_QBUF:
 793                case VIDIOC_DQBUF:
 794                        err = put_v4l2_buffer32(&karg.v2b, up);
 795                        break;
 796
 797                case VIDIOC_ENUMSTD:
 798                        err = put_v4l2_standard(&karg.v2s, up);
 799                        break;
 800
 801                case VIDIOC_ENUMSTD32:
 802                        err = put_v4l2_standard32(&karg.v2s, up);
 803                        break;
 804
 805                case VIDIOC_G_TUNER:
 806                case VIDIOC_S_TUNER:
 807                        err = put_v4l2_tuner(&karg.v2t, up);
 808                        break;
 809
 810                case VIDIOC_ENUMINPUT:
 811                        err = put_v4l2_input(&karg.v2i, up);
 812                        break;
 813
 814                case VIDIOC_ENUMINPUT32:
 815                        err = put_v4l2_input32(&karg.v2i, up);
 816                        break;
 817
 818#ifdef CONFIG_VIDEO_V4L1_COMPAT
 819                case VIDIOCGFREQ:
 820#endif
 821                case VIDIOC_G_INPUT:
 822                        err = put_user(((u32)karg.vx), (u32 __user *)up);
 823                        break;
 824                };
 825        }
 826out:
 827        return err;
 828}
 829
 830long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
 831{
 832        int ret = -ENOIOCTLCMD;
 833
 834        if (!file->f_op->ioctl)
 835                return ret;
 836
 837        switch (cmd) {
 838#ifdef CONFIG_VIDEO_V4L1_COMPAT
 839        case VIDIOCSWIN32:
 840                ret = do_set_window(file, cmd, arg);
 841                break;
 842        case VIDIOCGTUNER32:
 843        case VIDIOCSTUNER32:
 844        case VIDIOCGWIN32:
 845        case VIDIOCGFBUF32:
 846        case VIDIOCSFBUF32:
 847        case VIDIOCGFREQ32:
 848        case VIDIOCSFREQ32:
 849        case VIDIOCGAUDIO:
 850        case VIDIOCSAUDIO:
 851        case VIDIOCGVBIFMT:
 852        case VIDIOCSVBIFMT:
 853#endif
 854        case VIDIOC_QUERYCAP:
 855        case VIDIOC_ENUM_FMT:
 856        case VIDIOC_G_FMT32:
 857        case VIDIOC_CROPCAP:
 858        case VIDIOC_S_CROP:
 859        case VIDIOC_S_FMT32:
 860        case VIDIOC_REQBUFS:
 861        case VIDIOC_QUERYBUF32:
 862        case VIDIOC_G_FBUF32:
 863        case VIDIOC_S_FBUF32:
 864        case VIDIOC_OVERLAY32:
 865        case VIDIOC_QBUF32:
 866        case VIDIOC_DQBUF32:
 867        case VIDIOC_STREAMON32:
 868        case VIDIOC_STREAMOFF32:
 869        case VIDIOC_G_PARM:
 870        case VIDIOC_G_STD:
 871        case VIDIOC_S_STD:
 872        case VIDIOC_G_TUNER:
 873        case VIDIOC_S_TUNER:
 874        case VIDIOC_ENUMSTD:
 875        case VIDIOC_ENUMSTD32:
 876        case VIDIOC_ENUMINPUT:
 877        case VIDIOC_ENUMINPUT32:
 878        case VIDIOC_G_CTRL:
 879        case VIDIOC_S_CTRL:
 880        case VIDIOC_S_CTRL32:
 881        case VIDIOC_S_FREQUENCY:
 882        case VIDIOC_G_FREQUENCY:
 883        case VIDIOC_QUERYCTRL:
 884        case VIDIOC_G_INPUT32:
 885        case VIDIOC_S_INPUT32:
 886        case VIDIOC_TRY_FMT32:
 887                ret = do_video_ioctl(file, cmd, arg);
 888                break;
 889
 890#ifdef CONFIG_VIDEO_V4L1_COMPAT
 891        /* Little v, the video4linux ioctls (conflict?) */
 892        case VIDIOCGCAP:
 893        case VIDIOCGCHAN:
 894        case VIDIOCSCHAN:
 895        case VIDIOCGPICT:
 896        case VIDIOCSPICT:
 897        case VIDIOCCAPTURE:
 898        case VIDIOCKEY:
 899        case VIDIOCSYNC:
 900        case VIDIOCMCAPTURE:
 901        case VIDIOCGMBUF:
 902        case VIDIOCGUNIT:
 903        case VIDIOCGCAPTURE:
 904        case VIDIOCSCAPTURE:
 905
 906        /* BTTV specific... */
 907        case _IOW('v',  BASE_VIDIOCPRIVATE+0, char [256]):
 908        case _IOR('v',  BASE_VIDIOCPRIVATE+1, char [256]):
 909        case _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int):
 910        case _IOW('v' , BASE_VIDIOCPRIVATE+3, char [16]): /* struct bttv_pll_info */
 911        case _IOR('v' , BASE_VIDIOCPRIVATE+4, int):
 912        case _IOR('v' , BASE_VIDIOCPRIVATE+5, int):
 913        case _IOR('v' , BASE_VIDIOCPRIVATE+6, int):
 914        case _IOR('v' , BASE_VIDIOCPRIVATE+7, int):
 915                ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
 916                break;
 917#endif
 918        default:
 919                v4l_print_ioctl("compat_ioctl32", cmd);
 920        }
 921        return ret;
 922}
 923#else
 924long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
 925{
 926        return -ENOIOCTLCMD;
 927}
 928#endif
 929EXPORT_SYMBOL_GPL(v4l_compat_ioctl32);
 930
 931MODULE_LICENSE("GPL");
 932