Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
0004  *  Separated from fs stuff by Arnd Bergmann <arnd@arndb.de>
0005  *
0006  * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
0007  * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
0008  * Copyright (C) 2001,2002  Andi Kleen, SuSE Labs
0009  * Copyright (C) 2003       Pavel Machek (pavel@ucw.cz)
0010  * Copyright (C) 2005       Philippe De Muyter (phdm@macqel.be)
0011  * Copyright (C) 2008       Hans Verkuil <hverkuil@xs4all.nl>
0012  *
0013  * These routines maintain argument size conversion between 32bit and 64bit
0014  * ioctls.
0015  */
0016 
0017 #include <linux/compat.h>
0018 #include <linux/module.h>
0019 #include <linux/videodev2.h>
0020 #include <linux/v4l2-subdev.h>
0021 #include <media/v4l2-dev.h>
0022 #include <media/v4l2-fh.h>
0023 #include <media/v4l2-ctrls.h>
0024 #include <media/v4l2-ioctl.h>
0025 
0026 /*
0027  * Per-ioctl data copy handlers.
0028  *
0029  * Those come in pairs, with a get_v4l2_foo() and a put_v4l2_foo() routine,
0030  * where "v4l2_foo" is the name of the V4L2 struct.
0031  *
0032  * They basically get two __user pointers, one with a 32-bits struct that
0033  * came from the userspace call and a 64-bits struct, also allocated as
0034  * userspace, but filled internally by do_video_ioctl().
0035  *
0036  * For ioctls that have pointers inside it, the functions will also
0037  * receive an ancillary buffer with extra space, used to pass extra
0038  * data to the routine.
0039  */
0040 
0041 struct v4l2_clip32 {
0042     struct v4l2_rect        c;
0043     compat_caddr_t      next;
0044 };
0045 
0046 struct v4l2_window32 {
0047     struct v4l2_rect        w;
0048     __u32           field;  /* enum v4l2_field */
0049     __u32           chromakey;
0050     compat_caddr_t      clips; /* actually struct v4l2_clip32 * */
0051     __u32           clipcount;
0052     compat_caddr_t      bitmap;
0053     __u8                    global_alpha;
0054 };
0055 
0056 static int get_v4l2_window32(struct v4l2_window *p64,
0057                  struct v4l2_window32 __user *p32)
0058 {
0059     struct v4l2_window32 w32;
0060 
0061     if (copy_from_user(&w32, p32, sizeof(w32)))
0062         return -EFAULT;
0063 
0064     *p64 = (struct v4l2_window) {
0065         .w      = w32.w,
0066         .field      = w32.field,
0067         .chromakey  = w32.chromakey,
0068         .clips      = (void __force *)compat_ptr(w32.clips),
0069         .clipcount  = w32.clipcount,
0070         .bitmap     = compat_ptr(w32.bitmap),
0071         .global_alpha   = w32.global_alpha,
0072     };
0073 
0074     if (p64->clipcount > 2048)
0075         return -EINVAL;
0076     if (!p64->clipcount)
0077         p64->clips = NULL;
0078 
0079     return 0;
0080 }
0081 
0082 static int put_v4l2_window32(struct v4l2_window *p64,
0083                  struct v4l2_window32 __user *p32)
0084 {
0085     struct v4l2_window32 w32;
0086 
0087     memset(&w32, 0, sizeof(w32));
0088     w32 = (struct v4l2_window32) {
0089         .w      = p64->w,
0090         .field      = p64->field,
0091         .chromakey  = p64->chromakey,
0092         .clips      = (uintptr_t)p64->clips,
0093         .clipcount  = p64->clipcount,
0094         .bitmap     = ptr_to_compat(p64->bitmap),
0095         .global_alpha   = p64->global_alpha,
0096     };
0097 
0098     /* copy everything except the clips pointer */
0099     if (copy_to_user(p32, &w32, offsetof(struct v4l2_window32, clips)) ||
0100         copy_to_user(&p32->clipcount, &w32.clipcount,
0101              sizeof(w32) - offsetof(struct v4l2_window32, clipcount)))
0102         return -EFAULT;
0103 
0104     return 0;
0105 }
0106 
0107 struct v4l2_format32 {
0108     __u32   type;   /* enum v4l2_buf_type */
0109     union {
0110         struct v4l2_pix_format  pix;
0111         struct v4l2_pix_format_mplane   pix_mp;
0112         struct v4l2_window32    win;
0113         struct v4l2_vbi_format  vbi;
0114         struct v4l2_sliced_vbi_format   sliced;
0115         struct v4l2_sdr_format  sdr;
0116         struct v4l2_meta_format meta;
0117         __u8    raw_data[200];        /* user-defined */
0118     } fmt;
0119 };
0120 
0121 /**
0122  * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument
0123  * @index:  on return, index of the first created buffer
0124  * @count:  entry: number of requested buffers,
0125  *      return: number of created buffers
0126  * @memory: buffer memory type
0127  * @format: frame format, for which buffers are requested
0128  * @capabilities: capabilities of this buffer type.
0129  * @flags:  additional buffer management attributes (ignored unless the
0130  *      queue has V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS capability and
0131  *      configured for MMAP streaming I/O).
0132  * @reserved:   future extensions
0133  */
0134 struct v4l2_create_buffers32 {
0135     __u32           index;
0136     __u32           count;
0137     __u32           memory; /* enum v4l2_memory */
0138     struct v4l2_format32    format;
0139     __u32           capabilities;
0140     __u32           flags;
0141     __u32           reserved[6];
0142 };
0143 
0144 static int get_v4l2_format32(struct v4l2_format *p64,
0145                  struct v4l2_format32 __user *p32)
0146 {
0147     if (get_user(p64->type, &p32->type))
0148         return -EFAULT;
0149 
0150     switch (p64->type) {
0151     case V4L2_BUF_TYPE_VIDEO_CAPTURE:
0152     case V4L2_BUF_TYPE_VIDEO_OUTPUT:
0153         return copy_from_user(&p64->fmt.pix, &p32->fmt.pix,
0154                       sizeof(p64->fmt.pix)) ? -EFAULT : 0;
0155     case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
0156     case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
0157         return copy_from_user(&p64->fmt.pix_mp, &p32->fmt.pix_mp,
0158                       sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;
0159     case V4L2_BUF_TYPE_VIDEO_OVERLAY:
0160     case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
0161         return get_v4l2_window32(&p64->fmt.win, &p32->fmt.win);
0162     case V4L2_BUF_TYPE_VBI_CAPTURE:
0163     case V4L2_BUF_TYPE_VBI_OUTPUT:
0164         return copy_from_user(&p64->fmt.vbi, &p32->fmt.vbi,
0165                       sizeof(p64->fmt.vbi)) ? -EFAULT : 0;
0166     case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
0167     case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
0168         return copy_from_user(&p64->fmt.sliced, &p32->fmt.sliced,
0169                       sizeof(p64->fmt.sliced)) ? -EFAULT : 0;
0170     case V4L2_BUF_TYPE_SDR_CAPTURE:
0171     case V4L2_BUF_TYPE_SDR_OUTPUT:
0172         return copy_from_user(&p64->fmt.sdr, &p32->fmt.sdr,
0173                       sizeof(p64->fmt.sdr)) ? -EFAULT : 0;
0174     case V4L2_BUF_TYPE_META_CAPTURE:
0175     case V4L2_BUF_TYPE_META_OUTPUT:
0176         return copy_from_user(&p64->fmt.meta, &p32->fmt.meta,
0177                       sizeof(p64->fmt.meta)) ? -EFAULT : 0;
0178     default:
0179         return -EINVAL;
0180     }
0181 }
0182 
0183 static int get_v4l2_create32(struct v4l2_create_buffers *p64,
0184                  struct v4l2_create_buffers32 __user *p32)
0185 {
0186     if (copy_from_user(p64, p32,
0187                offsetof(struct v4l2_create_buffers32, format)))
0188         return -EFAULT;
0189     if (copy_from_user(&p64->flags, &p32->flags, sizeof(p32->flags)))
0190         return -EFAULT;
0191     return get_v4l2_format32(&p64->format, &p32->format);
0192 }
0193 
0194 static int put_v4l2_format32(struct v4l2_format *p64,
0195                  struct v4l2_format32 __user *p32)
0196 {
0197     switch (p64->type) {
0198     case V4L2_BUF_TYPE_VIDEO_CAPTURE:
0199     case V4L2_BUF_TYPE_VIDEO_OUTPUT:
0200         return copy_to_user(&p32->fmt.pix, &p64->fmt.pix,
0201                     sizeof(p64->fmt.pix)) ? -EFAULT : 0;
0202     case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
0203     case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
0204         return copy_to_user(&p32->fmt.pix_mp, &p64->fmt.pix_mp,
0205                     sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;
0206     case V4L2_BUF_TYPE_VIDEO_OVERLAY:
0207     case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
0208         return put_v4l2_window32(&p64->fmt.win, &p32->fmt.win);
0209     case V4L2_BUF_TYPE_VBI_CAPTURE:
0210     case V4L2_BUF_TYPE_VBI_OUTPUT:
0211         return copy_to_user(&p32->fmt.vbi, &p64->fmt.vbi,
0212                     sizeof(p64->fmt.vbi)) ? -EFAULT : 0;
0213     case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
0214     case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
0215         return copy_to_user(&p32->fmt.sliced, &p64->fmt.sliced,
0216                     sizeof(p64->fmt.sliced)) ? -EFAULT : 0;
0217     case V4L2_BUF_TYPE_SDR_CAPTURE:
0218     case V4L2_BUF_TYPE_SDR_OUTPUT:
0219         return copy_to_user(&p32->fmt.sdr, &p64->fmt.sdr,
0220                     sizeof(p64->fmt.sdr)) ? -EFAULT : 0;
0221     case V4L2_BUF_TYPE_META_CAPTURE:
0222     case V4L2_BUF_TYPE_META_OUTPUT:
0223         return copy_to_user(&p32->fmt.meta, &p64->fmt.meta,
0224                     sizeof(p64->fmt.meta)) ? -EFAULT : 0;
0225     default:
0226         return -EINVAL;
0227     }
0228 }
0229 
0230 static int put_v4l2_create32(struct v4l2_create_buffers *p64,
0231                  struct v4l2_create_buffers32 __user *p32)
0232 {
0233     if (copy_to_user(p32, p64,
0234              offsetof(struct v4l2_create_buffers32, format)) ||
0235         put_user(p64->capabilities, &p32->capabilities) ||
0236         put_user(p64->flags, &p32->flags) ||
0237         copy_to_user(p32->reserved, p64->reserved, sizeof(p64->reserved)))
0238         return -EFAULT;
0239     return put_v4l2_format32(&p64->format, &p32->format);
0240 }
0241 
0242 struct v4l2_standard32 {
0243     __u32            index;
0244     compat_u64       id;
0245     __u8             name[24];
0246     struct v4l2_fract    frameperiod; /* Frames, not fields */
0247     __u32            framelines;
0248     __u32            reserved[4];
0249 };
0250 
0251 static int get_v4l2_standard32(struct v4l2_standard *p64,
0252                    struct v4l2_standard32 __user *p32)
0253 {
0254     /* other fields are not set by the user, nor used by the driver */
0255     return get_user(p64->index, &p32->index);
0256 }
0257 
0258 static int put_v4l2_standard32(struct v4l2_standard *p64,
0259                    struct v4l2_standard32 __user *p32)
0260 {
0261     if (put_user(p64->index, &p32->index) ||
0262         put_user(p64->id, &p32->id) ||
0263         copy_to_user(p32->name, p64->name, sizeof(p32->name)) ||
0264         copy_to_user(&p32->frameperiod, &p64->frameperiod,
0265              sizeof(p32->frameperiod)) ||
0266         put_user(p64->framelines, &p32->framelines) ||
0267         copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
0268         return -EFAULT;
0269     return 0;
0270 }
0271 
0272 struct v4l2_plane32 {
0273     __u32           bytesused;
0274     __u32           length;
0275     union {
0276         __u32       mem_offset;
0277         compat_long_t   userptr;
0278         __s32       fd;
0279     } m;
0280     __u32           data_offset;
0281     __u32           reserved[11];
0282 };
0283 
0284 /*
0285  * This is correct for all architectures including i386, but not x32,
0286  * which has different alignment requirements for timestamp
0287  */
0288 struct v4l2_buffer32 {
0289     __u32           index;
0290     __u32           type;   /* enum v4l2_buf_type */
0291     __u32           bytesused;
0292     __u32           flags;
0293     __u32           field;  /* enum v4l2_field */
0294     struct {
0295         compat_s64  tv_sec;
0296         compat_s64  tv_usec;
0297     }           timestamp;
0298     struct v4l2_timecode    timecode;
0299     __u32           sequence;
0300 
0301     /* memory location */
0302     __u32           memory; /* enum v4l2_memory */
0303     union {
0304         __u32           offset;
0305         compat_long_t   userptr;
0306         compat_caddr_t  planes;
0307         __s32       fd;
0308     } m;
0309     __u32           length;
0310     __u32           reserved2;
0311     __s32           request_fd;
0312 };
0313 
0314 #ifdef CONFIG_COMPAT_32BIT_TIME
0315 struct v4l2_buffer32_time32 {
0316     __u32           index;
0317     __u32           type;   /* enum v4l2_buf_type */
0318     __u32           bytesused;
0319     __u32           flags;
0320     __u32           field;  /* enum v4l2_field */
0321     struct old_timeval32    timestamp;
0322     struct v4l2_timecode    timecode;
0323     __u32           sequence;
0324 
0325     /* memory location */
0326     __u32           memory; /* enum v4l2_memory */
0327     union {
0328         __u32           offset;
0329         compat_long_t   userptr;
0330         compat_caddr_t  planes;
0331         __s32       fd;
0332     } m;
0333     __u32           length;
0334     __u32           reserved2;
0335     __s32           request_fd;
0336 };
0337 #endif
0338 
0339 static int get_v4l2_plane32(struct v4l2_plane *p64,
0340                 struct v4l2_plane32 __user *p32,
0341                 enum v4l2_memory memory)
0342 {
0343     struct v4l2_plane32 plane32;
0344     typeof(p64->m) m = {};
0345 
0346     if (copy_from_user(&plane32, p32, sizeof(plane32)))
0347         return -EFAULT;
0348 
0349     switch (memory) {
0350     case V4L2_MEMORY_MMAP:
0351     case V4L2_MEMORY_OVERLAY:
0352         m.mem_offset = plane32.m.mem_offset;
0353         break;
0354     case V4L2_MEMORY_USERPTR:
0355         m.userptr = (unsigned long)compat_ptr(plane32.m.userptr);
0356         break;
0357     case V4L2_MEMORY_DMABUF:
0358         m.fd = plane32.m.fd;
0359         break;
0360     }
0361 
0362     memset(p64, 0, sizeof(*p64));
0363     *p64 = (struct v4l2_plane) {
0364         .bytesused  = plane32.bytesused,
0365         .length     = plane32.length,
0366         .m      = m,
0367         .data_offset    = plane32.data_offset,
0368     };
0369 
0370     return 0;
0371 }
0372 
0373 static int put_v4l2_plane32(struct v4l2_plane *p64,
0374                 struct v4l2_plane32 __user *p32,
0375                 enum v4l2_memory memory)
0376 {
0377     struct v4l2_plane32 plane32;
0378 
0379     memset(&plane32, 0, sizeof(plane32));
0380     plane32 = (struct v4l2_plane32) {
0381         .bytesused  = p64->bytesused,
0382         .length     = p64->length,
0383         .data_offset    = p64->data_offset,
0384     };
0385 
0386     switch (memory) {
0387     case V4L2_MEMORY_MMAP:
0388     case V4L2_MEMORY_OVERLAY:
0389         plane32.m.mem_offset = p64->m.mem_offset;
0390         break;
0391     case V4L2_MEMORY_USERPTR:
0392         plane32.m.userptr = (uintptr_t)(p64->m.userptr);
0393         break;
0394     case V4L2_MEMORY_DMABUF:
0395         plane32.m.fd = p64->m.fd;
0396         break;
0397     }
0398 
0399     if (copy_to_user(p32, &plane32, sizeof(plane32)))
0400         return -EFAULT;
0401 
0402     return 0;
0403 }
0404 
0405 static int get_v4l2_buffer32(struct v4l2_buffer *vb,
0406                  struct v4l2_buffer32 __user *arg)
0407 {
0408     struct v4l2_buffer32 vb32;
0409 
0410     if (copy_from_user(&vb32, arg, sizeof(vb32)))
0411         return -EFAULT;
0412 
0413     memset(vb, 0, sizeof(*vb));
0414     *vb = (struct v4l2_buffer) {
0415         .index      = vb32.index,
0416         .type       = vb32.type,
0417         .bytesused  = vb32.bytesused,
0418         .flags      = vb32.flags,
0419         .field      = vb32.field,
0420         .timestamp.tv_sec   = vb32.timestamp.tv_sec,
0421         .timestamp.tv_usec  = vb32.timestamp.tv_usec,
0422         .timecode   = vb32.timecode,
0423         .sequence   = vb32.sequence,
0424         .memory     = vb32.memory,
0425         .m.offset   = vb32.m.offset,
0426         .length     = vb32.length,
0427         .request_fd = vb32.request_fd,
0428     };
0429 
0430     switch (vb->memory) {
0431     case V4L2_MEMORY_MMAP:
0432     case V4L2_MEMORY_OVERLAY:
0433         vb->m.offset = vb32.m.offset;
0434         break;
0435     case V4L2_MEMORY_USERPTR:
0436         vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr);
0437         break;
0438     case V4L2_MEMORY_DMABUF:
0439         vb->m.fd = vb32.m.fd;
0440         break;
0441     }
0442 
0443     if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
0444         vb->m.planes = (void __force *)
0445                 compat_ptr(vb32.m.planes);
0446 
0447     return 0;
0448 }
0449 
0450 #ifdef CONFIG_COMPAT_32BIT_TIME
0451 static int get_v4l2_buffer32_time32(struct v4l2_buffer *vb,
0452                     struct v4l2_buffer32_time32 __user *arg)
0453 {
0454     struct v4l2_buffer32_time32 vb32;
0455 
0456     if (copy_from_user(&vb32, arg, sizeof(vb32)))
0457         return -EFAULT;
0458 
0459     *vb = (struct v4l2_buffer) {
0460         .index      = vb32.index,
0461         .type       = vb32.type,
0462         .bytesused  = vb32.bytesused,
0463         .flags      = vb32.flags,
0464         .field      = vb32.field,
0465         .timestamp.tv_sec   = vb32.timestamp.tv_sec,
0466         .timestamp.tv_usec  = vb32.timestamp.tv_usec,
0467         .timecode   = vb32.timecode,
0468         .sequence   = vb32.sequence,
0469         .memory     = vb32.memory,
0470         .m.offset   = vb32.m.offset,
0471         .length     = vb32.length,
0472         .request_fd = vb32.request_fd,
0473     };
0474     switch (vb->memory) {
0475     case V4L2_MEMORY_MMAP:
0476     case V4L2_MEMORY_OVERLAY:
0477         vb->m.offset = vb32.m.offset;
0478         break;
0479     case V4L2_MEMORY_USERPTR:
0480         vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr);
0481         break;
0482     case V4L2_MEMORY_DMABUF:
0483         vb->m.fd = vb32.m.fd;
0484         break;
0485     }
0486 
0487     if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
0488         vb->m.planes = (void __force *)
0489                 compat_ptr(vb32.m.planes);
0490 
0491     return 0;
0492 }
0493 #endif
0494 
0495 static int put_v4l2_buffer32(struct v4l2_buffer *vb,
0496                  struct v4l2_buffer32 __user *arg)
0497 {
0498     struct v4l2_buffer32 vb32;
0499 
0500     memset(&vb32, 0, sizeof(vb32));
0501     vb32 = (struct v4l2_buffer32) {
0502         .index      = vb->index,
0503         .type       = vb->type,
0504         .bytesused  = vb->bytesused,
0505         .flags      = vb->flags,
0506         .field      = vb->field,
0507         .timestamp.tv_sec   = vb->timestamp.tv_sec,
0508         .timestamp.tv_usec  = vb->timestamp.tv_usec,
0509         .timecode   = vb->timecode,
0510         .sequence   = vb->sequence,
0511         .memory     = vb->memory,
0512         .m.offset   = vb->m.offset,
0513         .length     = vb->length,
0514         .request_fd = vb->request_fd,
0515     };
0516 
0517     switch (vb->memory) {
0518     case V4L2_MEMORY_MMAP:
0519     case V4L2_MEMORY_OVERLAY:
0520         vb32.m.offset = vb->m.offset;
0521         break;
0522     case V4L2_MEMORY_USERPTR:
0523         vb32.m.userptr = (uintptr_t)(vb->m.userptr);
0524         break;
0525     case V4L2_MEMORY_DMABUF:
0526         vb32.m.fd = vb->m.fd;
0527         break;
0528     }
0529 
0530     if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
0531         vb32.m.planes = (uintptr_t)vb->m.planes;
0532 
0533     if (copy_to_user(arg, &vb32, sizeof(vb32)))
0534         return -EFAULT;
0535 
0536     return 0;
0537 }
0538 
0539 #ifdef CONFIG_COMPAT_32BIT_TIME
0540 static int put_v4l2_buffer32_time32(struct v4l2_buffer *vb,
0541                     struct v4l2_buffer32_time32 __user *arg)
0542 {
0543     struct v4l2_buffer32_time32 vb32;
0544 
0545     memset(&vb32, 0, sizeof(vb32));
0546     vb32 = (struct v4l2_buffer32_time32) {
0547         .index      = vb->index,
0548         .type       = vb->type,
0549         .bytesused  = vb->bytesused,
0550         .flags      = vb->flags,
0551         .field      = vb->field,
0552         .timestamp.tv_sec   = vb->timestamp.tv_sec,
0553         .timestamp.tv_usec  = vb->timestamp.tv_usec,
0554         .timecode   = vb->timecode,
0555         .sequence   = vb->sequence,
0556         .memory     = vb->memory,
0557         .m.offset   = vb->m.offset,
0558         .length     = vb->length,
0559         .request_fd = vb->request_fd,
0560     };
0561     switch (vb->memory) {
0562     case V4L2_MEMORY_MMAP:
0563     case V4L2_MEMORY_OVERLAY:
0564         vb32.m.offset = vb->m.offset;
0565         break;
0566     case V4L2_MEMORY_USERPTR:
0567         vb32.m.userptr = (uintptr_t)(vb->m.userptr);
0568         break;
0569     case V4L2_MEMORY_DMABUF:
0570         vb32.m.fd = vb->m.fd;
0571         break;
0572     }
0573 
0574     if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
0575         vb32.m.planes = (uintptr_t)vb->m.planes;
0576 
0577     if (copy_to_user(arg, &vb32, sizeof(vb32)))
0578         return -EFAULT;
0579 
0580     return 0;
0581 }
0582 #endif
0583 
0584 struct v4l2_framebuffer32 {
0585     __u32           capability;
0586     __u32           flags;
0587     compat_caddr_t      base;
0588     struct {
0589         __u32       width;
0590         __u32       height;
0591         __u32       pixelformat;
0592         __u32       field;
0593         __u32       bytesperline;
0594         __u32       sizeimage;
0595         __u32       colorspace;
0596         __u32       priv;
0597     } fmt;
0598 };
0599 
0600 static int get_v4l2_framebuffer32(struct v4l2_framebuffer *p64,
0601                   struct v4l2_framebuffer32 __user *p32)
0602 {
0603     compat_caddr_t tmp;
0604 
0605     if (get_user(tmp, &p32->base) ||
0606         get_user(p64->capability, &p32->capability) ||
0607         get_user(p64->flags, &p32->flags) ||
0608         copy_from_user(&p64->fmt, &p32->fmt, sizeof(p64->fmt)))
0609         return -EFAULT;
0610     p64->base = (void __force *)compat_ptr(tmp);
0611 
0612     return 0;
0613 }
0614 
0615 static int put_v4l2_framebuffer32(struct v4l2_framebuffer *p64,
0616                   struct v4l2_framebuffer32 __user *p32)
0617 {
0618     if (put_user((uintptr_t)p64->base, &p32->base) ||
0619         put_user(p64->capability, &p32->capability) ||
0620         put_user(p64->flags, &p32->flags) ||
0621         copy_to_user(&p32->fmt, &p64->fmt, sizeof(p64->fmt)))
0622         return -EFAULT;
0623 
0624     return 0;
0625 }
0626 
0627 struct v4l2_input32 {
0628     __u32        index;     /*  Which input */
0629     __u8         name[32];      /*  Label */
0630     __u32        type;      /*  Type of input */
0631     __u32        audioset;      /*  Associated audios (bitfield) */
0632     __u32        tuner;             /*  Associated tuner */
0633     compat_u64   std;
0634     __u32        status;
0635     __u32        capabilities;
0636     __u32        reserved[3];
0637 };
0638 
0639 /*
0640  * The 64-bit v4l2_input struct has extra padding at the end of the struct.
0641  * Otherwise it is identical to the 32-bit version.
0642  */
0643 static inline int get_v4l2_input32(struct v4l2_input *p64,
0644                    struct v4l2_input32 __user *p32)
0645 {
0646     if (copy_from_user(p64, p32, sizeof(*p32)))
0647         return -EFAULT;
0648     return 0;
0649 }
0650 
0651 static inline int put_v4l2_input32(struct v4l2_input *p64,
0652                    struct v4l2_input32 __user *p32)
0653 {
0654     if (copy_to_user(p32, p64, sizeof(*p32)))
0655         return -EFAULT;
0656     return 0;
0657 }
0658 
0659 struct v4l2_ext_controls32 {
0660     __u32 which;
0661     __u32 count;
0662     __u32 error_idx;
0663     __s32 request_fd;
0664     __u32 reserved[1];
0665     compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
0666 };
0667 
0668 struct v4l2_ext_control32 {
0669     __u32 id;
0670     __u32 size;
0671     __u32 reserved2[1];
0672     union {
0673         __s32 value;
0674         __s64 value64;
0675         compat_caddr_t string; /* actually char * */
0676     };
0677 } __attribute__ ((packed));
0678 
0679 /* Return true if this control is a pointer type. */
0680 static inline bool ctrl_is_pointer(struct file *file, u32 id)
0681 {
0682     struct video_device *vdev = video_devdata(file);
0683     struct v4l2_fh *fh = NULL;
0684     struct v4l2_ctrl_handler *hdl = NULL;
0685     struct v4l2_query_ext_ctrl qec = { id };
0686     const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
0687 
0688     if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
0689         fh = file->private_data;
0690 
0691     if (fh && fh->ctrl_handler)
0692         hdl = fh->ctrl_handler;
0693     else if (vdev->ctrl_handler)
0694         hdl = vdev->ctrl_handler;
0695 
0696     if (hdl) {
0697         struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id);
0698 
0699         return ctrl && ctrl->is_ptr;
0700     }
0701 
0702     if (!ops || !ops->vidioc_query_ext_ctrl)
0703         return false;
0704 
0705     return !ops->vidioc_query_ext_ctrl(file, fh, &qec) &&
0706         (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
0707 }
0708 
0709 static int get_v4l2_ext_controls32(struct v4l2_ext_controls *p64,
0710                    struct v4l2_ext_controls32 __user *p32)
0711 {
0712     struct v4l2_ext_controls32 ec32;
0713 
0714     if (copy_from_user(&ec32, p32, sizeof(ec32)))
0715         return -EFAULT;
0716 
0717     *p64 = (struct v4l2_ext_controls) {
0718         .which      = ec32.which,
0719         .count      = ec32.count,
0720         .error_idx  = ec32.error_idx,
0721         .request_fd = ec32.request_fd,
0722         .reserved[0]    = ec32.reserved[0],
0723         .controls   = (void __force *)compat_ptr(ec32.controls),
0724     };
0725 
0726     return 0;
0727 }
0728 
0729 static int put_v4l2_ext_controls32(struct v4l2_ext_controls *p64,
0730                    struct v4l2_ext_controls32 __user *p32)
0731 {
0732     struct v4l2_ext_controls32 ec32;
0733 
0734     memset(&ec32, 0, sizeof(ec32));
0735     ec32 = (struct v4l2_ext_controls32) {
0736         .which      = p64->which,
0737         .count      = p64->count,
0738         .error_idx  = p64->error_idx,
0739         .request_fd = p64->request_fd,
0740         .reserved[0]    = p64->reserved[0],
0741         .controls   = (uintptr_t)p64->controls,
0742     };
0743 
0744     if (copy_to_user(p32, &ec32, sizeof(ec32)))
0745         return -EFAULT;
0746 
0747     return 0;
0748 }
0749 
0750 #ifdef CONFIG_X86_64
0751 /*
0752  * x86 is the only compat architecture with different struct alignment
0753  * between 32-bit and 64-bit tasks.
0754  */
0755 struct v4l2_event32 {
0756     __u32               type;
0757     union {
0758         compat_s64      value64;
0759         __u8            data[64];
0760     } u;
0761     __u32               pending;
0762     __u32               sequence;
0763     struct {
0764         compat_s64      tv_sec;
0765         compat_s64      tv_nsec;
0766     } timestamp;
0767     __u32               id;
0768     __u32               reserved[8];
0769 };
0770 
0771 static int put_v4l2_event32(struct v4l2_event *p64,
0772                 struct v4l2_event32 __user *p32)
0773 {
0774     if (put_user(p64->type, &p32->type) ||
0775         copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) ||
0776         put_user(p64->pending, &p32->pending) ||
0777         put_user(p64->sequence, &p32->sequence) ||
0778         put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) ||
0779         put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) ||
0780         put_user(p64->id, &p32->id) ||
0781         copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
0782         return -EFAULT;
0783     return 0;
0784 }
0785 
0786 #endif
0787 
0788 #ifdef CONFIG_COMPAT_32BIT_TIME
0789 struct v4l2_event32_time32 {
0790     __u32               type;
0791     union {
0792         compat_s64      value64;
0793         __u8            data[64];
0794     } u;
0795     __u32               pending;
0796     __u32               sequence;
0797     struct old_timespec32       timestamp;
0798     __u32               id;
0799     __u32               reserved[8];
0800 };
0801 
0802 static int put_v4l2_event32_time32(struct v4l2_event *p64,
0803                    struct v4l2_event32_time32 __user *p32)
0804 {
0805     if (put_user(p64->type, &p32->type) ||
0806         copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) ||
0807         put_user(p64->pending, &p32->pending) ||
0808         put_user(p64->sequence, &p32->sequence) ||
0809         put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) ||
0810         put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) ||
0811         put_user(p64->id, &p32->id) ||
0812         copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
0813         return -EFAULT;
0814     return 0;
0815 }
0816 #endif
0817 
0818 struct v4l2_edid32 {
0819     __u32 pad;
0820     __u32 start_block;
0821     __u32 blocks;
0822     __u32 reserved[5];
0823     compat_caddr_t edid;
0824 };
0825 
0826 static int get_v4l2_edid32(struct v4l2_edid *p64,
0827                struct v4l2_edid32 __user *p32)
0828 {
0829     compat_uptr_t edid;
0830 
0831     if (copy_from_user(p64, p32, offsetof(struct v4l2_edid32, edid)) ||
0832         get_user(edid, &p32->edid))
0833         return -EFAULT;
0834 
0835     p64->edid = (void __force *)compat_ptr(edid);
0836     return 0;
0837 }
0838 
0839 static int put_v4l2_edid32(struct v4l2_edid *p64,
0840                struct v4l2_edid32 __user *p32)
0841 {
0842     if (copy_to_user(p32, p64, offsetof(struct v4l2_edid32, edid)))
0843         return -EFAULT;
0844     return 0;
0845 }
0846 
0847 /*
0848  * List of ioctls that require 32-bits/64-bits conversion
0849  *
0850  * The V4L2 ioctls that aren't listed there don't have pointer arguments
0851  * and the struct size is identical for both 32 and 64 bits versions, so
0852  * they don't need translations.
0853  */
0854 
0855 #define VIDIOC_G_FMT32      _IOWR('V',  4, struct v4l2_format32)
0856 #define VIDIOC_S_FMT32      _IOWR('V',  5, struct v4l2_format32)
0857 #define VIDIOC_QUERYBUF32   _IOWR('V',  9, struct v4l2_buffer32)
0858 #define VIDIOC_G_FBUF32     _IOR ('V', 10, struct v4l2_framebuffer32)
0859 #define VIDIOC_S_FBUF32     _IOW ('V', 11, struct v4l2_framebuffer32)
0860 #define VIDIOC_QBUF32       _IOWR('V', 15, struct v4l2_buffer32)
0861 #define VIDIOC_DQBUF32      _IOWR('V', 17, struct v4l2_buffer32)
0862 #define VIDIOC_ENUMSTD32    _IOWR('V', 25, struct v4l2_standard32)
0863 #define VIDIOC_ENUMINPUT32  _IOWR('V', 26, struct v4l2_input32)
0864 #define VIDIOC_G_EDID32     _IOWR('V', 40, struct v4l2_edid32)
0865 #define VIDIOC_S_EDID32     _IOWR('V', 41, struct v4l2_edid32)
0866 #define VIDIOC_TRY_FMT32    _IOWR('V', 64, struct v4l2_format32)
0867 #define VIDIOC_G_EXT_CTRLS32    _IOWR('V', 71, struct v4l2_ext_controls32)
0868 #define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
0869 #define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)
0870 #define VIDIOC_DQEVENT32    _IOR ('V', 89, struct v4l2_event32)
0871 #define VIDIOC_CREATE_BUFS32    _IOWR('V', 92, struct v4l2_create_buffers32)
0872 #define VIDIOC_PREPARE_BUF32    _IOWR('V', 93, struct v4l2_buffer32)
0873 
0874 #ifdef CONFIG_COMPAT_32BIT_TIME
0875 #define VIDIOC_QUERYBUF32_TIME32    _IOWR('V',  9, struct v4l2_buffer32_time32)
0876 #define VIDIOC_QBUF32_TIME32        _IOWR('V', 15, struct v4l2_buffer32_time32)
0877 #define VIDIOC_DQBUF32_TIME32       _IOWR('V', 17, struct v4l2_buffer32_time32)
0878 #define VIDIOC_DQEVENT32_TIME32     _IOR ('V', 89, struct v4l2_event32_time32)
0879 #define VIDIOC_PREPARE_BUF32_TIME32 _IOWR('V', 93, struct v4l2_buffer32_time32)
0880 #endif
0881 
0882 unsigned int v4l2_compat_translate_cmd(unsigned int cmd)
0883 {
0884     switch (cmd) {
0885     case VIDIOC_G_FMT32:
0886         return VIDIOC_G_FMT;
0887     case VIDIOC_S_FMT32:
0888         return VIDIOC_S_FMT;
0889     case VIDIOC_TRY_FMT32:
0890         return VIDIOC_TRY_FMT;
0891     case VIDIOC_G_FBUF32:
0892         return VIDIOC_G_FBUF;
0893     case VIDIOC_S_FBUF32:
0894         return VIDIOC_S_FBUF;
0895 #ifdef CONFIG_COMPAT_32BIT_TIME
0896     case VIDIOC_QUERYBUF32_TIME32:
0897         return VIDIOC_QUERYBUF;
0898     case VIDIOC_QBUF32_TIME32:
0899         return VIDIOC_QBUF;
0900     case VIDIOC_DQBUF32_TIME32:
0901         return VIDIOC_DQBUF;
0902     case VIDIOC_PREPARE_BUF32_TIME32:
0903         return VIDIOC_PREPARE_BUF;
0904 #endif
0905     case VIDIOC_QUERYBUF32:
0906         return VIDIOC_QUERYBUF;
0907     case VIDIOC_QBUF32:
0908         return VIDIOC_QBUF;
0909     case VIDIOC_DQBUF32:
0910         return VIDIOC_DQBUF;
0911     case VIDIOC_CREATE_BUFS32:
0912         return VIDIOC_CREATE_BUFS;
0913     case VIDIOC_G_EXT_CTRLS32:
0914         return VIDIOC_G_EXT_CTRLS;
0915     case VIDIOC_S_EXT_CTRLS32:
0916         return VIDIOC_S_EXT_CTRLS;
0917     case VIDIOC_TRY_EXT_CTRLS32:
0918         return VIDIOC_TRY_EXT_CTRLS;
0919     case VIDIOC_PREPARE_BUF32:
0920         return VIDIOC_PREPARE_BUF;
0921     case VIDIOC_ENUMSTD32:
0922         return VIDIOC_ENUMSTD;
0923     case VIDIOC_ENUMINPUT32:
0924         return VIDIOC_ENUMINPUT;
0925     case VIDIOC_G_EDID32:
0926         return VIDIOC_G_EDID;
0927     case VIDIOC_S_EDID32:
0928         return VIDIOC_S_EDID;
0929 #ifdef CONFIG_X86_64
0930     case VIDIOC_DQEVENT32:
0931         return VIDIOC_DQEVENT;
0932 #endif
0933 #ifdef CONFIG_COMPAT_32BIT_TIME
0934     case VIDIOC_DQEVENT32_TIME32:
0935         return VIDIOC_DQEVENT;
0936 #endif
0937     }
0938     return cmd;
0939 }
0940 
0941 int v4l2_compat_get_user(void __user *arg, void *parg, unsigned int cmd)
0942 {
0943     switch (cmd) {
0944     case VIDIOC_G_FMT32:
0945     case VIDIOC_S_FMT32:
0946     case VIDIOC_TRY_FMT32:
0947         return get_v4l2_format32(parg, arg);
0948 
0949     case VIDIOC_S_FBUF32:
0950         return get_v4l2_framebuffer32(parg, arg);
0951 #ifdef CONFIG_COMPAT_32BIT_TIME
0952     case VIDIOC_QUERYBUF32_TIME32:
0953     case VIDIOC_QBUF32_TIME32:
0954     case VIDIOC_DQBUF32_TIME32:
0955     case VIDIOC_PREPARE_BUF32_TIME32:
0956         return get_v4l2_buffer32_time32(parg, arg);
0957 #endif
0958     case VIDIOC_QUERYBUF32:
0959     case VIDIOC_QBUF32:
0960     case VIDIOC_DQBUF32:
0961     case VIDIOC_PREPARE_BUF32:
0962         return get_v4l2_buffer32(parg, arg);
0963 
0964     case VIDIOC_G_EXT_CTRLS32:
0965     case VIDIOC_S_EXT_CTRLS32:
0966     case VIDIOC_TRY_EXT_CTRLS32:
0967         return get_v4l2_ext_controls32(parg, arg);
0968 
0969     case VIDIOC_CREATE_BUFS32:
0970         return get_v4l2_create32(parg, arg);
0971 
0972     case VIDIOC_ENUMSTD32:
0973         return get_v4l2_standard32(parg, arg);
0974 
0975     case VIDIOC_ENUMINPUT32:
0976         return get_v4l2_input32(parg, arg);
0977 
0978     case VIDIOC_G_EDID32:
0979     case VIDIOC_S_EDID32:
0980         return get_v4l2_edid32(parg, arg);
0981     }
0982     return 0;
0983 }
0984 
0985 int v4l2_compat_put_user(void __user *arg, void *parg, unsigned int cmd)
0986 {
0987     switch (cmd) {
0988     case VIDIOC_G_FMT32:
0989     case VIDIOC_S_FMT32:
0990     case VIDIOC_TRY_FMT32:
0991         return put_v4l2_format32(parg, arg);
0992 
0993     case VIDIOC_G_FBUF32:
0994         return put_v4l2_framebuffer32(parg, arg);
0995 #ifdef CONFIG_COMPAT_32BIT_TIME
0996     case VIDIOC_QUERYBUF32_TIME32:
0997     case VIDIOC_QBUF32_TIME32:
0998     case VIDIOC_DQBUF32_TIME32:
0999     case VIDIOC_PREPARE_BUF32_TIME32:
1000         return put_v4l2_buffer32_time32(parg, arg);
1001 #endif
1002     case VIDIOC_QUERYBUF32:
1003     case VIDIOC_QBUF32:
1004     case VIDIOC_DQBUF32:
1005     case VIDIOC_PREPARE_BUF32:
1006         return put_v4l2_buffer32(parg, arg);
1007 
1008     case VIDIOC_G_EXT_CTRLS32:
1009     case VIDIOC_S_EXT_CTRLS32:
1010     case VIDIOC_TRY_EXT_CTRLS32:
1011         return put_v4l2_ext_controls32(parg, arg);
1012 
1013     case VIDIOC_CREATE_BUFS32:
1014         return put_v4l2_create32(parg, arg);
1015 
1016     case VIDIOC_ENUMSTD32:
1017         return put_v4l2_standard32(parg, arg);
1018 
1019     case VIDIOC_ENUMINPUT32:
1020         return put_v4l2_input32(parg, arg);
1021 
1022     case VIDIOC_G_EDID32:
1023     case VIDIOC_S_EDID32:
1024         return put_v4l2_edid32(parg, arg);
1025 #ifdef CONFIG_X86_64
1026     case VIDIOC_DQEVENT32:
1027         return put_v4l2_event32(parg, arg);
1028 #endif
1029 #ifdef CONFIG_COMPAT_32BIT_TIME
1030     case VIDIOC_DQEVENT32_TIME32:
1031         return put_v4l2_event32_time32(parg, arg);
1032 #endif
1033     }
1034     return 0;
1035 }
1036 
1037 int v4l2_compat_get_array_args(struct file *file, void *mbuf,
1038                    void __user *user_ptr, size_t array_size,
1039                    unsigned int cmd, void *arg)
1040 {
1041     int err = 0;
1042 
1043     memset(mbuf, 0, array_size);
1044 
1045     switch (cmd) {
1046     case VIDIOC_G_FMT32:
1047     case VIDIOC_S_FMT32:
1048     case VIDIOC_TRY_FMT32: {
1049         struct v4l2_format *f64 = arg;
1050         struct v4l2_clip *c64 = mbuf;
1051         struct v4l2_clip32 __user *c32 = user_ptr;
1052         u32 clipcount = f64->fmt.win.clipcount;
1053 
1054         if ((f64->type != V4L2_BUF_TYPE_VIDEO_OVERLAY &&
1055              f64->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) ||
1056             clipcount == 0)
1057             return 0;
1058         if (clipcount > 2048)
1059             return -EINVAL;
1060         while (clipcount--) {
1061             if (copy_from_user(c64, c32, sizeof(c64->c)))
1062                 return -EFAULT;
1063             c64->next = NULL;
1064             c64++;
1065             c32++;
1066         }
1067         break;
1068     }
1069 #ifdef CONFIG_COMPAT_32BIT_TIME
1070     case VIDIOC_QUERYBUF32_TIME32:
1071     case VIDIOC_QBUF32_TIME32:
1072     case VIDIOC_DQBUF32_TIME32:
1073     case VIDIOC_PREPARE_BUF32_TIME32:
1074 #endif
1075     case VIDIOC_QUERYBUF32:
1076     case VIDIOC_QBUF32:
1077     case VIDIOC_DQBUF32:
1078     case VIDIOC_PREPARE_BUF32: {
1079         struct v4l2_buffer *b64 = arg;
1080         struct v4l2_plane *p64 = mbuf;
1081         struct v4l2_plane32 __user *p32 = user_ptr;
1082 
1083         if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {
1084             u32 num_planes = b64->length;
1085 
1086             if (num_planes == 0)
1087                 return 0;
1088 
1089             while (num_planes--) {
1090                 err = get_v4l2_plane32(p64, p32, b64->memory);
1091                 if (err)
1092                     return err;
1093                 ++p64;
1094                 ++p32;
1095             }
1096         }
1097         break;
1098     }
1099     case VIDIOC_G_EXT_CTRLS32:
1100     case VIDIOC_S_EXT_CTRLS32:
1101     case VIDIOC_TRY_EXT_CTRLS32: {
1102         struct v4l2_ext_controls *ecs64 = arg;
1103         struct v4l2_ext_control *ec64 = mbuf;
1104         struct v4l2_ext_control32 __user *ec32 = user_ptr;
1105         int n;
1106 
1107         for (n = 0; n < ecs64->count; n++) {
1108             if (copy_from_user(ec64, ec32, sizeof(*ec32)))
1109                 return -EFAULT;
1110 
1111             if (ctrl_is_pointer(file, ec64->id)) {
1112                 compat_uptr_t p;
1113 
1114                 if (get_user(p, &ec32->string))
1115                     return -EFAULT;
1116                 ec64->string = compat_ptr(p);
1117             }
1118             ec32++;
1119             ec64++;
1120         }
1121         break;
1122     }
1123     default:
1124         if (copy_from_user(mbuf, user_ptr, array_size))
1125             err = -EFAULT;
1126         break;
1127     }
1128 
1129     return err;
1130 }
1131 
1132 int v4l2_compat_put_array_args(struct file *file, void __user *user_ptr,
1133                    void *mbuf, size_t array_size,
1134                    unsigned int cmd, void *arg)
1135 {
1136     int err = 0;
1137 
1138     switch (cmd) {
1139     case VIDIOC_G_FMT32:
1140     case VIDIOC_S_FMT32:
1141     case VIDIOC_TRY_FMT32: {
1142         struct v4l2_format *f64 = arg;
1143         struct v4l2_clip *c64 = mbuf;
1144         struct v4l2_clip32 __user *c32 = user_ptr;
1145         u32 clipcount = f64->fmt.win.clipcount;
1146 
1147         if ((f64->type != V4L2_BUF_TYPE_VIDEO_OVERLAY &&
1148              f64->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) ||
1149             clipcount == 0)
1150             return 0;
1151         if (clipcount > 2048)
1152             return -EINVAL;
1153         while (clipcount--) {
1154             if (copy_to_user(c32, c64, sizeof(c64->c)))
1155                 return -EFAULT;
1156             c64++;
1157             c32++;
1158         }
1159         break;
1160     }
1161 #ifdef CONFIG_COMPAT_32BIT_TIME
1162     case VIDIOC_QUERYBUF32_TIME32:
1163     case VIDIOC_QBUF32_TIME32:
1164     case VIDIOC_DQBUF32_TIME32:
1165     case VIDIOC_PREPARE_BUF32_TIME32:
1166 #endif
1167     case VIDIOC_QUERYBUF32:
1168     case VIDIOC_QBUF32:
1169     case VIDIOC_DQBUF32:
1170     case VIDIOC_PREPARE_BUF32: {
1171         struct v4l2_buffer *b64 = arg;
1172         struct v4l2_plane *p64 = mbuf;
1173         struct v4l2_plane32 __user *p32 = user_ptr;
1174 
1175         if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {
1176             u32 num_planes = b64->length;
1177 
1178             if (num_planes == 0)
1179                 return 0;
1180 
1181             while (num_planes--) {
1182                 err = put_v4l2_plane32(p64, p32, b64->memory);
1183                 if (err)
1184                     return err;
1185                 ++p64;
1186                 ++p32;
1187             }
1188         }
1189         break;
1190     }
1191     case VIDIOC_G_EXT_CTRLS32:
1192     case VIDIOC_S_EXT_CTRLS32:
1193     case VIDIOC_TRY_EXT_CTRLS32: {
1194         struct v4l2_ext_controls *ecs64 = arg;
1195         struct v4l2_ext_control *ec64 = mbuf;
1196         struct v4l2_ext_control32 __user *ec32 = user_ptr;
1197         int n;
1198 
1199         for (n = 0; n < ecs64->count; n++) {
1200             unsigned int size = sizeof(*ec32);
1201             /*
1202              * Do not modify the pointer when copying a pointer
1203              * control.  The contents of the pointer was changed,
1204              * not the pointer itself.
1205              * The structures are otherwise compatible.
1206              */
1207             if (ctrl_is_pointer(file, ec64->id))
1208                 size -= sizeof(ec32->value64);
1209 
1210             if (copy_to_user(ec32, ec64, size))
1211                 return -EFAULT;
1212 
1213             ec32++;
1214             ec64++;
1215         }
1216         break;
1217     }
1218     default:
1219         if (copy_to_user(user_ptr, mbuf, array_size))
1220             err = -EFAULT;
1221         break;
1222     }
1223 
1224     return err;
1225 }
1226 
1227 /**
1228  * v4l2_compat_ioctl32() - Handles a compat32 ioctl call
1229  *
1230  * @file: pointer to &struct file with the file handler
1231  * @cmd: ioctl to be called
1232  * @arg: arguments passed from/to the ioctl handler
1233  *
1234  * This function is meant to be used as .compat_ioctl fops at v4l2-dev.c
1235  * in order to deal with 32-bit calls on a 64-bits Kernel.
1236  *
1237  * This function calls do_video_ioctl() for non-private V4L2 ioctls.
1238  * If the function is a private one it calls vdev->fops->compat_ioctl32
1239  * instead.
1240  */
1241 long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
1242 {
1243     struct video_device *vdev = video_devdata(file);
1244     long ret = -ENOIOCTLCMD;
1245 
1246     if (!file->f_op->unlocked_ioctl)
1247         return ret;
1248 
1249     if (!video_is_registered(vdev))
1250         return -ENODEV;
1251 
1252     if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE)
1253         ret = file->f_op->unlocked_ioctl(file, cmd,
1254                     (unsigned long)compat_ptr(arg));
1255     else if (vdev->fops->compat_ioctl32)
1256         ret = vdev->fops->compat_ioctl32(file, cmd, arg);
1257 
1258     if (ret == -ENOIOCTLCMD)
1259         pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
1260              _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
1261     return ret;
1262 }
1263 EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);