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