2 * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
3 * Separated from fs stuff by Arnd Bergmann <arnd@arndb.de>
5 * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
6 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
7 * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs
8 * Copyright (C) 2003 Pavel Machek (pavel@ucw.cz)
9 * Copyright (C) 2005 Philippe De Muyter (phdm@macqel.be)
10 * Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
12 * These routines maintain argument size conversion between 32bit and 64bit
16 #include <linux/compat.h>
17 #include <linux/module.h>
18 #include <linux/videodev2.h>
19 #include <linux/v4l2-subdev.h>
20 #include <media/v4l2-dev.h>
21 #include <media/v4l2-fh.h>
22 #include <media/v4l2-ctrls.h>
23 #include <media/v4l2-ioctl.h>
25 /* Use the same argument order as copy_in_user */
26 #define assign_in_user(to, from) \
28 typeof(*from) __assign_tmp; \
30 get_user(__assign_tmp, from) || put_user(__assign_tmp, to); \
33 static long native_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
35 long ret
= -ENOIOCTLCMD
;
37 if (file
->f_op
->unlocked_ioctl
)
38 ret
= file
->f_op
->unlocked_ioctl(file
, cmd
, arg
);
49 struct v4l2_window32
{
51 __u32 field
; /* enum v4l2_field */
53 compat_caddr_t clips
; /* actually struct v4l2_clip32 * */
55 compat_caddr_t bitmap
;
59 static int get_v4l2_window32(struct v4l2_window __user
*kp
,
60 struct v4l2_window32 __user
*up
,
61 void __user
*aux_buf
, u32 aux_space
)
63 struct v4l2_clip32 __user
*uclips
;
64 struct v4l2_clip __user
*kclips
;
68 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
69 copy_in_user(&kp
->w
, &up
->w
, sizeof(up
->w
)) ||
70 assign_in_user(&kp
->field
, &up
->field
) ||
71 assign_in_user(&kp
->chromakey
, &up
->chromakey
) ||
72 assign_in_user(&kp
->global_alpha
, &up
->global_alpha
) ||
73 get_user(clipcount
, &up
->clipcount
) ||
74 put_user(clipcount
, &kp
->clipcount
))
79 return put_user(NULL
, &kp
->clips
);
81 if (get_user(p
, &up
->clips
))
83 uclips
= compat_ptr(p
);
84 if (aux_space
< clipcount
* sizeof(*kclips
))
87 if (put_user(kclips
, &kp
->clips
))
91 if (copy_in_user(&kclips
->c
, &uclips
->c
, sizeof(uclips
->c
)))
93 if (put_user(clipcount
? kclips
+ 1 : NULL
, &kclips
->next
))
101 static int put_v4l2_window32(struct v4l2_window __user
*kp
,
102 struct v4l2_window32 __user
*up
)
104 struct v4l2_clip __user
*kclips
= kp
->clips
;
105 struct v4l2_clip32 __user
*uclips
;
109 if (copy_in_user(&up
->w
, &kp
->w
, sizeof(kp
->w
)) ||
110 assign_in_user(&up
->field
, &kp
->field
) ||
111 assign_in_user(&up
->chromakey
, &kp
->chromakey
) ||
112 assign_in_user(&up
->global_alpha
, &kp
->global_alpha
) ||
113 get_user(clipcount
, &kp
->clipcount
) ||
114 put_user(clipcount
, &up
->clipcount
))
119 if (get_user(p
, &up
->clips
))
121 uclips
= compat_ptr(p
);
122 while (clipcount
--) {
123 if (copy_in_user(&uclips
->c
, &kclips
->c
, sizeof(uclips
->c
)))
131 struct v4l2_format32
{
132 __u32 type
; /* enum v4l2_buf_type */
134 struct v4l2_pix_format pix
;
135 struct v4l2_pix_format_mplane pix_mp
;
136 struct v4l2_window32 win
;
137 struct v4l2_vbi_format vbi
;
138 struct v4l2_sliced_vbi_format sliced
;
139 struct v4l2_sdr_format sdr
;
140 struct v4l2_meta_format meta
;
141 __u8 raw_data
[200]; /* user-defined */
146 * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument
147 * @index: on return, index of the first created buffer
148 * @count: entry: number of requested buffers,
149 * return: number of created buffers
150 * @memory: buffer memory type
151 * @format: frame format, for which buffers are requested
152 * @reserved: future extensions
154 struct v4l2_create_buffers32
{
157 __u32 memory
; /* enum v4l2_memory */
158 struct v4l2_format32 format
;
162 static int __bufsize_v4l2_format(struct v4l2_format32 __user
*up
, u32
*size
)
166 if (get_user(type
, &up
->type
))
170 case V4L2_BUF_TYPE_VIDEO_OVERLAY
:
171 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
: {
174 if (get_user(clipcount
, &up
->fmt
.win
.clipcount
))
176 if (clipcount
> 2048)
178 *size
= clipcount
* sizeof(struct v4l2_clip
);
187 static int bufsize_v4l2_format(struct v4l2_format32 __user
*up
, u32
*size
)
189 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)))
191 return __bufsize_v4l2_format(up
, size
);
194 static int __get_v4l2_format32(struct v4l2_format __user
*kp
,
195 struct v4l2_format32 __user
*up
,
196 void __user
*aux_buf
, u32 aux_space
)
200 if (get_user(type
, &up
->type
) || put_user(type
, &kp
->type
))
204 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
205 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
206 return copy_in_user(&kp
->fmt
.pix
, &up
->fmt
.pix
,
207 sizeof(kp
->fmt
.pix
)) ? -EFAULT
: 0;
208 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
209 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
210 return copy_in_user(&kp
->fmt
.pix_mp
, &up
->fmt
.pix_mp
,
211 sizeof(kp
->fmt
.pix_mp
)) ? -EFAULT
: 0;
212 case V4L2_BUF_TYPE_VIDEO_OVERLAY
:
213 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
:
214 return get_v4l2_window32(&kp
->fmt
.win
, &up
->fmt
.win
,
216 case V4L2_BUF_TYPE_VBI_CAPTURE
:
217 case V4L2_BUF_TYPE_VBI_OUTPUT
:
218 return copy_in_user(&kp
->fmt
.vbi
, &up
->fmt
.vbi
,
219 sizeof(kp
->fmt
.vbi
)) ? -EFAULT
: 0;
220 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE
:
221 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT
:
222 return copy_in_user(&kp
->fmt
.sliced
, &up
->fmt
.sliced
,
223 sizeof(kp
->fmt
.sliced
)) ? -EFAULT
: 0;
224 case V4L2_BUF_TYPE_SDR_CAPTURE
:
225 case V4L2_BUF_TYPE_SDR_OUTPUT
:
226 return copy_in_user(&kp
->fmt
.sdr
, &up
->fmt
.sdr
,
227 sizeof(kp
->fmt
.sdr
)) ? -EFAULT
: 0;
228 case V4L2_BUF_TYPE_META_CAPTURE
:
229 return copy_in_user(&kp
->fmt
.meta
, &up
->fmt
.meta
,
230 sizeof(kp
->fmt
.meta
)) ? -EFAULT
: 0;
236 static int get_v4l2_format32(struct v4l2_format __user
*kp
,
237 struct v4l2_format32 __user
*up
,
238 void __user
*aux_buf
, u32 aux_space
)
240 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)))
242 return __get_v4l2_format32(kp
, up
, aux_buf
, aux_space
);
245 static int bufsize_v4l2_create(struct v4l2_create_buffers32 __user
*up
,
248 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)))
250 return __bufsize_v4l2_format(&up
->format
, size
);
253 static int get_v4l2_create32(struct v4l2_create_buffers __user
*kp
,
254 struct v4l2_create_buffers32 __user
*up
,
255 void __user
*aux_buf
, u32 aux_space
)
257 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
259 offsetof(struct v4l2_create_buffers32
, format
)))
261 return __get_v4l2_format32(&kp
->format
, &up
->format
,
265 static int __put_v4l2_format32(struct v4l2_format __user
*kp
,
266 struct v4l2_format32 __user
*up
)
270 if (get_user(type
, &kp
->type
))
274 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
275 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
276 return copy_in_user(&up
->fmt
.pix
, &kp
->fmt
.pix
,
277 sizeof(kp
->fmt
.pix
)) ? -EFAULT
: 0;
278 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
279 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
280 return copy_in_user(&up
->fmt
.pix_mp
, &kp
->fmt
.pix_mp
,
281 sizeof(kp
->fmt
.pix_mp
)) ? -EFAULT
: 0;
282 case V4L2_BUF_TYPE_VIDEO_OVERLAY
:
283 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
:
284 return put_v4l2_window32(&kp
->fmt
.win
, &up
->fmt
.win
);
285 case V4L2_BUF_TYPE_VBI_CAPTURE
:
286 case V4L2_BUF_TYPE_VBI_OUTPUT
:
287 return copy_in_user(&up
->fmt
.vbi
, &kp
->fmt
.vbi
,
288 sizeof(kp
->fmt
.vbi
)) ? -EFAULT
: 0;
289 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE
:
290 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT
:
291 return copy_in_user(&up
->fmt
.sliced
, &kp
->fmt
.sliced
,
292 sizeof(kp
->fmt
.sliced
)) ? -EFAULT
: 0;
293 case V4L2_BUF_TYPE_SDR_CAPTURE
:
294 case V4L2_BUF_TYPE_SDR_OUTPUT
:
295 return copy_in_user(&up
->fmt
.sdr
, &kp
->fmt
.sdr
,
296 sizeof(kp
->fmt
.sdr
)) ? -EFAULT
: 0;
297 case V4L2_BUF_TYPE_META_CAPTURE
:
298 return copy_in_user(&up
->fmt
.meta
, &kp
->fmt
.meta
,
299 sizeof(kp
->fmt
.meta
)) ? -EFAULT
: 0;
305 static int put_v4l2_format32(struct v4l2_format __user
*kp
,
306 struct v4l2_format32 __user
*up
)
308 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)))
310 return __put_v4l2_format32(kp
, up
);
313 static int put_v4l2_create32(struct v4l2_create_buffers __user
*kp
,
314 struct v4l2_create_buffers32 __user
*up
)
316 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
318 offsetof(struct v4l2_create_buffers32
, format
)) ||
319 copy_in_user(up
->reserved
, kp
->reserved
, sizeof(kp
->reserved
)))
321 return __put_v4l2_format32(&kp
->format
, &up
->format
);
324 struct v4l2_standard32
{
328 struct v4l2_fract frameperiod
; /* Frames, not fields */
333 static int get_v4l2_standard32(struct v4l2_standard __user
*kp
,
334 struct v4l2_standard32 __user
*up
)
336 /* other fields are not set by the user, nor used by the driver */
337 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
338 assign_in_user(&kp
->index
, &up
->index
))
343 static int put_v4l2_standard32(struct v4l2_standard __user
*kp
,
344 struct v4l2_standard32 __user
*up
)
346 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
347 assign_in_user(&up
->index
, &kp
->index
) ||
348 assign_in_user(&up
->id
, &kp
->id
) ||
349 copy_in_user(up
->name
, kp
->name
, sizeof(up
->name
)) ||
350 copy_in_user(&up
->frameperiod
, &kp
->frameperiod
,
351 sizeof(up
->frameperiod
)) ||
352 assign_in_user(&up
->framelines
, &kp
->framelines
) ||
353 copy_in_user(up
->reserved
, kp
->reserved
, sizeof(up
->reserved
)))
358 struct v4l2_plane32
{
363 compat_long_t userptr
;
370 struct v4l2_buffer32
{
372 __u32 type
; /* enum v4l2_buf_type */
375 __u32 field
; /* enum v4l2_field */
376 struct compat_timeval timestamp
;
377 struct v4l2_timecode timecode
;
380 /* memory location */
381 __u32 memory
; /* enum v4l2_memory */
384 compat_long_t userptr
;
385 compat_caddr_t planes
;
393 static int get_v4l2_plane32(struct v4l2_plane __user
*up
,
394 struct v4l2_plane32 __user
*up32
,
395 enum v4l2_memory memory
)
399 if (copy_in_user(up
, up32
, 2 * sizeof(__u32
)) ||
400 copy_in_user(&up
->data_offset
, &up32
->data_offset
,
401 sizeof(up
->data_offset
)))
405 case V4L2_MEMORY_MMAP
:
406 case V4L2_MEMORY_OVERLAY
:
407 if (copy_in_user(&up
->m
.mem_offset
, &up32
->m
.mem_offset
,
408 sizeof(up32
->m
.mem_offset
)))
411 case V4L2_MEMORY_USERPTR
:
412 if (get_user(p
, &up32
->m
.userptr
) ||
413 put_user((unsigned long)compat_ptr(p
), &up
->m
.userptr
))
416 case V4L2_MEMORY_DMABUF
:
417 if (copy_in_user(&up
->m
.fd
, &up32
->m
.fd
, sizeof(up32
->m
.fd
)))
425 static int put_v4l2_plane32(struct v4l2_plane __user
*up
,
426 struct v4l2_plane32 __user
*up32
,
427 enum v4l2_memory memory
)
431 if (copy_in_user(up32
, up
, 2 * sizeof(__u32
)) ||
432 copy_in_user(&up32
->data_offset
, &up
->data_offset
,
433 sizeof(up
->data_offset
)))
437 case V4L2_MEMORY_MMAP
:
438 case V4L2_MEMORY_OVERLAY
:
439 if (copy_in_user(&up32
->m
.mem_offset
, &up
->m
.mem_offset
,
440 sizeof(up
->m
.mem_offset
)))
443 case V4L2_MEMORY_USERPTR
:
444 if (get_user(p
, &up
->m
.userptr
) ||
445 put_user((compat_ulong_t
)ptr_to_compat((__force
void *)p
),
449 case V4L2_MEMORY_DMABUF
:
450 if (copy_in_user(&up32
->m
.fd
, &up
->m
.fd
, sizeof(up
->m
.fd
)))
458 static int bufsize_v4l2_buffer(struct v4l2_buffer32 __user
*up
, u32
*size
)
463 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
464 get_user(type
, &up
->type
) ||
465 get_user(length
, &up
->length
))
468 if (V4L2_TYPE_IS_MULTIPLANAR(type
)) {
469 if (length
> VIDEO_MAX_PLANES
)
473 * We don't really care if userspace decides to kill itself
474 * by passing a very big length value
476 *size
= length
* sizeof(struct v4l2_plane
);
483 static int get_v4l2_buffer32(struct v4l2_buffer __user
*kp
,
484 struct v4l2_buffer32 __user
*up
,
485 void __user
*aux_buf
, u32 aux_space
)
489 enum v4l2_memory memory
;
490 struct v4l2_plane32 __user
*uplane32
;
491 struct v4l2_plane __user
*uplane
;
495 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
496 assign_in_user(&kp
->index
, &up
->index
) ||
497 get_user(type
, &up
->type
) ||
498 put_user(type
, &kp
->type
) ||
499 assign_in_user(&kp
->flags
, &up
->flags
) ||
500 get_user(memory
, &up
->memory
) ||
501 put_user(memory
, &kp
->memory
) ||
502 get_user(length
, &up
->length
) ||
503 put_user(length
, &kp
->length
))
506 if (V4L2_TYPE_IS_OUTPUT(type
))
507 if (assign_in_user(&kp
->bytesused
, &up
->bytesused
) ||
508 assign_in_user(&kp
->field
, &up
->field
) ||
509 assign_in_user(&kp
->timestamp
.tv_sec
,
510 &up
->timestamp
.tv_sec
) ||
511 assign_in_user(&kp
->timestamp
.tv_usec
,
512 &up
->timestamp
.tv_usec
))
515 if (V4L2_TYPE_IS_MULTIPLANAR(type
)) {
516 u32 num_planes
= length
;
518 if (num_planes
== 0) {
520 * num_planes == 0 is legal, e.g. when userspace doesn't
521 * need planes array on DQBUF
523 return put_user(NULL
, &kp
->m
.planes
);
525 if (num_planes
> VIDEO_MAX_PLANES
)
528 if (get_user(p
, &up
->m
.planes
))
531 uplane32
= compat_ptr(p
);
532 if (!access_ok(VERIFY_READ
, uplane32
,
533 num_planes
* sizeof(*uplane32
)))
537 * We don't really care if userspace decides to kill itself
538 * by passing a very big num_planes value
540 if (aux_space
< num_planes
* sizeof(*uplane
))
544 if (put_user((__force
struct v4l2_plane
*)uplane
,
548 while (num_planes
--) {
549 ret
= get_v4l2_plane32(uplane
, uplane32
, memory
);
557 case V4L2_MEMORY_MMAP
:
558 case V4L2_MEMORY_OVERLAY
:
559 if (assign_in_user(&kp
->m
.offset
, &up
->m
.offset
))
562 case V4L2_MEMORY_USERPTR
: {
563 compat_ulong_t userptr
;
565 if (get_user(userptr
, &up
->m
.userptr
) ||
566 put_user((unsigned long)compat_ptr(userptr
),
571 case V4L2_MEMORY_DMABUF
:
572 if (assign_in_user(&kp
->m
.fd
, &up
->m
.fd
))
581 static int put_v4l2_buffer32(struct v4l2_buffer __user
*kp
,
582 struct v4l2_buffer32 __user
*up
)
586 enum v4l2_memory memory
;
587 struct v4l2_plane32 __user
*uplane32
;
588 struct v4l2_plane __user
*uplane
;
592 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
593 assign_in_user(&up
->index
, &kp
->index
) ||
594 get_user(type
, &kp
->type
) ||
595 put_user(type
, &up
->type
) ||
596 assign_in_user(&up
->flags
, &kp
->flags
) ||
597 get_user(memory
, &kp
->memory
) ||
598 put_user(memory
, &up
->memory
))
601 if (assign_in_user(&up
->bytesused
, &kp
->bytesused
) ||
602 assign_in_user(&up
->field
, &kp
->field
) ||
603 assign_in_user(&up
->timestamp
.tv_sec
, &kp
->timestamp
.tv_sec
) ||
604 assign_in_user(&up
->timestamp
.tv_usec
, &kp
->timestamp
.tv_usec
) ||
605 copy_in_user(&up
->timecode
, &kp
->timecode
, sizeof(kp
->timecode
)) ||
606 assign_in_user(&up
->sequence
, &kp
->sequence
) ||
607 assign_in_user(&up
->reserved2
, &kp
->reserved2
) ||
608 assign_in_user(&up
->reserved
, &kp
->reserved
) ||
609 get_user(length
, &kp
->length
) ||
610 put_user(length
, &up
->length
))
613 if (V4L2_TYPE_IS_MULTIPLANAR(type
)) {
614 u32 num_planes
= length
;
619 if (get_user(uplane
, ((__force
struct v4l2_plane __user
**)&kp
->m
.planes
)))
621 if (get_user(p
, &up
->m
.planes
))
623 uplane32
= compat_ptr(p
);
625 while (num_planes
--) {
626 ret
= put_v4l2_plane32(uplane
, uplane32
, memory
);
634 case V4L2_MEMORY_MMAP
:
635 case V4L2_MEMORY_OVERLAY
:
636 if (assign_in_user(&up
->m
.offset
, &kp
->m
.offset
))
639 case V4L2_MEMORY_USERPTR
:
640 if (assign_in_user(&up
->m
.userptr
, &kp
->m
.userptr
))
643 case V4L2_MEMORY_DMABUF
:
644 if (assign_in_user(&up
->m
.fd
, &kp
->m
.fd
))
653 struct v4l2_framebuffer32
{
669 static int get_v4l2_framebuffer32(struct v4l2_framebuffer __user
*kp
,
670 struct v4l2_framebuffer32 __user
*up
)
674 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
675 get_user(tmp
, &up
->base
) ||
676 put_user((__force
void *)compat_ptr(tmp
), &kp
->base
) ||
677 assign_in_user(&kp
->capability
, &up
->capability
) ||
678 assign_in_user(&kp
->flags
, &up
->flags
) ||
679 copy_in_user(&kp
->fmt
, &up
->fmt
, sizeof(kp
->fmt
)))
684 static int put_v4l2_framebuffer32(struct v4l2_framebuffer __user
*kp
,
685 struct v4l2_framebuffer32 __user
*up
)
689 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
690 get_user(base
, &kp
->base
) ||
691 put_user(ptr_to_compat(base
), &up
->base
) ||
692 assign_in_user(&up
->capability
, &kp
->capability
) ||
693 assign_in_user(&up
->flags
, &kp
->flags
) ||
694 copy_in_user(&up
->fmt
, &kp
->fmt
, sizeof(kp
->fmt
)))
699 struct v4l2_input32
{
700 __u32 index
; /* Which input */
701 __u8 name
[32]; /* Label */
702 __u32 type
; /* Type of input */
703 __u32 audioset
; /* Associated audios (bitfield) */
704 __u32 tuner
; /* Associated tuner */
712 * The 64-bit v4l2_input struct has extra padding at the end of the struct.
713 * Otherwise it is identical to the 32-bit version.
715 static inline int get_v4l2_input32(struct v4l2_input __user
*kp
,
716 struct v4l2_input32 __user
*up
)
718 if (copy_in_user(kp
, up
, sizeof(*up
)))
723 static inline int put_v4l2_input32(struct v4l2_input __user
*kp
,
724 struct v4l2_input32 __user
*up
)
726 if (copy_in_user(up
, kp
, sizeof(*up
)))
731 struct v4l2_ext_controls32
{
736 compat_caddr_t controls
; /* actually struct v4l2_ext_control32 * */
739 struct v4l2_ext_control32
{
746 compat_caddr_t string
; /* actually char * */
748 } __attribute__ ((packed
));
750 /* Return true if this control is a pointer type. */
751 static inline bool ctrl_is_pointer(struct file
*file
, u32 id
)
753 struct video_device
*vdev
= video_devdata(file
);
754 struct v4l2_fh
*fh
= NULL
;
755 struct v4l2_ctrl_handler
*hdl
= NULL
;
756 struct v4l2_query_ext_ctrl qec
= { id
};
757 const struct v4l2_ioctl_ops
*ops
= vdev
->ioctl_ops
;
759 if (test_bit(V4L2_FL_USES_V4L2_FH
, &vdev
->flags
))
760 fh
= file
->private_data
;
762 if (fh
&& fh
->ctrl_handler
)
763 hdl
= fh
->ctrl_handler
;
764 else if (vdev
->ctrl_handler
)
765 hdl
= vdev
->ctrl_handler
;
768 struct v4l2_ctrl
*ctrl
= v4l2_ctrl_find(hdl
, id
);
770 return ctrl
&& ctrl
->is_ptr
;
773 if (!ops
|| !ops
->vidioc_query_ext_ctrl
)
776 return !ops
->vidioc_query_ext_ctrl(file
, fh
, &qec
) &&
777 (qec
.flags
& V4L2_CTRL_FLAG_HAS_PAYLOAD
);
780 static int bufsize_v4l2_ext_controls(struct v4l2_ext_controls32 __user
*up
,
785 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
786 get_user(count
, &up
->count
))
788 if (count
> V4L2_CID_MAX_CTRLS
)
790 *size
= count
* sizeof(struct v4l2_ext_control
);
794 static int get_v4l2_ext_controls32(struct file
*file
,
795 struct v4l2_ext_controls __user
*kp
,
796 struct v4l2_ext_controls32 __user
*up
,
797 void __user
*aux_buf
, u32 aux_space
)
799 struct v4l2_ext_control32 __user
*ucontrols
;
800 struct v4l2_ext_control __user
*kcontrols
;
805 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
806 assign_in_user(&kp
->which
, &up
->which
) ||
807 get_user(count
, &up
->count
) ||
808 put_user(count
, &kp
->count
) ||
809 assign_in_user(&kp
->error_idx
, &up
->error_idx
) ||
810 copy_in_user(kp
->reserved
, up
->reserved
, sizeof(kp
->reserved
)))
814 return put_user(NULL
, &kp
->controls
);
815 if (count
> V4L2_CID_MAX_CTRLS
)
817 if (get_user(p
, &up
->controls
))
819 ucontrols
= compat_ptr(p
);
820 if (!access_ok(VERIFY_READ
, ucontrols
, count
* sizeof(*ucontrols
)))
822 if (aux_space
< count
* sizeof(*kcontrols
))
825 if (put_user((__force
struct v4l2_ext_control
*)kcontrols
,
829 for (n
= 0; n
< count
; n
++) {
832 if (copy_in_user(kcontrols
, ucontrols
, sizeof(*ucontrols
)))
835 if (get_user(id
, &kcontrols
->id
))
838 if (ctrl_is_pointer(file
, id
)) {
841 if (get_user(p
, &ucontrols
->string
))
844 if (put_user(s
, &kcontrols
->string
))
853 static int put_v4l2_ext_controls32(struct file
*file
,
854 struct v4l2_ext_controls __user
*kp
,
855 struct v4l2_ext_controls32 __user
*up
)
857 struct v4l2_ext_control32 __user
*ucontrols
;
858 struct v4l2_ext_control __user
*kcontrols
;
863 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
864 assign_in_user(&up
->which
, &kp
->which
) ||
865 get_user(count
, &kp
->count
) ||
866 put_user(count
, &up
->count
) ||
867 assign_in_user(&up
->error_idx
, &kp
->error_idx
) ||
868 copy_in_user(up
->reserved
, kp
->reserved
, sizeof(up
->reserved
)) ||
869 get_user(kcontrols
, &kp
->controls
))
874 if (get_user(p
, &up
->controls
))
876 ucontrols
= compat_ptr(p
);
877 if (!access_ok(VERIFY_WRITE
, ucontrols
, count
* sizeof(*ucontrols
)))
880 for (n
= 0; n
< count
; n
++) {
881 unsigned int size
= sizeof(*ucontrols
);
884 if (get_user(id
, &kcontrols
->id
) ||
885 put_user(id
, &ucontrols
->id
) ||
886 assign_in_user(&ucontrols
->size
, &kcontrols
->size
) ||
887 copy_in_user(&ucontrols
->reserved2
, &kcontrols
->reserved2
,
888 sizeof(ucontrols
->reserved2
)))
892 * Do not modify the pointer when copying a pointer control.
893 * The contents of the pointer was changed, not the pointer
896 if (ctrl_is_pointer(file
, id
))
897 size
-= sizeof(ucontrols
->value64
);
899 if (copy_in_user(ucontrols
, kcontrols
, size
))
908 struct v4l2_event32
{
916 struct compat_timespec timestamp
;
921 static int put_v4l2_event32(struct v4l2_event __user
*kp
,
922 struct v4l2_event32 __user
*up
)
924 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
925 assign_in_user(&up
->type
, &kp
->type
) ||
926 copy_in_user(&up
->u
, &kp
->u
, sizeof(kp
->u
)) ||
927 assign_in_user(&up
->pending
, &kp
->pending
) ||
928 assign_in_user(&up
->sequence
, &kp
->sequence
) ||
929 assign_in_user(&up
->timestamp
.tv_sec
, &kp
->timestamp
.tv_sec
) ||
930 assign_in_user(&up
->timestamp
.tv_nsec
, &kp
->timestamp
.tv_nsec
) ||
931 assign_in_user(&up
->id
, &kp
->id
) ||
932 copy_in_user(up
->reserved
, kp
->reserved
, sizeof(up
->reserved
)))
945 static int get_v4l2_edid32(struct v4l2_edid __user
*kp
,
946 struct v4l2_edid32 __user
*up
)
950 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
951 assign_in_user(&kp
->pad
, &up
->pad
) ||
952 assign_in_user(&kp
->start_block
, &up
->start_block
) ||
953 assign_in_user(&kp
->blocks
, &up
->blocks
) ||
954 get_user(tmp
, &up
->edid
) ||
955 put_user(compat_ptr(tmp
), &kp
->edid
) ||
956 copy_in_user(kp
->reserved
, up
->reserved
, sizeof(kp
->reserved
)))
961 static int put_v4l2_edid32(struct v4l2_edid __user
*kp
,
962 struct v4l2_edid32 __user
*up
)
966 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
967 assign_in_user(&up
->pad
, &kp
->pad
) ||
968 assign_in_user(&up
->start_block
, &kp
->start_block
) ||
969 assign_in_user(&up
->blocks
, &kp
->blocks
) ||
970 get_user(edid
, &kp
->edid
) ||
971 put_user(ptr_to_compat(edid
), &up
->edid
) ||
972 copy_in_user(up
->reserved
, kp
->reserved
, sizeof(up
->reserved
)))
978 #define VIDIOC_G_FMT32 _IOWR('V', 4, struct v4l2_format32)
979 #define VIDIOC_S_FMT32 _IOWR('V', 5, struct v4l2_format32)
980 #define VIDIOC_QUERYBUF32 _IOWR('V', 9, struct v4l2_buffer32)
981 #define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32)
982 #define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32)
983 #define VIDIOC_QBUF32 _IOWR('V', 15, struct v4l2_buffer32)
984 #define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32)
985 #define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32)
986 #define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32)
987 #define VIDIOC_G_EDID32 _IOWR('V', 40, struct v4l2_edid32)
988 #define VIDIOC_S_EDID32 _IOWR('V', 41, struct v4l2_edid32)
989 #define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32)
990 #define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32)
991 #define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32)
992 #define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32)
993 #define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32)
994 #define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32)
995 #define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32)
997 #define VIDIOC_OVERLAY32 _IOW ('V', 14, s32)
998 #define VIDIOC_STREAMON32 _IOW ('V', 18, s32)
999 #define VIDIOC_STREAMOFF32 _IOW ('V', 19, s32)
1000 #define VIDIOC_G_INPUT32 _IOR ('V', 38, s32)
1001 #define VIDIOC_S_INPUT32 _IOWR('V', 39, s32)
1002 #define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32)
1003 #define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32)
1005 static int alloc_userspace(unsigned int size
, u32 aux_space
,
1006 void __user
**up_native
)
1008 *up_native
= compat_alloc_user_space(size
+ aux_space
);
1011 if (clear_user(*up_native
, size
))
1016 static long do_video_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
1018 void __user
*up
= compat_ptr(arg
);
1019 void __user
*up_native
= NULL
;
1020 void __user
*aux_buf
;
1022 int compatible_arg
= 1;
1025 /* First, convert the command. */
1027 case VIDIOC_G_FMT32
: cmd
= VIDIOC_G_FMT
; break;
1028 case VIDIOC_S_FMT32
: cmd
= VIDIOC_S_FMT
; break;
1029 case VIDIOC_QUERYBUF32
: cmd
= VIDIOC_QUERYBUF
; break;
1030 case VIDIOC_G_FBUF32
: cmd
= VIDIOC_G_FBUF
; break;
1031 case VIDIOC_S_FBUF32
: cmd
= VIDIOC_S_FBUF
; break;
1032 case VIDIOC_QBUF32
: cmd
= VIDIOC_QBUF
; break;
1033 case VIDIOC_DQBUF32
: cmd
= VIDIOC_DQBUF
; break;
1034 case VIDIOC_ENUMSTD32
: cmd
= VIDIOC_ENUMSTD
; break;
1035 case VIDIOC_ENUMINPUT32
: cmd
= VIDIOC_ENUMINPUT
; break;
1036 case VIDIOC_TRY_FMT32
: cmd
= VIDIOC_TRY_FMT
; break;
1037 case VIDIOC_G_EXT_CTRLS32
: cmd
= VIDIOC_G_EXT_CTRLS
; break;
1038 case VIDIOC_S_EXT_CTRLS32
: cmd
= VIDIOC_S_EXT_CTRLS
; break;
1039 case VIDIOC_TRY_EXT_CTRLS32
: cmd
= VIDIOC_TRY_EXT_CTRLS
; break;
1040 case VIDIOC_DQEVENT32
: cmd
= VIDIOC_DQEVENT
; break;
1041 case VIDIOC_OVERLAY32
: cmd
= VIDIOC_OVERLAY
; break;
1042 case VIDIOC_STREAMON32
: cmd
= VIDIOC_STREAMON
; break;
1043 case VIDIOC_STREAMOFF32
: cmd
= VIDIOC_STREAMOFF
; break;
1044 case VIDIOC_G_INPUT32
: cmd
= VIDIOC_G_INPUT
; break;
1045 case VIDIOC_S_INPUT32
: cmd
= VIDIOC_S_INPUT
; break;
1046 case VIDIOC_G_OUTPUT32
: cmd
= VIDIOC_G_OUTPUT
; break;
1047 case VIDIOC_S_OUTPUT32
: cmd
= VIDIOC_S_OUTPUT
; break;
1048 case VIDIOC_CREATE_BUFS32
: cmd
= VIDIOC_CREATE_BUFS
; break;
1049 case VIDIOC_PREPARE_BUF32
: cmd
= VIDIOC_PREPARE_BUF
; break;
1050 case VIDIOC_G_EDID32
: cmd
= VIDIOC_G_EDID
; break;
1051 case VIDIOC_S_EDID32
: cmd
= VIDIOC_S_EDID
; break;
1055 case VIDIOC_OVERLAY
:
1056 case VIDIOC_STREAMON
:
1057 case VIDIOC_STREAMOFF
:
1058 case VIDIOC_S_INPUT
:
1059 case VIDIOC_S_OUTPUT
:
1060 err
= alloc_userspace(sizeof(unsigned int), 0, &up_native
);
1061 if (!err
&& assign_in_user((unsigned int __user
*)up_native
,
1062 (compat_uint_t __user
*)up
))
1067 case VIDIOC_G_INPUT
:
1068 case VIDIOC_G_OUTPUT
:
1069 err
= alloc_userspace(sizeof(unsigned int), 0, &up_native
);
1075 err
= alloc_userspace(sizeof(struct v4l2_edid
), 0, &up_native
);
1077 err
= get_v4l2_edid32(up_native
, up
);
1083 case VIDIOC_TRY_FMT
:
1084 err
= bufsize_v4l2_format(up
, &aux_space
);
1086 err
= alloc_userspace(sizeof(struct v4l2_format
),
1087 aux_space
, &up_native
);
1089 aux_buf
= up_native
+ sizeof(struct v4l2_format
);
1090 err
= get_v4l2_format32(up_native
, up
,
1091 aux_buf
, aux_space
);
1096 case VIDIOC_CREATE_BUFS
:
1097 err
= bufsize_v4l2_create(up
, &aux_space
);
1099 err
= alloc_userspace(sizeof(struct v4l2_create_buffers
),
1100 aux_space
, &up_native
);
1102 aux_buf
= up_native
+ sizeof(struct v4l2_create_buffers
);
1103 err
= get_v4l2_create32(up_native
, up
,
1104 aux_buf
, aux_space
);
1109 case VIDIOC_PREPARE_BUF
:
1110 case VIDIOC_QUERYBUF
:
1113 err
= bufsize_v4l2_buffer(up
, &aux_space
);
1115 err
= alloc_userspace(sizeof(struct v4l2_buffer
),
1116 aux_space
, &up_native
);
1118 aux_buf
= up_native
+ sizeof(struct v4l2_buffer
);
1119 err
= get_v4l2_buffer32(up_native
, up
,
1120 aux_buf
, aux_space
);
1126 err
= alloc_userspace(sizeof(struct v4l2_framebuffer
), 0,
1129 err
= get_v4l2_framebuffer32(up_native
, up
);
1134 err
= alloc_userspace(sizeof(struct v4l2_framebuffer
), 0,
1139 case VIDIOC_ENUMSTD
:
1140 err
= alloc_userspace(sizeof(struct v4l2_standard
), 0,
1143 err
= get_v4l2_standard32(up_native
, up
);
1147 case VIDIOC_ENUMINPUT
:
1148 err
= alloc_userspace(sizeof(struct v4l2_input
), 0, &up_native
);
1150 err
= get_v4l2_input32(up_native
, up
);
1154 case VIDIOC_G_EXT_CTRLS
:
1155 case VIDIOC_S_EXT_CTRLS
:
1156 case VIDIOC_TRY_EXT_CTRLS
:
1157 err
= bufsize_v4l2_ext_controls(up
, &aux_space
);
1159 err
= alloc_userspace(sizeof(struct v4l2_ext_controls
),
1160 aux_space
, &up_native
);
1162 aux_buf
= up_native
+ sizeof(struct v4l2_ext_controls
);
1163 err
= get_v4l2_ext_controls32(file
, up_native
, up
,
1164 aux_buf
, aux_space
);
1168 case VIDIOC_DQEVENT
:
1169 err
= alloc_userspace(sizeof(struct v4l2_event
), 0, &up_native
);
1177 err
= native_ioctl(file
, cmd
, (unsigned long)up
);
1179 err
= native_ioctl(file
, cmd
, (unsigned long)up_native
);
1185 * Special case: even after an error we need to put the
1186 * results back for these ioctls since the error_idx will
1187 * contain information on which control failed.
1190 case VIDIOC_G_EXT_CTRLS
:
1191 case VIDIOC_S_EXT_CTRLS
:
1192 case VIDIOC_TRY_EXT_CTRLS
:
1193 if (put_v4l2_ext_controls32(file
, up_native
, up
))
1197 if (put_v4l2_edid32(up_native
, up
))
1205 case VIDIOC_S_INPUT
:
1206 case VIDIOC_S_OUTPUT
:
1207 case VIDIOC_G_INPUT
:
1208 case VIDIOC_G_OUTPUT
:
1209 if (assign_in_user((compat_uint_t __user
*)up
,
1210 ((unsigned int __user
*)up_native
)))
1215 err
= put_v4l2_framebuffer32(up_native
, up
);
1218 case VIDIOC_DQEVENT
:
1219 err
= put_v4l2_event32(up_native
, up
);
1223 err
= put_v4l2_edid32(up_native
, up
);
1228 case VIDIOC_TRY_FMT
:
1229 err
= put_v4l2_format32(up_native
, up
);
1232 case VIDIOC_CREATE_BUFS
:
1233 err
= put_v4l2_create32(up_native
, up
);
1236 case VIDIOC_PREPARE_BUF
:
1237 case VIDIOC_QUERYBUF
:
1240 err
= put_v4l2_buffer32(up_native
, up
);
1243 case VIDIOC_ENUMSTD
:
1244 err
= put_v4l2_standard32(up_native
, up
);
1247 case VIDIOC_ENUMINPUT
:
1248 err
= put_v4l2_input32(up_native
, up
);
1254 long v4l2_compat_ioctl32(struct file
*file
, unsigned int cmd
, unsigned long arg
)
1256 struct video_device
*vdev
= video_devdata(file
);
1257 long ret
= -ENOIOCTLCMD
;
1259 if (!file
->f_op
->unlocked_ioctl
)
1262 if (_IOC_TYPE(cmd
) == 'V' && _IOC_NR(cmd
) < BASE_VIDIOC_PRIVATE
)
1263 ret
= do_video_ioctl(file
, cmd
, arg
);
1264 else if (vdev
->fops
->compat_ioctl32
)
1265 ret
= vdev
->fops
->compat_ioctl32(file
, cmd
, arg
);
1267 if (ret
== -ENOIOCTLCMD
)
1268 pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
1269 _IOC_TYPE(cmd
), _IOC_DIR(cmd
), _IOC_NR(cmd
), cmd
);
1272 EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32
);