GNU Linux-libre 6.1.24-gnu
[releases.git] / drivers / media / v4l2-core / v4l2-compat-ioctl32.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
4  *      Separated from fs stuff by Arnd Bergmann <arnd@arndb.de>
5  *
6  * Copyright (C) 1997-2000  Jakub Jelinek  (jakub@redhat.com)
7  * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
8  * Copyright (C) 2001,2002  Andi Kleen, SuSE Labs
9  * Copyright (C) 2003       Pavel Machek (pavel@ucw.cz)
10  * Copyright (C) 2005       Philippe De Muyter (phdm@macqel.be)
11  * Copyright (C) 2008       Hans Verkuil <hverkuil@xs4all.nl>
12  *
13  * These routines maintain argument size conversion between 32bit and 64bit
14  * ioctls.
15  */
16
17 #include <linux/compat.h>
18 #include <linux/module.h>
19 #include <linux/videodev2.h>
20 #include <linux/v4l2-subdev.h>
21 #include <media/v4l2-dev.h>
22 #include <media/v4l2-fh.h>
23 #include <media/v4l2-ctrls.h>
24 #include <media/v4l2-ioctl.h>
25
26 /*
27  * Per-ioctl data copy handlers.
28  *
29  * Those come in pairs, with a get_v4l2_foo() and a put_v4l2_foo() routine,
30  * where "v4l2_foo" is the name of the V4L2 struct.
31  *
32  * They basically get two __user pointers, one with a 32-bits struct that
33  * came from the userspace call and a 64-bits struct, also allocated as
34  * userspace, but filled internally by do_video_ioctl().
35  *
36  * For ioctls that have pointers inside it, the functions will also
37  * receive an ancillary buffer with extra space, used to pass extra
38  * data to the routine.
39  */
40
41 struct v4l2_clip32 {
42         struct v4l2_rect        c;
43         compat_caddr_t          next;
44 };
45
46 struct v4l2_window32 {
47         struct v4l2_rect        w;
48         __u32                   field;  /* enum v4l2_field */
49         __u32                   chromakey;
50         compat_caddr_t          clips; /* actually struct v4l2_clip32 * */
51         __u32                   clipcount;
52         compat_caddr_t          bitmap;
53         __u8                    global_alpha;
54 };
55
56 static int get_v4l2_window32(struct v4l2_window *p64,
57                              struct v4l2_window32 __user *p32)
58 {
59         struct v4l2_window32 w32;
60
61         if (copy_from_user(&w32, p32, sizeof(w32)))
62                 return -EFAULT;
63
64         *p64 = (struct v4l2_window) {
65                 .w              = w32.w,
66                 .field          = w32.field,
67                 .chromakey      = w32.chromakey,
68                 .clips          = (void __force *)compat_ptr(w32.clips),
69                 .clipcount      = w32.clipcount,
70                 .bitmap         = compat_ptr(w32.bitmap),
71                 .global_alpha   = w32.global_alpha,
72         };
73
74         if (p64->clipcount > 2048)
75                 return -EINVAL;
76         if (!p64->clipcount)
77                 p64->clips = NULL;
78
79         return 0;
80 }
81
82 static int put_v4l2_window32(struct v4l2_window *p64,
83                              struct v4l2_window32 __user *p32)
84 {
85         struct v4l2_window32 w32;
86
87         memset(&w32, 0, sizeof(w32));
88         w32 = (struct v4l2_window32) {
89                 .w              = p64->w,
90                 .field          = p64->field,
91                 .chromakey      = p64->chromakey,
92                 .clips          = (uintptr_t)p64->clips,
93                 .clipcount      = p64->clipcount,
94                 .bitmap         = ptr_to_compat(p64->bitmap),
95                 .global_alpha   = p64->global_alpha,
96         };
97
98         /* copy everything except the clips pointer */
99         if (copy_to_user(p32, &w32, offsetof(struct v4l2_window32, clips)) ||
100             copy_to_user(&p32->clipcount, &w32.clipcount,
101                          sizeof(w32) - offsetof(struct v4l2_window32, clipcount)))
102                 return -EFAULT;
103
104         return 0;
105 }
106
107 struct v4l2_format32 {
108         __u32   type;   /* enum v4l2_buf_type */
109         union {
110                 struct v4l2_pix_format  pix;
111                 struct v4l2_pix_format_mplane   pix_mp;
112                 struct v4l2_window32    win;
113                 struct v4l2_vbi_format  vbi;
114                 struct v4l2_sliced_vbi_format   sliced;
115                 struct v4l2_sdr_format  sdr;
116                 struct v4l2_meta_format meta;
117                 __u8    raw_data[200];        /* user-defined */
118         } fmt;
119 };
120
121 /**
122  * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument
123  * @index:      on return, index of the first created buffer
124  * @count:      entry: number of requested buffers,
125  *              return: number of created buffers
126  * @memory:     buffer memory type
127  * @format:     frame format, for which buffers are requested
128  * @capabilities: capabilities of this buffer type.
129  * @flags:      additional buffer management attributes (ignored unless the
130  *              queue has V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS capability and
131  *              configured for MMAP streaming I/O).
132  * @reserved:   future extensions
133  */
134 struct v4l2_create_buffers32 {
135         __u32                   index;
136         __u32                   count;
137         __u32                   memory; /* enum v4l2_memory */
138         struct v4l2_format32    format;
139         __u32                   capabilities;
140         __u32                   flags;
141         __u32                   reserved[6];
142 };
143
144 static int get_v4l2_format32(struct v4l2_format *p64,
145                              struct v4l2_format32 __user *p32)
146 {
147         if (get_user(p64->type, &p32->type))
148                 return -EFAULT;
149
150         switch (p64->type) {
151         case V4L2_BUF_TYPE_VIDEO_CAPTURE:
152         case V4L2_BUF_TYPE_VIDEO_OUTPUT:
153                 return copy_from_user(&p64->fmt.pix, &p32->fmt.pix,
154                                       sizeof(p64->fmt.pix)) ? -EFAULT : 0;
155         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
156         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
157                 return copy_from_user(&p64->fmt.pix_mp, &p32->fmt.pix_mp,
158                                       sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;
159         case V4L2_BUF_TYPE_VIDEO_OVERLAY:
160         case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
161                 return get_v4l2_window32(&p64->fmt.win, &p32->fmt.win);
162         case V4L2_BUF_TYPE_VBI_CAPTURE:
163         case V4L2_BUF_TYPE_VBI_OUTPUT:
164                 return copy_from_user(&p64->fmt.vbi, &p32->fmt.vbi,
165                                       sizeof(p64->fmt.vbi)) ? -EFAULT : 0;
166         case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
167         case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
168                 return copy_from_user(&p64->fmt.sliced, &p32->fmt.sliced,
169                                       sizeof(p64->fmt.sliced)) ? -EFAULT : 0;
170         case V4L2_BUF_TYPE_SDR_CAPTURE:
171         case V4L2_BUF_TYPE_SDR_OUTPUT:
172                 return copy_from_user(&p64->fmt.sdr, &p32->fmt.sdr,
173                                       sizeof(p64->fmt.sdr)) ? -EFAULT : 0;
174         case V4L2_BUF_TYPE_META_CAPTURE:
175         case V4L2_BUF_TYPE_META_OUTPUT:
176                 return copy_from_user(&p64->fmt.meta, &p32->fmt.meta,
177                                       sizeof(p64->fmt.meta)) ? -EFAULT : 0;
178         default:
179                 return -EINVAL;
180         }
181 }
182
183 static int get_v4l2_create32(struct v4l2_create_buffers *p64,
184                              struct v4l2_create_buffers32 __user *p32)
185 {
186         if (copy_from_user(p64, p32,
187                            offsetof(struct v4l2_create_buffers32, format)))
188                 return -EFAULT;
189         if (copy_from_user(&p64->flags, &p32->flags, sizeof(p32->flags)))
190                 return -EFAULT;
191         return get_v4l2_format32(&p64->format, &p32->format);
192 }
193
194 static int put_v4l2_format32(struct v4l2_format *p64,
195                              struct v4l2_format32 __user *p32)
196 {
197         switch (p64->type) {
198         case V4L2_BUF_TYPE_VIDEO_CAPTURE:
199         case V4L2_BUF_TYPE_VIDEO_OUTPUT:
200                 return copy_to_user(&p32->fmt.pix, &p64->fmt.pix,
201                                     sizeof(p64->fmt.pix)) ? -EFAULT : 0;
202         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
203         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
204                 return copy_to_user(&p32->fmt.pix_mp, &p64->fmt.pix_mp,
205                                     sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;
206         case V4L2_BUF_TYPE_VIDEO_OVERLAY:
207         case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
208                 return put_v4l2_window32(&p64->fmt.win, &p32->fmt.win);
209         case V4L2_BUF_TYPE_VBI_CAPTURE:
210         case V4L2_BUF_TYPE_VBI_OUTPUT:
211                 return copy_to_user(&p32->fmt.vbi, &p64->fmt.vbi,
212                                     sizeof(p64->fmt.vbi)) ? -EFAULT : 0;
213         case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
214         case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
215                 return copy_to_user(&p32->fmt.sliced, &p64->fmt.sliced,
216                                     sizeof(p64->fmt.sliced)) ? -EFAULT : 0;
217         case V4L2_BUF_TYPE_SDR_CAPTURE:
218         case V4L2_BUF_TYPE_SDR_OUTPUT:
219                 return copy_to_user(&p32->fmt.sdr, &p64->fmt.sdr,
220                                     sizeof(p64->fmt.sdr)) ? -EFAULT : 0;
221         case V4L2_BUF_TYPE_META_CAPTURE:
222         case V4L2_BUF_TYPE_META_OUTPUT:
223                 return copy_to_user(&p32->fmt.meta, &p64->fmt.meta,
224                                     sizeof(p64->fmt.meta)) ? -EFAULT : 0;
225         default:
226                 return -EINVAL;
227         }
228 }
229
230 static int put_v4l2_create32(struct v4l2_create_buffers *p64,
231                              struct v4l2_create_buffers32 __user *p32)
232 {
233         if (copy_to_user(p32, p64,
234                          offsetof(struct v4l2_create_buffers32, format)) ||
235             put_user(p64->capabilities, &p32->capabilities) ||
236             put_user(p64->flags, &p32->flags) ||
237             copy_to_user(p32->reserved, p64->reserved, sizeof(p64->reserved)))
238                 return -EFAULT;
239         return put_v4l2_format32(&p64->format, &p32->format);
240 }
241
242 struct v4l2_standard32 {
243         __u32                index;
244         compat_u64           id;
245         __u8                 name[24];
246         struct v4l2_fract    frameperiod; /* Frames, not fields */
247         __u32                framelines;
248         __u32                reserved[4];
249 };
250
251 static int get_v4l2_standard32(struct v4l2_standard *p64,
252                                struct v4l2_standard32 __user *p32)
253 {
254         /* other fields are not set by the user, nor used by the driver */
255         return get_user(p64->index, &p32->index);
256 }
257
258 static int put_v4l2_standard32(struct v4l2_standard *p64,
259                                struct v4l2_standard32 __user *p32)
260 {
261         if (put_user(p64->index, &p32->index) ||
262             put_user(p64->id, &p32->id) ||
263             copy_to_user(p32->name, p64->name, sizeof(p32->name)) ||
264             copy_to_user(&p32->frameperiod, &p64->frameperiod,
265                          sizeof(p32->frameperiod)) ||
266             put_user(p64->framelines, &p32->framelines) ||
267             copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
268                 return -EFAULT;
269         return 0;
270 }
271
272 struct v4l2_plane32 {
273         __u32                   bytesused;
274         __u32                   length;
275         union {
276                 __u32           mem_offset;
277                 compat_long_t   userptr;
278                 __s32           fd;
279         } m;
280         __u32                   data_offset;
281         __u32                   reserved[11];
282 };
283
284 /*
285  * This is correct for all architectures including i386, but not x32,
286  * which has different alignment requirements for timestamp
287  */
288 struct v4l2_buffer32 {
289         __u32                   index;
290         __u32                   type;   /* enum v4l2_buf_type */
291         __u32                   bytesused;
292         __u32                   flags;
293         __u32                   field;  /* enum v4l2_field */
294         struct {
295                 compat_s64      tv_sec;
296                 compat_s64      tv_usec;
297         }                       timestamp;
298         struct v4l2_timecode    timecode;
299         __u32                   sequence;
300
301         /* memory location */
302         __u32                   memory; /* enum v4l2_memory */
303         union {
304                 __u32           offset;
305                 compat_long_t   userptr;
306                 compat_caddr_t  planes;
307                 __s32           fd;
308         } m;
309         __u32                   length;
310         __u32                   reserved2;
311         __s32                   request_fd;
312 };
313
314 #ifdef CONFIG_COMPAT_32BIT_TIME
315 struct v4l2_buffer32_time32 {
316         __u32                   index;
317         __u32                   type;   /* enum v4l2_buf_type */
318         __u32                   bytesused;
319         __u32                   flags;
320         __u32                   field;  /* enum v4l2_field */
321         struct old_timeval32    timestamp;
322         struct v4l2_timecode    timecode;
323         __u32                   sequence;
324
325         /* memory location */
326         __u32                   memory; /* enum v4l2_memory */
327         union {
328                 __u32           offset;
329                 compat_long_t   userptr;
330                 compat_caddr_t  planes;
331                 __s32           fd;
332         } m;
333         __u32                   length;
334         __u32                   reserved2;
335         __s32                   request_fd;
336 };
337 #endif
338
339 static int get_v4l2_plane32(struct v4l2_plane *p64,
340                             struct v4l2_plane32 __user *p32,
341                             enum v4l2_memory memory)
342 {
343         struct v4l2_plane32 plane32;
344         typeof(p64->m) m = {};
345
346         if (copy_from_user(&plane32, p32, sizeof(plane32)))
347                 return -EFAULT;
348
349         switch (memory) {
350         case V4L2_MEMORY_MMAP:
351         case V4L2_MEMORY_OVERLAY:
352                 m.mem_offset = plane32.m.mem_offset;
353                 break;
354         case V4L2_MEMORY_USERPTR:
355                 m.userptr = (unsigned long)compat_ptr(plane32.m.userptr);
356                 break;
357         case V4L2_MEMORY_DMABUF:
358                 m.fd = plane32.m.fd;
359                 break;
360         }
361
362         memset(p64, 0, sizeof(*p64));
363         *p64 = (struct v4l2_plane) {
364                 .bytesused      = plane32.bytesused,
365                 .length         = plane32.length,
366                 .m              = m,
367                 .data_offset    = plane32.data_offset,
368         };
369
370         return 0;
371 }
372
373 static int put_v4l2_plane32(struct v4l2_plane *p64,
374                             struct v4l2_plane32 __user *p32,
375                             enum v4l2_memory memory)
376 {
377         struct v4l2_plane32 plane32;
378
379         memset(&plane32, 0, sizeof(plane32));
380         plane32 = (struct v4l2_plane32) {
381                 .bytesused      = p64->bytesused,
382                 .length         = p64->length,
383                 .data_offset    = p64->data_offset,
384         };
385
386         switch (memory) {
387         case V4L2_MEMORY_MMAP:
388         case V4L2_MEMORY_OVERLAY:
389                 plane32.m.mem_offset = p64->m.mem_offset;
390                 break;
391         case V4L2_MEMORY_USERPTR:
392                 plane32.m.userptr = (uintptr_t)(p64->m.userptr);
393                 break;
394         case V4L2_MEMORY_DMABUF:
395                 plane32.m.fd = p64->m.fd;
396                 break;
397         }
398
399         if (copy_to_user(p32, &plane32, sizeof(plane32)))
400                 return -EFAULT;
401
402         return 0;
403 }
404
405 static int get_v4l2_buffer32(struct v4l2_buffer *vb,
406                              struct v4l2_buffer32 __user *arg)
407 {
408         struct v4l2_buffer32 vb32;
409
410         if (copy_from_user(&vb32, arg, sizeof(vb32)))
411                 return -EFAULT;
412
413         memset(vb, 0, sizeof(*vb));
414         *vb = (struct v4l2_buffer) {
415                 .index          = vb32.index,
416                 .type           = vb32.type,
417                 .bytesused      = vb32.bytesused,
418                 .flags          = vb32.flags,
419                 .field          = vb32.field,
420                 .timestamp.tv_sec       = vb32.timestamp.tv_sec,
421                 .timestamp.tv_usec      = vb32.timestamp.tv_usec,
422                 .timecode       = vb32.timecode,
423                 .sequence       = vb32.sequence,
424                 .memory         = vb32.memory,
425                 .m.offset       = vb32.m.offset,
426                 .length         = vb32.length,
427                 .request_fd     = vb32.request_fd,
428         };
429
430         switch (vb->memory) {
431         case V4L2_MEMORY_MMAP:
432         case V4L2_MEMORY_OVERLAY:
433                 vb->m.offset = vb32.m.offset;
434                 break;
435         case V4L2_MEMORY_USERPTR:
436                 vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr);
437                 break;
438         case V4L2_MEMORY_DMABUF:
439                 vb->m.fd = vb32.m.fd;
440                 break;
441         }
442
443         if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
444                 vb->m.planes = (void __force *)
445                                 compat_ptr(vb32.m.planes);
446
447         return 0;
448 }
449
450 #ifdef CONFIG_COMPAT_32BIT_TIME
451 static int get_v4l2_buffer32_time32(struct v4l2_buffer *vb,
452                                     struct v4l2_buffer32_time32 __user *arg)
453 {
454         struct v4l2_buffer32_time32 vb32;
455
456         if (copy_from_user(&vb32, arg, sizeof(vb32)))
457                 return -EFAULT;
458
459         *vb = (struct v4l2_buffer) {
460                 .index          = vb32.index,
461                 .type           = vb32.type,
462                 .bytesused      = vb32.bytesused,
463                 .flags          = vb32.flags,
464                 .field          = vb32.field,
465                 .timestamp.tv_sec       = vb32.timestamp.tv_sec,
466                 .timestamp.tv_usec      = vb32.timestamp.tv_usec,
467                 .timecode       = vb32.timecode,
468                 .sequence       = vb32.sequence,
469                 .memory         = vb32.memory,
470                 .m.offset       = vb32.m.offset,
471                 .length         = vb32.length,
472                 .request_fd     = vb32.request_fd,
473         };
474         switch (vb->memory) {
475         case V4L2_MEMORY_MMAP:
476         case V4L2_MEMORY_OVERLAY:
477                 vb->m.offset = vb32.m.offset;
478                 break;
479         case V4L2_MEMORY_USERPTR:
480                 vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr);
481                 break;
482         case V4L2_MEMORY_DMABUF:
483                 vb->m.fd = vb32.m.fd;
484                 break;
485         }
486
487         if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
488                 vb->m.planes = (void __force *)
489                                 compat_ptr(vb32.m.planes);
490
491         return 0;
492 }
493 #endif
494
495 static int put_v4l2_buffer32(struct v4l2_buffer *vb,
496                              struct v4l2_buffer32 __user *arg)
497 {
498         struct v4l2_buffer32 vb32;
499
500         memset(&vb32, 0, sizeof(vb32));
501         vb32 = (struct v4l2_buffer32) {
502                 .index          = vb->index,
503                 .type           = vb->type,
504                 .bytesused      = vb->bytesused,
505                 .flags          = vb->flags,
506                 .field          = vb->field,
507                 .timestamp.tv_sec       = vb->timestamp.tv_sec,
508                 .timestamp.tv_usec      = vb->timestamp.tv_usec,
509                 .timecode       = vb->timecode,
510                 .sequence       = vb->sequence,
511                 .memory         = vb->memory,
512                 .m.offset       = vb->m.offset,
513                 .length         = vb->length,
514                 .request_fd     = vb->request_fd,
515         };
516
517         switch (vb->memory) {
518         case V4L2_MEMORY_MMAP:
519         case V4L2_MEMORY_OVERLAY:
520                 vb32.m.offset = vb->m.offset;
521                 break;
522         case V4L2_MEMORY_USERPTR:
523                 vb32.m.userptr = (uintptr_t)(vb->m.userptr);
524                 break;
525         case V4L2_MEMORY_DMABUF:
526                 vb32.m.fd = vb->m.fd;
527                 break;
528         }
529
530         if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
531                 vb32.m.planes = (uintptr_t)vb->m.planes;
532
533         if (copy_to_user(arg, &vb32, sizeof(vb32)))
534                 return -EFAULT;
535
536         return 0;
537 }
538
539 #ifdef CONFIG_COMPAT_32BIT_TIME
540 static int put_v4l2_buffer32_time32(struct v4l2_buffer *vb,
541                                     struct v4l2_buffer32_time32 __user *arg)
542 {
543         struct v4l2_buffer32_time32 vb32;
544
545         memset(&vb32, 0, sizeof(vb32));
546         vb32 = (struct v4l2_buffer32_time32) {
547                 .index          = vb->index,
548                 .type           = vb->type,
549                 .bytesused      = vb->bytesused,
550                 .flags          = vb->flags,
551                 .field          = vb->field,
552                 .timestamp.tv_sec       = vb->timestamp.tv_sec,
553                 .timestamp.tv_usec      = vb->timestamp.tv_usec,
554                 .timecode       = vb->timecode,
555                 .sequence       = vb->sequence,
556                 .memory         = vb->memory,
557                 .m.offset       = vb->m.offset,
558                 .length         = vb->length,
559                 .request_fd     = vb->request_fd,
560         };
561         switch (vb->memory) {
562         case V4L2_MEMORY_MMAP:
563         case V4L2_MEMORY_OVERLAY:
564                 vb32.m.offset = vb->m.offset;
565                 break;
566         case V4L2_MEMORY_USERPTR:
567                 vb32.m.userptr = (uintptr_t)(vb->m.userptr);
568                 break;
569         case V4L2_MEMORY_DMABUF:
570                 vb32.m.fd = vb->m.fd;
571                 break;
572         }
573
574         if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
575                 vb32.m.planes = (uintptr_t)vb->m.planes;
576
577         if (copy_to_user(arg, &vb32, sizeof(vb32)))
578                 return -EFAULT;
579
580         return 0;
581 }
582 #endif
583
584 struct v4l2_framebuffer32 {
585         __u32                   capability;
586         __u32                   flags;
587         compat_caddr_t          base;
588         struct {
589                 __u32           width;
590                 __u32           height;
591                 __u32           pixelformat;
592                 __u32           field;
593                 __u32           bytesperline;
594                 __u32           sizeimage;
595                 __u32           colorspace;
596                 __u32           priv;
597         } fmt;
598 };
599
600 static int get_v4l2_framebuffer32(struct v4l2_framebuffer *p64,
601                                   struct v4l2_framebuffer32 __user *p32)
602 {
603         compat_caddr_t tmp;
604
605         if (get_user(tmp, &p32->base) ||
606             get_user(p64->capability, &p32->capability) ||
607             get_user(p64->flags, &p32->flags) ||
608             copy_from_user(&p64->fmt, &p32->fmt, sizeof(p64->fmt)))
609                 return -EFAULT;
610         p64->base = (void __force *)compat_ptr(tmp);
611
612         return 0;
613 }
614
615 static int put_v4l2_framebuffer32(struct v4l2_framebuffer *p64,
616                                   struct v4l2_framebuffer32 __user *p32)
617 {
618         if (put_user((uintptr_t)p64->base, &p32->base) ||
619             put_user(p64->capability, &p32->capability) ||
620             put_user(p64->flags, &p32->flags) ||
621             copy_to_user(&p32->fmt, &p64->fmt, sizeof(p64->fmt)))
622                 return -EFAULT;
623
624         return 0;
625 }
626
627 struct v4l2_input32 {
628         __u32        index;             /*  Which input */
629         __u8         name[32];          /*  Label */
630         __u32        type;              /*  Type of input */
631         __u32        audioset;          /*  Associated audios (bitfield) */
632         __u32        tuner;             /*  Associated tuner */
633         compat_u64   std;
634         __u32        status;
635         __u32        capabilities;
636         __u32        reserved[3];
637 };
638
639 /*
640  * The 64-bit v4l2_input struct has extra padding at the end of the struct.
641  * Otherwise it is identical to the 32-bit version.
642  */
643 static inline int get_v4l2_input32(struct v4l2_input *p64,
644                                    struct v4l2_input32 __user *p32)
645 {
646         if (copy_from_user(p64, p32, sizeof(*p32)))
647                 return -EFAULT;
648         return 0;
649 }
650
651 static inline int put_v4l2_input32(struct v4l2_input *p64,
652                                    struct v4l2_input32 __user *p32)
653 {
654         if (copy_to_user(p32, p64, sizeof(*p32)))
655                 return -EFAULT;
656         return 0;
657 }
658
659 struct v4l2_ext_controls32 {
660         __u32 which;
661         __u32 count;
662         __u32 error_idx;
663         __s32 request_fd;
664         __u32 reserved[1];
665         compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
666 };
667
668 struct v4l2_ext_control32 {
669         __u32 id;
670         __u32 size;
671         __u32 reserved2[1];
672         union {
673                 __s32 value;
674                 __s64 value64;
675                 compat_caddr_t string; /* actually char * */
676         };
677 } __attribute__ ((packed));
678
679 /* Return true if this control is a pointer type. */
680 static inline bool ctrl_is_pointer(struct file *file, u32 id)
681 {
682         struct video_device *vdev = video_devdata(file);
683         struct v4l2_fh *fh = NULL;
684         struct v4l2_ctrl_handler *hdl = NULL;
685         struct v4l2_query_ext_ctrl qec = { id };
686         const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
687
688         if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
689                 fh = file->private_data;
690
691         if (fh && fh->ctrl_handler)
692                 hdl = fh->ctrl_handler;
693         else if (vdev->ctrl_handler)
694                 hdl = vdev->ctrl_handler;
695
696         if (hdl) {
697                 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id);
698
699                 return ctrl && ctrl->is_ptr;
700         }
701
702         if (!ops || !ops->vidioc_query_ext_ctrl)
703                 return false;
704
705         return !ops->vidioc_query_ext_ctrl(file, fh, &qec) &&
706                 (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
707 }
708
709 static int get_v4l2_ext_controls32(struct v4l2_ext_controls *p64,
710                                    struct v4l2_ext_controls32 __user *p32)
711 {
712         struct v4l2_ext_controls32 ec32;
713
714         if (copy_from_user(&ec32, p32, sizeof(ec32)))
715                 return -EFAULT;
716
717         *p64 = (struct v4l2_ext_controls) {
718                 .which          = ec32.which,
719                 .count          = ec32.count,
720                 .error_idx      = ec32.error_idx,
721                 .request_fd     = ec32.request_fd,
722                 .reserved[0]    = ec32.reserved[0],
723                 .controls       = (void __force *)compat_ptr(ec32.controls),
724         };
725
726         return 0;
727 }
728
729 static int put_v4l2_ext_controls32(struct v4l2_ext_controls *p64,
730                                    struct v4l2_ext_controls32 __user *p32)
731 {
732         struct v4l2_ext_controls32 ec32;
733
734         memset(&ec32, 0, sizeof(ec32));
735         ec32 = (struct v4l2_ext_controls32) {
736                 .which          = p64->which,
737                 .count          = p64->count,
738                 .error_idx      = p64->error_idx,
739                 .request_fd     = p64->request_fd,
740                 .reserved[0]    = p64->reserved[0],
741                 .controls       = (uintptr_t)p64->controls,
742         };
743
744         if (copy_to_user(p32, &ec32, sizeof(ec32)))
745                 return -EFAULT;
746
747         return 0;
748 }
749
750 #ifdef CONFIG_X86_64
751 /*
752  * x86 is the only compat architecture with different struct alignment
753  * between 32-bit and 64-bit tasks.
754  */
755 struct v4l2_event32 {
756         __u32                           type;
757         union {
758                 compat_s64              value64;
759                 __u8                    data[64];
760         } u;
761         __u32                           pending;
762         __u32                           sequence;
763         struct {
764                 compat_s64              tv_sec;
765                 compat_s64              tv_nsec;
766         } timestamp;
767         __u32                           id;
768         __u32                           reserved[8];
769 };
770
771 static int put_v4l2_event32(struct v4l2_event *p64,
772                             struct v4l2_event32 __user *p32)
773 {
774         if (put_user(p64->type, &p32->type) ||
775             copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) ||
776             put_user(p64->pending, &p32->pending) ||
777             put_user(p64->sequence, &p32->sequence) ||
778             put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) ||
779             put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) ||
780             put_user(p64->id, &p32->id) ||
781             copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
782                 return -EFAULT;
783         return 0;
784 }
785
786 #endif
787
788 #ifdef CONFIG_COMPAT_32BIT_TIME
789 struct v4l2_event32_time32 {
790         __u32                           type;
791         union {
792                 compat_s64              value64;
793                 __u8                    data[64];
794         } u;
795         __u32                           pending;
796         __u32                           sequence;
797         struct old_timespec32           timestamp;
798         __u32                           id;
799         __u32                           reserved[8];
800 };
801
802 static int put_v4l2_event32_time32(struct v4l2_event *p64,
803                                    struct v4l2_event32_time32 __user *p32)
804 {
805         if (put_user(p64->type, &p32->type) ||
806             copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) ||
807             put_user(p64->pending, &p32->pending) ||
808             put_user(p64->sequence, &p32->sequence) ||
809             put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) ||
810             put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) ||
811             put_user(p64->id, &p32->id) ||
812             copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
813                 return -EFAULT;
814         return 0;
815 }
816 #endif
817
818 struct v4l2_edid32 {
819         __u32 pad;
820         __u32 start_block;
821         __u32 blocks;
822         __u32 reserved[5];
823         compat_caddr_t edid;
824 };
825
826 static int get_v4l2_edid32(struct v4l2_edid *p64,
827                            struct v4l2_edid32 __user *p32)
828 {
829         compat_uptr_t edid;
830
831         if (copy_from_user(p64, p32, offsetof(struct v4l2_edid32, edid)) ||
832             get_user(edid, &p32->edid))
833                 return -EFAULT;
834
835         p64->edid = (void __force *)compat_ptr(edid);
836         return 0;
837 }
838
839 static int put_v4l2_edid32(struct v4l2_edid *p64,
840                            struct v4l2_edid32 __user *p32)
841 {
842         if (copy_to_user(p32, p64, offsetof(struct v4l2_edid32, edid)))
843                 return -EFAULT;
844         return 0;
845 }
846
847 /*
848  * List of ioctls that require 32-bits/64-bits conversion
849  *
850  * The V4L2 ioctls that aren't listed there don't have pointer arguments
851  * and the struct size is identical for both 32 and 64 bits versions, so
852  * they don't need translations.
853  */
854
855 #define VIDIOC_G_FMT32          _IOWR('V',  4, struct v4l2_format32)
856 #define VIDIOC_S_FMT32          _IOWR('V',  5, struct v4l2_format32)
857 #define VIDIOC_QUERYBUF32       _IOWR('V',  9, struct v4l2_buffer32)
858 #define VIDIOC_G_FBUF32         _IOR ('V', 10, struct v4l2_framebuffer32)
859 #define VIDIOC_S_FBUF32         _IOW ('V', 11, struct v4l2_framebuffer32)
860 #define VIDIOC_QBUF32           _IOWR('V', 15, struct v4l2_buffer32)
861 #define VIDIOC_DQBUF32          _IOWR('V', 17, struct v4l2_buffer32)
862 #define VIDIOC_ENUMSTD32        _IOWR('V', 25, struct v4l2_standard32)
863 #define VIDIOC_ENUMINPUT32      _IOWR('V', 26, struct v4l2_input32)
864 #define VIDIOC_G_EDID32         _IOWR('V', 40, struct v4l2_edid32)
865 #define VIDIOC_S_EDID32         _IOWR('V', 41, struct v4l2_edid32)
866 #define VIDIOC_TRY_FMT32        _IOWR('V', 64, struct v4l2_format32)
867 #define VIDIOC_G_EXT_CTRLS32    _IOWR('V', 71, struct v4l2_ext_controls32)
868 #define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
869 #define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)
870 #define VIDIOC_DQEVENT32        _IOR ('V', 89, struct v4l2_event32)
871 #define VIDIOC_CREATE_BUFS32    _IOWR('V', 92, struct v4l2_create_buffers32)
872 #define VIDIOC_PREPARE_BUF32    _IOWR('V', 93, struct v4l2_buffer32)
873
874 #ifdef CONFIG_COMPAT_32BIT_TIME
875 #define VIDIOC_QUERYBUF32_TIME32        _IOWR('V',  9, struct v4l2_buffer32_time32)
876 #define VIDIOC_QBUF32_TIME32            _IOWR('V', 15, struct v4l2_buffer32_time32)
877 #define VIDIOC_DQBUF32_TIME32           _IOWR('V', 17, struct v4l2_buffer32_time32)
878 #define VIDIOC_DQEVENT32_TIME32         _IOR ('V', 89, struct v4l2_event32_time32)
879 #define VIDIOC_PREPARE_BUF32_TIME32     _IOWR('V', 93, struct v4l2_buffer32_time32)
880 #endif
881
882 unsigned int v4l2_compat_translate_cmd(unsigned int cmd)
883 {
884         switch (cmd) {
885         case VIDIOC_G_FMT32:
886                 return VIDIOC_G_FMT;
887         case VIDIOC_S_FMT32:
888                 return VIDIOC_S_FMT;
889         case VIDIOC_TRY_FMT32:
890                 return VIDIOC_TRY_FMT;
891         case VIDIOC_G_FBUF32:
892                 return VIDIOC_G_FBUF;
893         case VIDIOC_S_FBUF32:
894                 return VIDIOC_S_FBUF;
895 #ifdef CONFIG_COMPAT_32BIT_TIME
896         case VIDIOC_QUERYBUF32_TIME32:
897                 return VIDIOC_QUERYBUF;
898         case VIDIOC_QBUF32_TIME32:
899                 return VIDIOC_QBUF;
900         case VIDIOC_DQBUF32_TIME32:
901                 return VIDIOC_DQBUF;
902         case VIDIOC_PREPARE_BUF32_TIME32:
903                 return VIDIOC_PREPARE_BUF;
904 #endif
905         case VIDIOC_QUERYBUF32:
906                 return VIDIOC_QUERYBUF;
907         case VIDIOC_QBUF32:
908                 return VIDIOC_QBUF;
909         case VIDIOC_DQBUF32:
910                 return VIDIOC_DQBUF;
911         case VIDIOC_CREATE_BUFS32:
912                 return VIDIOC_CREATE_BUFS;
913         case VIDIOC_G_EXT_CTRLS32:
914                 return VIDIOC_G_EXT_CTRLS;
915         case VIDIOC_S_EXT_CTRLS32:
916                 return VIDIOC_S_EXT_CTRLS;
917         case VIDIOC_TRY_EXT_CTRLS32:
918                 return VIDIOC_TRY_EXT_CTRLS;
919         case VIDIOC_PREPARE_BUF32:
920                 return VIDIOC_PREPARE_BUF;
921         case VIDIOC_ENUMSTD32:
922                 return VIDIOC_ENUMSTD;
923         case VIDIOC_ENUMINPUT32:
924                 return VIDIOC_ENUMINPUT;
925         case VIDIOC_G_EDID32:
926                 return VIDIOC_G_EDID;
927         case VIDIOC_S_EDID32:
928                 return VIDIOC_S_EDID;
929 #ifdef CONFIG_X86_64
930         case VIDIOC_DQEVENT32:
931                 return VIDIOC_DQEVENT;
932 #endif
933 #ifdef CONFIG_COMPAT_32BIT_TIME
934         case VIDIOC_DQEVENT32_TIME32:
935                 return VIDIOC_DQEVENT;
936 #endif
937         }
938         return cmd;
939 }
940
941 int v4l2_compat_get_user(void __user *arg, void *parg, unsigned int cmd)
942 {
943         switch (cmd) {
944         case VIDIOC_G_FMT32:
945         case VIDIOC_S_FMT32:
946         case VIDIOC_TRY_FMT32:
947                 return get_v4l2_format32(parg, arg);
948
949         case VIDIOC_S_FBUF32:
950                 return get_v4l2_framebuffer32(parg, arg);
951 #ifdef CONFIG_COMPAT_32BIT_TIME
952         case VIDIOC_QUERYBUF32_TIME32:
953         case VIDIOC_QBUF32_TIME32:
954         case VIDIOC_DQBUF32_TIME32:
955         case VIDIOC_PREPARE_BUF32_TIME32:
956                 return get_v4l2_buffer32_time32(parg, arg);
957 #endif
958         case VIDIOC_QUERYBUF32:
959         case VIDIOC_QBUF32:
960         case VIDIOC_DQBUF32:
961         case VIDIOC_PREPARE_BUF32:
962                 return get_v4l2_buffer32(parg, arg);
963
964         case VIDIOC_G_EXT_CTRLS32:
965         case VIDIOC_S_EXT_CTRLS32:
966         case VIDIOC_TRY_EXT_CTRLS32:
967                 return get_v4l2_ext_controls32(parg, arg);
968
969         case VIDIOC_CREATE_BUFS32:
970                 return get_v4l2_create32(parg, arg);
971
972         case VIDIOC_ENUMSTD32:
973                 return get_v4l2_standard32(parg, arg);
974
975         case VIDIOC_ENUMINPUT32:
976                 return get_v4l2_input32(parg, arg);
977
978         case VIDIOC_G_EDID32:
979         case VIDIOC_S_EDID32:
980                 return get_v4l2_edid32(parg, arg);
981         }
982         return 0;
983 }
984
985 int v4l2_compat_put_user(void __user *arg, void *parg, unsigned int cmd)
986 {
987         switch (cmd) {
988         case VIDIOC_G_FMT32:
989         case VIDIOC_S_FMT32:
990         case VIDIOC_TRY_FMT32:
991                 return put_v4l2_format32(parg, arg);
992
993         case VIDIOC_G_FBUF32:
994                 return put_v4l2_framebuffer32(parg, arg);
995 #ifdef CONFIG_COMPAT_32BIT_TIME
996         case VIDIOC_QUERYBUF32_TIME32:
997         case VIDIOC_QBUF32_TIME32:
998         case VIDIOC_DQBUF32_TIME32:
999         case VIDIOC_PREPARE_BUF32_TIME32:
1000                 return put_v4l2_buffer32_time32(parg, arg);
1001 #endif
1002         case VIDIOC_QUERYBUF32:
1003         case VIDIOC_QBUF32:
1004         case VIDIOC_DQBUF32:
1005         case VIDIOC_PREPARE_BUF32:
1006                 return put_v4l2_buffer32(parg, arg);
1007
1008         case VIDIOC_G_EXT_CTRLS32:
1009         case VIDIOC_S_EXT_CTRLS32:
1010         case VIDIOC_TRY_EXT_CTRLS32:
1011                 return put_v4l2_ext_controls32(parg, arg);
1012
1013         case VIDIOC_CREATE_BUFS32:
1014                 return put_v4l2_create32(parg, arg);
1015
1016         case VIDIOC_ENUMSTD32:
1017                 return put_v4l2_standard32(parg, arg);
1018
1019         case VIDIOC_ENUMINPUT32:
1020                 return put_v4l2_input32(parg, arg);
1021
1022         case VIDIOC_G_EDID32:
1023         case VIDIOC_S_EDID32:
1024                 return put_v4l2_edid32(parg, arg);
1025 #ifdef CONFIG_X86_64
1026         case VIDIOC_DQEVENT32:
1027                 return put_v4l2_event32(parg, arg);
1028 #endif
1029 #ifdef CONFIG_COMPAT_32BIT_TIME
1030         case VIDIOC_DQEVENT32_TIME32:
1031                 return put_v4l2_event32_time32(parg, arg);
1032 #endif
1033         }
1034         return 0;
1035 }
1036
1037 int v4l2_compat_get_array_args(struct file *file, void *mbuf,
1038                                void __user *user_ptr, size_t array_size,
1039                                unsigned int cmd, void *arg)
1040 {
1041         int err = 0;
1042
1043         memset(mbuf, 0, array_size);
1044
1045         switch (cmd) {
1046         case VIDIOC_G_FMT32:
1047         case VIDIOC_S_FMT32:
1048         case VIDIOC_TRY_FMT32: {
1049                 struct v4l2_format *f64 = arg;
1050                 struct v4l2_clip *c64 = mbuf;
1051                 struct v4l2_clip32 __user *c32 = user_ptr;
1052                 u32 clipcount = f64->fmt.win.clipcount;
1053
1054                 if ((f64->type != V4L2_BUF_TYPE_VIDEO_OVERLAY &&
1055                      f64->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) ||
1056                     clipcount == 0)
1057                         return 0;
1058                 if (clipcount > 2048)
1059                         return -EINVAL;
1060                 while (clipcount--) {
1061                         if (copy_from_user(c64, c32, sizeof(c64->c)))
1062                                 return -EFAULT;
1063                         c64->next = NULL;
1064                         c64++;
1065                         c32++;
1066                 }
1067                 break;
1068         }
1069 #ifdef CONFIG_COMPAT_32BIT_TIME
1070         case VIDIOC_QUERYBUF32_TIME32:
1071         case VIDIOC_QBUF32_TIME32:
1072         case VIDIOC_DQBUF32_TIME32:
1073         case VIDIOC_PREPARE_BUF32_TIME32:
1074 #endif
1075         case VIDIOC_QUERYBUF32:
1076         case VIDIOC_QBUF32:
1077         case VIDIOC_DQBUF32:
1078         case VIDIOC_PREPARE_BUF32: {
1079                 struct v4l2_buffer *b64 = arg;
1080                 struct v4l2_plane *p64 = mbuf;
1081                 struct v4l2_plane32 __user *p32 = user_ptr;
1082
1083                 if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {
1084                         u32 num_planes = b64->length;
1085
1086                         if (num_planes == 0)
1087                                 return 0;
1088
1089                         while (num_planes--) {
1090                                 err = get_v4l2_plane32(p64, p32, b64->memory);
1091                                 if (err)
1092                                         return err;
1093                                 ++p64;
1094                                 ++p32;
1095                         }
1096                 }
1097                 break;
1098         }
1099         case VIDIOC_G_EXT_CTRLS32:
1100         case VIDIOC_S_EXT_CTRLS32:
1101         case VIDIOC_TRY_EXT_CTRLS32: {
1102                 struct v4l2_ext_controls *ecs64 = arg;
1103                 struct v4l2_ext_control *ec64 = mbuf;
1104                 struct v4l2_ext_control32 __user *ec32 = user_ptr;
1105                 int n;
1106
1107                 for (n = 0; n < ecs64->count; n++) {
1108                         if (copy_from_user(ec64, ec32, sizeof(*ec32)))
1109                                 return -EFAULT;
1110
1111                         if (ctrl_is_pointer(file, ec64->id)) {
1112                                 compat_uptr_t p;
1113
1114                                 if (get_user(p, &ec32->string))
1115                                         return -EFAULT;
1116                                 ec64->string = compat_ptr(p);
1117                         }
1118                         ec32++;
1119                         ec64++;
1120                 }
1121                 break;
1122         }
1123         default:
1124                 if (copy_from_user(mbuf, user_ptr, array_size))
1125                         err = -EFAULT;
1126                 break;
1127         }
1128
1129         return err;
1130 }
1131
1132 int v4l2_compat_put_array_args(struct file *file, void __user *user_ptr,
1133                                void *mbuf, size_t array_size,
1134                                unsigned int cmd, void *arg)
1135 {
1136         int err = 0;
1137
1138         switch (cmd) {
1139         case VIDIOC_G_FMT32:
1140         case VIDIOC_S_FMT32:
1141         case VIDIOC_TRY_FMT32: {
1142                 struct v4l2_format *f64 = arg;
1143                 struct v4l2_clip *c64 = mbuf;
1144                 struct v4l2_clip32 __user *c32 = user_ptr;
1145                 u32 clipcount = f64->fmt.win.clipcount;
1146
1147                 if ((f64->type != V4L2_BUF_TYPE_VIDEO_OVERLAY &&
1148                      f64->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) ||
1149                     clipcount == 0)
1150                         return 0;
1151                 if (clipcount > 2048)
1152                         return -EINVAL;
1153                 while (clipcount--) {
1154                         if (copy_to_user(c32, c64, sizeof(c64->c)))
1155                                 return -EFAULT;
1156                         c64++;
1157                         c32++;
1158                 }
1159                 break;
1160         }
1161 #ifdef CONFIG_COMPAT_32BIT_TIME
1162         case VIDIOC_QUERYBUF32_TIME32:
1163         case VIDIOC_QBUF32_TIME32:
1164         case VIDIOC_DQBUF32_TIME32:
1165         case VIDIOC_PREPARE_BUF32_TIME32:
1166 #endif
1167         case VIDIOC_QUERYBUF32:
1168         case VIDIOC_QBUF32:
1169         case VIDIOC_DQBUF32:
1170         case VIDIOC_PREPARE_BUF32: {
1171                 struct v4l2_buffer *b64 = arg;
1172                 struct v4l2_plane *p64 = mbuf;
1173                 struct v4l2_plane32 __user *p32 = user_ptr;
1174
1175                 if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {
1176                         u32 num_planes = b64->length;
1177
1178                         if (num_planes == 0)
1179                                 return 0;
1180
1181                         while (num_planes--) {
1182                                 err = put_v4l2_plane32(p64, p32, b64->memory);
1183                                 if (err)
1184                                         return err;
1185                                 ++p64;
1186                                 ++p32;
1187                         }
1188                 }
1189                 break;
1190         }
1191         case VIDIOC_G_EXT_CTRLS32:
1192         case VIDIOC_S_EXT_CTRLS32:
1193         case VIDIOC_TRY_EXT_CTRLS32: {
1194                 struct v4l2_ext_controls *ecs64 = arg;
1195                 struct v4l2_ext_control *ec64 = mbuf;
1196                 struct v4l2_ext_control32 __user *ec32 = user_ptr;
1197                 int n;
1198
1199                 for (n = 0; n < ecs64->count; n++) {
1200                         unsigned int size = sizeof(*ec32);
1201                         /*
1202                          * Do not modify the pointer when copying a pointer
1203                          * control.  The contents of the pointer was changed,
1204                          * not the pointer itself.
1205                          * The structures are otherwise compatible.
1206                          */
1207                         if (ctrl_is_pointer(file, ec64->id))
1208                                 size -= sizeof(ec32->value64);
1209
1210                         if (copy_to_user(ec32, ec64, size))
1211                                 return -EFAULT;
1212
1213                         ec32++;
1214                         ec64++;
1215                 }
1216                 break;
1217         }
1218         default:
1219                 if (copy_to_user(user_ptr, mbuf, array_size))
1220                         err = -EFAULT;
1221                 break;
1222         }
1223
1224         return err;
1225 }
1226
1227 /**
1228  * v4l2_compat_ioctl32() - Handles a compat32 ioctl call
1229  *
1230  * @file: pointer to &struct file with the file handler
1231  * @cmd: ioctl to be called
1232  * @arg: arguments passed from/to the ioctl handler
1233  *
1234  * This function is meant to be used as .compat_ioctl fops at v4l2-dev.c
1235  * in order to deal with 32-bit calls on a 64-bits Kernel.
1236  *
1237  * This function calls do_video_ioctl() for non-private V4L2 ioctls.
1238  * If the function is a private one it calls vdev->fops->compat_ioctl32
1239  * instead.
1240  */
1241 long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
1242 {
1243         struct video_device *vdev = video_devdata(file);
1244         long ret = -ENOIOCTLCMD;
1245
1246         if (!file->f_op->unlocked_ioctl)
1247                 return ret;
1248
1249         if (!video_is_registered(vdev))
1250                 return -ENODEV;
1251
1252         if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE)
1253                 ret = file->f_op->unlocked_ioctl(file, cmd,
1254                                         (unsigned long)compat_ptr(arg));
1255         else if (vdev->fops->compat_ioctl32)
1256                 ret = vdev->fops->compat_ioctl32(file, cmd, arg);
1257
1258         if (ret == -ENOIOCTLCMD)
1259                 pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
1260                          _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
1261         return ret;
1262 }
1263 EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);