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