Linux Audio

Check our new training course

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