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