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