xref: /linux/drivers/media/v4l2-core/v4l2-compat-ioctl32.c (revision 151ebcf0797b1a3ba53c8843dc21748c80e098c7)
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 
41 struct 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 
51 static 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 
72 static 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 
94 struct 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  */
124 struct 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 
135 static 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 
174 static 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 
188 static 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 
224 static 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 
237 struct 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 
246 static 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 
253 static 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 
267 struct 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  */
283 struct 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
310 struct 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 
334 static 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 
368 static 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 
400 static 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
446 static 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 
490 static 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
535 static 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 
579 struct 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 
595 static 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 
607 static 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 
619 struct 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  */
635 static 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 
643 static 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 
651 struct 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 
660 struct 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. */
672 static 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 
701 static 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 
721 static 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  */
747 struct 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 
763 static 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
781 struct 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 
794 static 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 
810 struct v4l2_edid32 {
811 	__u32 pad;
812 	__u32 start_block;
813 	__u32 blocks;
814 	__u32 reserved[5];
815 	compat_caddr_t edid;
816 };
817 
818 static 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 
831 static 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 
874 unsigned 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 
933 int 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 
977 int 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 
1029 int 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 
1101 int 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  */
1188 long 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 }
1210 EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);
1211