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
;
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(kclips
, &kp
->clips
))
121 if (get_user(p
, &up
->clips
))
123 uclips
= compat_ptr(p
);
124 while (clipcount
--) {
125 if (copy_in_user(&uclips
->c
, &kclips
->c
, sizeof(uclips
->c
)))
133 struct v4l2_format32
{
134 __u32 type
; /* enum v4l2_buf_type */
136 struct v4l2_pix_format pix
;
137 struct v4l2_pix_format_mplane pix_mp
;
138 struct v4l2_window32 win
;
139 struct v4l2_vbi_format vbi
;
140 struct v4l2_sliced_vbi_format sliced
;
141 struct v4l2_sdr_format sdr
;
142 struct v4l2_meta_format meta
;
143 __u8 raw_data
[200]; /* user-defined */
148 * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument
149 * @index: on return, index of the first created buffer
150 * @count: entry: number of requested buffers,
151 * return: number of created buffers
152 * @memory: buffer memory type
153 * @format: frame format, for which buffers are requested
154 * @reserved: future extensions
156 struct v4l2_create_buffers32
{
159 __u32 memory
; /* enum v4l2_memory */
160 struct v4l2_format32 format
;
164 static int __bufsize_v4l2_format(struct v4l2_format32 __user
*up
, u32
*size
)
168 if (get_user(type
, &up
->type
))
172 case V4L2_BUF_TYPE_VIDEO_OVERLAY
:
173 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
: {
176 if (get_user(clipcount
, &up
->fmt
.win
.clipcount
))
178 if (clipcount
> 2048)
180 *size
= clipcount
* sizeof(struct v4l2_clip
);
189 static int bufsize_v4l2_format(struct v4l2_format32 __user
*up
, u32
*size
)
191 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)))
193 return __bufsize_v4l2_format(up
, size
);
196 static int __get_v4l2_format32(struct v4l2_format __user
*kp
,
197 struct v4l2_format32 __user
*up
,
198 void __user
*aux_buf
, u32 aux_space
)
202 if (get_user(type
, &up
->type
) || put_user(type
, &kp
->type
))
206 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
207 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
208 return copy_in_user(&kp
->fmt
.pix
, &up
->fmt
.pix
,
209 sizeof(kp
->fmt
.pix
)) ? -EFAULT
: 0;
210 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
211 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
212 return copy_in_user(&kp
->fmt
.pix_mp
, &up
->fmt
.pix_mp
,
213 sizeof(kp
->fmt
.pix_mp
)) ? -EFAULT
: 0;
214 case V4L2_BUF_TYPE_VIDEO_OVERLAY
:
215 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
:
216 return get_v4l2_window32(&kp
->fmt
.win
, &up
->fmt
.win
,
218 case V4L2_BUF_TYPE_VBI_CAPTURE
:
219 case V4L2_BUF_TYPE_VBI_OUTPUT
:
220 return copy_in_user(&kp
->fmt
.vbi
, &up
->fmt
.vbi
,
221 sizeof(kp
->fmt
.vbi
)) ? -EFAULT
: 0;
222 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE
:
223 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT
:
224 return copy_in_user(&kp
->fmt
.sliced
, &up
->fmt
.sliced
,
225 sizeof(kp
->fmt
.sliced
)) ? -EFAULT
: 0;
226 case V4L2_BUF_TYPE_SDR_CAPTURE
:
227 case V4L2_BUF_TYPE_SDR_OUTPUT
:
228 return copy_in_user(&kp
->fmt
.sdr
, &up
->fmt
.sdr
,
229 sizeof(kp
->fmt
.sdr
)) ? -EFAULT
: 0;
230 case V4L2_BUF_TYPE_META_CAPTURE
:
231 return copy_in_user(&kp
->fmt
.meta
, &up
->fmt
.meta
,
232 sizeof(kp
->fmt
.meta
)) ? -EFAULT
: 0;
238 static int get_v4l2_format32(struct v4l2_format __user
*kp
,
239 struct v4l2_format32 __user
*up
,
240 void __user
*aux_buf
, u32 aux_space
)
242 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)))
244 return __get_v4l2_format32(kp
, up
, aux_buf
, aux_space
);
247 static int bufsize_v4l2_create(struct v4l2_create_buffers32 __user
*up
,
250 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)))
252 return __bufsize_v4l2_format(&up
->format
, size
);
255 static int get_v4l2_create32(struct v4l2_create_buffers __user
*kp
,
256 struct v4l2_create_buffers32 __user
*up
,
257 void __user
*aux_buf
, u32 aux_space
)
259 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
261 offsetof(struct v4l2_create_buffers32
, format
)))
263 return __get_v4l2_format32(&kp
->format
, &up
->format
,
267 static int __put_v4l2_format32(struct v4l2_format __user
*kp
,
268 struct v4l2_format32 __user
*up
)
272 if (get_user(type
, &kp
->type
))
276 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
277 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
278 return copy_in_user(&up
->fmt
.pix
, &kp
->fmt
.pix
,
279 sizeof(kp
->fmt
.pix
)) ? -EFAULT
: 0;
280 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
281 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
282 return copy_in_user(&up
->fmt
.pix_mp
, &kp
->fmt
.pix_mp
,
283 sizeof(kp
->fmt
.pix_mp
)) ? -EFAULT
: 0;
284 case V4L2_BUF_TYPE_VIDEO_OVERLAY
:
285 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
:
286 return put_v4l2_window32(&kp
->fmt
.win
, &up
->fmt
.win
);
287 case V4L2_BUF_TYPE_VBI_CAPTURE
:
288 case V4L2_BUF_TYPE_VBI_OUTPUT
:
289 return copy_in_user(&up
->fmt
.vbi
, &kp
->fmt
.vbi
,
290 sizeof(kp
->fmt
.vbi
)) ? -EFAULT
: 0;
291 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE
:
292 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT
:
293 return copy_in_user(&up
->fmt
.sliced
, &kp
->fmt
.sliced
,
294 sizeof(kp
->fmt
.sliced
)) ? -EFAULT
: 0;
295 case V4L2_BUF_TYPE_SDR_CAPTURE
:
296 case V4L2_BUF_TYPE_SDR_OUTPUT
:
297 return copy_in_user(&up
->fmt
.sdr
, &kp
->fmt
.sdr
,
298 sizeof(kp
->fmt
.sdr
)) ? -EFAULT
: 0;
299 case V4L2_BUF_TYPE_META_CAPTURE
:
300 return copy_in_user(&up
->fmt
.meta
, &kp
->fmt
.meta
,
301 sizeof(kp
->fmt
.meta
)) ? -EFAULT
: 0;
307 static int put_v4l2_format32(struct v4l2_format __user
*kp
,
308 struct v4l2_format32 __user
*up
)
310 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)))
312 return __put_v4l2_format32(kp
, up
);
315 static int put_v4l2_create32(struct v4l2_create_buffers __user
*kp
,
316 struct v4l2_create_buffers32 __user
*up
)
318 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
320 offsetof(struct v4l2_create_buffers32
, format
)) ||
321 copy_in_user(up
->reserved
, kp
->reserved
, sizeof(kp
->reserved
)))
323 return __put_v4l2_format32(&kp
->format
, &up
->format
);
326 struct v4l2_standard32
{
330 struct v4l2_fract frameperiod
; /* Frames, not fields */
335 static int get_v4l2_standard32(struct v4l2_standard __user
*kp
,
336 struct v4l2_standard32 __user
*up
)
338 /* other fields are not set by the user, nor used by the driver */
339 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
340 assign_in_user(&kp
->index
, &up
->index
))
345 static int put_v4l2_standard32(struct v4l2_standard __user
*kp
,
346 struct v4l2_standard32 __user
*up
)
348 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
349 assign_in_user(&up
->index
, &kp
->index
) ||
350 assign_in_user(&up
->id
, &kp
->id
) ||
351 copy_in_user(up
->name
, kp
->name
, sizeof(up
->name
)) ||
352 copy_in_user(&up
->frameperiod
, &kp
->frameperiod
,
353 sizeof(up
->frameperiod
)) ||
354 assign_in_user(&up
->framelines
, &kp
->framelines
) ||
355 copy_in_user(up
->reserved
, kp
->reserved
, sizeof(up
->reserved
)))
360 struct v4l2_plane32
{
365 compat_long_t userptr
;
372 struct v4l2_buffer32
{
374 __u32 type
; /* enum v4l2_buf_type */
377 __u32 field
; /* enum v4l2_field */
378 struct compat_timeval timestamp
;
379 struct v4l2_timecode timecode
;
382 /* memory location */
383 __u32 memory
; /* enum v4l2_memory */
386 compat_long_t userptr
;
387 compat_caddr_t planes
;
395 static int get_v4l2_plane32(struct v4l2_plane __user
*up
,
396 struct v4l2_plane32 __user
*up32
,
397 enum v4l2_memory memory
)
401 if (copy_in_user(up
, up32
, 2 * sizeof(__u32
)) ||
402 copy_in_user(&up
->data_offset
, &up32
->data_offset
,
403 sizeof(up
->data_offset
)))
407 case V4L2_MEMORY_MMAP
:
408 case V4L2_MEMORY_OVERLAY
:
409 if (copy_in_user(&up
->m
.mem_offset
, &up32
->m
.mem_offset
,
410 sizeof(up32
->m
.mem_offset
)))
413 case V4L2_MEMORY_USERPTR
:
414 if (get_user(p
, &up32
->m
.userptr
) ||
415 put_user((unsigned long)compat_ptr(p
), &up
->m
.userptr
))
418 case V4L2_MEMORY_DMABUF
:
419 if (copy_in_user(&up
->m
.fd
, &up32
->m
.fd
, sizeof(up32
->m
.fd
)))
427 static int put_v4l2_plane32(struct v4l2_plane __user
*up
,
428 struct v4l2_plane32 __user
*up32
,
429 enum v4l2_memory memory
)
433 if (copy_in_user(up32
, up
, 2 * sizeof(__u32
)) ||
434 copy_in_user(&up32
->data_offset
, &up
->data_offset
,
435 sizeof(up
->data_offset
)))
439 case V4L2_MEMORY_MMAP
:
440 case V4L2_MEMORY_OVERLAY
:
441 if (copy_in_user(&up32
->m
.mem_offset
, &up
->m
.mem_offset
,
442 sizeof(up
->m
.mem_offset
)))
445 case V4L2_MEMORY_USERPTR
:
446 if (get_user(p
, &up
->m
.userptr
) ||
447 put_user((compat_ulong_t
)ptr_to_compat((__force
void *)p
),
451 case V4L2_MEMORY_DMABUF
:
452 if (copy_in_user(&up32
->m
.fd
, &up
->m
.fd
, sizeof(up
->m
.fd
)))
460 static int bufsize_v4l2_buffer(struct v4l2_buffer32 __user
*up
, u32
*size
)
465 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
466 get_user(type
, &up
->type
) ||
467 get_user(length
, &up
->length
))
470 if (V4L2_TYPE_IS_MULTIPLANAR(type
)) {
471 if (length
> VIDEO_MAX_PLANES
)
475 * We don't really care if userspace decides to kill itself
476 * by passing a very big length value
478 *size
= length
* sizeof(struct v4l2_plane
);
485 static int get_v4l2_buffer32(struct v4l2_buffer __user
*kp
,
486 struct v4l2_buffer32 __user
*up
,
487 void __user
*aux_buf
, u32 aux_space
)
491 enum v4l2_memory memory
;
492 struct v4l2_plane32 __user
*uplane32
;
493 struct v4l2_plane __user
*uplane
;
497 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
498 assign_in_user(&kp
->index
, &up
->index
) ||
499 get_user(type
, &up
->type
) ||
500 put_user(type
, &kp
->type
) ||
501 assign_in_user(&kp
->flags
, &up
->flags
) ||
502 get_user(memory
, &up
->memory
) ||
503 put_user(memory
, &kp
->memory
) ||
504 get_user(length
, &up
->length
) ||
505 put_user(length
, &kp
->length
))
508 if (V4L2_TYPE_IS_OUTPUT(type
))
509 if (assign_in_user(&kp
->bytesused
, &up
->bytesused
) ||
510 assign_in_user(&kp
->field
, &up
->field
) ||
511 assign_in_user(&kp
->timestamp
.tv_sec
,
512 &up
->timestamp
.tv_sec
) ||
513 assign_in_user(&kp
->timestamp
.tv_usec
,
514 &up
->timestamp
.tv_usec
))
517 if (V4L2_TYPE_IS_MULTIPLANAR(type
)) {
518 u32 num_planes
= length
;
520 if (num_planes
== 0) {
522 * num_planes == 0 is legal, e.g. when userspace doesn't
523 * need planes array on DQBUF
525 return put_user(NULL
, &kp
->m
.planes
);
527 if (num_planes
> VIDEO_MAX_PLANES
)
530 if (get_user(p
, &up
->m
.planes
))
533 uplane32
= compat_ptr(p
);
534 if (!access_ok(VERIFY_READ
, uplane32
,
535 num_planes
* sizeof(*uplane32
)))
539 * We don't really care if userspace decides to kill itself
540 * by passing a very big num_planes value
542 if (aux_space
< num_planes
* sizeof(*uplane
))
546 if (put_user((__force
struct v4l2_plane
*)uplane
,
550 while (num_planes
--) {
551 ret
= get_v4l2_plane32(uplane
, uplane32
, memory
);
559 case V4L2_MEMORY_MMAP
:
560 case V4L2_MEMORY_OVERLAY
:
561 if (assign_in_user(&kp
->m
.offset
, &up
->m
.offset
))
564 case V4L2_MEMORY_USERPTR
: {
565 compat_ulong_t userptr
;
567 if (get_user(userptr
, &up
->m
.userptr
) ||
568 put_user((unsigned long)compat_ptr(userptr
),
573 case V4L2_MEMORY_DMABUF
:
574 if (assign_in_user(&kp
->m
.fd
, &up
->m
.fd
))
583 static int put_v4l2_buffer32(struct v4l2_buffer __user
*kp
,
584 struct v4l2_buffer32 __user
*up
)
588 enum v4l2_memory memory
;
589 struct v4l2_plane32 __user
*uplane32
;
590 struct v4l2_plane __user
*uplane
;
594 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
595 assign_in_user(&up
->index
, &kp
->index
) ||
596 get_user(type
, &kp
->type
) ||
597 put_user(type
, &up
->type
) ||
598 assign_in_user(&up
->flags
, &kp
->flags
) ||
599 get_user(memory
, &kp
->memory
) ||
600 put_user(memory
, &up
->memory
))
603 if (assign_in_user(&up
->bytesused
, &kp
->bytesused
) ||
604 assign_in_user(&up
->field
, &kp
->field
) ||
605 assign_in_user(&up
->timestamp
.tv_sec
, &kp
->timestamp
.tv_sec
) ||
606 assign_in_user(&up
->timestamp
.tv_usec
, &kp
->timestamp
.tv_usec
) ||
607 copy_in_user(&up
->timecode
, &kp
->timecode
, sizeof(kp
->timecode
)) ||
608 assign_in_user(&up
->sequence
, &kp
->sequence
) ||
609 assign_in_user(&up
->reserved2
, &kp
->reserved2
) ||
610 assign_in_user(&up
->reserved
, &kp
->reserved
) ||
611 get_user(length
, &kp
->length
) ||
612 put_user(length
, &up
->length
))
615 if (V4L2_TYPE_IS_MULTIPLANAR(type
)) {
616 u32 num_planes
= length
;
621 if (get_user(uplane
, ((__force
struct v4l2_plane __user
**)&kp
->m
.planes
)))
623 if (get_user(p
, &up
->m
.planes
))
625 uplane32
= compat_ptr(p
);
627 while (num_planes
--) {
628 ret
= put_v4l2_plane32(uplane
, uplane32
, memory
);
636 case V4L2_MEMORY_MMAP
:
637 case V4L2_MEMORY_OVERLAY
:
638 if (assign_in_user(&up
->m
.offset
, &kp
->m
.offset
))
641 case V4L2_MEMORY_USERPTR
:
642 if (assign_in_user(&up
->m
.userptr
, &kp
->m
.userptr
))
645 case V4L2_MEMORY_DMABUF
:
646 if (assign_in_user(&up
->m
.fd
, &kp
->m
.fd
))
655 struct v4l2_framebuffer32
{
671 static int get_v4l2_framebuffer32(struct v4l2_framebuffer __user
*kp
,
672 struct v4l2_framebuffer32 __user
*up
)
676 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
677 get_user(tmp
, &up
->base
) ||
678 put_user((__force
void *)compat_ptr(tmp
), &kp
->base
) ||
679 assign_in_user(&kp
->capability
, &up
->capability
) ||
680 assign_in_user(&kp
->flags
, &up
->flags
) ||
681 copy_in_user(&kp
->fmt
, &up
->fmt
, sizeof(kp
->fmt
)))
686 static int put_v4l2_framebuffer32(struct v4l2_framebuffer __user
*kp
,
687 struct v4l2_framebuffer32 __user
*up
)
691 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
692 get_user(base
, &kp
->base
) ||
693 put_user(ptr_to_compat(base
), &up
->base
) ||
694 assign_in_user(&up
->capability
, &kp
->capability
) ||
695 assign_in_user(&up
->flags
, &kp
->flags
) ||
696 copy_in_user(&up
->fmt
, &kp
->fmt
, sizeof(kp
->fmt
)))
701 struct v4l2_input32
{
702 __u32 index
; /* Which input */
703 __u8 name
[32]; /* Label */
704 __u32 type
; /* Type of input */
705 __u32 audioset
; /* Associated audios (bitfield) */
706 __u32 tuner
; /* Associated tuner */
714 * The 64-bit v4l2_input struct has extra padding at the end of the struct.
715 * Otherwise it is identical to the 32-bit version.
717 static inline int get_v4l2_input32(struct v4l2_input __user
*kp
,
718 struct v4l2_input32 __user
*up
)
720 if (copy_in_user(kp
, up
, sizeof(*up
)))
725 static inline int put_v4l2_input32(struct v4l2_input __user
*kp
,
726 struct v4l2_input32 __user
*up
)
728 if (copy_in_user(up
, kp
, sizeof(*up
)))
733 struct v4l2_ext_controls32
{
738 compat_caddr_t controls
; /* actually struct v4l2_ext_control32 * */
741 struct v4l2_ext_control32
{
748 compat_caddr_t string
; /* actually char * */
750 } __attribute__ ((packed
));
752 /* Return true if this control is a pointer type. */
753 static inline bool ctrl_is_pointer(struct file
*file
, u32 id
)
755 struct video_device
*vdev
= video_devdata(file
);
756 struct v4l2_fh
*fh
= NULL
;
757 struct v4l2_ctrl_handler
*hdl
= NULL
;
758 struct v4l2_query_ext_ctrl qec
= { id
};
759 const struct v4l2_ioctl_ops
*ops
= vdev
->ioctl_ops
;
761 if (test_bit(V4L2_FL_USES_V4L2_FH
, &vdev
->flags
))
762 fh
= file
->private_data
;
764 if (fh
&& fh
->ctrl_handler
)
765 hdl
= fh
->ctrl_handler
;
766 else if (vdev
->ctrl_handler
)
767 hdl
= vdev
->ctrl_handler
;
770 struct v4l2_ctrl
*ctrl
= v4l2_ctrl_find(hdl
, id
);
772 return ctrl
&& ctrl
->is_ptr
;
775 if (!ops
|| !ops
->vidioc_query_ext_ctrl
)
778 return !ops
->vidioc_query_ext_ctrl(file
, fh
, &qec
) &&
779 (qec
.flags
& V4L2_CTRL_FLAG_HAS_PAYLOAD
);
782 static int bufsize_v4l2_ext_controls(struct v4l2_ext_controls32 __user
*up
,
787 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
788 get_user(count
, &up
->count
))
790 if (count
> V4L2_CID_MAX_CTRLS
)
792 *size
= count
* sizeof(struct v4l2_ext_control
);
796 static int get_v4l2_ext_controls32(struct file
*file
,
797 struct v4l2_ext_controls __user
*kp
,
798 struct v4l2_ext_controls32 __user
*up
,
799 void __user
*aux_buf
, u32 aux_space
)
801 struct v4l2_ext_control32 __user
*ucontrols
;
802 struct v4l2_ext_control __user
*kcontrols
;
807 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
808 assign_in_user(&kp
->which
, &up
->which
) ||
809 get_user(count
, &up
->count
) ||
810 put_user(count
, &kp
->count
) ||
811 assign_in_user(&kp
->error_idx
, &up
->error_idx
) ||
812 copy_in_user(kp
->reserved
, up
->reserved
, sizeof(kp
->reserved
)))
816 return put_user(NULL
, &kp
->controls
);
817 if (count
> V4L2_CID_MAX_CTRLS
)
819 if (get_user(p
, &up
->controls
))
821 ucontrols
= compat_ptr(p
);
822 if (!access_ok(VERIFY_READ
, ucontrols
, count
* sizeof(*ucontrols
)))
824 if (aux_space
< count
* sizeof(*kcontrols
))
827 if (put_user((__force
struct v4l2_ext_control
*)kcontrols
,
831 for (n
= 0; n
< count
; n
++) {
834 if (copy_in_user(kcontrols
, ucontrols
, sizeof(*ucontrols
)))
837 if (get_user(id
, &kcontrols
->id
))
840 if (ctrl_is_pointer(file
, id
)) {
843 if (get_user(p
, &ucontrols
->string
))
846 if (put_user(s
, &kcontrols
->string
))
855 static int put_v4l2_ext_controls32(struct file
*file
,
856 struct v4l2_ext_controls __user
*kp
,
857 struct v4l2_ext_controls32 __user
*up
)
859 struct v4l2_ext_control32 __user
*ucontrols
;
860 struct v4l2_ext_control __user
*kcontrols
;
865 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
866 assign_in_user(&up
->which
, &kp
->which
) ||
867 get_user(count
, &kp
->count
) ||
868 put_user(count
, &up
->count
) ||
869 assign_in_user(&up
->error_idx
, &kp
->error_idx
) ||
870 copy_in_user(up
->reserved
, kp
->reserved
, sizeof(up
->reserved
)) ||
871 get_user(kcontrols
, &kp
->controls
))
874 if (!count
|| count
> (U32_MAX
/sizeof(*ucontrols
)))
876 if (get_user(p
, &up
->controls
))
878 ucontrols
= compat_ptr(p
);
879 if (!access_ok(VERIFY_WRITE
, ucontrols
, count
* sizeof(*ucontrols
)))
882 for (n
= 0; n
< count
; n
++) {
883 unsigned int size
= sizeof(*ucontrols
);
886 if (get_user(id
, &kcontrols
->id
) ||
887 put_user(id
, &ucontrols
->id
) ||
888 assign_in_user(&ucontrols
->size
, &kcontrols
->size
) ||
889 copy_in_user(&ucontrols
->reserved2
, &kcontrols
->reserved2
,
890 sizeof(ucontrols
->reserved2
)))
894 * Do not modify the pointer when copying a pointer control.
895 * The contents of the pointer was changed, not the pointer
898 if (ctrl_is_pointer(file
, id
))
899 size
-= sizeof(ucontrols
->value64
);
901 if (copy_in_user(ucontrols
, kcontrols
, size
))
910 struct v4l2_event32
{
918 struct compat_timespec timestamp
;
923 static int put_v4l2_event32(struct v4l2_event __user
*kp
,
924 struct v4l2_event32 __user
*up
)
926 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
927 assign_in_user(&up
->type
, &kp
->type
) ||
928 copy_in_user(&up
->u
, &kp
->u
, sizeof(kp
->u
)) ||
929 assign_in_user(&up
->pending
, &kp
->pending
) ||
930 assign_in_user(&up
->sequence
, &kp
->sequence
) ||
931 assign_in_user(&up
->timestamp
.tv_sec
, &kp
->timestamp
.tv_sec
) ||
932 assign_in_user(&up
->timestamp
.tv_nsec
, &kp
->timestamp
.tv_nsec
) ||
933 assign_in_user(&up
->id
, &kp
->id
) ||
934 copy_in_user(up
->reserved
, kp
->reserved
, sizeof(up
->reserved
)))
947 static int get_v4l2_edid32(struct v4l2_edid __user
*kp
,
948 struct v4l2_edid32 __user
*up
)
952 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
953 assign_in_user(&kp
->pad
, &up
->pad
) ||
954 assign_in_user(&kp
->start_block
, &up
->start_block
) ||
955 assign_in_user(&kp
->blocks
, &up
->blocks
) ||
956 get_user(tmp
, &up
->edid
) ||
957 put_user(compat_ptr(tmp
), &kp
->edid
) ||
958 copy_in_user(kp
->reserved
, up
->reserved
, sizeof(kp
->reserved
)))
963 static int put_v4l2_edid32(struct v4l2_edid __user
*kp
,
964 struct v4l2_edid32 __user
*up
)
968 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
969 assign_in_user(&up
->pad
, &kp
->pad
) ||
970 assign_in_user(&up
->start_block
, &kp
->start_block
) ||
971 assign_in_user(&up
->blocks
, &kp
->blocks
) ||
972 get_user(edid
, &kp
->edid
) ||
973 put_user(ptr_to_compat(edid
), &up
->edid
) ||
974 copy_in_user(up
->reserved
, kp
->reserved
, sizeof(up
->reserved
)))
980 #define VIDIOC_G_FMT32 _IOWR('V', 4, struct v4l2_format32)
981 #define VIDIOC_S_FMT32 _IOWR('V', 5, struct v4l2_format32)
982 #define VIDIOC_QUERYBUF32 _IOWR('V', 9, struct v4l2_buffer32)
983 #define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32)
984 #define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32)
985 #define VIDIOC_QBUF32 _IOWR('V', 15, struct v4l2_buffer32)
986 #define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32)
987 #define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32)
988 #define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32)
989 #define VIDIOC_G_EDID32 _IOWR('V', 40, struct v4l2_edid32)
990 #define VIDIOC_S_EDID32 _IOWR('V', 41, struct v4l2_edid32)
991 #define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32)
992 #define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32)
993 #define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32)
994 #define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32)
995 #define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32)
996 #define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32)
997 #define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32)
999 #define VIDIOC_OVERLAY32 _IOW ('V', 14, s32)
1000 #define VIDIOC_STREAMON32 _IOW ('V', 18, s32)
1001 #define VIDIOC_STREAMOFF32 _IOW ('V', 19, s32)
1002 #define VIDIOC_G_INPUT32 _IOR ('V', 38, s32)
1003 #define VIDIOC_S_INPUT32 _IOWR('V', 39, s32)
1004 #define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32)
1005 #define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32)
1007 static int alloc_userspace(unsigned int size
, u32 aux_space
,
1008 void __user
**up_native
)
1010 *up_native
= compat_alloc_user_space(size
+ aux_space
);
1013 if (clear_user(*up_native
, size
))
1018 static long do_video_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
1020 void __user
*up
= compat_ptr(arg
);
1021 void __user
*up_native
= NULL
;
1022 void __user
*aux_buf
;
1024 int compatible_arg
= 1;
1027 /* First, convert the command. */
1029 case VIDIOC_G_FMT32
: cmd
= VIDIOC_G_FMT
; break;
1030 case VIDIOC_S_FMT32
: cmd
= VIDIOC_S_FMT
; break;
1031 case VIDIOC_QUERYBUF32
: cmd
= VIDIOC_QUERYBUF
; break;
1032 case VIDIOC_G_FBUF32
: cmd
= VIDIOC_G_FBUF
; break;
1033 case VIDIOC_S_FBUF32
: cmd
= VIDIOC_S_FBUF
; break;
1034 case VIDIOC_QBUF32
: cmd
= VIDIOC_QBUF
; break;
1035 case VIDIOC_DQBUF32
: cmd
= VIDIOC_DQBUF
; break;
1036 case VIDIOC_ENUMSTD32
: cmd
= VIDIOC_ENUMSTD
; break;
1037 case VIDIOC_ENUMINPUT32
: cmd
= VIDIOC_ENUMINPUT
; break;
1038 case VIDIOC_TRY_FMT32
: cmd
= VIDIOC_TRY_FMT
; break;
1039 case VIDIOC_G_EXT_CTRLS32
: cmd
= VIDIOC_G_EXT_CTRLS
; break;
1040 case VIDIOC_S_EXT_CTRLS32
: cmd
= VIDIOC_S_EXT_CTRLS
; break;
1041 case VIDIOC_TRY_EXT_CTRLS32
: cmd
= VIDIOC_TRY_EXT_CTRLS
; break;
1042 case VIDIOC_DQEVENT32
: cmd
= VIDIOC_DQEVENT
; break;
1043 case VIDIOC_OVERLAY32
: cmd
= VIDIOC_OVERLAY
; break;
1044 case VIDIOC_STREAMON32
: cmd
= VIDIOC_STREAMON
; break;
1045 case VIDIOC_STREAMOFF32
: cmd
= VIDIOC_STREAMOFF
; break;
1046 case VIDIOC_G_INPUT32
: cmd
= VIDIOC_G_INPUT
; break;
1047 case VIDIOC_S_INPUT32
: cmd
= VIDIOC_S_INPUT
; break;
1048 case VIDIOC_G_OUTPUT32
: cmd
= VIDIOC_G_OUTPUT
; break;
1049 case VIDIOC_S_OUTPUT32
: cmd
= VIDIOC_S_OUTPUT
; break;
1050 case VIDIOC_CREATE_BUFS32
: cmd
= VIDIOC_CREATE_BUFS
; break;
1051 case VIDIOC_PREPARE_BUF32
: cmd
= VIDIOC_PREPARE_BUF
; break;
1052 case VIDIOC_G_EDID32
: cmd
= VIDIOC_G_EDID
; break;
1053 case VIDIOC_S_EDID32
: cmd
= VIDIOC_S_EDID
; break;
1057 case VIDIOC_OVERLAY
:
1058 case VIDIOC_STREAMON
:
1059 case VIDIOC_STREAMOFF
:
1060 case VIDIOC_S_INPUT
:
1061 case VIDIOC_S_OUTPUT
:
1062 err
= alloc_userspace(sizeof(unsigned int), 0, &up_native
);
1063 if (!err
&& assign_in_user((unsigned int __user
*)up_native
,
1064 (compat_uint_t __user
*)up
))
1069 case VIDIOC_G_INPUT
:
1070 case VIDIOC_G_OUTPUT
:
1071 err
= alloc_userspace(sizeof(unsigned int), 0, &up_native
);
1077 err
= alloc_userspace(sizeof(struct v4l2_edid
), 0, &up_native
);
1079 err
= get_v4l2_edid32(up_native
, up
);
1085 case VIDIOC_TRY_FMT
:
1086 err
= bufsize_v4l2_format(up
, &aux_space
);
1088 err
= alloc_userspace(sizeof(struct v4l2_format
),
1089 aux_space
, &up_native
);
1091 aux_buf
= up_native
+ sizeof(struct v4l2_format
);
1092 err
= get_v4l2_format32(up_native
, up
,
1093 aux_buf
, aux_space
);
1098 case VIDIOC_CREATE_BUFS
:
1099 err
= bufsize_v4l2_create(up
, &aux_space
);
1101 err
= alloc_userspace(sizeof(struct v4l2_create_buffers
),
1102 aux_space
, &up_native
);
1104 aux_buf
= up_native
+ sizeof(struct v4l2_create_buffers
);
1105 err
= get_v4l2_create32(up_native
, up
,
1106 aux_buf
, aux_space
);
1111 case VIDIOC_PREPARE_BUF
:
1112 case VIDIOC_QUERYBUF
:
1115 err
= bufsize_v4l2_buffer(up
, &aux_space
);
1117 err
= alloc_userspace(sizeof(struct v4l2_buffer
),
1118 aux_space
, &up_native
);
1120 aux_buf
= up_native
+ sizeof(struct v4l2_buffer
);
1121 err
= get_v4l2_buffer32(up_native
, up
,
1122 aux_buf
, aux_space
);
1128 err
= alloc_userspace(sizeof(struct v4l2_framebuffer
), 0,
1131 err
= get_v4l2_framebuffer32(up_native
, up
);
1136 err
= alloc_userspace(sizeof(struct v4l2_framebuffer
), 0,
1141 case VIDIOC_ENUMSTD
:
1142 err
= alloc_userspace(sizeof(struct v4l2_standard
), 0,
1145 err
= get_v4l2_standard32(up_native
, up
);
1149 case VIDIOC_ENUMINPUT
:
1150 err
= alloc_userspace(sizeof(struct v4l2_input
), 0, &up_native
);
1152 err
= get_v4l2_input32(up_native
, up
);
1156 case VIDIOC_G_EXT_CTRLS
:
1157 case VIDIOC_S_EXT_CTRLS
:
1158 case VIDIOC_TRY_EXT_CTRLS
:
1159 err
= bufsize_v4l2_ext_controls(up
, &aux_space
);
1161 err
= alloc_userspace(sizeof(struct v4l2_ext_controls
),
1162 aux_space
, &up_native
);
1164 aux_buf
= up_native
+ sizeof(struct v4l2_ext_controls
);
1165 err
= get_v4l2_ext_controls32(file
, up_native
, up
,
1166 aux_buf
, aux_space
);
1170 case VIDIOC_DQEVENT
:
1171 err
= alloc_userspace(sizeof(struct v4l2_event
), 0, &up_native
);
1179 err
= native_ioctl(file
, cmd
, (unsigned long)up
);
1181 err
= native_ioctl(file
, cmd
, (unsigned long)up_native
);
1187 * Special case: even after an error we need to put the
1188 * results back for these ioctls since the error_idx will
1189 * contain information on which control failed.
1192 case VIDIOC_G_EXT_CTRLS
:
1193 case VIDIOC_S_EXT_CTRLS
:
1194 case VIDIOC_TRY_EXT_CTRLS
:
1195 if (put_v4l2_ext_controls32(file
, up_native
, up
))
1199 if (put_v4l2_edid32(up_native
, up
))
1207 case VIDIOC_S_INPUT
:
1208 case VIDIOC_S_OUTPUT
:
1209 case VIDIOC_G_INPUT
:
1210 case VIDIOC_G_OUTPUT
:
1211 if (assign_in_user((compat_uint_t __user
*)up
,
1212 ((unsigned int __user
*)up_native
)))
1217 err
= put_v4l2_framebuffer32(up_native
, up
);
1220 case VIDIOC_DQEVENT
:
1221 err
= put_v4l2_event32(up_native
, up
);
1225 err
= put_v4l2_edid32(up_native
, up
);
1230 case VIDIOC_TRY_FMT
:
1231 err
= put_v4l2_format32(up_native
, up
);
1234 case VIDIOC_CREATE_BUFS
:
1235 err
= put_v4l2_create32(up_native
, up
);
1238 case VIDIOC_PREPARE_BUF
:
1239 case VIDIOC_QUERYBUF
:
1242 err
= put_v4l2_buffer32(up_native
, up
);
1245 case VIDIOC_ENUMSTD
:
1246 err
= put_v4l2_standard32(up_native
, up
);
1249 case VIDIOC_ENUMINPUT
:
1250 err
= put_v4l2_input32(up_native
, up
);
1256 long v4l2_compat_ioctl32(struct file
*file
, unsigned int cmd
, unsigned long arg
)
1258 struct video_device
*vdev
= video_devdata(file
);
1259 long ret
= -ENOIOCTLCMD
;
1261 if (!file
->f_op
->unlocked_ioctl
)
1264 if (_IOC_TYPE(cmd
) == 'V' && _IOC_NR(cmd
) < BASE_VIDIOC_PRIVATE
)
1265 ret
= do_video_ioctl(file
, cmd
, arg
);
1266 else if (vdev
->fops
->compat_ioctl32
)
1267 ret
= vdev
->fops
->compat_ioctl32(file
, cmd
, arg
);
1269 if (ret
== -ENOIOCTLCMD
)
1270 pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
1271 _IOC_TYPE(cmd
), _IOC_DIR(cmd
), _IOC_NR(cmd
), cmd
);
1274 EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32
);