cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

v4l2-compat-ioctl32.c (32680B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
      4 *	Separated from fs stuff by Arnd Bergmann <arnd@arndb.de>
      5 *
      6 * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
      7 * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
      8 * Copyright (C) 2001,2002  Andi Kleen, SuSE Labs
      9 * Copyright (C) 2003       Pavel Machek (pavel@ucw.cz)
     10 * Copyright (C) 2005       Philippe De Muyter (phdm@macqel.be)
     11 * Copyright (C) 2008       Hans Verkuil <hverkuil@xs4all.nl>
     12 *
     13 * These routines maintain argument size conversion between 32bit and 64bit
     14 * ioctls.
     15 */
     16
     17#include <linux/compat.h>
     18#include <linux/module.h>
     19#include <linux/videodev2.h>
     20#include <linux/v4l2-subdev.h>
     21#include <media/v4l2-dev.h>
     22#include <media/v4l2-fh.h>
     23#include <media/v4l2-ctrls.h>
     24#include <media/v4l2-ioctl.h>
     25
     26/*
     27 * Per-ioctl data copy handlers.
     28 *
     29 * Those come in pairs, with a get_v4l2_foo() and a put_v4l2_foo() routine,
     30 * where "v4l2_foo" is the name of the V4L2 struct.
     31 *
     32 * They basically get two __user pointers, one with a 32-bits struct that
     33 * came from the userspace call and a 64-bits struct, also allocated as
     34 * userspace, but filled internally by do_video_ioctl().
     35 *
     36 * For ioctls that have pointers inside it, the functions will also
     37 * receive an ancillary buffer with extra space, used to pass extra
     38 * data to the routine.
     39 */
     40
     41struct v4l2_clip32 {
     42	struct v4l2_rect        c;
     43	compat_caddr_t		next;
     44};
     45
     46struct v4l2_window32 {
     47	struct v4l2_rect        w;
     48	__u32			field;	/* enum v4l2_field */
     49	__u32			chromakey;
     50	compat_caddr_t		clips; /* actually struct v4l2_clip32 * */
     51	__u32			clipcount;
     52	compat_caddr_t		bitmap;
     53	__u8                    global_alpha;
     54};
     55
     56static int get_v4l2_window32(struct v4l2_window *p64,
     57			     struct v4l2_window32 __user *p32)
     58{
     59	struct v4l2_window32 w32;
     60
     61	if (copy_from_user(&w32, p32, sizeof(w32)))
     62		return -EFAULT;
     63
     64	*p64 = (struct v4l2_window) {
     65		.w		= w32.w,
     66		.field		= w32.field,
     67		.chromakey	= w32.chromakey,
     68		.clips		= (void __force *)compat_ptr(w32.clips),
     69		.clipcount	= w32.clipcount,
     70		.bitmap		= compat_ptr(w32.bitmap),
     71		.global_alpha	= w32.global_alpha,
     72	};
     73
     74	if (p64->clipcount > 2048)
     75		return -EINVAL;
     76	if (!p64->clipcount)
     77		p64->clips = NULL;
     78
     79	return 0;
     80}
     81
     82static int put_v4l2_window32(struct v4l2_window *p64,
     83			     struct v4l2_window32 __user *p32)
     84{
     85	struct v4l2_window32 w32;
     86
     87	memset(&w32, 0, sizeof(w32));
     88	w32 = (struct v4l2_window32) {
     89		.w		= p64->w,
     90		.field		= p64->field,
     91		.chromakey	= p64->chromakey,
     92		.clips		= (uintptr_t)p64->clips,
     93		.clipcount	= p64->clipcount,
     94		.bitmap		= ptr_to_compat(p64->bitmap),
     95		.global_alpha	= p64->global_alpha,
     96	};
     97
     98	/* copy everything except the clips pointer */
     99	if (copy_to_user(p32, &w32, offsetof(struct v4l2_window32, clips)) ||
    100	    copy_to_user(&p32->clipcount, &w32.clipcount,
    101			 sizeof(w32) - offsetof(struct v4l2_window32, clipcount)))
    102		return -EFAULT;
    103
    104	return 0;
    105}
    106
    107struct v4l2_format32 {
    108	__u32	type;	/* enum v4l2_buf_type */
    109	union {
    110		struct v4l2_pix_format	pix;
    111		struct v4l2_pix_format_mplane	pix_mp;
    112		struct v4l2_window32	win;
    113		struct v4l2_vbi_format	vbi;
    114		struct v4l2_sliced_vbi_format	sliced;
    115		struct v4l2_sdr_format	sdr;
    116		struct v4l2_meta_format	meta;
    117		__u8	raw_data[200];        /* user-defined */
    118	} fmt;
    119};
    120
    121/**
    122 * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument
    123 * @index:	on return, index of the first created buffer
    124 * @count:	entry: number of requested buffers,
    125 *		return: number of created buffers
    126 * @memory:	buffer memory type
    127 * @format:	frame format, for which buffers are requested
    128 * @capabilities: capabilities of this buffer type.
    129 * @flags:	additional buffer management attributes (ignored unless the
    130 *		queue has V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS capability and
    131 *		configured for MMAP streaming I/O).
    132 * @reserved:	future extensions
    133 */
    134struct v4l2_create_buffers32 {
    135	__u32			index;
    136	__u32			count;
    137	__u32			memory;	/* enum v4l2_memory */
    138	struct v4l2_format32	format;
    139	__u32			capabilities;
    140	__u32			flags;
    141	__u32			reserved[6];
    142};
    143
    144static int get_v4l2_format32(struct v4l2_format *p64,
    145			     struct v4l2_format32 __user *p32)
    146{
    147	if (get_user(p64->type, &p32->type))
    148		return -EFAULT;
    149
    150	switch (p64->type) {
    151	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
    152	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
    153		return copy_from_user(&p64->fmt.pix, &p32->fmt.pix,
    154				      sizeof(p64->fmt.pix)) ? -EFAULT : 0;
    155	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
    156	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
    157		return copy_from_user(&p64->fmt.pix_mp, &p32->fmt.pix_mp,
    158				      sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;
    159	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
    160	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
    161		return get_v4l2_window32(&p64->fmt.win, &p32->fmt.win);
    162	case V4L2_BUF_TYPE_VBI_CAPTURE:
    163	case V4L2_BUF_TYPE_VBI_OUTPUT:
    164		return copy_from_user(&p64->fmt.vbi, &p32->fmt.vbi,
    165				      sizeof(p64->fmt.vbi)) ? -EFAULT : 0;
    166	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
    167	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
    168		return copy_from_user(&p64->fmt.sliced, &p32->fmt.sliced,
    169				      sizeof(p64->fmt.sliced)) ? -EFAULT : 0;
    170	case V4L2_BUF_TYPE_SDR_CAPTURE:
    171	case V4L2_BUF_TYPE_SDR_OUTPUT:
    172		return copy_from_user(&p64->fmt.sdr, &p32->fmt.sdr,
    173				      sizeof(p64->fmt.sdr)) ? -EFAULT : 0;
    174	case V4L2_BUF_TYPE_META_CAPTURE:
    175	case V4L2_BUF_TYPE_META_OUTPUT:
    176		return copy_from_user(&p64->fmt.meta, &p32->fmt.meta,
    177				      sizeof(p64->fmt.meta)) ? -EFAULT : 0;
    178	default:
    179		return -EINVAL;
    180	}
    181}
    182
    183static int get_v4l2_create32(struct v4l2_create_buffers *p64,
    184			     struct v4l2_create_buffers32 __user *p32)
    185{
    186	if (copy_from_user(p64, p32,
    187			   offsetof(struct v4l2_create_buffers32, format)))
    188		return -EFAULT;
    189	if (copy_from_user(&p64->flags, &p32->flags, sizeof(p32->flags)))
    190		return -EFAULT;
    191	return get_v4l2_format32(&p64->format, &p32->format);
    192}
    193
    194static int put_v4l2_format32(struct v4l2_format *p64,
    195			     struct v4l2_format32 __user *p32)
    196{
    197	switch (p64->type) {
    198	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
    199	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
    200		return copy_to_user(&p32->fmt.pix, &p64->fmt.pix,
    201				    sizeof(p64->fmt.pix)) ? -EFAULT : 0;
    202	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
    203	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
    204		return copy_to_user(&p32->fmt.pix_mp, &p64->fmt.pix_mp,
    205				    sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;
    206	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
    207	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
    208		return put_v4l2_window32(&p64->fmt.win, &p32->fmt.win);
    209	case V4L2_BUF_TYPE_VBI_CAPTURE:
    210	case V4L2_BUF_TYPE_VBI_OUTPUT:
    211		return copy_to_user(&p32->fmt.vbi, &p64->fmt.vbi,
    212				    sizeof(p64->fmt.vbi)) ? -EFAULT : 0;
    213	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
    214	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
    215		return copy_to_user(&p32->fmt.sliced, &p64->fmt.sliced,
    216				    sizeof(p64->fmt.sliced)) ? -EFAULT : 0;
    217	case V4L2_BUF_TYPE_SDR_CAPTURE:
    218	case V4L2_BUF_TYPE_SDR_OUTPUT:
    219		return copy_to_user(&p32->fmt.sdr, &p64->fmt.sdr,
    220				    sizeof(p64->fmt.sdr)) ? -EFAULT : 0;
    221	case V4L2_BUF_TYPE_META_CAPTURE:
    222	case V4L2_BUF_TYPE_META_OUTPUT:
    223		return copy_to_user(&p32->fmt.meta, &p64->fmt.meta,
    224				    sizeof(p64->fmt.meta)) ? -EFAULT : 0;
    225	default:
    226		return -EINVAL;
    227	}
    228}
    229
    230static int put_v4l2_create32(struct v4l2_create_buffers *p64,
    231			     struct v4l2_create_buffers32 __user *p32)
    232{
    233	if (copy_to_user(p32, p64,
    234			 offsetof(struct v4l2_create_buffers32, format)) ||
    235	    put_user(p64->capabilities, &p32->capabilities) ||
    236	    put_user(p64->flags, &p32->flags) ||
    237	    copy_to_user(p32->reserved, p64->reserved, sizeof(p64->reserved)))
    238		return -EFAULT;
    239	return put_v4l2_format32(&p64->format, &p32->format);
    240}
    241
    242struct v4l2_standard32 {
    243	__u32		     index;
    244	compat_u64	     id;
    245	__u8		     name[24];
    246	struct v4l2_fract    frameperiod; /* Frames, not fields */
    247	__u32		     framelines;
    248	__u32		     reserved[4];
    249};
    250
    251static int get_v4l2_standard32(struct v4l2_standard *p64,
    252			       struct v4l2_standard32 __user *p32)
    253{
    254	/* other fields are not set by the user, nor used by the driver */
    255	return get_user(p64->index, &p32->index);
    256}
    257
    258static int put_v4l2_standard32(struct v4l2_standard *p64,
    259			       struct v4l2_standard32 __user *p32)
    260{
    261	if (put_user(p64->index, &p32->index) ||
    262	    put_user(p64->id, &p32->id) ||
    263	    copy_to_user(p32->name, p64->name, sizeof(p32->name)) ||
    264	    copy_to_user(&p32->frameperiod, &p64->frameperiod,
    265			 sizeof(p32->frameperiod)) ||
    266	    put_user(p64->framelines, &p32->framelines) ||
    267	    copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
    268		return -EFAULT;
    269	return 0;
    270}
    271
    272struct v4l2_plane32 {
    273	__u32			bytesused;
    274	__u32			length;
    275	union {
    276		__u32		mem_offset;
    277		compat_long_t	userptr;
    278		__s32		fd;
    279	} m;
    280	__u32			data_offset;
    281	__u32			reserved[11];
    282};
    283
    284/*
    285 * This is correct for all architectures including i386, but not x32,
    286 * which has different alignment requirements for timestamp
    287 */
    288struct v4l2_buffer32 {
    289	__u32			index;
    290	__u32			type;	/* enum v4l2_buf_type */
    291	__u32			bytesused;
    292	__u32			flags;
    293	__u32			field;	/* enum v4l2_field */
    294	struct {
    295		compat_s64	tv_sec;
    296		compat_s64	tv_usec;
    297	}			timestamp;
    298	struct v4l2_timecode	timecode;
    299	__u32			sequence;
    300
    301	/* memory location */
    302	__u32			memory;	/* enum v4l2_memory */
    303	union {
    304		__u32           offset;
    305		compat_long_t   userptr;
    306		compat_caddr_t  planes;
    307		__s32		fd;
    308	} m;
    309	__u32			length;
    310	__u32			reserved2;
    311	__s32			request_fd;
    312};
    313
    314#ifdef CONFIG_COMPAT_32BIT_TIME
    315struct v4l2_buffer32_time32 {
    316	__u32			index;
    317	__u32			type;	/* enum v4l2_buf_type */
    318	__u32			bytesused;
    319	__u32			flags;
    320	__u32			field;	/* enum v4l2_field */
    321	struct old_timeval32	timestamp;
    322	struct v4l2_timecode	timecode;
    323	__u32			sequence;
    324
    325	/* memory location */
    326	__u32			memory;	/* enum v4l2_memory */
    327	union {
    328		__u32           offset;
    329		compat_long_t   userptr;
    330		compat_caddr_t  planes;
    331		__s32		fd;
    332	} m;
    333	__u32			length;
    334	__u32			reserved2;
    335	__s32			request_fd;
    336};
    337#endif
    338
    339static int get_v4l2_plane32(struct v4l2_plane *p64,
    340			    struct v4l2_plane32 __user *p32,
    341			    enum v4l2_memory memory)
    342{
    343	struct v4l2_plane32 plane32;
    344	typeof(p64->m) m = {};
    345
    346	if (copy_from_user(&plane32, p32, sizeof(plane32)))
    347		return -EFAULT;
    348
    349	switch (memory) {
    350	case V4L2_MEMORY_MMAP:
    351	case V4L2_MEMORY_OVERLAY:
    352		m.mem_offset = plane32.m.mem_offset;
    353		break;
    354	case V4L2_MEMORY_USERPTR:
    355		m.userptr = (unsigned long)compat_ptr(plane32.m.userptr);
    356		break;
    357	case V4L2_MEMORY_DMABUF:
    358		m.fd = plane32.m.fd;
    359		break;
    360	}
    361
    362	memset(p64, 0, sizeof(*p64));
    363	*p64 = (struct v4l2_plane) {
    364		.bytesused	= plane32.bytesused,
    365		.length		= plane32.length,
    366		.m		= m,
    367		.data_offset	= plane32.data_offset,
    368	};
    369
    370	return 0;
    371}
    372
    373static int put_v4l2_plane32(struct v4l2_plane *p64,
    374			    struct v4l2_plane32 __user *p32,
    375			    enum v4l2_memory memory)
    376{
    377	struct v4l2_plane32 plane32;
    378
    379	memset(&plane32, 0, sizeof(plane32));
    380	plane32 = (struct v4l2_plane32) {
    381		.bytesused	= p64->bytesused,
    382		.length		= p64->length,
    383		.data_offset	= p64->data_offset,
    384	};
    385
    386	switch (memory) {
    387	case V4L2_MEMORY_MMAP:
    388	case V4L2_MEMORY_OVERLAY:
    389		plane32.m.mem_offset = p64->m.mem_offset;
    390		break;
    391	case V4L2_MEMORY_USERPTR:
    392		plane32.m.userptr = (uintptr_t)(p64->m.userptr);
    393		break;
    394	case V4L2_MEMORY_DMABUF:
    395		plane32.m.fd = p64->m.fd;
    396		break;
    397	}
    398
    399	if (copy_to_user(p32, &plane32, sizeof(plane32)))
    400		return -EFAULT;
    401
    402	return 0;
    403}
    404
    405static int get_v4l2_buffer32(struct v4l2_buffer *vb,
    406			     struct v4l2_buffer32 __user *arg)
    407{
    408	struct v4l2_buffer32 vb32;
    409
    410	if (copy_from_user(&vb32, arg, sizeof(vb32)))
    411		return -EFAULT;
    412
    413	memset(vb, 0, sizeof(*vb));
    414	*vb = (struct v4l2_buffer) {
    415		.index		= vb32.index,
    416		.type		= vb32.type,
    417		.bytesused	= vb32.bytesused,
    418		.flags		= vb32.flags,
    419		.field		= vb32.field,
    420		.timestamp.tv_sec	= vb32.timestamp.tv_sec,
    421		.timestamp.tv_usec	= vb32.timestamp.tv_usec,
    422		.timecode	= vb32.timecode,
    423		.sequence	= vb32.sequence,
    424		.memory		= vb32.memory,
    425		.m.offset	= vb32.m.offset,
    426		.length		= vb32.length,
    427		.request_fd	= vb32.request_fd,
    428	};
    429
    430	switch (vb->memory) {
    431	case V4L2_MEMORY_MMAP:
    432	case V4L2_MEMORY_OVERLAY:
    433		vb->m.offset = vb32.m.offset;
    434		break;
    435	case V4L2_MEMORY_USERPTR:
    436		vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr);
    437		break;
    438	case V4L2_MEMORY_DMABUF:
    439		vb->m.fd = vb32.m.fd;
    440		break;
    441	}
    442
    443	if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
    444		vb->m.planes = (void __force *)
    445				compat_ptr(vb32.m.planes);
    446
    447	return 0;
    448}
    449
    450#ifdef CONFIG_COMPAT_32BIT_TIME
    451static int get_v4l2_buffer32_time32(struct v4l2_buffer *vb,
    452				    struct v4l2_buffer32_time32 __user *arg)
    453{
    454	struct v4l2_buffer32_time32 vb32;
    455
    456	if (copy_from_user(&vb32, arg, sizeof(vb32)))
    457		return -EFAULT;
    458
    459	*vb = (struct v4l2_buffer) {
    460		.index		= vb32.index,
    461		.type		= vb32.type,
    462		.bytesused	= vb32.bytesused,
    463		.flags		= vb32.flags,
    464		.field		= vb32.field,
    465		.timestamp.tv_sec	= vb32.timestamp.tv_sec,
    466		.timestamp.tv_usec	= vb32.timestamp.tv_usec,
    467		.timecode	= vb32.timecode,
    468		.sequence	= vb32.sequence,
    469		.memory		= vb32.memory,
    470		.m.offset	= vb32.m.offset,
    471		.length		= vb32.length,
    472		.request_fd	= vb32.request_fd,
    473	};
    474	switch (vb->memory) {
    475	case V4L2_MEMORY_MMAP:
    476	case V4L2_MEMORY_OVERLAY:
    477		vb->m.offset = vb32.m.offset;
    478		break;
    479	case V4L2_MEMORY_USERPTR:
    480		vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr);
    481		break;
    482	case V4L2_MEMORY_DMABUF:
    483		vb->m.fd = vb32.m.fd;
    484		break;
    485	}
    486
    487	if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
    488		vb->m.planes = (void __force *)
    489				compat_ptr(vb32.m.planes);
    490
    491	return 0;
    492}
    493#endif
    494
    495static int put_v4l2_buffer32(struct v4l2_buffer *vb,
    496			     struct v4l2_buffer32 __user *arg)
    497{
    498	struct v4l2_buffer32 vb32;
    499
    500	memset(&vb32, 0, sizeof(vb32));
    501	vb32 = (struct v4l2_buffer32) {
    502		.index		= vb->index,
    503		.type		= vb->type,
    504		.bytesused	= vb->bytesused,
    505		.flags		= vb->flags,
    506		.field		= vb->field,
    507		.timestamp.tv_sec	= vb->timestamp.tv_sec,
    508		.timestamp.tv_usec	= vb->timestamp.tv_usec,
    509		.timecode	= vb->timecode,
    510		.sequence	= vb->sequence,
    511		.memory		= vb->memory,
    512		.m.offset	= vb->m.offset,
    513		.length		= vb->length,
    514		.request_fd	= vb->request_fd,
    515	};
    516
    517	switch (vb->memory) {
    518	case V4L2_MEMORY_MMAP:
    519	case V4L2_MEMORY_OVERLAY:
    520		vb32.m.offset = vb->m.offset;
    521		break;
    522	case V4L2_MEMORY_USERPTR:
    523		vb32.m.userptr = (uintptr_t)(vb->m.userptr);
    524		break;
    525	case V4L2_MEMORY_DMABUF:
    526		vb32.m.fd = vb->m.fd;
    527		break;
    528	}
    529
    530	if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
    531		vb32.m.planes = (uintptr_t)vb->m.planes;
    532
    533	if (copy_to_user(arg, &vb32, sizeof(vb32)))
    534		return -EFAULT;
    535
    536	return 0;
    537}
    538
    539#ifdef CONFIG_COMPAT_32BIT_TIME
    540static int put_v4l2_buffer32_time32(struct v4l2_buffer *vb,
    541				    struct v4l2_buffer32_time32 __user *arg)
    542{
    543	struct v4l2_buffer32_time32 vb32;
    544
    545	memset(&vb32, 0, sizeof(vb32));
    546	vb32 = (struct v4l2_buffer32_time32) {
    547		.index		= vb->index,
    548		.type		= vb->type,
    549		.bytesused	= vb->bytesused,
    550		.flags		= vb->flags,
    551		.field		= vb->field,
    552		.timestamp.tv_sec	= vb->timestamp.tv_sec,
    553		.timestamp.tv_usec	= vb->timestamp.tv_usec,
    554		.timecode	= vb->timecode,
    555		.sequence	= vb->sequence,
    556		.memory		= vb->memory,
    557		.m.offset	= vb->m.offset,
    558		.length		= vb->length,
    559		.request_fd	= vb->request_fd,
    560	};
    561	switch (vb->memory) {
    562	case V4L2_MEMORY_MMAP:
    563	case V4L2_MEMORY_OVERLAY:
    564		vb32.m.offset = vb->m.offset;
    565		break;
    566	case V4L2_MEMORY_USERPTR:
    567		vb32.m.userptr = (uintptr_t)(vb->m.userptr);
    568		break;
    569	case V4L2_MEMORY_DMABUF:
    570		vb32.m.fd = vb->m.fd;
    571		break;
    572	}
    573
    574	if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
    575		vb32.m.planes = (uintptr_t)vb->m.planes;
    576
    577	if (copy_to_user(arg, &vb32, sizeof(vb32)))
    578		return -EFAULT;
    579
    580	return 0;
    581}
    582#endif
    583
    584struct v4l2_framebuffer32 {
    585	__u32			capability;
    586	__u32			flags;
    587	compat_caddr_t		base;
    588	struct {
    589		__u32		width;
    590		__u32		height;
    591		__u32		pixelformat;
    592		__u32		field;
    593		__u32		bytesperline;
    594		__u32		sizeimage;
    595		__u32		colorspace;
    596		__u32		priv;
    597	} fmt;
    598};
    599
    600static int get_v4l2_framebuffer32(struct v4l2_framebuffer *p64,
    601				  struct v4l2_framebuffer32 __user *p32)
    602{
    603	compat_caddr_t tmp;
    604
    605	if (get_user(tmp, &p32->base) ||
    606	    get_user(p64->capability, &p32->capability) ||
    607	    get_user(p64->flags, &p32->flags) ||
    608	    copy_from_user(&p64->fmt, &p32->fmt, sizeof(p64->fmt)))
    609		return -EFAULT;
    610	p64->base = (void __force *)compat_ptr(tmp);
    611
    612	return 0;
    613}
    614
    615static int put_v4l2_framebuffer32(struct v4l2_framebuffer *p64,
    616				  struct v4l2_framebuffer32 __user *p32)
    617{
    618	if (put_user((uintptr_t)p64->base, &p32->base) ||
    619	    put_user(p64->capability, &p32->capability) ||
    620	    put_user(p64->flags, &p32->flags) ||
    621	    copy_to_user(&p32->fmt, &p64->fmt, sizeof(p64->fmt)))
    622		return -EFAULT;
    623
    624	return 0;
    625}
    626
    627struct v4l2_input32 {
    628	__u32	     index;		/*  Which input */
    629	__u8	     name[32];		/*  Label */
    630	__u32	     type;		/*  Type of input */
    631	__u32	     audioset;		/*  Associated audios (bitfield) */
    632	__u32        tuner;             /*  Associated tuner */
    633	compat_u64   std;
    634	__u32	     status;
    635	__u32	     capabilities;
    636	__u32	     reserved[3];
    637};
    638
    639/*
    640 * The 64-bit v4l2_input struct has extra padding at the end of the struct.
    641 * Otherwise it is identical to the 32-bit version.
    642 */
    643static inline int get_v4l2_input32(struct v4l2_input *p64,
    644				   struct v4l2_input32 __user *p32)
    645{
    646	if (copy_from_user(p64, p32, sizeof(*p32)))
    647		return -EFAULT;
    648	return 0;
    649}
    650
    651static inline int put_v4l2_input32(struct v4l2_input *p64,
    652				   struct v4l2_input32 __user *p32)
    653{
    654	if (copy_to_user(p32, p64, sizeof(*p32)))
    655		return -EFAULT;
    656	return 0;
    657}
    658
    659struct v4l2_ext_controls32 {
    660	__u32 which;
    661	__u32 count;
    662	__u32 error_idx;
    663	__s32 request_fd;
    664	__u32 reserved[1];
    665	compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
    666};
    667
    668struct v4l2_ext_control32 {
    669	__u32 id;
    670	__u32 size;
    671	__u32 reserved2[1];
    672	union {
    673		__s32 value;
    674		__s64 value64;
    675		compat_caddr_t string; /* actually char * */
    676	};
    677} __attribute__ ((packed));
    678
    679/* Return true if this control is a pointer type. */
    680static inline bool ctrl_is_pointer(struct file *file, u32 id)
    681{
    682	struct video_device *vdev = video_devdata(file);
    683	struct v4l2_fh *fh = NULL;
    684	struct v4l2_ctrl_handler *hdl = NULL;
    685	struct v4l2_query_ext_ctrl qec = { id };
    686	const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
    687
    688	if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
    689		fh = file->private_data;
    690
    691	if (fh && fh->ctrl_handler)
    692		hdl = fh->ctrl_handler;
    693	else if (vdev->ctrl_handler)
    694		hdl = vdev->ctrl_handler;
    695
    696	if (hdl) {
    697		struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id);
    698
    699		return ctrl && ctrl->is_ptr;
    700	}
    701
    702	if (!ops || !ops->vidioc_query_ext_ctrl)
    703		return false;
    704
    705	return !ops->vidioc_query_ext_ctrl(file, fh, &qec) &&
    706		(qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
    707}
    708
    709static int get_v4l2_ext_controls32(struct v4l2_ext_controls *p64,
    710				   struct v4l2_ext_controls32 __user *p32)
    711{
    712	struct v4l2_ext_controls32 ec32;
    713
    714	if (copy_from_user(&ec32, p32, sizeof(ec32)))
    715		return -EFAULT;
    716
    717	*p64 = (struct v4l2_ext_controls) {
    718		.which		= ec32.which,
    719		.count		= ec32.count,
    720		.error_idx	= ec32.error_idx,
    721		.request_fd	= ec32.request_fd,
    722		.reserved[0]	= ec32.reserved[0],
    723		.controls	= (void __force *)compat_ptr(ec32.controls),
    724	};
    725
    726	return 0;
    727}
    728
    729static int put_v4l2_ext_controls32(struct v4l2_ext_controls *p64,
    730				   struct v4l2_ext_controls32 __user *p32)
    731{
    732	struct v4l2_ext_controls32 ec32;
    733
    734	memset(&ec32, 0, sizeof(ec32));
    735	ec32 = (struct v4l2_ext_controls32) {
    736		.which		= p64->which,
    737		.count		= p64->count,
    738		.error_idx	= p64->error_idx,
    739		.request_fd	= p64->request_fd,
    740		.reserved[0]	= p64->reserved[0],
    741		.controls	= (uintptr_t)p64->controls,
    742	};
    743
    744	if (copy_to_user(p32, &ec32, sizeof(ec32)))
    745		return -EFAULT;
    746
    747	return 0;
    748}
    749
    750#ifdef CONFIG_X86_64
    751/*
    752 * x86 is the only compat architecture with different struct alignment
    753 * between 32-bit and 64-bit tasks.
    754 */
    755struct v4l2_event32 {
    756	__u32				type;
    757	union {
    758		compat_s64		value64;
    759		__u8			data[64];
    760	} u;
    761	__u32				pending;
    762	__u32				sequence;
    763	struct {
    764		compat_s64		tv_sec;
    765		compat_s64		tv_nsec;
    766	} timestamp;
    767	__u32				id;
    768	__u32				reserved[8];
    769};
    770
    771static int put_v4l2_event32(struct v4l2_event *p64,
    772			    struct v4l2_event32 __user *p32)
    773{
    774	if (put_user(p64->type, &p32->type) ||
    775	    copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) ||
    776	    put_user(p64->pending, &p32->pending) ||
    777	    put_user(p64->sequence, &p32->sequence) ||
    778	    put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) ||
    779	    put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) ||
    780	    put_user(p64->id, &p32->id) ||
    781	    copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
    782		return -EFAULT;
    783	return 0;
    784}
    785
    786#endif
    787
    788#ifdef CONFIG_COMPAT_32BIT_TIME
    789struct v4l2_event32_time32 {
    790	__u32				type;
    791	union {
    792		compat_s64		value64;
    793		__u8			data[64];
    794	} u;
    795	__u32				pending;
    796	__u32				sequence;
    797	struct old_timespec32		timestamp;
    798	__u32				id;
    799	__u32				reserved[8];
    800};
    801
    802static int put_v4l2_event32_time32(struct v4l2_event *p64,
    803				   struct v4l2_event32_time32 __user *p32)
    804{
    805	if (put_user(p64->type, &p32->type) ||
    806	    copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) ||
    807	    put_user(p64->pending, &p32->pending) ||
    808	    put_user(p64->sequence, &p32->sequence) ||
    809	    put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) ||
    810	    put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) ||
    811	    put_user(p64->id, &p32->id) ||
    812	    copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
    813		return -EFAULT;
    814	return 0;
    815}
    816#endif
    817
    818struct v4l2_edid32 {
    819	__u32 pad;
    820	__u32 start_block;
    821	__u32 blocks;
    822	__u32 reserved[5];
    823	compat_caddr_t edid;
    824};
    825
    826static int get_v4l2_edid32(struct v4l2_edid *p64,
    827			   struct v4l2_edid32 __user *p32)
    828{
    829	compat_uptr_t edid;
    830
    831	if (copy_from_user(p64, p32, offsetof(struct v4l2_edid32, edid)) ||
    832	    get_user(edid, &p32->edid))
    833		return -EFAULT;
    834
    835	p64->edid = (void __force *)compat_ptr(edid);
    836	return 0;
    837}
    838
    839static int put_v4l2_edid32(struct v4l2_edid *p64,
    840			   struct v4l2_edid32 __user *p32)
    841{
    842	if (copy_to_user(p32, p64, offsetof(struct v4l2_edid32, edid)))
    843		return -EFAULT;
    844	return 0;
    845}
    846
    847/*
    848 * List of ioctls that require 32-bits/64-bits conversion
    849 *
    850 * The V4L2 ioctls that aren't listed there don't have pointer arguments
    851 * and the struct size is identical for both 32 and 64 bits versions, so
    852 * they don't need translations.
    853 */
    854
    855#define VIDIOC_G_FMT32		_IOWR('V',  4, struct v4l2_format32)
    856#define VIDIOC_S_FMT32		_IOWR('V',  5, struct v4l2_format32)
    857#define VIDIOC_QUERYBUF32	_IOWR('V',  9, struct v4l2_buffer32)
    858#define VIDIOC_G_FBUF32		_IOR ('V', 10, struct v4l2_framebuffer32)
    859#define VIDIOC_S_FBUF32		_IOW ('V', 11, struct v4l2_framebuffer32)
    860#define VIDIOC_QBUF32		_IOWR('V', 15, struct v4l2_buffer32)
    861#define VIDIOC_DQBUF32		_IOWR('V', 17, struct v4l2_buffer32)
    862#define VIDIOC_ENUMSTD32	_IOWR('V', 25, struct v4l2_standard32)
    863#define VIDIOC_ENUMINPUT32	_IOWR('V', 26, struct v4l2_input32)
    864#define VIDIOC_G_EDID32		_IOWR('V', 40, struct v4l2_edid32)
    865#define VIDIOC_S_EDID32		_IOWR('V', 41, struct v4l2_edid32)
    866#define VIDIOC_TRY_FMT32	_IOWR('V', 64, struct v4l2_format32)
    867#define VIDIOC_G_EXT_CTRLS32    _IOWR('V', 71, struct v4l2_ext_controls32)
    868#define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
    869#define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)
    870#define	VIDIOC_DQEVENT32	_IOR ('V', 89, struct v4l2_event32)
    871#define VIDIOC_CREATE_BUFS32	_IOWR('V', 92, struct v4l2_create_buffers32)
    872#define VIDIOC_PREPARE_BUF32	_IOWR('V', 93, struct v4l2_buffer32)
    873
    874#ifdef CONFIG_COMPAT_32BIT_TIME
    875#define VIDIOC_QUERYBUF32_TIME32	_IOWR('V',  9, struct v4l2_buffer32_time32)
    876#define VIDIOC_QBUF32_TIME32		_IOWR('V', 15, struct v4l2_buffer32_time32)
    877#define VIDIOC_DQBUF32_TIME32		_IOWR('V', 17, struct v4l2_buffer32_time32)
    878#define	VIDIOC_DQEVENT32_TIME32		_IOR ('V', 89, struct v4l2_event32_time32)
    879#define VIDIOC_PREPARE_BUF32_TIME32	_IOWR('V', 93, struct v4l2_buffer32_time32)
    880#endif
    881
    882unsigned int v4l2_compat_translate_cmd(unsigned int cmd)
    883{
    884	switch (cmd) {
    885	case VIDIOC_G_FMT32:
    886		return VIDIOC_G_FMT;
    887	case VIDIOC_S_FMT32:
    888		return VIDIOC_S_FMT;
    889	case VIDIOC_TRY_FMT32:
    890		return VIDIOC_TRY_FMT;
    891	case VIDIOC_G_FBUF32:
    892		return VIDIOC_G_FBUF;
    893	case VIDIOC_S_FBUF32:
    894		return VIDIOC_S_FBUF;
    895#ifdef CONFIG_COMPAT_32BIT_TIME
    896	case VIDIOC_QUERYBUF32_TIME32:
    897		return VIDIOC_QUERYBUF;
    898	case VIDIOC_QBUF32_TIME32:
    899		return VIDIOC_QBUF;
    900	case VIDIOC_DQBUF32_TIME32:
    901		return VIDIOC_DQBUF;
    902	case VIDIOC_PREPARE_BUF32_TIME32:
    903		return VIDIOC_PREPARE_BUF;
    904#endif
    905	case VIDIOC_QUERYBUF32:
    906		return VIDIOC_QUERYBUF;
    907	case VIDIOC_QBUF32:
    908		return VIDIOC_QBUF;
    909	case VIDIOC_DQBUF32:
    910		return VIDIOC_DQBUF;
    911	case VIDIOC_CREATE_BUFS32:
    912		return VIDIOC_CREATE_BUFS;
    913	case VIDIOC_G_EXT_CTRLS32:
    914		return VIDIOC_G_EXT_CTRLS;
    915	case VIDIOC_S_EXT_CTRLS32:
    916		return VIDIOC_S_EXT_CTRLS;
    917	case VIDIOC_TRY_EXT_CTRLS32:
    918		return VIDIOC_TRY_EXT_CTRLS;
    919	case VIDIOC_PREPARE_BUF32:
    920		return VIDIOC_PREPARE_BUF;
    921	case VIDIOC_ENUMSTD32:
    922		return VIDIOC_ENUMSTD;
    923	case VIDIOC_ENUMINPUT32:
    924		return VIDIOC_ENUMINPUT;
    925	case VIDIOC_G_EDID32:
    926		return VIDIOC_G_EDID;
    927	case VIDIOC_S_EDID32:
    928		return VIDIOC_S_EDID;
    929#ifdef CONFIG_X86_64
    930	case VIDIOC_DQEVENT32:
    931		return VIDIOC_DQEVENT;
    932#endif
    933#ifdef CONFIG_COMPAT_32BIT_TIME
    934	case VIDIOC_DQEVENT32_TIME32:
    935		return VIDIOC_DQEVENT;
    936#endif
    937	}
    938	return cmd;
    939}
    940
    941int v4l2_compat_get_user(void __user *arg, void *parg, unsigned int cmd)
    942{
    943	switch (cmd) {
    944	case VIDIOC_G_FMT32:
    945	case VIDIOC_S_FMT32:
    946	case VIDIOC_TRY_FMT32:
    947		return get_v4l2_format32(parg, arg);
    948
    949	case VIDIOC_S_FBUF32:
    950		return get_v4l2_framebuffer32(parg, arg);
    951#ifdef CONFIG_COMPAT_32BIT_TIME
    952	case VIDIOC_QUERYBUF32_TIME32:
    953	case VIDIOC_QBUF32_TIME32:
    954	case VIDIOC_DQBUF32_TIME32:
    955	case VIDIOC_PREPARE_BUF32_TIME32:
    956		return get_v4l2_buffer32_time32(parg, arg);
    957#endif
    958	case VIDIOC_QUERYBUF32:
    959	case VIDIOC_QBUF32:
    960	case VIDIOC_DQBUF32:
    961	case VIDIOC_PREPARE_BUF32:
    962		return get_v4l2_buffer32(parg, arg);
    963
    964	case VIDIOC_G_EXT_CTRLS32:
    965	case VIDIOC_S_EXT_CTRLS32:
    966	case VIDIOC_TRY_EXT_CTRLS32:
    967		return get_v4l2_ext_controls32(parg, arg);
    968
    969	case VIDIOC_CREATE_BUFS32:
    970		return get_v4l2_create32(parg, arg);
    971
    972	case VIDIOC_ENUMSTD32:
    973		return get_v4l2_standard32(parg, arg);
    974
    975	case VIDIOC_ENUMINPUT32:
    976		return get_v4l2_input32(parg, arg);
    977
    978	case VIDIOC_G_EDID32:
    979	case VIDIOC_S_EDID32:
    980		return get_v4l2_edid32(parg, arg);
    981	}
    982	return 0;
    983}
    984
    985int v4l2_compat_put_user(void __user *arg, void *parg, unsigned int cmd)
    986{
    987	switch (cmd) {
    988	case VIDIOC_G_FMT32:
    989	case VIDIOC_S_FMT32:
    990	case VIDIOC_TRY_FMT32:
    991		return put_v4l2_format32(parg, arg);
    992
    993	case VIDIOC_G_FBUF32:
    994		return put_v4l2_framebuffer32(parg, arg);
    995#ifdef CONFIG_COMPAT_32BIT_TIME
    996	case VIDIOC_QUERYBUF32_TIME32:
    997	case VIDIOC_QBUF32_TIME32:
    998	case VIDIOC_DQBUF32_TIME32:
    999	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
   1037int 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	switch (cmd) {
   1044	case VIDIOC_G_FMT32:
   1045	case VIDIOC_S_FMT32:
   1046	case VIDIOC_TRY_FMT32: {
   1047		struct v4l2_format *f64 = arg;
   1048		struct v4l2_clip *c64 = mbuf;
   1049		struct v4l2_clip32 __user *c32 = user_ptr;
   1050		u32 clipcount = f64->fmt.win.clipcount;
   1051
   1052		if ((f64->type != V4L2_BUF_TYPE_VIDEO_OVERLAY &&
   1053		     f64->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) ||
   1054		    clipcount == 0)
   1055			return 0;
   1056		if (clipcount > 2048)
   1057			return -EINVAL;
   1058		while (clipcount--) {
   1059			if (copy_from_user(c64, c32, sizeof(c64->c)))
   1060				return -EFAULT;
   1061			c64->next = NULL;
   1062			c64++;
   1063			c32++;
   1064		}
   1065		break;
   1066	}
   1067#ifdef CONFIG_COMPAT_32BIT_TIME
   1068	case VIDIOC_QUERYBUF32_TIME32:
   1069	case VIDIOC_QBUF32_TIME32:
   1070	case VIDIOC_DQBUF32_TIME32:
   1071	case VIDIOC_PREPARE_BUF32_TIME32:
   1072#endif
   1073	case VIDIOC_QUERYBUF32:
   1074	case VIDIOC_QBUF32:
   1075	case VIDIOC_DQBUF32:
   1076	case VIDIOC_PREPARE_BUF32: {
   1077		struct v4l2_buffer *b64 = arg;
   1078		struct v4l2_plane *p64 = mbuf;
   1079		struct v4l2_plane32 __user *p32 = user_ptr;
   1080
   1081		if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {
   1082			u32 num_planes = b64->length;
   1083
   1084			if (num_planes == 0)
   1085				return 0;
   1086
   1087			while (num_planes--) {
   1088				err = get_v4l2_plane32(p64, p32, b64->memory);
   1089				if (err)
   1090					return err;
   1091				++p64;
   1092				++p32;
   1093			}
   1094		}
   1095		break;
   1096	}
   1097	case VIDIOC_G_EXT_CTRLS32:
   1098	case VIDIOC_S_EXT_CTRLS32:
   1099	case VIDIOC_TRY_EXT_CTRLS32: {
   1100		struct v4l2_ext_controls *ecs64 = arg;
   1101		struct v4l2_ext_control *ec64 = mbuf;
   1102		struct v4l2_ext_control32 __user *ec32 = user_ptr;
   1103		int n;
   1104
   1105		for (n = 0; n < ecs64->count; n++) {
   1106			if (copy_from_user(ec64, ec32, sizeof(*ec32)))
   1107				return -EFAULT;
   1108
   1109			if (ctrl_is_pointer(file, ec64->id)) {
   1110				compat_uptr_t p;
   1111
   1112				if (get_user(p, &ec32->string))
   1113					return -EFAULT;
   1114				ec64->string = compat_ptr(p);
   1115			}
   1116			ec32++;
   1117			ec64++;
   1118		}
   1119		break;
   1120	}
   1121	default:
   1122		if (copy_from_user(mbuf, user_ptr, array_size))
   1123			err = -EFAULT;
   1124		break;
   1125	}
   1126
   1127	return err;
   1128}
   1129
   1130int v4l2_compat_put_array_args(struct file *file, void __user *user_ptr,
   1131			       void *mbuf, size_t array_size,
   1132			       unsigned int cmd, void *arg)
   1133{
   1134	int err = 0;
   1135
   1136	switch (cmd) {
   1137	case VIDIOC_G_FMT32:
   1138	case VIDIOC_S_FMT32:
   1139	case VIDIOC_TRY_FMT32: {
   1140		struct v4l2_format *f64 = arg;
   1141		struct v4l2_clip *c64 = mbuf;
   1142		struct v4l2_clip32 __user *c32 = user_ptr;
   1143		u32 clipcount = f64->fmt.win.clipcount;
   1144
   1145		if ((f64->type != V4L2_BUF_TYPE_VIDEO_OVERLAY &&
   1146		     f64->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) ||
   1147		    clipcount == 0)
   1148			return 0;
   1149		if (clipcount > 2048)
   1150			return -EINVAL;
   1151		while (clipcount--) {
   1152			if (copy_to_user(c32, c64, sizeof(c64->c)))
   1153				return -EFAULT;
   1154			c64++;
   1155			c32++;
   1156		}
   1157		break;
   1158	}
   1159#ifdef CONFIG_COMPAT_32BIT_TIME
   1160	case VIDIOC_QUERYBUF32_TIME32:
   1161	case VIDIOC_QBUF32_TIME32:
   1162	case VIDIOC_DQBUF32_TIME32:
   1163	case VIDIOC_PREPARE_BUF32_TIME32:
   1164#endif
   1165	case VIDIOC_QUERYBUF32:
   1166	case VIDIOC_QBUF32:
   1167	case VIDIOC_DQBUF32:
   1168	case VIDIOC_PREPARE_BUF32: {
   1169		struct v4l2_buffer *b64 = arg;
   1170		struct v4l2_plane *p64 = mbuf;
   1171		struct v4l2_plane32 __user *p32 = user_ptr;
   1172
   1173		if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {
   1174			u32 num_planes = b64->length;
   1175
   1176			if (num_planes == 0)
   1177				return 0;
   1178
   1179			while (num_planes--) {
   1180				err = put_v4l2_plane32(p64, p32, b64->memory);
   1181				if (err)
   1182					return err;
   1183				++p64;
   1184				++p32;
   1185			}
   1186		}
   1187		break;
   1188	}
   1189	case VIDIOC_G_EXT_CTRLS32:
   1190	case VIDIOC_S_EXT_CTRLS32:
   1191	case VIDIOC_TRY_EXT_CTRLS32: {
   1192		struct v4l2_ext_controls *ecs64 = arg;
   1193		struct v4l2_ext_control *ec64 = mbuf;
   1194		struct v4l2_ext_control32 __user *ec32 = user_ptr;
   1195		int n;
   1196
   1197		for (n = 0; n < ecs64->count; n++) {
   1198			unsigned int size = sizeof(*ec32);
   1199			/*
   1200			 * Do not modify the pointer when copying a pointer
   1201			 * control.  The contents of the pointer was changed,
   1202			 * not the pointer itself.
   1203			 * The structures are otherwise compatible.
   1204			 */
   1205			if (ctrl_is_pointer(file, ec64->id))
   1206				size -= sizeof(ec32->value64);
   1207
   1208			if (copy_to_user(ec32, ec64, size))
   1209				return -EFAULT;
   1210
   1211			ec32++;
   1212			ec64++;
   1213		}
   1214		break;
   1215	}
   1216	default:
   1217		if (copy_to_user(user_ptr, mbuf, array_size))
   1218			err = -EFAULT;
   1219		break;
   1220	}
   1221
   1222	return err;
   1223}
   1224
   1225/**
   1226 * v4l2_compat_ioctl32() - Handles a compat32 ioctl call
   1227 *
   1228 * @file: pointer to &struct file with the file handler
   1229 * @cmd: ioctl to be called
   1230 * @arg: arguments passed from/to the ioctl handler
   1231 *
   1232 * This function is meant to be used as .compat_ioctl fops at v4l2-dev.c
   1233 * in order to deal with 32-bit calls on a 64-bits Kernel.
   1234 *
   1235 * This function calls do_video_ioctl() for non-private V4L2 ioctls.
   1236 * If the function is a private one it calls vdev->fops->compat_ioctl32
   1237 * instead.
   1238 */
   1239long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
   1240{
   1241	struct video_device *vdev = video_devdata(file);
   1242	long ret = -ENOIOCTLCMD;
   1243
   1244	if (!file->f_op->unlocked_ioctl)
   1245		return ret;
   1246
   1247	if (!video_is_registered(vdev))
   1248		return -ENODEV;
   1249
   1250	if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE)
   1251		ret = file->f_op->unlocked_ioctl(file, cmd,
   1252					(unsigned long)compat_ptr(arg));
   1253	else if (vdev->fops->compat_ioctl32)
   1254		ret = vdev->fops->compat_ioctl32(file, cmd, arg);
   1255
   1256	if (ret == -ENOIOCTLCMD)
   1257		pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
   1258			 _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
   1259	return ret;
   1260}
   1261EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);