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