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 static long native_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
27 long ret
= -ENOIOCTLCMD
;
29 if (file
->f_op
->unlocked_ioctl
)
30 ret
= file
->f_op
->unlocked_ioctl(file
, cmd
, arg
);
41 struct v4l2_window32
{
43 __u32 field
; /* enum v4l2_field */
45 compat_caddr_t clips
; /* actually struct v4l2_clip32 * */
47 compat_caddr_t bitmap
;
51 static int get_v4l2_window32(struct v4l2_window
*kp
, struct v4l2_window32 __user
*up
)
53 struct v4l2_clip32 __user
*uclips
;
54 struct v4l2_clip __user
*kclips
;
58 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
59 copy_from_user(&kp
->w
, &up
->w
, sizeof(up
->w
)) ||
60 get_user(kp
->field
, &up
->field
) ||
61 get_user(kp
->chromakey
, &up
->chromakey
) ||
62 get_user(kp
->clipcount
, &up
->clipcount
) ||
63 get_user(kp
->global_alpha
, &up
->global_alpha
))
65 if (kp
->clipcount
> 2048)
73 if (get_user(p
, &up
->clips
))
75 uclips
= compat_ptr(p
);
76 kclips
= compat_alloc_user_space(n
* sizeof(*kclips
));
79 if (copy_in_user(&kclips
->c
, &uclips
->c
, sizeof(uclips
->c
)))
81 if (put_user(n
? kclips
+ 1 : NULL
, &kclips
->next
))
89 static int put_v4l2_window32(struct v4l2_window
*kp
, struct v4l2_window32 __user
*up
)
91 struct v4l2_clip __user
*kclips
= kp
->clips
;
92 struct v4l2_clip32 __user
*uclips
;
93 u32 n
= kp
->clipcount
;
96 if (copy_to_user(&up
->w
, &kp
->w
, sizeof(kp
->w
)) ||
97 put_user(kp
->field
, &up
->field
) ||
98 put_user(kp
->chromakey
, &up
->chromakey
) ||
99 put_user(kp
->clipcount
, &up
->clipcount
) ||
100 put_user(kp
->global_alpha
, &up
->global_alpha
))
106 if (get_user(p
, &up
->clips
))
108 uclips
= compat_ptr(p
);
110 if (copy_in_user(&uclips
->c
, &kclips
->c
, sizeof(uclips
->c
)))
118 struct v4l2_format32
{
119 __u32 type
; /* enum v4l2_buf_type */
121 struct v4l2_pix_format pix
;
122 struct v4l2_pix_format_mplane pix_mp
;
123 struct v4l2_window32 win
;
124 struct v4l2_vbi_format vbi
;
125 struct v4l2_sliced_vbi_format sliced
;
126 struct v4l2_sdr_format sdr
;
127 struct v4l2_meta_format meta
;
128 __u8 raw_data
[200]; /* user-defined */
133 * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument
134 * @index: on return, index of the first created buffer
135 * @count: entry: number of requested buffers,
136 * return: number of created buffers
137 * @memory: buffer memory type
138 * @format: frame format, for which buffers are requested
139 * @reserved: future extensions
141 struct v4l2_create_buffers32
{
144 __u32 memory
; /* enum v4l2_memory */
145 struct v4l2_format32 format
;
149 static int __get_v4l2_format32(struct v4l2_format
*kp
, struct v4l2_format32 __user
*up
)
151 if (get_user(kp
->type
, &up
->type
))
155 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
156 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
157 return copy_from_user(&kp
->fmt
.pix
, &up
->fmt
.pix
,
158 sizeof(kp
->fmt
.pix
)) ? -EFAULT
: 0;
159 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
160 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
161 return copy_from_user(&kp
->fmt
.pix_mp
, &up
->fmt
.pix_mp
,
162 sizeof(kp
->fmt
.pix_mp
)) ? -EFAULT
: 0;
163 case V4L2_BUF_TYPE_VIDEO_OVERLAY
:
164 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
:
165 return get_v4l2_window32(&kp
->fmt
.win
, &up
->fmt
.win
);
166 case V4L2_BUF_TYPE_VBI_CAPTURE
:
167 case V4L2_BUF_TYPE_VBI_OUTPUT
:
168 return copy_from_user(&kp
->fmt
.vbi
, &up
->fmt
.vbi
,
169 sizeof(kp
->fmt
.vbi
)) ? -EFAULT
: 0;
170 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE
:
171 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT
:
172 return copy_from_user(&kp
->fmt
.sliced
, &up
->fmt
.sliced
,
173 sizeof(kp
->fmt
.sliced
)) ? -EFAULT
: 0;
174 case V4L2_BUF_TYPE_SDR_CAPTURE
:
175 case V4L2_BUF_TYPE_SDR_OUTPUT
:
176 return copy_from_user(&kp
->fmt
.sdr
, &up
->fmt
.sdr
,
177 sizeof(kp
->fmt
.sdr
)) ? -EFAULT
: 0;
178 case V4L2_BUF_TYPE_META_CAPTURE
:
179 return copy_from_user(&kp
->fmt
.meta
, &up
->fmt
.meta
,
180 sizeof(kp
->fmt
.meta
)) ? -EFAULT
: 0;
186 static int get_v4l2_format32(struct v4l2_format
*kp
, struct v4l2_format32 __user
*up
)
188 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)))
190 return __get_v4l2_format32(kp
, up
);
193 static int get_v4l2_create32(struct v4l2_create_buffers
*kp
, struct v4l2_create_buffers32 __user
*up
)
195 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
196 copy_from_user(kp
, up
, offsetof(struct v4l2_create_buffers32
, format
)))
198 return __get_v4l2_format32(&kp
->format
, &up
->format
);
201 static int __put_v4l2_format32(struct v4l2_format
*kp
, struct v4l2_format32 __user
*up
)
203 if (put_user(kp
->type
, &up
->type
))
207 case V4L2_BUF_TYPE_VIDEO_CAPTURE
:
208 case V4L2_BUF_TYPE_VIDEO_OUTPUT
:
209 return copy_to_user(&up
->fmt
.pix
, &kp
->fmt
.pix
,
210 sizeof(kp
->fmt
.pix
)) ? -EFAULT
: 0;
211 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
:
212 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE
:
213 return copy_to_user(&up
->fmt
.pix_mp
, &kp
->fmt
.pix_mp
,
214 sizeof(kp
->fmt
.pix_mp
)) ? -EFAULT
: 0;
215 case V4L2_BUF_TYPE_VIDEO_OVERLAY
:
216 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
:
217 return put_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_to_user(&up
->fmt
.vbi
, &kp
->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_to_user(&up
->fmt
.sliced
, &kp
->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_to_user(&up
->fmt
.sdr
, &kp
->fmt
.sdr
,
229 sizeof(kp
->fmt
.sdr
)) ? -EFAULT
: 0;
230 case V4L2_BUF_TYPE_META_CAPTURE
:
231 return copy_to_user(&up
->fmt
.meta
, &kp
->fmt
.meta
,
232 sizeof(kp
->fmt
.meta
)) ? -EFAULT
: 0;
238 static int put_v4l2_format32(struct v4l2_format
*kp
, struct v4l2_format32 __user
*up
)
240 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)))
242 return __put_v4l2_format32(kp
, up
);
245 static int put_v4l2_create32(struct v4l2_create_buffers
*kp
, struct v4l2_create_buffers32 __user
*up
)
247 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
248 copy_to_user(up
, kp
, offsetof(struct v4l2_create_buffers32
, format
)) ||
249 copy_to_user(up
->reserved
, kp
->reserved
, sizeof(kp
->reserved
)))
251 return __put_v4l2_format32(&kp
->format
, &up
->format
);
254 struct v4l2_standard32
{
258 struct v4l2_fract frameperiod
; /* Frames, not fields */
263 static int get_v4l2_standard32(struct v4l2_standard
*kp
, struct v4l2_standard32 __user
*up
)
265 /* other fields are not set by the user, nor used by the driver */
266 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
267 get_user(kp
->index
, &up
->index
))
272 static int put_v4l2_standard32(struct v4l2_standard
*kp
, struct v4l2_standard32 __user
*up
)
274 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
275 put_user(kp
->index
, &up
->index
) ||
276 put_user(kp
->id
, &up
->id
) ||
277 copy_to_user(up
->name
, kp
->name
, sizeof(up
->name
)) ||
278 copy_to_user(&up
->frameperiod
, &kp
->frameperiod
,
279 sizeof(kp
->frameperiod
)) ||
280 put_user(kp
->framelines
, &up
->framelines
) ||
281 copy_to_user(up
->reserved
, kp
->reserved
, sizeof(kp
->reserved
)))
286 struct v4l2_plane32
{
291 compat_long_t userptr
;
298 struct v4l2_buffer32
{
300 __u32 type
; /* enum v4l2_buf_type */
303 __u32 field
; /* enum v4l2_field */
304 struct compat_timeval timestamp
;
305 struct v4l2_timecode timecode
;
308 /* memory location */
309 __u32 memory
; /* enum v4l2_memory */
312 compat_long_t userptr
;
313 compat_caddr_t planes
;
321 static int get_v4l2_plane32(struct v4l2_plane __user
*up
, struct v4l2_plane32 __user
*up32
,
322 enum v4l2_memory memory
)
327 if (copy_in_user(up
, up32
, 2 * sizeof(__u32
)) ||
328 copy_in_user(&up
->data_offset
, &up32
->data_offset
,
329 sizeof(up
->data_offset
)))
333 case V4L2_MEMORY_MMAP
:
334 case V4L2_MEMORY_OVERLAY
:
335 if (copy_in_user(&up
->m
.mem_offset
, &up32
->m
.mem_offset
,
336 sizeof(up32
->m
.mem_offset
)))
339 case V4L2_MEMORY_USERPTR
:
340 if (get_user(p
, &up32
->m
.userptr
))
342 up_pln
= compat_ptr(p
);
343 if (put_user((unsigned long)up_pln
, &up
->m
.userptr
))
346 case V4L2_MEMORY_DMABUF
:
347 if (copy_in_user(&up
->m
.fd
, &up32
->m
.fd
, sizeof(up32
->m
.fd
)))
355 static int put_v4l2_plane32(struct v4l2_plane __user
*up
, struct v4l2_plane32 __user
*up32
,
356 enum v4l2_memory memory
)
360 if (copy_in_user(up32
, up
, 2 * sizeof(__u32
)) ||
361 copy_in_user(&up32
->data_offset
, &up
->data_offset
,
362 sizeof(up
->data_offset
)))
366 case V4L2_MEMORY_MMAP
:
367 case V4L2_MEMORY_OVERLAY
:
368 if (copy_in_user(&up32
->m
.mem_offset
, &up
->m
.mem_offset
,
369 sizeof(up
->m
.mem_offset
)))
372 case V4L2_MEMORY_USERPTR
:
373 if (get_user(p
, &up
->m
.userptr
) ||
374 put_user((compat_ulong_t
)ptr_to_compat((__force
void *)p
),
378 case V4L2_MEMORY_DMABUF
:
379 if (copy_in_user(&up32
->m
.fd
, &up
->m
.fd
,
388 static int get_v4l2_buffer32(struct v4l2_buffer
*kp
, struct v4l2_buffer32 __user
*up
)
390 struct v4l2_plane32 __user
*uplane32
;
391 struct v4l2_plane __user
*uplane
;
395 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
396 get_user(kp
->index
, &up
->index
) ||
397 get_user(kp
->type
, &up
->type
) ||
398 get_user(kp
->flags
, &up
->flags
) ||
399 get_user(kp
->memory
, &up
->memory
) ||
400 get_user(kp
->length
, &up
->length
))
403 if (V4L2_TYPE_IS_OUTPUT(kp
->type
))
404 if (get_user(kp
->bytesused
, &up
->bytesused
) ||
405 get_user(kp
->field
, &up
->field
) ||
406 get_user(kp
->timestamp
.tv_sec
, &up
->timestamp
.tv_sec
) ||
407 get_user(kp
->timestamp
.tv_usec
, &up
->timestamp
.tv_usec
))
410 if (V4L2_TYPE_IS_MULTIPLANAR(kp
->type
)) {
411 unsigned int num_planes
;
413 if (kp
->length
== 0) {
415 /* num_planes == 0 is legal, e.g. when userspace doesn't
416 * need planes array on DQBUF*/
418 } else if (kp
->length
> VIDEO_MAX_PLANES
) {
422 if (get_user(p
, &up
->m
.planes
))
425 uplane32
= compat_ptr(p
);
426 if (!access_ok(VERIFY_READ
, uplane32
,
427 kp
->length
* sizeof(*uplane32
)))
430 /* We don't really care if userspace decides to kill itself
431 * by passing a very big num_planes value */
432 uplane
= compat_alloc_user_space(kp
->length
* sizeof(*uplane
));
433 kp
->m
.planes
= (__force
struct v4l2_plane
*)uplane
;
435 for (num_planes
= 0; num_planes
< kp
->length
; num_planes
++) {
436 ret
= get_v4l2_plane32(uplane
, uplane32
, kp
->memory
);
443 switch (kp
->memory
) {
444 case V4L2_MEMORY_MMAP
:
445 case V4L2_MEMORY_OVERLAY
:
446 if (get_user(kp
->m
.offset
, &up
->m
.offset
))
449 case V4L2_MEMORY_USERPTR
:
453 if (get_user(tmp
, &up
->m
.userptr
))
456 kp
->m
.userptr
= (unsigned long)compat_ptr(tmp
);
459 case V4L2_MEMORY_DMABUF
:
460 if (get_user(kp
->m
.fd
, &up
->m
.fd
))
469 static int put_v4l2_buffer32(struct v4l2_buffer
*kp
, struct v4l2_buffer32 __user
*up
)
471 struct v4l2_plane32 __user
*uplane32
;
472 struct v4l2_plane __user
*uplane
;
477 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
478 put_user(kp
->index
, &up
->index
) ||
479 put_user(kp
->type
, &up
->type
) ||
480 put_user(kp
->flags
, &up
->flags
) ||
481 put_user(kp
->memory
, &up
->memory
))
484 if (put_user(kp
->bytesused
, &up
->bytesused
) ||
485 put_user(kp
->field
, &up
->field
) ||
486 put_user(kp
->timestamp
.tv_sec
, &up
->timestamp
.tv_sec
) ||
487 put_user(kp
->timestamp
.tv_usec
, &up
->timestamp
.tv_usec
) ||
488 copy_to_user(&up
->timecode
, &kp
->timecode
, sizeof(kp
->timecode
)) ||
489 put_user(kp
->sequence
, &up
->sequence
) ||
490 put_user(kp
->reserved2
, &up
->reserved2
) ||
491 put_user(kp
->reserved
, &up
->reserved
) ||
492 put_user(kp
->length
, &up
->length
))
495 if (V4L2_TYPE_IS_MULTIPLANAR(kp
->type
)) {
496 num_planes
= kp
->length
;
500 uplane
= (__force
struct v4l2_plane __user
*)kp
->m
.planes
;
501 if (get_user(p
, &up
->m
.planes
))
503 uplane32
= compat_ptr(p
);
505 while (--num_planes
>= 0) {
506 ret
= put_v4l2_plane32(uplane
, uplane32
, kp
->memory
);
513 switch (kp
->memory
) {
514 case V4L2_MEMORY_MMAP
:
515 case V4L2_MEMORY_OVERLAY
:
516 if (put_user(kp
->m
.offset
, &up
->m
.offset
))
519 case V4L2_MEMORY_USERPTR
:
520 if (put_user(kp
->m
.userptr
, &up
->m
.userptr
))
523 case V4L2_MEMORY_DMABUF
:
524 if (put_user(kp
->m
.fd
, &up
->m
.fd
))
533 struct v4l2_framebuffer32
{
549 static int get_v4l2_framebuffer32(struct v4l2_framebuffer
*kp
, struct v4l2_framebuffer32 __user
*up
)
553 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
554 get_user(tmp
, &up
->base
) ||
555 get_user(kp
->capability
, &up
->capability
) ||
556 get_user(kp
->flags
, &up
->flags
) ||
557 copy_from_user(&kp
->fmt
, &up
->fmt
, sizeof(up
->fmt
)))
559 kp
->base
= (__force
void *)compat_ptr(tmp
);
563 static int put_v4l2_framebuffer32(struct v4l2_framebuffer
*kp
, struct v4l2_framebuffer32 __user
*up
)
565 u32 tmp
= (u32
)((unsigned long)kp
->base
);
567 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
568 put_user(tmp
, &up
->base
) ||
569 put_user(kp
->capability
, &up
->capability
) ||
570 put_user(kp
->flags
, &up
->flags
) ||
571 copy_to_user(&up
->fmt
, &kp
->fmt
, sizeof(up
->fmt
)))
576 struct v4l2_input32
{
577 __u32 index
; /* Which input */
578 __u8 name
[32]; /* Label */
579 __u32 type
; /* Type of input */
580 __u32 audioset
; /* Associated audios (bitfield) */
581 __u32 tuner
; /* Associated tuner */
588 /* The 64-bit v4l2_input struct has extra padding at the end of the struct.
589 Otherwise it is identical to the 32-bit version. */
590 static inline int get_v4l2_input32(struct v4l2_input
*kp
, struct v4l2_input32 __user
*up
)
592 if (copy_from_user(kp
, up
, sizeof(*up
)))
597 static inline int put_v4l2_input32(struct v4l2_input
*kp
, struct v4l2_input32 __user
*up
)
599 if (copy_to_user(up
, kp
, sizeof(*up
)))
604 struct v4l2_ext_controls32
{
609 compat_caddr_t controls
; /* actually struct v4l2_ext_control32 * */
612 struct v4l2_ext_control32
{
619 compat_caddr_t string
; /* actually char * */
621 } __attribute__ ((packed
));
623 /* Return true if this control is a pointer type. */
624 static inline bool ctrl_is_pointer(struct file
*file
, u32 id
)
626 struct video_device
*vdev
= video_devdata(file
);
627 struct v4l2_fh
*fh
= NULL
;
628 struct v4l2_ctrl_handler
*hdl
= NULL
;
629 struct v4l2_query_ext_ctrl qec
= { id
};
630 const struct v4l2_ioctl_ops
*ops
= vdev
->ioctl_ops
;
632 if (test_bit(V4L2_FL_USES_V4L2_FH
, &vdev
->flags
))
633 fh
= file
->private_data
;
635 if (fh
&& fh
->ctrl_handler
)
636 hdl
= fh
->ctrl_handler
;
637 else if (vdev
->ctrl_handler
)
638 hdl
= vdev
->ctrl_handler
;
641 struct v4l2_ctrl
*ctrl
= v4l2_ctrl_find(hdl
, id
);
643 return ctrl
&& ctrl
->is_ptr
;
646 if (!ops
->vidioc_query_ext_ctrl
)
649 return !ops
->vidioc_query_ext_ctrl(file
, fh
, &qec
) &&
650 (qec
.flags
& V4L2_CTRL_FLAG_HAS_PAYLOAD
);
653 static int get_v4l2_ext_controls32(struct file
*file
,
654 struct v4l2_ext_controls
*kp
,
655 struct v4l2_ext_controls32 __user
*up
)
657 struct v4l2_ext_control32 __user
*ucontrols
;
658 struct v4l2_ext_control __user
*kcontrols
;
662 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
663 get_user(kp
->which
, &up
->which
) ||
664 get_user(kp
->count
, &up
->count
) ||
665 get_user(kp
->error_idx
, &up
->error_idx
) ||
666 copy_from_user(kp
->reserved
, up
->reserved
, sizeof(kp
->reserved
)))
668 if (kp
->count
== 0) {
671 } else if (kp
->count
> V4L2_CID_MAX_CTRLS
) {
674 if (get_user(p
, &up
->controls
))
676 ucontrols
= compat_ptr(p
);
677 if (!access_ok(VERIFY_READ
, ucontrols
, kp
->count
* sizeof(*ucontrols
)))
679 kcontrols
= compat_alloc_user_space(kp
->count
* sizeof(*kcontrols
));
680 kp
->controls
= (__force
struct v4l2_ext_control
*)kcontrols
;
681 for (n
= 0; n
< kp
->count
; n
++) {
684 if (copy_in_user(kcontrols
, ucontrols
, sizeof(*ucontrols
)))
686 if (get_user(id
, &kcontrols
->id
))
688 if (ctrl_is_pointer(file
, id
)) {
691 if (get_user(p
, &ucontrols
->string
))
694 if (put_user(s
, &kcontrols
->string
))
703 static int put_v4l2_ext_controls32(struct file
*file
,
704 struct v4l2_ext_controls
*kp
,
705 struct v4l2_ext_controls32 __user
*up
)
707 struct v4l2_ext_control32 __user
*ucontrols
;
708 struct v4l2_ext_control __user
*kcontrols
=
709 (__force
struct v4l2_ext_control __user
*)kp
->controls
;
713 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
714 put_user(kp
->which
, &up
->which
) ||
715 put_user(kp
->count
, &up
->count
) ||
716 put_user(kp
->error_idx
, &up
->error_idx
) ||
717 copy_to_user(up
->reserved
, kp
->reserved
, sizeof(up
->reserved
)))
722 if (get_user(p
, &up
->controls
))
724 ucontrols
= compat_ptr(p
);
725 if (!access_ok(VERIFY_WRITE
, ucontrols
, n
* sizeof(*ucontrols
)))
729 unsigned size
= sizeof(*ucontrols
);
732 if (get_user(id
, &kcontrols
->id
))
734 /* Do not modify the pointer when copying a pointer control.
735 The contents of the pointer was changed, not the pointer
737 if (ctrl_is_pointer(file
, id
))
738 size
-= sizeof(ucontrols
->value64
);
739 if (copy_in_user(ucontrols
, kcontrols
, size
))
747 struct v4l2_event32
{
755 struct compat_timespec timestamp
;
760 static int put_v4l2_event32(struct v4l2_event
*kp
, struct v4l2_event32 __user
*up
)
762 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
763 put_user(kp
->type
, &up
->type
) ||
764 copy_to_user(&up
->u
, &kp
->u
, sizeof(kp
->u
)) ||
765 put_user(kp
->pending
, &up
->pending
) ||
766 put_user(kp
->sequence
, &up
->sequence
) ||
767 put_user(kp
->timestamp
.tv_sec
, &up
->timestamp
.tv_sec
) ||
768 put_user(kp
->timestamp
.tv_nsec
, &up
->timestamp
.tv_nsec
) ||
769 put_user(kp
->id
, &up
->id
) ||
770 copy_to_user(up
->reserved
, kp
->reserved
, sizeof(kp
->reserved
)))
783 static int get_v4l2_edid32(struct v4l2_edid
*kp
, struct v4l2_edid32 __user
*up
)
787 if (!access_ok(VERIFY_READ
, up
, sizeof(*up
)) ||
788 get_user(kp
->pad
, &up
->pad
) ||
789 get_user(kp
->start_block
, &up
->start_block
) ||
790 get_user(kp
->blocks
, &up
->blocks
) ||
791 get_user(tmp
, &up
->edid
) ||
792 copy_from_user(kp
->reserved
, up
->reserved
, sizeof(kp
->reserved
)))
794 kp
->edid
= (__force u8
*)compat_ptr(tmp
);
798 static int put_v4l2_edid32(struct v4l2_edid
*kp
, struct v4l2_edid32 __user
*up
)
800 u32 tmp
= (u32
)((unsigned long)kp
->edid
);
802 if (!access_ok(VERIFY_WRITE
, up
, sizeof(*up
)) ||
803 put_user(kp
->pad
, &up
->pad
) ||
804 put_user(kp
->start_block
, &up
->start_block
) ||
805 put_user(kp
->blocks
, &up
->blocks
) ||
806 put_user(tmp
, &up
->edid
) ||
807 copy_to_user(up
->reserved
, kp
->reserved
, sizeof(up
->reserved
)))
813 #define VIDIOC_G_FMT32 _IOWR('V', 4, struct v4l2_format32)
814 #define VIDIOC_S_FMT32 _IOWR('V', 5, struct v4l2_format32)
815 #define VIDIOC_QUERYBUF32 _IOWR('V', 9, struct v4l2_buffer32)
816 #define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32)
817 #define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32)
818 #define VIDIOC_QBUF32 _IOWR('V', 15, struct v4l2_buffer32)
819 #define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32)
820 #define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32)
821 #define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32)
822 #define VIDIOC_G_EDID32 _IOWR('V', 40, struct v4l2_edid32)
823 #define VIDIOC_S_EDID32 _IOWR('V', 41, struct v4l2_edid32)
824 #define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32)
825 #define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32)
826 #define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32)
827 #define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32)
828 #define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32)
829 #define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32)
830 #define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32)
832 #define VIDIOC_OVERLAY32 _IOW ('V', 14, s32)
833 #define VIDIOC_STREAMON32 _IOW ('V', 18, s32)
834 #define VIDIOC_STREAMOFF32 _IOW ('V', 19, s32)
835 #define VIDIOC_G_INPUT32 _IOR ('V', 38, s32)
836 #define VIDIOC_S_INPUT32 _IOWR('V', 39, s32)
837 #define VIDIOC_G_OUTPUT32 _IOR ('V', 46, s32)
838 #define VIDIOC_S_OUTPUT32 _IOWR('V', 47, s32)
840 static long do_video_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
843 struct v4l2_format v2f
;
844 struct v4l2_buffer v2b
;
845 struct v4l2_framebuffer v2fb
;
846 struct v4l2_input v2i
;
847 struct v4l2_standard v2s
;
848 struct v4l2_ext_controls v2ecs
;
849 struct v4l2_event v2ev
;
850 struct v4l2_create_buffers v2crt
;
851 struct v4l2_edid v2edid
;
855 void __user
*up
= compat_ptr(arg
);
856 int compatible_arg
= 1;
859 /* First, convert the command. */
861 case VIDIOC_G_FMT32
: cmd
= VIDIOC_G_FMT
; break;
862 case VIDIOC_S_FMT32
: cmd
= VIDIOC_S_FMT
; break;
863 case VIDIOC_QUERYBUF32
: cmd
= VIDIOC_QUERYBUF
; break;
864 case VIDIOC_G_FBUF32
: cmd
= VIDIOC_G_FBUF
; break;
865 case VIDIOC_S_FBUF32
: cmd
= VIDIOC_S_FBUF
; break;
866 case VIDIOC_QBUF32
: cmd
= VIDIOC_QBUF
; break;
867 case VIDIOC_DQBUF32
: cmd
= VIDIOC_DQBUF
; break;
868 case VIDIOC_ENUMSTD32
: cmd
= VIDIOC_ENUMSTD
; break;
869 case VIDIOC_ENUMINPUT32
: cmd
= VIDIOC_ENUMINPUT
; break;
870 case VIDIOC_TRY_FMT32
: cmd
= VIDIOC_TRY_FMT
; break;
871 case VIDIOC_G_EXT_CTRLS32
: cmd
= VIDIOC_G_EXT_CTRLS
; break;
872 case VIDIOC_S_EXT_CTRLS32
: cmd
= VIDIOC_S_EXT_CTRLS
; break;
873 case VIDIOC_TRY_EXT_CTRLS32
: cmd
= VIDIOC_TRY_EXT_CTRLS
; break;
874 case VIDIOC_DQEVENT32
: cmd
= VIDIOC_DQEVENT
; break;
875 case VIDIOC_OVERLAY32
: cmd
= VIDIOC_OVERLAY
; break;
876 case VIDIOC_STREAMON32
: cmd
= VIDIOC_STREAMON
; break;
877 case VIDIOC_STREAMOFF32
: cmd
= VIDIOC_STREAMOFF
; break;
878 case VIDIOC_G_INPUT32
: cmd
= VIDIOC_G_INPUT
; break;
879 case VIDIOC_S_INPUT32
: cmd
= VIDIOC_S_INPUT
; break;
880 case VIDIOC_G_OUTPUT32
: cmd
= VIDIOC_G_OUTPUT
; break;
881 case VIDIOC_S_OUTPUT32
: cmd
= VIDIOC_S_OUTPUT
; break;
882 case VIDIOC_CREATE_BUFS32
: cmd
= VIDIOC_CREATE_BUFS
; break;
883 case VIDIOC_PREPARE_BUF32
: cmd
= VIDIOC_PREPARE_BUF
; break;
884 case VIDIOC_G_EDID32
: cmd
= VIDIOC_G_EDID
; break;
885 case VIDIOC_S_EDID32
: cmd
= VIDIOC_S_EDID
; break;
890 case VIDIOC_STREAMON
:
891 case VIDIOC_STREAMOFF
:
893 case VIDIOC_S_OUTPUT
:
894 err
= get_user(karg
.vi
, (s32 __user
*)up
);
899 case VIDIOC_G_OUTPUT
:
905 err
= get_v4l2_edid32(&karg
.v2edid
, up
);
912 err
= get_v4l2_format32(&karg
.v2f
, up
);
916 case VIDIOC_CREATE_BUFS
:
917 err
= get_v4l2_create32(&karg
.v2crt
, up
);
921 case VIDIOC_PREPARE_BUF
:
922 case VIDIOC_QUERYBUF
:
925 err
= get_v4l2_buffer32(&karg
.v2b
, up
);
930 err
= get_v4l2_framebuffer32(&karg
.v2fb
, up
);
939 err
= get_v4l2_standard32(&karg
.v2s
, up
);
943 case VIDIOC_ENUMINPUT
:
944 err
= get_v4l2_input32(&karg
.v2i
, up
);
948 case VIDIOC_G_EXT_CTRLS
:
949 case VIDIOC_S_EXT_CTRLS
:
950 case VIDIOC_TRY_EXT_CTRLS
:
951 err
= get_v4l2_ext_controls32(file
, &karg
.v2ecs
, up
);
962 err
= native_ioctl(file
, cmd
, (unsigned long)up
);
964 mm_segment_t old_fs
= get_fs();
967 err
= native_ioctl(file
, cmd
, (unsigned long)&karg
);
974 /* Special case: even after an error we need to put the
975 results back for these ioctls since the error_idx will
976 contain information on which control failed. */
978 case VIDIOC_G_EXT_CTRLS
:
979 case VIDIOC_S_EXT_CTRLS
:
980 case VIDIOC_TRY_EXT_CTRLS
:
981 if (put_v4l2_ext_controls32(file
, &karg
.v2ecs
, up
))
985 if (put_v4l2_edid32(&karg
.v2edid
, up
))
994 case VIDIOC_S_OUTPUT
:
996 case VIDIOC_G_OUTPUT
:
997 err
= put_user(((s32
)karg
.vi
), (s32 __user
*)up
);
1001 err
= put_v4l2_framebuffer32(&karg
.v2fb
, up
);
1004 case VIDIOC_DQEVENT
:
1005 err
= put_v4l2_event32(&karg
.v2ev
, up
);
1009 err
= put_v4l2_edid32(&karg
.v2edid
, up
);
1014 case VIDIOC_TRY_FMT
:
1015 err
= put_v4l2_format32(&karg
.v2f
, up
);
1018 case VIDIOC_CREATE_BUFS
:
1019 err
= put_v4l2_create32(&karg
.v2crt
, up
);
1022 case VIDIOC_PREPARE_BUF
:
1023 case VIDIOC_QUERYBUF
:
1026 err
= put_v4l2_buffer32(&karg
.v2b
, up
);
1029 case VIDIOC_ENUMSTD
:
1030 err
= put_v4l2_standard32(&karg
.v2s
, up
);
1033 case VIDIOC_ENUMINPUT
:
1034 err
= put_v4l2_input32(&karg
.v2i
, up
);
1040 long v4l2_compat_ioctl32(struct file
*file
, unsigned int cmd
, unsigned long arg
)
1042 struct video_device
*vdev
= video_devdata(file
);
1043 long ret
= -ENOIOCTLCMD
;
1045 if (!file
->f_op
->unlocked_ioctl
)
1048 if (_IOC_TYPE(cmd
) == 'V' && _IOC_NR(cmd
) < BASE_VIDIOC_PRIVATE
)
1049 ret
= do_video_ioctl(file
, cmd
, arg
);
1050 else if (vdev
->fops
->compat_ioctl32
)
1051 ret
= vdev
->fops
->compat_ioctl32(file
, cmd
, arg
);
1053 if (ret
== -ENOIOCTLCMD
)
1054 pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
1055 _IOC_TYPE(cmd
), _IOC_DIR(cmd
), _IOC_NR(cmd
), cmd
);
1058 EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32
);