aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/v4l2-compat-ioctl32.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/video/v4l2-compat-ioctl32.c')
-rw-r--r--drivers/media/video/v4l2-compat-ioctl32.c1082
1 files changed, 1082 insertions, 0 deletions
diff --git a/drivers/media/video/v4l2-compat-ioctl32.c b/drivers/media/video/v4l2-compat-ioctl32.c
new file mode 100644
index 000000000000..d0e1bd3ace6a
--- /dev/null
+++ b/drivers/media/video/v4l2-compat-ioctl32.c
@@ -0,0 +1,1082 @@
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
27struct 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
35static 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
49static 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
63struct video_buffer32 {
64 compat_caddr_t base;
65 compat_int_t height, width, depth, bytesperline;
66};
67
68static 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
88static 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
102struct video_clip32 {
103 s32 x, y, width, height; /* It's really s32 in videodev.h */
104 compat_caddr_t next;
105};
106
107struct video_window32 {
108 u32 x, y, width, height, chromakey, flags;
109 compat_caddr_t clips;
110 compat_int_t clipcount;
111};
112
113static 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... */
179static 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
193struct video_code32 {
194 char loadwhat[16]; /* name or tag of file being passed */
195 compat_int_t datasize;
196 unsigned char *data;
197};
198
199static 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
225static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
226{
227 int 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
241struct v4l2_clip32 {
242 struct v4l2_rect c;
243 compat_caddr_t next;
244};
245
246struct 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
255static 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
289static 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
299static 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
306static 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
313static 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
320static 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
327static 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
334static 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
341struct 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
352static 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
383static 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
414struct 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
423static 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
432static 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
445struct 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
466static 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
498static 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
534struct v4l2_framebuffer32 {
535 __u32 capability;
536 __u32 flags;
537 compat_caddr_t base;
538 struct v4l2_pix_format fmt;
539};
540
541static 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
555static 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
568struct 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. */
581static 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
588static 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
595struct 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
603static 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
644static 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
708static int 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 int 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
940long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
941{
942 int 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_G_CHIP_IDENT:
1050 case VIDIOC_S_HW_FREQ_SEEK:
1051 ret = do_video_ioctl(file, cmd, arg);
1052 break;
1053
1054#ifdef CONFIG_VIDEO_V4L1_COMPAT
1055 /* BTTV specific... */
1056 case _IOW('v', BASE_VIDIOCPRIVATE+0, char [256]):
1057 case _IOR('v', BASE_VIDIOCPRIVATE+1, char [256]):
1058 case _IOR('v' , BASE_VIDIOCPRIVATE+2, unsigned int):
1059 case _IOW('v' , BASE_VIDIOCPRIVATE+3, char [16]): /* struct bttv_pll_info */
1060 case _IOR('v' , BASE_VIDIOCPRIVATE+4, int):
1061 case _IOR('v' , BASE_VIDIOCPRIVATE+5, int):
1062 case _IOR('v' , BASE_VIDIOCPRIVATE+6, int):
1063 case _IOR('v' , BASE_VIDIOCPRIVATE+7, int):
1064 ret = native_ioctl(file, cmd, (unsigned long)compat_ptr(arg));
1065 break;
1066#endif
1067 default:
1068 v4l_print_ioctl("compat_ioctl32", cmd);
1069 printk(KERN_CONT "\n");
1070 break;
1071 }
1072 return ret;
1073}
1074#else
1075long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
1076{
1077 return -ENOIOCTLCMD;
1078}
1079#endif
1080EXPORT_SYMBOL_GPL(v4l_compat_ioctl32);
1081
1082MODULE_LICENSE("GPL");