]> Git Repo - linux.git/blob - drivers/media/v4l2-core/v4l2-compat-ioctl32.c
Merge tag 'at91-soc-5.15' of git://git.kernel.org/pub/scm/linux/kernel/git/at91/linux...
[linux.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 <[email protected]>
5  *
6  * Copyright (C) 1997-2000  Jakub Jelinek  ([email protected])
7  * Copyright (C) 1998  Eddie C. Dost  ([email protected])
8  * Copyright (C) 2001,2002  Andi Kleen, SuSE Labs
9  * Copyright (C) 2003       Pavel Machek ([email protected])
10  * Copyright (C) 2005       Philippe De Muyter ([email protected])
11  * Copyright (C) 2008       Hans Verkuil <[email protected]>
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  * @reserved:   future extensions
130  */
131 struct v4l2_create_buffers32 {
132         __u32                   index;
133         __u32                   count;
134         __u32                   memory; /* enum v4l2_memory */
135         struct v4l2_format32    format;
136         __u32                   capabilities;
137         __u32                   reserved[7];
138 };
139
140 static int get_v4l2_format32(struct v4l2_format *p64,
141                              struct v4l2_format32 __user *p32)
142 {
143         if (get_user(p64->type, &p32->type))
144                 return -EFAULT;
145
146         switch (p64->type) {
147         case V4L2_BUF_TYPE_VIDEO_CAPTURE:
148         case V4L2_BUF_TYPE_VIDEO_OUTPUT:
149                 return copy_from_user(&p64->fmt.pix, &p32->fmt.pix,
150                                       sizeof(p64->fmt.pix)) ? -EFAULT : 0;
151         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
152         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
153                 return copy_from_user(&p64->fmt.pix_mp, &p32->fmt.pix_mp,
154                                       sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;
155         case V4L2_BUF_TYPE_VIDEO_OVERLAY:
156         case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
157                 return get_v4l2_window32(&p64->fmt.win, &p32->fmt.win);
158         case V4L2_BUF_TYPE_VBI_CAPTURE:
159         case V4L2_BUF_TYPE_VBI_OUTPUT:
160                 return copy_from_user(&p64->fmt.vbi, &p32->fmt.vbi,
161                                       sizeof(p64->fmt.vbi)) ? -EFAULT : 0;
162         case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
163         case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
164                 return copy_from_user(&p64->fmt.sliced, &p32->fmt.sliced,
165                                       sizeof(p64->fmt.sliced)) ? -EFAULT : 0;
166         case V4L2_BUF_TYPE_SDR_CAPTURE:
167         case V4L2_BUF_TYPE_SDR_OUTPUT:
168                 return copy_from_user(&p64->fmt.sdr, &p32->fmt.sdr,
169                                       sizeof(p64->fmt.sdr)) ? -EFAULT : 0;
170         case V4L2_BUF_TYPE_META_CAPTURE:
171         case V4L2_BUF_TYPE_META_OUTPUT:
172                 return copy_from_user(&p64->fmt.meta, &p32->fmt.meta,
173                                       sizeof(p64->fmt.meta)) ? -EFAULT : 0;
174         default:
175                 return -EINVAL;
176         }
177 }
178
179 static int get_v4l2_create32(struct v4l2_create_buffers *p64,
180                              struct v4l2_create_buffers32 __user *p32)
181 {
182         if (copy_from_user(p64, p32,
183                            offsetof(struct v4l2_create_buffers32, format)))
184                 return -EFAULT;
185         return get_v4l2_format32(&p64->format, &p32->format);
186 }
187
188 static int put_v4l2_format32(struct v4l2_format *p64,
189                              struct v4l2_format32 __user *p32)
190 {
191         switch (p64->type) {
192         case V4L2_BUF_TYPE_VIDEO_CAPTURE:
193         case V4L2_BUF_TYPE_VIDEO_OUTPUT:
194                 return copy_to_user(&p32->fmt.pix, &p64->fmt.pix,
195                                     sizeof(p64->fmt.pix)) ? -EFAULT : 0;
196         case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
197         case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
198                 return copy_to_user(&p32->fmt.pix_mp, &p64->fmt.pix_mp,
199                                     sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;
200         case V4L2_BUF_TYPE_VIDEO_OVERLAY:
201         case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
202                 return put_v4l2_window32(&p64->fmt.win, &p32->fmt.win);
203         case V4L2_BUF_TYPE_VBI_CAPTURE:
204         case V4L2_BUF_TYPE_VBI_OUTPUT:
205                 return copy_to_user(&p32->fmt.vbi, &p64->fmt.vbi,
206                                     sizeof(p64->fmt.vbi)) ? -EFAULT : 0;
207         case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
208         case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
209                 return copy_to_user(&p32->fmt.sliced, &p64->fmt.sliced,
210                                     sizeof(p64->fmt.sliced)) ? -EFAULT : 0;
211         case V4L2_BUF_TYPE_SDR_CAPTURE:
212         case V4L2_BUF_TYPE_SDR_OUTPUT:
213                 return copy_to_user(&p32->fmt.sdr, &p64->fmt.sdr,
214                                     sizeof(p64->fmt.sdr)) ? -EFAULT : 0;
215         case V4L2_BUF_TYPE_META_CAPTURE:
216         case V4L2_BUF_TYPE_META_OUTPUT:
217                 return copy_to_user(&p32->fmt.meta, &p64->fmt.meta,
218                                     sizeof(p64->fmt.meta)) ? -EFAULT : 0;
219         default:
220                 return -EINVAL;
221         }
222 }
223
224 static int put_v4l2_create32(struct v4l2_create_buffers *p64,
225                              struct v4l2_create_buffers32 __user *p32)
226 {
227         if (copy_to_user(p32, p64,
228                          offsetof(struct v4l2_create_buffers32, format)) ||
229             put_user(p64->capabilities, &p32->capabilities) ||
230             copy_to_user(p32->reserved, p64->reserved, sizeof(p64->reserved)))
231                 return -EFAULT;
232         return put_v4l2_format32(&p64->format, &p32->format);
233 }
234
235 struct v4l2_standard32 {
236         __u32                index;
237         compat_u64           id;
238         __u8                 name[24];
239         struct v4l2_fract    frameperiod; /* Frames, not fields */
240         __u32                framelines;
241         __u32                reserved[4];
242 };
243
244 static int get_v4l2_standard32(struct v4l2_standard *p64,
245                                struct v4l2_standard32 __user *p32)
246 {
247         /* other fields are not set by the user, nor used by the driver */
248         return get_user(p64->index, &p32->index);
249 }
250
251 static int put_v4l2_standard32(struct v4l2_standard *p64,
252                                struct v4l2_standard32 __user *p32)
253 {
254         if (put_user(p64->index, &p32->index) ||
255             put_user(p64->id, &p32->id) ||
256             copy_to_user(p32->name, p64->name, sizeof(p32->name)) ||
257             copy_to_user(&p32->frameperiod, &p64->frameperiod,
258                          sizeof(p32->frameperiod)) ||
259             put_user(p64->framelines, &p32->framelines) ||
260             copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
261                 return -EFAULT;
262         return 0;
263 }
264
265 struct v4l2_plane32 {
266         __u32                   bytesused;
267         __u32                   length;
268         union {
269                 __u32           mem_offset;
270                 compat_long_t   userptr;
271                 __s32           fd;
272         } m;
273         __u32                   data_offset;
274         __u32                   reserved[11];
275 };
276
277 /*
278  * This is correct for all architectures including i386, but not x32,
279  * which has different alignment requirements for timestamp
280  */
281 struct v4l2_buffer32 {
282         __u32                   index;
283         __u32                   type;   /* enum v4l2_buf_type */
284         __u32                   bytesused;
285         __u32                   flags;
286         __u32                   field;  /* enum v4l2_field */
287         struct {
288                 compat_s64      tv_sec;
289                 compat_s64      tv_usec;
290         }                       timestamp;
291         struct v4l2_timecode    timecode;
292         __u32                   sequence;
293
294         /* memory location */
295         __u32                   memory; /* enum v4l2_memory */
296         union {
297                 __u32           offset;
298                 compat_long_t   userptr;
299                 compat_caddr_t  planes;
300                 __s32           fd;
301         } m;
302         __u32                   length;
303         __u32                   reserved2;
304         __s32                   request_fd;
305 };
306
307 #ifdef CONFIG_COMPAT_32BIT_TIME
308 struct v4l2_buffer32_time32 {
309         __u32                   index;
310         __u32                   type;   /* enum v4l2_buf_type */
311         __u32                   bytesused;
312         __u32                   flags;
313         __u32                   field;  /* enum v4l2_field */
314         struct old_timeval32    timestamp;
315         struct v4l2_timecode    timecode;
316         __u32                   sequence;
317
318         /* memory location */
319         __u32                   memory; /* enum v4l2_memory */
320         union {
321                 __u32           offset;
322                 compat_long_t   userptr;
323                 compat_caddr_t  planes;
324                 __s32           fd;
325         } m;
326         __u32                   length;
327         __u32                   reserved2;
328         __s32                   request_fd;
329 };
330 #endif
331
332 static int get_v4l2_plane32(struct v4l2_plane *p64,
333                             struct v4l2_plane32 __user *p32,
334                             enum v4l2_memory memory)
335 {
336         struct v4l2_plane32 plane32;
337         typeof(p64->m) m = {};
338
339         if (copy_from_user(&plane32, p32, sizeof(plane32)))
340                 return -EFAULT;
341
342         switch (memory) {
343         case V4L2_MEMORY_MMAP:
344         case V4L2_MEMORY_OVERLAY:
345                 m.mem_offset = plane32.m.mem_offset;
346                 break;
347         case V4L2_MEMORY_USERPTR:
348                 m.userptr = (unsigned long)compat_ptr(plane32.m.userptr);
349                 break;
350         case V4L2_MEMORY_DMABUF:
351                 m.fd = plane32.m.fd;
352                 break;
353         }
354
355         memset(p64, 0, sizeof(*p64));
356         *p64 = (struct v4l2_plane) {
357                 .bytesused      = plane32.bytesused,
358                 .length         = plane32.length,
359                 .m              = m,
360                 .data_offset    = plane32.data_offset,
361         };
362
363         return 0;
364 }
365
366 static int put_v4l2_plane32(struct v4l2_plane *p64,
367                             struct v4l2_plane32 __user *p32,
368                             enum v4l2_memory memory)
369 {
370         struct v4l2_plane32 plane32;
371
372         memset(&plane32, 0, sizeof(plane32));
373         plane32 = (struct v4l2_plane32) {
374                 .bytesused      = p64->bytesused,
375                 .length         = p64->length,
376                 .data_offset    = p64->data_offset,
377         };
378
379         switch (memory) {
380         case V4L2_MEMORY_MMAP:
381         case V4L2_MEMORY_OVERLAY:
382                 plane32.m.mem_offset = p64->m.mem_offset;
383                 break;
384         case V4L2_MEMORY_USERPTR:
385                 plane32.m.userptr = (uintptr_t)(p64->m.userptr);
386                 break;
387         case V4L2_MEMORY_DMABUF:
388                 plane32.m.fd = p64->m.fd;
389                 break;
390         }
391
392         if (copy_to_user(p32, &plane32, sizeof(plane32)))
393                 return -EFAULT;
394
395         return 0;
396 }
397
398 static int get_v4l2_buffer32(struct v4l2_buffer *vb,
399                              struct v4l2_buffer32 __user *arg)
400 {
401         struct v4l2_buffer32 vb32;
402
403         if (copy_from_user(&vb32, arg, sizeof(vb32)))
404                 return -EFAULT;
405
406         memset(vb, 0, sizeof(*vb));
407         *vb = (struct v4l2_buffer) {
408                 .index          = vb32.index,
409                 .type           = vb32.type,
410                 .bytesused      = vb32.bytesused,
411                 .flags          = vb32.flags,
412                 .field          = vb32.field,
413                 .timestamp.tv_sec       = vb32.timestamp.tv_sec,
414                 .timestamp.tv_usec      = vb32.timestamp.tv_usec,
415                 .timecode       = vb32.timecode,
416                 .sequence       = vb32.sequence,
417                 .memory         = vb32.memory,
418                 .m.offset       = vb32.m.offset,
419                 .length         = vb32.length,
420                 .request_fd     = vb32.request_fd,
421         };
422
423         switch (vb->memory) {
424         case V4L2_MEMORY_MMAP:
425         case V4L2_MEMORY_OVERLAY:
426                 vb->m.offset = vb32.m.offset;
427                 break;
428         case V4L2_MEMORY_USERPTR:
429                 vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr);
430                 break;
431         case V4L2_MEMORY_DMABUF:
432                 vb->m.fd = vb32.m.fd;
433                 break;
434         }
435
436         if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
437                 vb->m.planes = (void __force *)
438                                 compat_ptr(vb32.m.planes);
439
440         return 0;
441 }
442
443 #ifdef CONFIG_COMPAT_32BIT_TIME
444 static int get_v4l2_buffer32_time32(struct v4l2_buffer *vb,
445                                     struct v4l2_buffer32_time32 __user *arg)
446 {
447         struct v4l2_buffer32_time32 vb32;
448
449         if (copy_from_user(&vb32, arg, sizeof(vb32)))
450                 return -EFAULT;
451
452         *vb = (struct v4l2_buffer) {
453                 .index          = vb32.index,
454                 .type           = vb32.type,
455                 .bytesused      = vb32.bytesused,
456                 .flags          = vb32.flags,
457                 .field          = vb32.field,
458                 .timestamp.tv_sec       = vb32.timestamp.tv_sec,
459                 .timestamp.tv_usec      = vb32.timestamp.tv_usec,
460                 .timecode       = vb32.timecode,
461                 .sequence       = vb32.sequence,
462                 .memory         = vb32.memory,
463                 .m.offset       = vb32.m.offset,
464                 .length         = vb32.length,
465                 .request_fd     = vb32.request_fd,
466         };
467         switch (vb->memory) {
468         case V4L2_MEMORY_MMAP:
469         case V4L2_MEMORY_OVERLAY:
470                 vb->m.offset = vb32.m.offset;
471                 break;
472         case V4L2_MEMORY_USERPTR:
473                 vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr);
474                 break;
475         case V4L2_MEMORY_DMABUF:
476                 vb->m.fd = vb32.m.fd;
477                 break;
478         }
479
480         if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
481                 vb->m.planes = (void __force *)
482                                 compat_ptr(vb32.m.planes);
483
484         return 0;
485 }
486 #endif
487
488 static int put_v4l2_buffer32(struct v4l2_buffer *vb,
489                              struct v4l2_buffer32 __user *arg)
490 {
491         struct v4l2_buffer32 vb32;
492
493         memset(&vb32, 0, sizeof(vb32));
494         vb32 = (struct v4l2_buffer32) {
495                 .index          = vb->index,
496                 .type           = vb->type,
497                 .bytesused      = vb->bytesused,
498                 .flags          = vb->flags,
499                 .field          = vb->field,
500                 .timestamp.tv_sec       = vb->timestamp.tv_sec,
501                 .timestamp.tv_usec      = vb->timestamp.tv_usec,
502                 .timecode       = vb->timecode,
503                 .sequence       = vb->sequence,
504                 .memory         = vb->memory,
505                 .m.offset       = vb->m.offset,
506                 .length         = vb->length,
507                 .request_fd     = vb->request_fd,
508         };
509
510         switch (vb->memory) {
511         case V4L2_MEMORY_MMAP:
512         case V4L2_MEMORY_OVERLAY:
513                 vb32.m.offset = vb->m.offset;
514                 break;
515         case V4L2_MEMORY_USERPTR:
516                 vb32.m.userptr = (uintptr_t)(vb->m.userptr);
517                 break;
518         case V4L2_MEMORY_DMABUF:
519                 vb32.m.fd = vb->m.fd;
520                 break;
521         }
522
523         if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
524                 vb32.m.planes = (uintptr_t)vb->m.planes;
525
526         if (copy_to_user(arg, &vb32, sizeof(vb32)))
527                 return -EFAULT;
528
529         return 0;
530 }
531
532 #ifdef CONFIG_COMPAT_32BIT_TIME
533 static int put_v4l2_buffer32_time32(struct v4l2_buffer *vb,
534                                     struct v4l2_buffer32_time32 __user *arg)
535 {
536         struct v4l2_buffer32_time32 vb32;
537
538         memset(&vb32, 0, sizeof(vb32));
539         vb32 = (struct v4l2_buffer32_time32) {
540                 .index          = vb->index,
541                 .type           = vb->type,
542                 .bytesused      = vb->bytesused,
543                 .flags          = vb->flags,
544                 .field          = vb->field,
545                 .timestamp.tv_sec       = vb->timestamp.tv_sec,
546                 .timestamp.tv_usec      = vb->timestamp.tv_usec,
547                 .timecode       = vb->timecode,
548                 .sequence       = vb->sequence,
549                 .memory         = vb->memory,
550                 .m.offset       = vb->m.offset,
551                 .length         = vb->length,
552                 .request_fd     = vb->request_fd,
553         };
554         switch (vb->memory) {
555         case V4L2_MEMORY_MMAP:
556         case V4L2_MEMORY_OVERLAY:
557                 vb32.m.offset = vb->m.offset;
558                 break;
559         case V4L2_MEMORY_USERPTR:
560                 vb32.m.userptr = (uintptr_t)(vb->m.userptr);
561                 break;
562         case V4L2_MEMORY_DMABUF:
563                 vb32.m.fd = vb->m.fd;
564                 break;
565         }
566
567         if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
568                 vb32.m.planes = (uintptr_t)vb->m.planes;
569
570         if (copy_to_user(arg, &vb32, sizeof(vb32)))
571                 return -EFAULT;
572
573         return 0;
574 }
575 #endif
576
577 struct v4l2_framebuffer32 {
578         __u32                   capability;
579         __u32                   flags;
580         compat_caddr_t          base;
581         struct {
582                 __u32           width;
583                 __u32           height;
584                 __u32           pixelformat;
585                 __u32           field;
586                 __u32           bytesperline;
587                 __u32           sizeimage;
588                 __u32           colorspace;
589                 __u32           priv;
590         } fmt;
591 };
592
593 static int get_v4l2_framebuffer32(struct v4l2_framebuffer *p64,
594                                   struct v4l2_framebuffer32 __user *p32)
595 {
596         compat_caddr_t tmp;
597
598         if (get_user(tmp, &p32->base) ||
599             get_user(p64->capability, &p32->capability) ||
600             get_user(p64->flags, &p32->flags) ||
601             copy_from_user(&p64->fmt, &p32->fmt, sizeof(p64->fmt)))
602                 return -EFAULT;
603         p64->base = (void __force *)compat_ptr(tmp);
604
605         return 0;
606 }
607
608 static int put_v4l2_framebuffer32(struct v4l2_framebuffer *p64,
609                                   struct v4l2_framebuffer32 __user *p32)
610 {
611         if (put_user((uintptr_t)p64->base, &p32->base) ||
612             put_user(p64->capability, &p32->capability) ||
613             put_user(p64->flags, &p32->flags) ||
614             copy_to_user(&p32->fmt, &p64->fmt, sizeof(p64->fmt)))
615                 return -EFAULT;
616
617         return 0;
618 }
619
620 struct v4l2_input32 {
621         __u32        index;             /*  Which input */
622         __u8         name[32];          /*  Label */
623         __u32        type;              /*  Type of input */
624         __u32        audioset;          /*  Associated audios (bitfield) */
625         __u32        tuner;             /*  Associated tuner */
626         compat_u64   std;
627         __u32        status;
628         __u32        capabilities;
629         __u32        reserved[3];
630 };
631
632 /*
633  * The 64-bit v4l2_input struct has extra padding at the end of the struct.
634  * Otherwise it is identical to the 32-bit version.
635  */
636 static inline int get_v4l2_input32(struct v4l2_input *p64,
637                                    struct v4l2_input32 __user *p32)
638 {
639         if (copy_from_user(p64, p32, sizeof(*p32)))
640                 return -EFAULT;
641         return 0;
642 }
643
644 static inline int put_v4l2_input32(struct v4l2_input *p64,
645                                    struct v4l2_input32 __user *p32)
646 {
647         if (copy_to_user(p32, p64, sizeof(*p32)))
648                 return -EFAULT;
649         return 0;
650 }
651
652 struct v4l2_ext_controls32 {
653         __u32 which;
654         __u32 count;
655         __u32 error_idx;
656         __s32 request_fd;
657         __u32 reserved[1];
658         compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
659 };
660
661 struct v4l2_ext_control32 {
662         __u32 id;
663         __u32 size;
664         __u32 reserved2[1];
665         union {
666                 __s32 value;
667                 __s64 value64;
668                 compat_caddr_t string; /* actually char * */
669         };
670 } __attribute__ ((packed));
671
672 /* Return true if this control is a pointer type. */
673 static inline bool ctrl_is_pointer(struct file *file, u32 id)
674 {
675         struct video_device *vdev = video_devdata(file);
676         struct v4l2_fh *fh = NULL;
677         struct v4l2_ctrl_handler *hdl = NULL;
678         struct v4l2_query_ext_ctrl qec = { id };
679         const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
680
681         if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
682                 fh = file->private_data;
683
684         if (fh && fh->ctrl_handler)
685                 hdl = fh->ctrl_handler;
686         else if (vdev->ctrl_handler)
687                 hdl = vdev->ctrl_handler;
688
689         if (hdl) {
690                 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id);
691
692                 return ctrl && ctrl->is_ptr;
693         }
694
695         if (!ops || !ops->vidioc_query_ext_ctrl)
696                 return false;
697
698         return !ops->vidioc_query_ext_ctrl(file, fh, &qec) &&
699                 (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
700 }
701
702 static int get_v4l2_ext_controls32(struct v4l2_ext_controls *p64,
703                                    struct v4l2_ext_controls32 __user *p32)
704 {
705         struct v4l2_ext_controls32 ec32;
706
707         if (copy_from_user(&ec32, p32, sizeof(ec32)))
708                 return -EFAULT;
709
710         *p64 = (struct v4l2_ext_controls) {
711                 .which          = ec32.which,
712                 .count          = ec32.count,
713                 .error_idx      = ec32.error_idx,
714                 .request_fd     = ec32.request_fd,
715                 .reserved[0]    = ec32.reserved[0],
716                 .controls       = (void __force *)compat_ptr(ec32.controls),
717         };
718
719         return 0;
720 }
721
722 static int put_v4l2_ext_controls32(struct v4l2_ext_controls *p64,
723                                    struct v4l2_ext_controls32 __user *p32)
724 {
725         struct v4l2_ext_controls32 ec32;
726
727         memset(&ec32, 0, sizeof(ec32));
728         ec32 = (struct v4l2_ext_controls32) {
729                 .which          = p64->which,
730                 .count          = p64->count,
731                 .error_idx      = p64->error_idx,
732                 .request_fd     = p64->request_fd,
733                 .reserved[0]    = p64->reserved[0],
734                 .controls       = (uintptr_t)p64->controls,
735         };
736
737         if (copy_to_user(p32, &ec32, sizeof(ec32)))
738                 return -EFAULT;
739
740         return 0;
741 }
742
743 #ifdef CONFIG_X86_64
744 /*
745  * x86 is the only compat architecture with different struct alignment
746  * between 32-bit and 64-bit tasks.
747  *
748  * On all other architectures, v4l2_event32 and v4l2_event32_time32 are
749  * the same as v4l2_event and v4l2_event_time32, so we can use the native
750  * handlers, converting v4l2_event to v4l2_event_time32 if necessary.
751  */
752 struct v4l2_event32 {
753         __u32                           type;
754         union {
755                 compat_s64              value64;
756                 __u8                    data[64];
757         } u;
758         __u32                           pending;
759         __u32                           sequence;
760         struct {
761                 compat_s64              tv_sec;
762                 compat_s64              tv_nsec;
763         } timestamp;
764         __u32                           id;
765         __u32                           reserved[8];
766 };
767
768 #ifdef CONFIG_COMPAT_32BIT_TIME
769 struct v4l2_event32_time32 {
770         __u32                           type;
771         union {
772                 compat_s64              value64;
773                 __u8                    data[64];
774         } u;
775         __u32                           pending;
776         __u32                           sequence;
777         struct old_timespec32           timestamp;
778         __u32                           id;
779         __u32                           reserved[8];
780 };
781 #endif
782
783 static int put_v4l2_event32(struct v4l2_event *p64,
784                             struct v4l2_event32 __user *p32)
785 {
786         if (put_user(p64->type, &p32->type) ||
787             copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) ||
788             put_user(p64->pending, &p32->pending) ||
789             put_user(p64->sequence, &p32->sequence) ||
790             put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) ||
791             put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) ||
792             put_user(p64->id, &p32->id) ||
793             copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
794                 return -EFAULT;
795         return 0;
796 }
797
798 #ifdef CONFIG_COMPAT_32BIT_TIME
799 static int put_v4l2_event32_time32(struct v4l2_event *p64,
800                                    struct v4l2_event32_time32 __user *p32)
801 {
802         if (put_user(p64->type, &p32->type) ||
803             copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) ||
804             put_user(p64->pending, &p32->pending) ||
805             put_user(p64->sequence, &p32->sequence) ||
806             put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) ||
807             put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) ||
808             put_user(p64->id, &p32->id) ||
809             copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
810                 return -EFAULT;
811         return 0;
812 }
813 #endif
814 #endif
815
816 struct v4l2_edid32 {
817         __u32 pad;
818         __u32 start_block;
819         __u32 blocks;
820         __u32 reserved[5];
821         compat_caddr_t edid;
822 };
823
824 static int get_v4l2_edid32(struct v4l2_edid *p64,
825                            struct v4l2_edid32 __user *p32)
826 {
827         compat_uptr_t edid;
828
829         if (copy_from_user(p64, p32, offsetof(struct v4l2_edid32, edid)) ||
830             get_user(edid, &p32->edid))
831                 return -EFAULT;
832
833         p64->edid = (void __force *)compat_ptr(edid);
834         return 0;
835 }
836
837 static int put_v4l2_edid32(struct v4l2_edid *p64,
838                            struct v4l2_edid32 __user *p32)
839 {
840         if (copy_to_user(p32, p64, offsetof(struct v4l2_edid32, edid)))
841                 return -EFAULT;
842         return 0;
843 }
844
845 /*
846  * List of ioctls that require 32-bits/64-bits conversion
847  *
848  * The V4L2 ioctls that aren't listed there don't have pointer arguments
849  * and the struct size is identical for both 32 and 64 bits versions, so
850  * they don't need translations.
851  */
852
853 #define VIDIOC_G_FMT32          _IOWR('V',  4, struct v4l2_format32)
854 #define VIDIOC_S_FMT32          _IOWR('V',  5, struct v4l2_format32)
855 #define VIDIOC_QUERYBUF32       _IOWR('V',  9, struct v4l2_buffer32)
856 #define VIDIOC_G_FBUF32         _IOR ('V', 10, struct v4l2_framebuffer32)
857 #define VIDIOC_S_FBUF32         _IOW ('V', 11, struct v4l2_framebuffer32)
858 #define VIDIOC_QBUF32           _IOWR('V', 15, struct v4l2_buffer32)
859 #define VIDIOC_DQBUF32          _IOWR('V', 17, struct v4l2_buffer32)
860 #define VIDIOC_ENUMSTD32        _IOWR('V', 25, struct v4l2_standard32)
861 #define VIDIOC_ENUMINPUT32      _IOWR('V', 26, struct v4l2_input32)
862 #define VIDIOC_G_EDID32         _IOWR('V', 40, struct v4l2_edid32)
863 #define VIDIOC_S_EDID32         _IOWR('V', 41, struct v4l2_edid32)
864 #define VIDIOC_TRY_FMT32        _IOWR('V', 64, struct v4l2_format32)
865 #define VIDIOC_G_EXT_CTRLS32    _IOWR('V', 71, struct v4l2_ext_controls32)
866 #define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
867 #define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)
868 #define VIDIOC_DQEVENT32        _IOR ('V', 89, struct v4l2_event32)
869 #define VIDIOC_CREATE_BUFS32    _IOWR('V', 92, struct v4l2_create_buffers32)
870 #define VIDIOC_PREPARE_BUF32    _IOWR('V', 93, struct v4l2_buffer32)
871
872 #ifdef CONFIG_COMPAT_32BIT_TIME
873 #define VIDIOC_QUERYBUF32_TIME32        _IOWR('V',  9, struct v4l2_buffer32_time32)
874 #define VIDIOC_QBUF32_TIME32            _IOWR('V', 15, struct v4l2_buffer32_time32)
875 #define VIDIOC_DQBUF32_TIME32           _IOWR('V', 17, struct v4l2_buffer32_time32)
876 #ifdef CONFIG_X86_64
877 #define VIDIOC_DQEVENT32_TIME32         _IOR ('V', 89, struct v4l2_event32_time32)
878 #endif
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 #ifdef CONFIG_COMPAT_32BIT_TIME
933         case VIDIOC_DQEVENT32_TIME32:
934                 return VIDIOC_DQEVENT;
935 #endif
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 #ifdef CONFIG_COMPAT_32BIT_TIME
1029         case VIDIOC_DQEVENT32_TIME32:
1030                 return put_v4l2_event32_time32(parg, arg);
1031 #endif
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         switch (cmd) {
1044         case VIDIOC_G_FMT32:
1045         case VIDIOC_S_FMT32:
1046         case VIDIOC_TRY_FMT32: {
1047                 struct v4l2_format *f64 = arg;
1048                 struct v4l2_clip *c64 = mbuf;
1049                 struct v4l2_clip32 __user *c32 = user_ptr;
1050                 u32 clipcount = f64->fmt.win.clipcount;
1051
1052                 if ((f64->type != V4L2_BUF_TYPE_VIDEO_OVERLAY &&
1053                      f64->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) ||
1054                     clipcount == 0)
1055                         return 0;
1056                 if (clipcount > 2048)
1057                         return -EINVAL;
1058                 while (clipcount--) {
1059                         if (copy_from_user(c64, c32, sizeof(c64->c)))
1060                                 return -EFAULT;
1061                         c64->next = NULL;
1062                         c64++;
1063                         c32++;
1064                 }
1065                 break;
1066         }
1067 #ifdef CONFIG_COMPAT_32BIT_TIME
1068         case VIDIOC_QUERYBUF32_TIME32:
1069         case VIDIOC_QBUF32_TIME32:
1070         case VIDIOC_DQBUF32_TIME32:
1071         case VIDIOC_PREPARE_BUF32_TIME32:
1072 #endif
1073         case VIDIOC_QUERYBUF32:
1074         case VIDIOC_QBUF32:
1075         case VIDIOC_DQBUF32:
1076         case VIDIOC_PREPARE_BUF32: {
1077                 struct v4l2_buffer *b64 = arg;
1078                 struct v4l2_plane *p64 = mbuf;
1079                 struct v4l2_plane32 __user *p32 = user_ptr;
1080
1081                 if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {
1082                         u32 num_planes = b64->length;
1083
1084                         if (num_planes == 0)
1085                                 return 0;
1086
1087                         while (num_planes--) {
1088                                 err = get_v4l2_plane32(p64, p32, b64->memory);
1089                                 if (err)
1090                                         return err;
1091                                 ++p64;
1092                                 ++p32;
1093                         }
1094                 }
1095                 break;
1096         }
1097         case VIDIOC_G_EXT_CTRLS32:
1098         case VIDIOC_S_EXT_CTRLS32:
1099         case VIDIOC_TRY_EXT_CTRLS32: {
1100                 struct v4l2_ext_controls *ecs64 = arg;
1101                 struct v4l2_ext_control *ec64 = mbuf;
1102                 struct v4l2_ext_control32 __user *ec32 = user_ptr;
1103                 int n;
1104
1105                 for (n = 0; n < ecs64->count; n++) {
1106                         if (copy_from_user(ec64, ec32, sizeof(*ec32)))
1107                                 return -EFAULT;
1108
1109                         if (ctrl_is_pointer(file, ec64->id)) {
1110                                 compat_uptr_t p;
1111
1112                                 if (get_user(p, &ec32->string))
1113                                         return -EFAULT;
1114                                 ec64->string = compat_ptr(p);
1115                         }
1116                         ec32++;
1117                         ec64++;
1118                 }
1119                 break;
1120         }
1121         default:
1122                 if (copy_from_user(mbuf, user_ptr, array_size))
1123                         err = -EFAULT;
1124                 break;
1125         }
1126
1127         return err;
1128 }
1129
1130 int v4l2_compat_put_array_args(struct file *file, void __user *user_ptr,
1131                                void *mbuf, size_t array_size,
1132                                unsigned int cmd, void *arg)
1133 {
1134         int err = 0;
1135
1136         switch (cmd) {
1137         case VIDIOC_G_FMT32:
1138         case VIDIOC_S_FMT32:
1139         case VIDIOC_TRY_FMT32: {
1140                 struct v4l2_format *f64 = arg;
1141                 struct v4l2_clip *c64 = mbuf;
1142                 struct v4l2_clip32 __user *c32 = user_ptr;
1143                 u32 clipcount = f64->fmt.win.clipcount;
1144
1145                 if ((f64->type != V4L2_BUF_TYPE_VIDEO_OVERLAY &&
1146                      f64->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY) ||
1147                     clipcount == 0)
1148                         return 0;
1149                 if (clipcount > 2048)
1150                         return -EINVAL;
1151                 while (clipcount--) {
1152                         if (copy_to_user(c32, c64, sizeof(c64->c)))
1153                                 return -EFAULT;
1154                         c64++;
1155                         c32++;
1156                 }
1157                 break;
1158         }
1159 #ifdef CONFIG_COMPAT_32BIT_TIME
1160         case VIDIOC_QUERYBUF32_TIME32:
1161         case VIDIOC_QBUF32_TIME32:
1162         case VIDIOC_DQBUF32_TIME32:
1163         case VIDIOC_PREPARE_BUF32_TIME32:
1164 #endif
1165         case VIDIOC_QUERYBUF32:
1166         case VIDIOC_QBUF32:
1167         case VIDIOC_DQBUF32:
1168         case VIDIOC_PREPARE_BUF32: {
1169                 struct v4l2_buffer *b64 = arg;
1170                 struct v4l2_plane *p64 = mbuf;
1171                 struct v4l2_plane32 __user *p32 = user_ptr;
1172
1173                 if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {
1174                         u32 num_planes = b64->length;
1175
1176                         if (num_planes == 0)
1177                                 return 0;
1178
1179                         while (num_planes--) {
1180                                 err = put_v4l2_plane32(p64, p32, b64->memory);
1181                                 if (err)
1182                                         return err;
1183                                 ++p64;
1184                                 ++p32;
1185                         }
1186                 }
1187                 break;
1188         }
1189         case VIDIOC_G_EXT_CTRLS32:
1190         case VIDIOC_S_EXT_CTRLS32:
1191         case VIDIOC_TRY_EXT_CTRLS32: {
1192                 struct v4l2_ext_controls *ecs64 = arg;
1193                 struct v4l2_ext_control *ec64 = mbuf;
1194                 struct v4l2_ext_control32 __user *ec32 = user_ptr;
1195                 int n;
1196
1197                 for (n = 0; n < ecs64->count; n++) {
1198                         unsigned int size = sizeof(*ec32);
1199                         /*
1200                          * Do not modify the pointer when copying a pointer
1201                          * control.  The contents of the pointer was changed,
1202                          * not the pointer itself.
1203                          * The structures are otherwise compatible.
1204                          */
1205                         if (ctrl_is_pointer(file, ec64->id))
1206                                 size -= sizeof(ec32->value64);
1207
1208                         if (copy_to_user(ec32, ec64, size))
1209                                 return -EFAULT;
1210
1211                         ec32++;
1212                         ec64++;
1213                 }
1214                 break;
1215         }
1216         default:
1217                 if (copy_to_user(user_ptr, mbuf, array_size))
1218                         err = -EFAULT;
1219                 break;
1220         }
1221
1222         return err;
1223 }
1224
1225 /**
1226  * v4l2_compat_ioctl32() - Handles a compat32 ioctl call
1227  *
1228  * @file: pointer to &struct file with the file handler
1229  * @cmd: ioctl to be called
1230  * @arg: arguments passed from/to the ioctl handler
1231  *
1232  * This function is meant to be used as .compat_ioctl fops at v4l2-dev.c
1233  * in order to deal with 32-bit calls on a 64-bits Kernel.
1234  *
1235  * This function calls do_video_ioctl() for non-private V4L2 ioctls.
1236  * If the function is a private one it calls vdev->fops->compat_ioctl32
1237  * instead.
1238  */
1239 long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
1240 {
1241         struct video_device *vdev = video_devdata(file);
1242         long ret = -ENOIOCTLCMD;
1243
1244         if (!file->f_op->unlocked_ioctl)
1245                 return ret;
1246
1247         if (!video_is_registered(vdev))
1248                 return -ENODEV;
1249
1250         if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE)
1251                 ret = file->f_op->unlocked_ioctl(file, cmd,
1252                                         (unsigned long)compat_ptr(arg));
1253         else if (vdev->fops->compat_ioctl32)
1254                 ret = vdev->fops->compat_ioctl32(file, cmd, arg);
1255
1256         if (ret == -ENOIOCTLCMD)
1257                 pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
1258                          _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
1259         return ret;
1260 }
1261 EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);
This page took 0.116264 seconds and 4 git commands to generate.