• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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@suse.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 #define __OLD_VIDIOC_ /* To allow fixing old calls*/
18 #include <linux/videodev.h>
19 #include <linux/videodev2.h>
20 #include <linux/module.h>
21 #include <linux/smp_lock.h>
22 #include <media/v4l2-ioctl.h>
23 
24 #ifdef CONFIG_COMPAT
25 
26 #ifdef CONFIG_VIDEO_V4L1_COMPAT
27 struct video_tuner32 {
28 	compat_int_t tuner;
29 	char name[32];
30 	compat_ulong_t rangelow, rangehigh;
31 	u32 flags;	/* It is really u32 in videodev.h */
32 	u16 mode, signal;
33 };
34 
get_video_tuner32(struct video_tuner * kp,struct video_tuner32 __user * up)35 static int get_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
36 {
37 	if (!access_ok(VERIFY_READ, up, sizeof(struct video_tuner32)) ||
38 		get_user(kp->tuner, &up->tuner) ||
39 		copy_from_user(kp->name, up->name, 32) ||
40 		get_user(kp->rangelow, &up->rangelow) ||
41 		get_user(kp->rangehigh, &up->rangehigh) ||
42 		get_user(kp->flags, &up->flags) ||
43 		get_user(kp->mode, &up->mode) ||
44 		get_user(kp->signal, &up->signal))
45 		return -EFAULT;
46 	return 0;
47 }
48 
put_video_tuner32(struct video_tuner * kp,struct video_tuner32 __user * up)49 static int put_video_tuner32(struct video_tuner *kp, struct video_tuner32 __user *up)
50 {
51 	if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_tuner32)) ||
52 		put_user(kp->tuner, &up->tuner) ||
53 		copy_to_user(up->name, kp->name, 32) ||
54 		put_user(kp->rangelow, &up->rangelow) ||
55 		put_user(kp->rangehigh, &up->rangehigh) ||
56 		put_user(kp->flags, &up->flags) ||
57 		put_user(kp->mode, &up->mode) ||
58 		put_user(kp->signal, &up->signal))
59 			return -EFAULT;
60 	return 0;
61 }
62 
63 struct video_buffer32 {
64 	compat_caddr_t base;
65 	compat_int_t height, width, depth, bytesperline;
66 };
67 
get_video_buffer32(struct video_buffer * kp,struct video_buffer32 __user * up)68 static int get_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up)
69 {
70 	u32 tmp;
71 
72 	if (!access_ok(VERIFY_READ, up, sizeof(struct video_buffer32)) ||
73 		get_user(tmp, &up->base) ||
74 		get_user(kp->height, &up->height) ||
75 		get_user(kp->width, &up->width) ||
76 		get_user(kp->depth, &up->depth) ||
77 		get_user(kp->bytesperline, &up->bytesperline))
78 			return -EFAULT;
79 
80 	/* This is actually a physical address stored
81 	 * as a void pointer.
82 	 */
83 	kp->base = (void *)(unsigned long) tmp;
84 
85 	return 0;
86 }
87 
put_video_buffer32(struct video_buffer * kp,struct video_buffer32 __user * up)88 static int put_video_buffer32(struct video_buffer *kp, struct video_buffer32 __user *up)
89 {
90 	u32 tmp = (u32)((unsigned long)kp->base);
91 
92 	if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_buffer32)) ||
93 		put_user(tmp, &up->base) ||
94 		put_user(kp->height, &up->height) ||
95 		put_user(kp->width, &up->width) ||
96 		put_user(kp->depth, &up->depth) ||
97 		put_user(kp->bytesperline, &up->bytesperline))
98 			return -EFAULT;
99 	return 0;
100 }
101 
102 struct video_clip32 {
103 	s32 x, y, width, height;	/* It's really s32 in videodev.h */
104 	compat_caddr_t next;
105 };
106 
107 struct video_window32 {
108 	u32 x, y, width, height, chromakey, flags;
109 	compat_caddr_t clips;
110 	compat_int_t clipcount;
111 };
112 
get_video_window32(struct video_window * kp,struct video_window32 __user * up)113 static int get_video_window32(struct video_window *kp, struct video_window32 __user *up)
114 {
115 	struct video_clip __user *uclips;
116 	struct video_clip __user *kclips;
117 	compat_caddr_t p;
118 	int nclips;
119 
120 	if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32)))
121 		return -EFAULT;
122 
123 	if (get_user(nclips, &up->clipcount))
124 		return -EFAULT;
125 
126 	if (!access_ok(VERIFY_READ, up, sizeof(struct video_window32)) ||
127 	    get_user(kp->x, &up->x) ||
128 	    get_user(kp->y, &up->y) ||
129 	    get_user(kp->width, &up->width) ||
130 	    get_user(kp->height, &up->height) ||
131 	    get_user(kp->chromakey, &up->chromakey) ||
132 	    get_user(kp->flags, &up->flags) ||
133 	    get_user(kp->clipcount, &up->clipcount))
134 		return -EFAULT;
135 
136 	nclips = kp->clipcount;
137 	kp->clips = NULL;
138 
139 	if (nclips == 0)
140 		return 0;
141 	if (get_user(p, &up->clips))
142 		return -EFAULT;
143 	uclips = compat_ptr(p);
144 
145 	/* If nclips < 0, then it is a clipping bitmap of size
146 	   VIDEO_CLIPMAP_SIZE */
147 	if (nclips < 0) {
148 		if (!access_ok(VERIFY_READ, uclips, VIDEO_CLIPMAP_SIZE))
149 			return -EFAULT;
150 		kp->clips = compat_alloc_user_space(VIDEO_CLIPMAP_SIZE);
151 		if (copy_in_user(kp->clips, uclips, VIDEO_CLIPMAP_SIZE))
152 			return -EFAULT;
153 		return 0;
154 	}
155 
156 	/* Otherwise it is an array of video_clip structs. */
157 	if (!access_ok(VERIFY_READ, uclips, nclips * sizeof(struct video_clip)))
158 		return -EFAULT;
159 
160 	kp->clips = compat_alloc_user_space(nclips * sizeof(struct video_clip));
161 	kclips = kp->clips;
162 	while (nclips--) {
163 		int err;
164 
165 		err = copy_in_user(&kclips->x, &uclips->x, sizeof(kclips->x));
166 		err |= copy_in_user(&kclips->y, &uclips->y, sizeof(kclips->y));
167 		err |= copy_in_user(&kclips->width, &uclips->width, sizeof(kclips->width));
168 		err |= copy_in_user(&kclips->height, &uclips->height, sizeof(kclips->height));
169 		kclips->next = NULL;
170 		if (err)
171 			return -EFAULT;
172 		kclips++;
173 		uclips++;
174 	}
175 	return 0;
176 }
177 
178 /* You get back everything except the clips... */
put_video_window32(struct video_window * kp,struct video_window32 __user * up)179 static int put_video_window32(struct video_window *kp, struct video_window32 __user *up)
180 {
181 	if (!access_ok(VERIFY_WRITE, up, sizeof(struct video_window32)) ||
182 		put_user(kp->x, &up->x) ||
183 		put_user(kp->y, &up->y) ||
184 		put_user(kp->width, &up->width) ||
185 		put_user(kp->height, &up->height) ||
186 		put_user(kp->chromakey, &up->chromakey) ||
187 		put_user(kp->flags, &up->flags) ||
188 		put_user(kp->clipcount, &up->clipcount))
189 			return -EFAULT;
190 	return 0;
191 }
192 
193 struct video_code32 {
194 	char		loadwhat[16];	/* name or tag of file being passed */
195 	compat_int_t	datasize;
196 	unsigned char	*data;
197 };
198 
get_microcode32(struct video_code * kp,struct video_code32 __user * up)199 static int get_microcode32(struct video_code *kp, struct video_code32 __user *up)
200 {
201 	if (!access_ok(VERIFY_READ, up, sizeof(struct video_code32)) ||
202 		copy_from_user(kp->loadwhat, up->loadwhat, sizeof(up->loadwhat)) ||
203 		get_user(kp->datasize, &up->datasize) ||
204 		copy_from_user(kp->data, up->data, up->datasize))
205 			return -EFAULT;
206 	return 0;
207 }
208 
209 #define VIDIOCGTUNER32		_IOWR('v', 4, struct video_tuner32)
210 #define VIDIOCSTUNER32		_IOW('v', 5, struct video_tuner32)
211 #define VIDIOCGWIN32		_IOR('v', 9, struct video_window32)
212 #define VIDIOCSWIN32		_IOW('v', 10, struct video_window32)
213 #define VIDIOCGFBUF32		_IOR('v', 11, struct video_buffer32)
214 #define VIDIOCSFBUF32		_IOW('v', 12, struct video_buffer32)
215 #define VIDIOCGFREQ32		_IOR('v', 14, u32)
216 #define VIDIOCSFREQ32		_IOW('v', 15, u32)
217 #define VIDIOCSMICROCODE32	_IOW('v', 27, struct video_code32)
218 
219 #define VIDIOCCAPTURE32		_IOW('v', 8, s32)
220 #define VIDIOCSYNC32		_IOW('v', 18, s32)
221 #define VIDIOCSWRITEMODE32	_IOW('v', 25, s32)
222 
223 #endif
224 
native_ioctl(struct file * file,unsigned int cmd,unsigned long arg)225 static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
226 {
227 	long ret = -ENOIOCTLCMD;
228 
229 	if (file->f_op->unlocked_ioctl)
230 		ret = file->f_op->unlocked_ioctl(file, cmd, arg);
231 	else if (file->f_op->ioctl) {
232 		lock_kernel();
233 		ret = file->f_op->ioctl(file->f_path.dentry->d_inode, file, cmd, arg);
234 		unlock_kernel();
235 	}
236 
237 	return ret;
238 }
239 
240 
241 struct v4l2_clip32 {
242 	struct v4l2_rect        c;
243 	compat_caddr_t 		next;
244 };
245 
246 struct v4l2_window32 {
247 	struct v4l2_rect        w;
248 	enum v4l2_field  	field;
249 	__u32			chromakey;
250 	compat_caddr_t		clips; /* actually struct v4l2_clip32 * */
251 	__u32			clipcount;
252 	compat_caddr_t		bitmap;
253 };
254 
get_v4l2_window32(struct v4l2_window * kp,struct v4l2_window32 __user * up)255 static int get_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
256 {
257 	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
258 		copy_from_user(&kp->w, &up->w, sizeof(up->w)) ||
259 		get_user(kp->field, &up->field) ||
260 		get_user(kp->chromakey, &up->chromakey) ||
261 		get_user(kp->clipcount, &up->clipcount))
262 			return -EFAULT;
263 	if (kp->clipcount > 2048)
264 		return -EINVAL;
265 	if (kp->clipcount) {
266 		struct v4l2_clip32 __user *uclips;
267 		struct v4l2_clip __user *kclips;
268 		int n = kp->clipcount;
269 		compat_caddr_t p;
270 
271 		if (get_user(p, &up->clips))
272 			return -EFAULT;
273 		uclips = compat_ptr(p);
274 		kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
275 		kp->clips = kclips;
276 		while (--n >= 0) {
277 			if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
278 				return -EFAULT;
279 			if (put_user(n ? kclips + 1 : NULL, &kclips->next))
280 				return -EFAULT;
281 			uclips += 1;
282 			kclips += 1;
283 		}
284 	} else
285 		kp->clips = NULL;
286 	return 0;
287 }
288 
put_v4l2_window32(struct v4l2_window * kp,struct v4l2_window32 __user * up)289 static int put_v4l2_window32(struct v4l2_window *kp, struct v4l2_window32 __user *up)
290 {
291 	if (copy_to_user(&up->w, &kp->w, sizeof(up->w)) ||
292 		put_user(kp->field, &up->field) ||
293 		put_user(kp->chromakey, &up->chromakey) ||
294 		put_user(kp->clipcount, &up->clipcount))
295 			return -EFAULT;
296 	return 0;
297 }
298 
get_v4l2_pix_format(struct v4l2_pix_format * kp,struct v4l2_pix_format __user * up)299 static inline int get_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
300 {
301 	if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format)))
302 		return -EFAULT;
303 	return 0;
304 }
305 
put_v4l2_pix_format(struct v4l2_pix_format * kp,struct v4l2_pix_format __user * up)306 static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
307 {
308 	if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
309 		return -EFAULT;
310 	return 0;
311 }
312 
get_v4l2_vbi_format(struct v4l2_vbi_format * kp,struct v4l2_vbi_format __user * up)313 static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
314 {
315 	if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
316 		return -EFAULT;
317 	return 0;
318 }
319 
put_v4l2_vbi_format(struct v4l2_vbi_format * kp,struct v4l2_vbi_format __user * up)320 static inline int put_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
321 {
322 	if (copy_to_user(up, kp, sizeof(struct v4l2_vbi_format)))
323 		return -EFAULT;
324 	return 0;
325 }
326 
get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format * kp,struct v4l2_sliced_vbi_format __user * up)327 static inline int get_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up)
328 {
329 	if (copy_from_user(kp, up, sizeof(struct v4l2_sliced_vbi_format)))
330 		return -EFAULT;
331 	return 0;
332 }
333 
put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format * kp,struct v4l2_sliced_vbi_format __user * up)334 static inline int put_v4l2_sliced_vbi_format(struct v4l2_sliced_vbi_format *kp, struct v4l2_sliced_vbi_format __user *up)
335 {
336 	if (copy_to_user(up, kp, sizeof(struct v4l2_sliced_vbi_format)))
337 		return -EFAULT;
338 	return 0;
339 }
340 
341 struct v4l2_format32 {
342 	enum v4l2_buf_type type;
343 	union {
344 		struct v4l2_pix_format	pix;
345 		struct v4l2_window32	win;
346 		struct v4l2_vbi_format	vbi;
347 		struct v4l2_sliced_vbi_format	sliced;
348 		__u8	raw_data[200];        /* user-defined */
349 	} fmt;
350 };
351 
get_v4l2_format32(struct v4l2_format * kp,struct v4l2_format32 __user * up)352 static int get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
353 {
354 	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
355 			get_user(kp->type, &up->type))
356 			return -EFAULT;
357 	switch (kp->type) {
358 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
359 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
360 		return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
361 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
362 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
363 		return get_v4l2_window32(&kp->fmt.win, &up->fmt.win);
364 	case V4L2_BUF_TYPE_VBI_CAPTURE:
365 	case V4L2_BUF_TYPE_VBI_OUTPUT:
366 		return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
367 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
368 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
369 		return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
370 	case V4L2_BUF_TYPE_PRIVATE:
371 		if (copy_from_user(kp, up, sizeof(kp->fmt.raw_data)))
372 			return -EFAULT;
373 		return 0;
374 	case 0:
375 		return -EINVAL;
376 	default:
377 		printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
378 								kp->type);
379 		return -EINVAL;
380 	}
381 }
382 
put_v4l2_format32(struct v4l2_format * kp,struct v4l2_format32 __user * up)383 static int put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __user *up)
384 {
385 	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
386 		put_user(kp->type, &up->type))
387 		return -EFAULT;
388 	switch (kp->type) {
389 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
390 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
391 		return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
392 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
393 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
394 		return put_v4l2_window32(&kp->fmt.win, &up->fmt.win);
395 	case V4L2_BUF_TYPE_VBI_CAPTURE:
396 	case V4L2_BUF_TYPE_VBI_OUTPUT:
397 		return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
398 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
399 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
400 		return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
401 	case V4L2_BUF_TYPE_PRIVATE:
402 		if (copy_to_user(up, kp, sizeof(up->fmt.raw_data)))
403 			return -EFAULT;
404 		return 0;
405 	case 0:
406 		return -EINVAL;
407 	default:
408 		printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
409 								kp->type);
410 		return -EINVAL;
411 	}
412 }
413 
414 struct v4l2_standard32 {
415 	__u32		     index;
416 	__u32		     id[2]; /* __u64 would get the alignment wrong */
417 	__u8		     name[24];
418 	struct v4l2_fract    frameperiod; /* Frames, not fields */
419 	__u32		     framelines;
420 	__u32		     reserved[4];
421 };
422 
get_v4l2_standard32(struct v4l2_standard * kp,struct v4l2_standard32 __user * up)423 static int get_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
424 {
425 	/* other fields are not set by the user, nor used by the driver */
426 	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
427 		get_user(kp->index, &up->index))
428 		return -EFAULT;
429 	return 0;
430 }
431 
put_v4l2_standard32(struct v4l2_standard * kp,struct v4l2_standard32 __user * up)432 static int put_v4l2_standard32(struct v4l2_standard *kp, struct v4l2_standard32 __user *up)
433 {
434 	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
435 		put_user(kp->index, &up->index) ||
436 		copy_to_user(up->id, &kp->id, sizeof(__u64)) ||
437 		copy_to_user(up->name, kp->name, 24) ||
438 		copy_to_user(&up->frameperiod, &kp->frameperiod, sizeof(kp->frameperiod)) ||
439 		put_user(kp->framelines, &up->framelines) ||
440 		copy_to_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
441 			return -EFAULT;
442 	return 0;
443 }
444 
445 struct v4l2_buffer32 {
446 	__u32			index;
447 	enum v4l2_buf_type      type;
448 	__u32			bytesused;
449 	__u32			flags;
450 	enum v4l2_field		field;
451 	struct compat_timeval	timestamp;
452 	struct v4l2_timecode	timecode;
453 	__u32			sequence;
454 
455 	/* memory location */
456 	enum v4l2_memory        memory;
457 	union {
458 		__u32           offset;
459 		compat_long_t   userptr;
460 	} m;
461 	__u32			length;
462 	__u32			input;
463 	__u32			reserved;
464 };
465 
get_v4l2_buffer32(struct v4l2_buffer * kp,struct v4l2_buffer32 __user * up)466 static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
467 {
468 
469 	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) ||
470 		get_user(kp->index, &up->index) ||
471 		get_user(kp->type, &up->type) ||
472 		get_user(kp->flags, &up->flags) ||
473 		get_user(kp->memory, &up->memory) ||
474 		get_user(kp->input, &up->input))
475 			return -EFAULT;
476 	switch (kp->memory) {
477 	case V4L2_MEMORY_MMAP:
478 		break;
479 	case V4L2_MEMORY_USERPTR:
480 		{
481 		compat_long_t tmp;
482 
483 		if (get_user(kp->length, &up->length) ||
484 		    get_user(tmp, &up->m.userptr))
485 			return -EFAULT;
486 
487 		kp->m.userptr = (unsigned long)compat_ptr(tmp);
488 		}
489 		break;
490 	case V4L2_MEMORY_OVERLAY:
491 		if (get_user(kp->m.offset, &up->m.offset))
492 			return -EFAULT;
493 		break;
494 	}
495 	return 0;
496 }
497 
put_v4l2_buffer32(struct v4l2_buffer * kp,struct v4l2_buffer32 __user * up)498 static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
499 {
500 	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) ||
501 		put_user(kp->index, &up->index) ||
502 		put_user(kp->type, &up->type) ||
503 		put_user(kp->flags, &up->flags) ||
504 		put_user(kp->memory, &up->memory) ||
505 		put_user(kp->input, &up->input))
506 			return -EFAULT;
507 	switch (kp->memory) {
508 	case V4L2_MEMORY_MMAP:
509 		if (put_user(kp->length, &up->length) ||
510 			put_user(kp->m.offset, &up->m.offset))
511 			return -EFAULT;
512 		break;
513 	case V4L2_MEMORY_USERPTR:
514 		if (put_user(kp->length, &up->length) ||
515 			put_user(kp->m.userptr, &up->m.userptr))
516 			return -EFAULT;
517 		break;
518 	case V4L2_MEMORY_OVERLAY:
519 		if (put_user(kp->m.offset, &up->m.offset))
520 			return -EFAULT;
521 		break;
522 	}
523 	if (put_user(kp->bytesused, &up->bytesused) ||
524 		put_user(kp->field, &up->field) ||
525 		put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
526 		put_user(kp->timestamp.tv_usec, &up->timestamp.tv_usec) ||
527 		copy_to_user(&up->timecode, &kp->timecode, sizeof(struct v4l2_timecode)) ||
528 		put_user(kp->sequence, &up->sequence) ||
529 		put_user(kp->reserved, &up->reserved))
530 			return -EFAULT;
531 	return 0;
532 }
533 
534 struct v4l2_framebuffer32 {
535 	__u32			capability;
536 	__u32			flags;
537 	compat_caddr_t 		base;
538 	struct v4l2_pix_format	fmt;
539 };
540 
get_v4l2_framebuffer32(struct v4l2_framebuffer * kp,struct v4l2_framebuffer32 __user * up)541 static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
542 {
543 	u32 tmp;
544 
545 	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
546 		get_user(tmp, &up->base) ||
547 		get_user(kp->capability, &up->capability) ||
548 		get_user(kp->flags, &up->flags))
549 			return -EFAULT;
550 	kp->base = compat_ptr(tmp);
551 	get_v4l2_pix_format(&kp->fmt, &up->fmt);
552 	return 0;
553 }
554 
put_v4l2_framebuffer32(struct v4l2_framebuffer * kp,struct v4l2_framebuffer32 __user * up)555 static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
556 {
557 	u32 tmp = (u32)((unsigned long)kp->base);
558 
559 	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
560 		put_user(tmp, &up->base) ||
561 		put_user(kp->capability, &up->capability) ||
562 		put_user(kp->flags, &up->flags))
563 			return -EFAULT;
564 	put_v4l2_pix_format(&kp->fmt, &up->fmt);
565 	return 0;
566 }
567 
568 struct v4l2_input32 {
569 	__u32	     index;		/*  Which input */
570 	__u8	     name[32];		/*  Label */
571 	__u32	     type;		/*  Type of input */
572 	__u32	     audioset;		/*  Associated audios (bitfield) */
573 	__u32        tuner;             /*  Associated tuner */
574 	v4l2_std_id  std;
575 	__u32	     status;
576 	__u32	     reserved[4];
577 } __attribute__ ((packed));
578 
579 /* The 64-bit v4l2_input struct has extra padding at the end of the struct.
580    Otherwise it is identical to the 32-bit version. */
get_v4l2_input32(struct v4l2_input * kp,struct v4l2_input32 __user * up)581 static inline int get_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
582 {
583 	if (copy_from_user(kp, up, sizeof(struct v4l2_input32)))
584 		return -EFAULT;
585 	return 0;
586 }
587 
put_v4l2_input32(struct v4l2_input * kp,struct v4l2_input32 __user * up)588 static inline int put_v4l2_input32(struct v4l2_input *kp, struct v4l2_input32 __user *up)
589 {
590 	if (copy_to_user(up, kp, sizeof(struct v4l2_input32)))
591 		return -EFAULT;
592 	return 0;
593 }
594 
595 struct v4l2_ext_controls32 {
596        __u32 ctrl_class;
597        __u32 count;
598        __u32 error_idx;
599        __u32 reserved[2];
600        compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
601 };
602 
get_v4l2_ext_controls32(struct v4l2_ext_controls * kp,struct v4l2_ext_controls32 __user * up)603 static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
604 {
605 	struct v4l2_ext_control __user *ucontrols;
606 	struct v4l2_ext_control __user *kcontrols;
607 	int n;
608 	compat_caddr_t p;
609 
610 	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) ||
611 		get_user(kp->ctrl_class, &up->ctrl_class) ||
612 		get_user(kp->count, &up->count) ||
613 		get_user(kp->error_idx, &up->error_idx) ||
614 		copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
615 			return -EFAULT;
616 	n = kp->count;
617 	if (n == 0) {
618 		kp->controls = NULL;
619 		return 0;
620 	}
621 	if (get_user(p, &up->controls))
622 		return -EFAULT;
623 	ucontrols = compat_ptr(p);
624 	if (!access_ok(VERIFY_READ, ucontrols, n * sizeof(struct v4l2_ext_control)))
625 		return -EFAULT;
626 	kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
627 	kp->controls = kcontrols;
628 	while (--n >= 0) {
629 		if (copy_in_user(&kcontrols->id, &ucontrols->id, sizeof(__u32)))
630 			return -EFAULT;
631 		if (copy_in_user(&kcontrols->reserved2, &ucontrols->reserved2, sizeof(ucontrols->reserved2)))
632 			return -EFAULT;
633 		/* Note: if the void * part of the union ever becomes relevant
634 		   then we need to know the type of the control in order to do
635 		   the right thing here. Luckily, that is not yet an issue. */
636 		if (copy_in_user(&kcontrols->value, &ucontrols->value, sizeof(ucontrols->value)))
637 			return -EFAULT;
638 		ucontrols++;
639 		kcontrols++;
640 	}
641 	return 0;
642 }
643 
put_v4l2_ext_controls32(struct v4l2_ext_controls * kp,struct v4l2_ext_controls32 __user * up)644 static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
645 {
646 	struct v4l2_ext_control __user *ucontrols;
647 	struct v4l2_ext_control __user *kcontrols = kp->controls;
648 	int n = kp->count;
649 	compat_caddr_t p;
650 
651 	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) ||
652 		put_user(kp->ctrl_class, &up->ctrl_class) ||
653 		put_user(kp->count, &up->count) ||
654 		put_user(kp->error_idx, &up->error_idx) ||
655 		copy_to_user(up->reserved, kp->reserved, sizeof(up->reserved)))
656 			return -EFAULT;
657 	if (!kp->count)
658 		return 0;
659 
660 	if (get_user(p, &up->controls))
661 		return -EFAULT;
662 	ucontrols = compat_ptr(p);
663 	if (!access_ok(VERIFY_WRITE, ucontrols, n * sizeof(struct v4l2_ext_control)))
664 		return -EFAULT;
665 
666 	while (--n >= 0) {
667 		if (copy_in_user(&ucontrols->id, &kcontrols->id, sizeof(__u32)))
668 			return -EFAULT;
669 		if (copy_in_user(&ucontrols->reserved2, &kcontrols->reserved2,
670 					sizeof(ucontrols->reserved2)))
671 			return -EFAULT;
672 		/* Note: if the void * part of the union ever becomes relevant
673 		   then we need to know the type of the control in order to do
674 		   the right thing here. Luckily, that is not yet an issue. */
675 		if (copy_in_user(&ucontrols->value, &kcontrols->value, sizeof(ucontrols->value)))
676 			return -EFAULT;
677 		ucontrols++;
678 		kcontrols++;
679 	}
680 	return 0;
681 }
682 
683 #define VIDIOC_G_FMT32		_IOWR('V',  4, struct v4l2_format32)
684 #define VIDIOC_S_FMT32		_IOWR('V',  5, struct v4l2_format32)
685 #define VIDIOC_QUERYBUF32	_IOWR('V',  9, struct v4l2_buffer32)
686 #define VIDIOC_G_FBUF32		_IOR ('V', 10, struct v4l2_framebuffer32)
687 #define VIDIOC_S_FBUF32		_IOW ('V', 11, struct v4l2_framebuffer32)
688 #define VIDIOC_QBUF32		_IOWR('V', 15, struct v4l2_buffer32)
689 #define VIDIOC_DQBUF32		_IOWR('V', 17, struct v4l2_buffer32)
690 #define VIDIOC_ENUMSTD32	_IOWR('V', 25, struct v4l2_standard32)
691 #define VIDIOC_ENUMINPUT32	_IOWR('V', 26, struct v4l2_input32)
692 #define VIDIOC_TRY_FMT32      	_IOWR('V', 64, struct v4l2_format32)
693 #define VIDIOC_G_EXT_CTRLS32    _IOWR('V', 71, struct v4l2_ext_controls32)
694 #define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
695 #define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)
696 
697 #define VIDIOC_OVERLAY32	_IOW ('V', 14, s32)
698 #ifdef __OLD_VIDIOC_
699 #define VIDIOC_OVERLAY32_OLD	_IOWR('V', 14, s32)
700 #endif
701 #define VIDIOC_STREAMON32	_IOW ('V', 18, s32)
702 #define VIDIOC_STREAMOFF32	_IOW ('V', 19, s32)
703 #define VIDIOC_G_INPUT32	_IOR ('V', 38, s32)
704 #define VIDIOC_S_INPUT32	_IOWR('V', 39, s32)
705 #define VIDIOC_G_OUTPUT32	_IOR ('V', 46, s32)
706 #define VIDIOC_S_OUTPUT32	_IOWR('V', 47, s32)
707 
do_video_ioctl(struct file * file,unsigned int cmd,unsigned long arg)708 static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
709 {
710 	union {
711 #ifdef CONFIG_VIDEO_V4L1_COMPAT
712 		struct video_tuner vt;
713 		struct video_buffer vb;
714 		struct video_window vw;
715 		struct video_code vc;
716 		struct video_audio va;
717 #endif
718 		struct v4l2_format v2f;
719 		struct v4l2_buffer v2b;
720 		struct v4l2_framebuffer v2fb;
721 		struct v4l2_input v2i;
722 		struct v4l2_standard v2s;
723 		struct v4l2_ext_controls v2ecs;
724 		unsigned long vx;
725 		int vi;
726 	} karg;
727 	void __user *up = compat_ptr(arg);
728 	int compatible_arg = 1;
729 	long err = 0;
730 
731 	/* First, convert the command. */
732 	switch (cmd) {
733 #ifdef CONFIG_VIDEO_V4L1_COMPAT
734 	case VIDIOCGTUNER32: cmd = VIDIOCGTUNER; break;
735 	case VIDIOCSTUNER32: cmd = VIDIOCSTUNER; break;
736 	case VIDIOCGWIN32: cmd = VIDIOCGWIN; break;
737 	case VIDIOCSWIN32: cmd = VIDIOCSWIN; break;
738 	case VIDIOCGFBUF32: cmd = VIDIOCGFBUF; break;
739 	case VIDIOCSFBUF32: cmd = VIDIOCSFBUF; break;
740 	case VIDIOCGFREQ32: cmd = VIDIOCGFREQ; break;
741 	case VIDIOCSFREQ32: cmd = VIDIOCSFREQ; break;
742 	case VIDIOCSMICROCODE32: cmd = VIDIOCSMICROCODE; break;
743 #endif
744 	case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
745 	case VIDIOC_S_FMT32: cmd = VIDIOC_S_FMT; break;
746 	case VIDIOC_QUERYBUF32: cmd = VIDIOC_QUERYBUF; break;
747 	case VIDIOC_G_FBUF32: cmd = VIDIOC_G_FBUF; break;
748 	case VIDIOC_S_FBUF32: cmd = VIDIOC_S_FBUF; break;
749 	case VIDIOC_QBUF32: cmd = VIDIOC_QBUF; break;
750 	case VIDIOC_DQBUF32: cmd = VIDIOC_DQBUF; break;
751 	case VIDIOC_ENUMSTD32: cmd = VIDIOC_ENUMSTD; break;
752 	case VIDIOC_ENUMINPUT32: cmd = VIDIOC_ENUMINPUT; break;
753 	case VIDIOC_TRY_FMT32: cmd = VIDIOC_TRY_FMT; break;
754 	case VIDIOC_G_EXT_CTRLS32: cmd = VIDIOC_G_EXT_CTRLS; break;
755 	case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break;
756 	case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break;
757 	case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
758 #ifdef __OLD_VIDIOC_
759 	case VIDIOC_OVERLAY32_OLD: cmd = VIDIOC_OVERLAY; break;
760 #endif
761 	case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break;
762 	case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
763 	case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
764 	case VIDIOC_S_INPUT32: cmd = VIDIOC_S_INPUT; break;
765 	case VIDIOC_G_OUTPUT32: cmd = VIDIOC_G_OUTPUT; break;
766 	case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
767 	}
768 
769 	switch (cmd) {
770 #ifdef CONFIG_VIDEO_V4L1_COMPAT
771 	case VIDIOCSTUNER:
772 	case VIDIOCGTUNER:
773 		err = get_video_tuner32(&karg.vt, up);
774 		compatible_arg = 0;
775 		break;
776 
777 	case VIDIOCSFBUF:
778 		err = get_video_buffer32(&karg.vb, up);
779 		compatible_arg = 0;
780 		break;
781 
782 	case VIDIOCSWIN:
783 		err = get_video_window32(&karg.vw, up);
784 		compatible_arg = 0;
785 		break;
786 
787 	case VIDIOCGWIN:
788 	case VIDIOCGFBUF:
789 	case VIDIOCGFREQ:
790 		compatible_arg = 0;
791 		break;
792 
793 	case VIDIOCSMICROCODE:
794 		err = get_microcode32(&karg.vc, up);
795 		compatible_arg = 0;
796 		break;
797 
798 	case VIDIOCSFREQ:
799 		err = get_user(karg.vx, (u32 __user *)up);
800 		compatible_arg = 0;
801 		break;
802 
803 	case VIDIOCCAPTURE:
804 	case VIDIOCSYNC:
805 	case VIDIOCSWRITEMODE:
806 #endif
807 	case VIDIOC_OVERLAY:
808 	case VIDIOC_STREAMON:
809 	case VIDIOC_STREAMOFF:
810 	case VIDIOC_S_INPUT:
811 	case VIDIOC_S_OUTPUT:
812 		err = get_user(karg.vi, (s32 __user *)up);
813 		compatible_arg = 0;
814 		break;
815 
816 	case VIDIOC_G_INPUT:
817 	case VIDIOC_G_OUTPUT:
818 		compatible_arg = 0;
819 		break;
820 
821 	case VIDIOC_G_FMT:
822 	case VIDIOC_S_FMT:
823 	case VIDIOC_TRY_FMT:
824 		err = get_v4l2_format32(&karg.v2f, up);
825 		compatible_arg = 0;
826 		break;
827 
828 	case VIDIOC_QUERYBUF:
829 	case VIDIOC_QBUF:
830 	case VIDIOC_DQBUF:
831 		err = get_v4l2_buffer32(&karg.v2b, up);
832 		compatible_arg = 0;
833 		break;
834 
835 	case VIDIOC_S_FBUF:
836 		err = get_v4l2_framebuffer32(&karg.v2fb, up);
837 		compatible_arg = 0;
838 		break;
839 
840 	case VIDIOC_G_FBUF:
841 		compatible_arg = 0;
842 		break;
843 
844 	case VIDIOC_ENUMSTD:
845 		err = get_v4l2_standard32(&karg.v2s, up);
846 		compatible_arg = 0;
847 		break;
848 
849 	case VIDIOC_ENUMINPUT:
850 		err = get_v4l2_input32(&karg.v2i, up);
851 		compatible_arg = 0;
852 		break;
853 
854 	case VIDIOC_G_EXT_CTRLS:
855 	case VIDIOC_S_EXT_CTRLS:
856 	case VIDIOC_TRY_EXT_CTRLS:
857 		err = get_v4l2_ext_controls32(&karg.v2ecs, up);
858 		compatible_arg = 0;
859 		break;
860 	}
861 	if (err)
862 		return err;
863 
864 	if (compatible_arg)
865 		err = native_ioctl(file, cmd, (unsigned long)up);
866 	else {
867 		mm_segment_t old_fs = get_fs();
868 
869 		set_fs(KERNEL_DS);
870 		err = native_ioctl(file, cmd, (unsigned long)&karg);
871 		set_fs(old_fs);
872 	}
873 
874 	/* Special case: even after an error we need to put the
875 	   results back for these ioctls since the error_idx will
876 	   contain information on which control failed. */
877 	switch (cmd) {
878 	case VIDIOC_G_EXT_CTRLS:
879 	case VIDIOC_S_EXT_CTRLS:
880 	case VIDIOC_TRY_EXT_CTRLS:
881 		if (put_v4l2_ext_controls32(&karg.v2ecs, up))
882 			err = -EFAULT;
883 		break;
884 	}
885 	if (err)
886 		return err;
887 
888 	switch (cmd) {
889 #ifdef CONFIG_VIDEO_V4L1_COMPAT
890 	case VIDIOCGTUNER:
891 		err = put_video_tuner32(&karg.vt, up);
892 		break;
893 
894 	case VIDIOCGWIN:
895 		err = put_video_window32(&karg.vw, up);
896 		break;
897 
898 	case VIDIOCGFBUF:
899 		err = put_video_buffer32(&karg.vb, up);
900 		break;
901 
902 	case VIDIOCGFREQ:
903 		err = put_user(((u32)karg.vx), (u32 __user *)up);
904 		break;
905 #endif
906 	case VIDIOC_S_INPUT:
907 	case VIDIOC_S_OUTPUT:
908 	case VIDIOC_G_INPUT:
909 	case VIDIOC_G_OUTPUT:
910 		err = put_user(((s32)karg.vi), (s32 __user *)up);
911 		break;
912 
913 	case VIDIOC_G_FBUF:
914 		err = put_v4l2_framebuffer32(&karg.v2fb, up);
915 		break;
916 
917 	case VIDIOC_G_FMT:
918 	case VIDIOC_S_FMT:
919 	case VIDIOC_TRY_FMT:
920 		err = put_v4l2_format32(&karg.v2f, up);
921 		break;
922 
923 	case VIDIOC_QUERYBUF:
924 	case VIDIOC_QBUF:
925 	case VIDIOC_DQBUF:
926 		err = put_v4l2_buffer32(&karg.v2b, up);
927 		break;
928 
929 	case VIDIOC_ENUMSTD:
930 		err = put_v4l2_standard32(&karg.v2s, up);
931 		break;
932 
933 	case VIDIOC_ENUMINPUT:
934 		err = put_v4l2_input32(&karg.v2i, up);
935 		break;
936 	}
937 	return err;
938 }
939 
v4l2_compat_ioctl32(struct file * file,unsigned int cmd,unsigned long arg)940 long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
941 {
942 	long ret = -ENOIOCTLCMD;
943 
944 	if (!file->f_op->ioctl && !file->f_op->unlocked_ioctl)
945 		return ret;
946 
947 	switch (cmd) {
948 #ifdef CONFIG_VIDEO_V4L1_COMPAT
949 	case VIDIOCGCAP:
950 	case VIDIOCGCHAN:
951 	case VIDIOCSCHAN:
952 	case VIDIOCGTUNER32:
953 	case VIDIOCSTUNER32:
954 	case VIDIOCGPICT:
955 	case VIDIOCSPICT:
956 	case VIDIOCCAPTURE32:
957 	case VIDIOCGWIN32:
958 	case VIDIOCSWIN32:
959 	case VIDIOCGFBUF32:
960 	case VIDIOCSFBUF32:
961 	case VIDIOCKEY:
962 	case VIDIOCGFREQ32:
963 	case VIDIOCSFREQ32:
964 	case VIDIOCGAUDIO:
965 	case VIDIOCSAUDIO:
966 	case VIDIOCSYNC32:
967 	case VIDIOCMCAPTURE:
968 	case VIDIOCGMBUF:
969 	case VIDIOCGUNIT:
970 	case VIDIOCGCAPTURE:
971 	case VIDIOCSCAPTURE:
972 	case VIDIOCSPLAYMODE:
973 	case VIDIOCSWRITEMODE32:
974 	case VIDIOCGPLAYINFO:
975 	case VIDIOCSMICROCODE32:
976 	case VIDIOCGVBIFMT:
977 	case VIDIOCSVBIFMT:
978 #endif
979 #ifdef __OLD_VIDIOC_
980 	case VIDIOC_OVERLAY32_OLD:
981 	case VIDIOC_S_PARM_OLD:
982 	case VIDIOC_S_CTRL_OLD:
983 	case VIDIOC_G_AUDIO_OLD:
984 	case VIDIOC_G_AUDOUT_OLD:
985 	case VIDIOC_CROPCAP_OLD:
986 #endif
987 	case VIDIOC_QUERYCAP:
988 	case VIDIOC_RESERVED:
989 	case VIDIOC_ENUM_FMT:
990 	case VIDIOC_G_FMT32:
991 	case VIDIOC_S_FMT32:
992 	case VIDIOC_REQBUFS:
993 	case VIDIOC_QUERYBUF32:
994 	case VIDIOC_G_FBUF32:
995 	case VIDIOC_S_FBUF32:
996 	case VIDIOC_OVERLAY32:
997 	case VIDIOC_QBUF32:
998 	case VIDIOC_DQBUF32:
999 	case VIDIOC_STREAMON32:
1000 	case VIDIOC_STREAMOFF32:
1001 	case VIDIOC_G_PARM:
1002 	case VIDIOC_S_PARM:
1003 	case VIDIOC_G_STD:
1004 	case VIDIOC_S_STD:
1005 	case VIDIOC_ENUMSTD32:
1006 	case VIDIOC_ENUMINPUT32:
1007 	case VIDIOC_G_CTRL:
1008 	case VIDIOC_S_CTRL:
1009 	case VIDIOC_G_TUNER:
1010 	case VIDIOC_S_TUNER:
1011 	case VIDIOC_G_AUDIO:
1012 	case VIDIOC_S_AUDIO:
1013 	case VIDIOC_QUERYCTRL:
1014 	case VIDIOC_QUERYMENU:
1015 	case VIDIOC_G_INPUT32:
1016 	case VIDIOC_S_INPUT32:
1017 	case VIDIOC_G_OUTPUT32:
1018 	case VIDIOC_S_OUTPUT32:
1019 	case VIDIOC_ENUMOUTPUT:
1020 	case VIDIOC_G_AUDOUT:
1021 	case VIDIOC_S_AUDOUT:
1022 	case VIDIOC_G_MODULATOR:
1023 	case VIDIOC_S_MODULATOR:
1024 	case VIDIOC_S_FREQUENCY:
1025 	case VIDIOC_G_FREQUENCY:
1026 	case VIDIOC_CROPCAP:
1027 	case VIDIOC_G_CROP:
1028 	case VIDIOC_S_CROP:
1029 	case VIDIOC_G_JPEGCOMP:
1030 	case VIDIOC_S_JPEGCOMP:
1031 	case VIDIOC_QUERYSTD:
1032 	case VIDIOC_TRY_FMT32:
1033 	case VIDIOC_ENUMAUDIO:
1034 	case VIDIOC_ENUMAUDOUT:
1035 	case VIDIOC_G_PRIORITY:
1036 	case VIDIOC_S_PRIORITY:
1037 	case VIDIOC_G_SLICED_VBI_CAP:
1038 	case VIDIOC_LOG_STATUS:
1039 	case VIDIOC_G_EXT_CTRLS32:
1040 	case VIDIOC_S_EXT_CTRLS32:
1041 	case VIDIOC_TRY_EXT_CTRLS32:
1042 	case VIDIOC_ENUM_FRAMESIZES:
1043 	case VIDIOC_ENUM_FRAMEINTERVALS:
1044 	case VIDIOC_G_ENC_INDEX:
1045 	case VIDIOC_ENCODER_CMD:
1046 	case VIDIOC_TRY_ENCODER_CMD:
1047 	case VIDIOC_DBG_S_REGISTER:
1048 	case VIDIOC_DBG_G_REGISTER:
1049 	case VIDIOC_DBG_G_CHIP_IDENT:
1050 	case VIDIOC_G_CHIP_IDENT_OLD:
1051 	case VIDIOC_S_HW_FREQ_SEEK:
1052 		ret = do_video_ioctl(file, cmd, arg);
1053 		break;
1054 
1055 #ifdef CONFIG_VIDEO_V4L1_COMPAT
1056 	/* BTTV specific... */
1057 	case _IOW('v',  BASE_VIDIOCPRIVATE+0, char [256]):
1058 	case _IOR('v',  BASE_VIDIOCPRIVATE+1, char [256]):
1059 	case _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int):
1060 	case _IOW('v' , BASE_VIDIOCPRIVATE+3, char [16]): /* struct bttv_pll_info */
1061 	case _IOR('v' , BASE_VIDIOCPRIVATE+4, int):
1062 	case _IOR('v' , BASE_VIDIOCPRIVATE+5, int):
1063 	case _IOR('v' , BASE_VIDIOCPRIVATE+6, int):
1064 	case _IOR('v' , BASE_VIDIOCPRIVATE+7, int):
1065 		ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
1066 		break;
1067 #endif
1068 	default:
1069 		printk(KERN_WARNING "compat_ioctl32: "
1070 			"unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
1071 			_IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
1072 		break;
1073 	}
1074 	return ret;
1075 }
1076 EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);
1077 #endif
1078 
1079 MODULE_LICENSE("GPL");
1080