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