1 // SPDX-License-Identifier: GPL-2.0-only
3 * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
4 * Separated from fs stuff by Arnd Bergmann <arnd@arndb.de>
6 * Copyright (C) 1997-2000 Jakub Jelinek (jakub@redhat.com)
7 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
8 * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs
9 * Copyright (C) 2003 Pavel Machek (pavel@ucw.cz)
10 * Copyright (C) 2005 Philippe De Muyter (phdm@macqel.be)
11 * Copyright (C) 2008 Hans Verkuil <hverkuil@xs4all.nl>
13 * These routines maintain argument size conversion between 32bit and 64bit
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>
27 * Per-ioctl data copy handlers.
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.
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().
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.
46 struct v4l2_window32
{
48 __u32 field
; /* enum v4l2_field */
50 compat_caddr_t clips
; /* actually struct v4l2_clip32 * */
52 compat_caddr_t bitmap
;
56 static int get_v4l2_window32(struct v4l2_window
*p64
,
57 struct v4l2_window32 __user
*p32
)
59 struct v4l2_window32 w32
;
61 if (copy_from_user(&w32
, p32
, sizeof(w32
)))
64 *p64
= (struct v4l2_window
) {
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
,
74 if (p64
->clipcount
> 2048)
82 static int put_v4l2_window32(struct v4l2_window
*p64
,
83 struct v4l2_window32 __user
*p32
)
85 struct v4l2_window32 w32
;
87 memset(&w32
, 0, sizeof(w32
));
88 w32
= (struct v4l2_window32
) {
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
,
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
)))
107 struct v4l2_format32
{
108 __u32 type
; /* enum v4l2_buf_type */
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 */
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
131 struct v4l2_create_buffers32
{
134 __u32 memory
; /* enum v4l2_memory */
135 struct v4l2_format32 format
;
140 static int get_v4l2_format32(struct v4l2_format
*p64
,
141 struct v4l2_format32 __user
*p32
)
143 if (get_user(p64
->type
, &p32
->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;
179 static int get_v4l2_create32(struct v4l2_create_buffers
*p64
,
180 struct v4l2_create_buffers32 __user
*p32
)
182 if (copy_from_user(p64
, p32
,
183 offsetof(struct v4l2_create_buffers32
, format
)))
185 return get_v4l2_format32(&p64
->format
, &p32
->format
);
188 static int put_v4l2_format32(struct v4l2_format
*p64
,
189 struct v4l2_format32 __user
*p32
)
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;
224 static int put_v4l2_create32(struct v4l2_create_buffers
*p64
,
225 struct v4l2_create_buffers32 __user
*p32
)
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
)))
232 return put_v4l2_format32(&p64
->format
, &p32
->format
);
235 struct v4l2_standard32
{
239 struct v4l2_fract frameperiod
; /* Frames, not fields */
244 static int get_v4l2_standard32(struct v4l2_standard
*p64
,
245 struct v4l2_standard32 __user
*p32
)
247 /* other fields are not set by the user, nor used by the driver */
248 return get_user(p64
->index
, &p32
->index
);
251 static int put_v4l2_standard32(struct v4l2_standard
*p64
,
252 struct v4l2_standard32 __user
*p32
)
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
)))
265 struct v4l2_plane32
{
270 compat_long_t userptr
;
278 * This is correct for all architectures including i386, but not x32,
279 * which has different alignment requirements for timestamp
281 struct v4l2_buffer32
{
283 __u32 type
; /* enum v4l2_buf_type */
286 __u32 field
; /* enum v4l2_field */
291 struct v4l2_timecode timecode
;
294 /* memory location */
295 __u32 memory
; /* enum v4l2_memory */
298 compat_long_t userptr
;
299 compat_caddr_t planes
;
307 #ifdef CONFIG_COMPAT_32BIT_TIME
308 struct v4l2_buffer32_time32
{
310 __u32 type
; /* enum v4l2_buf_type */
313 __u32 field
; /* enum v4l2_field */
314 struct old_timeval32 timestamp
;
315 struct v4l2_timecode timecode
;
318 /* memory location */
319 __u32 memory
; /* enum v4l2_memory */
322 compat_long_t userptr
;
323 compat_caddr_t planes
;
332 static int get_v4l2_plane32(struct v4l2_plane
*p64
,
333 struct v4l2_plane32 __user
*p32
,
334 enum v4l2_memory memory
)
336 struct v4l2_plane32 plane32
;
337 typeof(p64
->m
) m
= {};
339 if (copy_from_user(&plane32
, p32
, sizeof(plane32
)))
343 case V4L2_MEMORY_MMAP
:
344 case V4L2_MEMORY_OVERLAY
:
345 m
.mem_offset
= plane32
.m
.mem_offset
;
347 case V4L2_MEMORY_USERPTR
:
348 m
.userptr
= (unsigned long)compat_ptr(plane32
.m
.userptr
);
350 case V4L2_MEMORY_DMABUF
:
355 memset(p64
, 0, sizeof(*p64
));
356 *p64
= (struct v4l2_plane
) {
357 .bytesused
= plane32
.bytesused
,
358 .length
= plane32
.length
,
360 .data_offset
= plane32
.data_offset
,
366 static int put_v4l2_plane32(struct v4l2_plane
*p64
,
367 struct v4l2_plane32 __user
*p32
,
368 enum v4l2_memory memory
)
370 struct v4l2_plane32 plane32
;
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
,
380 case V4L2_MEMORY_MMAP
:
381 case V4L2_MEMORY_OVERLAY
:
382 plane32
.m
.mem_offset
= p64
->m
.mem_offset
;
384 case V4L2_MEMORY_USERPTR
:
385 plane32
.m
.userptr
= (uintptr_t)(p64
->m
.userptr
);
387 case V4L2_MEMORY_DMABUF
:
388 plane32
.m
.fd
= p64
->m
.fd
;
392 if (copy_to_user(p32
, &plane32
, sizeof(plane32
)))
398 static int get_v4l2_buffer32(struct v4l2_buffer
*vb
,
399 struct v4l2_buffer32 __user
*arg
)
401 struct v4l2_buffer32 vb32
;
403 if (copy_from_user(&vb32
, arg
, sizeof(vb32
)))
406 memset(vb
, 0, sizeof(*vb
));
407 *vb
= (struct v4l2_buffer
) {
410 .bytesused
= vb32
.bytesused
,
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
,
423 switch (vb
->memory
) {
424 case V4L2_MEMORY_MMAP
:
425 case V4L2_MEMORY_OVERLAY
:
426 vb
->m
.offset
= vb32
.m
.offset
;
428 case V4L2_MEMORY_USERPTR
:
429 vb
->m
.userptr
= (unsigned long)compat_ptr(vb32
.m
.userptr
);
431 case V4L2_MEMORY_DMABUF
:
432 vb
->m
.fd
= vb32
.m
.fd
;
436 if (V4L2_TYPE_IS_MULTIPLANAR(vb
->type
))
437 vb
->m
.planes
= (void __force
*)
438 compat_ptr(vb32
.m
.planes
);
443 #ifdef CONFIG_COMPAT_32BIT_TIME
444 static int get_v4l2_buffer32_time32(struct v4l2_buffer
*vb
,
445 struct v4l2_buffer32_time32 __user
*arg
)
447 struct v4l2_buffer32_time32 vb32
;
449 if (copy_from_user(&vb32
, arg
, sizeof(vb32
)))
452 *vb
= (struct v4l2_buffer
) {
455 .bytesused
= vb32
.bytesused
,
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
,
467 switch (vb
->memory
) {
468 case V4L2_MEMORY_MMAP
:
469 case V4L2_MEMORY_OVERLAY
:
470 vb
->m
.offset
= vb32
.m
.offset
;
472 case V4L2_MEMORY_USERPTR
:
473 vb
->m
.userptr
= (unsigned long)compat_ptr(vb32
.m
.userptr
);
475 case V4L2_MEMORY_DMABUF
:
476 vb
->m
.fd
= vb32
.m
.fd
;
480 if (V4L2_TYPE_IS_MULTIPLANAR(vb
->type
))
481 vb
->m
.planes
= (void __force
*)
482 compat_ptr(vb32
.m
.planes
);
488 static int put_v4l2_buffer32(struct v4l2_buffer
*vb
,
489 struct v4l2_buffer32 __user
*arg
)
491 struct v4l2_buffer32 vb32
;
493 memset(&vb32
, 0, sizeof(vb32
));
494 vb32
= (struct v4l2_buffer32
) {
497 .bytesused
= vb
->bytesused
,
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
,
510 switch (vb
->memory
) {
511 case V4L2_MEMORY_MMAP
:
512 case V4L2_MEMORY_OVERLAY
:
513 vb32
.m
.offset
= vb
->m
.offset
;
515 case V4L2_MEMORY_USERPTR
:
516 vb32
.m
.userptr
= (uintptr_t)(vb
->m
.userptr
);
518 case V4L2_MEMORY_DMABUF
:
519 vb32
.m
.fd
= vb
->m
.fd
;
523 if (V4L2_TYPE_IS_MULTIPLANAR(vb
->type
))
524 vb32
.m
.planes
= (uintptr_t)vb
->m
.planes
;
526 if (copy_to_user(arg
, &vb32
, sizeof(vb32
)))
532 #ifdef CONFIG_COMPAT_32BIT_TIME
533 static int put_v4l2_buffer32_time32(struct v4l2_buffer
*vb
,
534 struct v4l2_buffer32_time32 __user
*arg
)
536 struct v4l2_buffer32_time32 vb32
;
538 memset(&vb32
, 0, sizeof(vb32
));
539 vb32
= (struct v4l2_buffer32_time32
) {
542 .bytesused
= vb
->bytesused
,
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
,
554 switch (vb
->memory
) {
555 case V4L2_MEMORY_MMAP
:
556 case V4L2_MEMORY_OVERLAY
:
557 vb32
.m
.offset
= vb
->m
.offset
;
559 case V4L2_MEMORY_USERPTR
:
560 vb32
.m
.userptr
= (uintptr_t)(vb
->m
.userptr
);
562 case V4L2_MEMORY_DMABUF
:
563 vb32
.m
.fd
= vb
->m
.fd
;
567 if (V4L2_TYPE_IS_MULTIPLANAR(vb
->type
))
568 vb32
.m
.planes
= (uintptr_t)vb
->m
.planes
;
570 if (copy_to_user(arg
, &vb32
, sizeof(vb32
)))
577 struct v4l2_framebuffer32
{
593 static int get_v4l2_framebuffer32(struct v4l2_framebuffer
*p64
,
594 struct v4l2_framebuffer32 __user
*p32
)
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
)))
603 p64
->base
= (void __force
*)compat_ptr(tmp
);
608 static int put_v4l2_framebuffer32(struct v4l2_framebuffer
*p64
,
609 struct v4l2_framebuffer32 __user
*p32
)
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
)))
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 */
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.
636 static inline int get_v4l2_input32(struct v4l2_input
*p64
,
637 struct v4l2_input32 __user
*p32
)
639 if (copy_from_user(p64
, p32
, sizeof(*p32
)))
644 static inline int put_v4l2_input32(struct v4l2_input
*p64
,
645 struct v4l2_input32 __user
*p32
)
647 if (copy_to_user(p32
, p64
, sizeof(*p32
)))
652 struct v4l2_ext_controls32
{
658 compat_caddr_t controls
; /* actually struct v4l2_ext_control32 * */
661 struct v4l2_ext_control32
{
668 compat_caddr_t string
; /* actually char * */
670 } __attribute__ ((packed
));
672 /* Return true if this control is a pointer type. */
673 static inline bool ctrl_is_pointer(struct file
*file
, u32 id
)
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
;
681 if (test_bit(V4L2_FL_USES_V4L2_FH
, &vdev
->flags
))
682 fh
= file
->private_data
;
684 if (fh
&& fh
->ctrl_handler
)
685 hdl
= fh
->ctrl_handler
;
686 else if (vdev
->ctrl_handler
)
687 hdl
= vdev
->ctrl_handler
;
690 struct v4l2_ctrl
*ctrl
= v4l2_ctrl_find(hdl
, id
);
692 return ctrl
&& ctrl
->is_ptr
;
695 if (!ops
|| !ops
->vidioc_query_ext_ctrl
)
698 return !ops
->vidioc_query_ext_ctrl(file
, fh
, &qec
) &&
699 (qec
.flags
& V4L2_CTRL_FLAG_HAS_PAYLOAD
);
702 static int get_v4l2_ext_controls32(struct v4l2_ext_controls
*p64
,
703 struct v4l2_ext_controls32 __user
*p32
)
705 struct v4l2_ext_controls32 ec32
;
707 if (copy_from_user(&ec32
, p32
, sizeof(ec32
)))
710 *p64
= (struct v4l2_ext_controls
) {
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
),
722 static int put_v4l2_ext_controls32(struct v4l2_ext_controls
*p64
,
723 struct v4l2_ext_controls32 __user
*p32
)
725 struct v4l2_ext_controls32 ec32
;
727 memset(&ec32
, 0, sizeof(ec32
));
728 ec32
= (struct v4l2_ext_controls32
) {
731 .error_idx
= p64
->error_idx
,
732 .request_fd
= p64
->request_fd
,
733 .reserved
[0] = p64
->reserved
[0],
734 .controls
= (uintptr_t)p64
->controls
,
737 if (copy_to_user(p32
, &ec32
, sizeof(ec32
)))
745 * x86 is the only compat architecture with different struct alignment
746 * between 32-bit and 64-bit tasks.
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.
752 struct v4l2_event32
{
768 #ifdef CONFIG_COMPAT_32BIT_TIME
769 struct v4l2_event32_time32
{
777 struct old_timespec32 timestamp
;
783 static int put_v4l2_event32(struct v4l2_event
*p64
,
784 struct v4l2_event32 __user
*p32
)
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
)))
798 #ifdef CONFIG_COMPAT_32BIT_TIME
799 static int put_v4l2_event32_time32(struct v4l2_event
*p64
,
800 struct v4l2_event32_time32 __user
*p32
)
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
)))
824 static int get_v4l2_edid32(struct v4l2_edid
*p64
,
825 struct v4l2_edid32 __user
*p32
)
829 if (copy_from_user(p64
, p32
, offsetof(struct v4l2_edid32
, edid
)) ||
830 get_user(edid
, &p32
->edid
))
833 p64
->edid
= (void __force
*)compat_ptr(edid
);
837 static int put_v4l2_edid32(struct v4l2_edid
*p64
,
838 struct v4l2_edid32 __user
*p32
)
840 if (copy_to_user(p32
, p64
, offsetof(struct v4l2_edid32
, edid
)))
846 * List of ioctls that require 32-bits/64-bits conversion
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.
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)
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)
877 #define VIDIOC_DQEVENT32_TIME32 _IOR ('V', 89, struct v4l2_event32_time32)
879 #define VIDIOC_PREPARE_BUF32_TIME32 _IOWR('V', 93, struct v4l2_buffer32_time32)
882 unsigned int v4l2_compat_translate_cmd(unsigned int cmd
)
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
:
900 case VIDIOC_DQBUF32_TIME32
:
902 case VIDIOC_PREPARE_BUF32_TIME32
:
903 return VIDIOC_PREPARE_BUF
;
905 case VIDIOC_QUERYBUF32
:
906 return VIDIOC_QUERYBUF
;
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
;
930 case VIDIOC_DQEVENT32
:
931 return VIDIOC_DQEVENT
;
932 #ifdef CONFIG_COMPAT_32BIT_TIME
933 case VIDIOC_DQEVENT32_TIME32
:
934 return VIDIOC_DQEVENT
;
941 int v4l2_compat_get_user(void __user
*arg
, void *parg
, unsigned int cmd
)
946 case VIDIOC_TRY_FMT32
:
947 return get_v4l2_format32(parg
, arg
);
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
);
958 case VIDIOC_QUERYBUF32
:
961 case VIDIOC_PREPARE_BUF32
:
962 return get_v4l2_buffer32(parg
, arg
);
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
);
969 case VIDIOC_CREATE_BUFS32
:
970 return get_v4l2_create32(parg
, arg
);
972 case VIDIOC_ENUMSTD32
:
973 return get_v4l2_standard32(parg
, arg
);
975 case VIDIOC_ENUMINPUT32
:
976 return get_v4l2_input32(parg
, arg
);
978 case VIDIOC_G_EDID32
:
979 case VIDIOC_S_EDID32
:
980 return get_v4l2_edid32(parg
, arg
);
985 int v4l2_compat_put_user(void __user
*arg
, void *parg
, unsigned int cmd
)
990 case VIDIOC_TRY_FMT32
:
991 return put_v4l2_format32(parg
, arg
);
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
);
1002 case VIDIOC_QUERYBUF32
:
1004 case VIDIOC_DQBUF32
:
1005 case VIDIOC_PREPARE_BUF32
:
1006 return put_v4l2_buffer32(parg
, arg
);
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
);
1013 case VIDIOC_CREATE_BUFS32
:
1014 return put_v4l2_create32(parg
, arg
);
1016 case VIDIOC_ENUMSTD32
:
1017 return put_v4l2_standard32(parg
, arg
);
1019 case VIDIOC_ENUMINPUT32
:
1020 return put_v4l2_input32(parg
, arg
);
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
);
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
)
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
;
1052 if ((f64
->type
!= V4L2_BUF_TYPE_VIDEO_OVERLAY
&&
1053 f64
->type
!= V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
) ||
1056 if (clipcount
> 2048)
1058 while (clipcount
--) {
1059 if (copy_from_user(c64
, c32
, sizeof(c64
->c
)))
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
:
1073 case VIDIOC_QUERYBUF32
:
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
;
1081 if (V4L2_TYPE_IS_MULTIPLANAR(b64
->type
)) {
1082 u32 num_planes
= b64
->length
;
1084 if (num_planes
== 0)
1087 while (num_planes
--) {
1088 err
= get_v4l2_plane32(p64
, p32
, b64
->memory
);
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
;
1105 for (n
= 0; n
< ecs64
->count
; n
++) {
1106 if (copy_from_user(ec64
, ec32
, sizeof(*ec32
)))
1109 if (ctrl_is_pointer(file
, ec64
->id
)) {
1112 if (get_user(p
, &ec32
->string
))
1114 ec64
->string
= compat_ptr(p
);
1122 if (copy_from_user(mbuf
, user_ptr
, array_size
))
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
)
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
;
1145 if ((f64
->type
!= V4L2_BUF_TYPE_VIDEO_OVERLAY
&&
1146 f64
->type
!= V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY
) ||
1149 if (clipcount
> 2048)
1151 while (clipcount
--) {
1152 if (copy_to_user(c32
, c64
, sizeof(c64
->c
)))
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
:
1165 case VIDIOC_QUERYBUF32
:
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
;
1173 if (V4L2_TYPE_IS_MULTIPLANAR(b64
->type
)) {
1174 u32 num_planes
= b64
->length
;
1176 if (num_planes
== 0)
1179 while (num_planes
--) {
1180 err
= put_v4l2_plane32(p64
, p32
, b64
->memory
);
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
;
1197 for (n
= 0; n
< ecs64
->count
; n
++) {
1198 unsigned int size
= sizeof(*ec32
);
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.
1205 if (ctrl_is_pointer(file
, ec64
->id
))
1206 size
-= sizeof(ec32
->value64
);
1208 if (copy_to_user(ec32
, ec64
, size
))
1217 if (copy_to_user(user_ptr
, mbuf
, array_size
))
1226 * v4l2_compat_ioctl32() - Handles a compat32 ioctl call
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
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.
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
1239 long v4l2_compat_ioctl32(struct file
*file
, unsigned int cmd
, unsigned long arg
)
1241 struct video_device
*vdev
= video_devdata(file
);
1242 long ret
= -ENOIOCTLCMD
;
1244 if (!file
->f_op
->unlocked_ioctl
)
1247 if (_IOC_TYPE(cmd
) == 'V' && _IOC_NR(cmd
) < BASE_VIDIOC_PRIVATE
)
1248 ret
= file
->f_op
->unlocked_ioctl(file
, cmd
,
1249 (unsigned long)compat_ptr(arg
));
1250 else if (vdev
->fops
->compat_ioctl32
)
1251 ret
= vdev
->fops
->compat_ioctl32(file
, cmd
, arg
);
1253 if (ret
== -ENOIOCTLCMD
)
1254 pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
1255 _IOC_TYPE(cmd
), _IOC_DIR(cmd
), _IOC_NR(cmd
), cmd
);
1258 EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32
);