1 // SPDX-License-Identifier: GPL-2.0-only
3 * ioctl32.c: Conversion between 32bit and 64bit native ioctls.
8 * Copyright (C) 2001,2002 Andi Kleen, SuSE Labs
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.
41 struct v4l2_window32 {
43 __u32 field; /* enum v4l2_field */
45 compat_caddr_t clips; /* always NULL */
46 __u32 clipcount; /* always 0 */
47 compat_caddr_t bitmap; /* always NULL */
51 static int get_v4l2_window32(struct v4l2_window *p64,
52 struct v4l2_window32 __user *p32)
54 struct v4l2_window32 w32;
56 if (copy_from_user(&w32, p32, sizeof(w32)))
59 *p64 = (struct v4l2_window) {
62 .chromakey = w32.chromakey,
66 .global_alpha = w32.global_alpha,
72 static int put_v4l2_window32(struct v4l2_window *p64,
73 struct v4l2_window32 __user *p32)
75 struct v4l2_window32 w32;
77 memset(&w32, 0, sizeof(w32));
78 w32 = (struct v4l2_window32) {
81 .chromakey = p64->chromakey,
85 .global_alpha = p64->global_alpha,
88 if (copy_to_user(p32, &w32, sizeof(w32)))
94 struct v4l2_format32 {
95 __u32 type; /* enum v4l2_buf_type */
97 struct v4l2_pix_format pix;
98 struct v4l2_pix_format_mplane pix_mp;
99 struct v4l2_window32 win;
100 struct v4l2_vbi_format vbi;
101 struct v4l2_sliced_vbi_format sliced;
102 struct v4l2_sdr_format sdr;
103 struct v4l2_meta_format meta;
104 __u8 raw_data[200]; /* user-defined */
109 * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument
110 * @index: on return, index of the first created buffer
111 * @count: entry: number of requested buffers,
112 * return: number of created buffers
113 * @memory: buffer memory type
114 * @format: frame format, for which buffers are requested
115 * @capabilities: capabilities of this buffer type.
116 * @flags: additional buffer management attributes (ignored unless the
117 * queue has V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS capability and
118 * configured for MMAP streaming I/O).
119 * @reserved: future extensions
121 struct v4l2_create_buffers32 {
124 __u32 memory; /* enum v4l2_memory */
125 struct v4l2_format32 format;
131 static int get_v4l2_format32(struct v4l2_format *p64,
132 struct v4l2_format32 __user *p32)
134 if (get_user(p64->type, &p32->type))
138 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
139 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
140 return copy_from_user(&p64->fmt.pix, &p32->fmt.pix,
141 sizeof(p64->fmt.pix)) ? -EFAULT : 0;
142 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
143 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
144 return copy_from_user(&p64->fmt.pix_mp, &p32->fmt.pix_mp,
145 sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;
146 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
147 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
148 return get_v4l2_window32(&p64->fmt.win, &p32->fmt.win);
149 case V4L2_BUF_TYPE_VBI_CAPTURE:
150 case V4L2_BUF_TYPE_VBI_OUTPUT:
151 return copy_from_user(&p64->fmt.vbi, &p32->fmt.vbi,
152 sizeof(p64->fmt.vbi)) ? -EFAULT : 0;
153 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
154 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
155 return copy_from_user(&p64->fmt.sliced, &p32->fmt.sliced,
156 sizeof(p64->fmt.sliced)) ? -EFAULT : 0;
157 case V4L2_BUF_TYPE_SDR_CAPTURE:
158 case V4L2_BUF_TYPE_SDR_OUTPUT:
159 return copy_from_user(&p64->fmt.sdr, &p32->fmt.sdr,
160 sizeof(p64->fmt.sdr)) ? -EFAULT : 0;
161 case V4L2_BUF_TYPE_META_CAPTURE:
162 case V4L2_BUF_TYPE_META_OUTPUT:
163 return copy_from_user(&p64->fmt.meta, &p32->fmt.meta,
164 sizeof(p64->fmt.meta)) ? -EFAULT : 0;
170 static int get_v4l2_create32(struct v4l2_create_buffers *p64,
171 struct v4l2_create_buffers32 __user *p32)
173 if (copy_from_user(p64, p32,
174 offsetof(struct v4l2_create_buffers32, format)))
176 if (copy_from_user(&p64->flags, &p32->flags, sizeof(p32->flags)))
178 return get_v4l2_format32(&p64->format, &p32->format);
181 static int put_v4l2_format32(struct v4l2_format *p64,
182 struct v4l2_format32 __user *p32)
185 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
186 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
187 return copy_to_user(&p32->fmt.pix, &p64->fmt.pix,
188 sizeof(p64->fmt.pix)) ? -EFAULT : 0;
189 case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
190 case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
191 return copy_to_user(&p32->fmt.pix_mp, &p64->fmt.pix_mp,
192 sizeof(p64->fmt.pix_mp)) ? -EFAULT : 0;
193 case V4L2_BUF_TYPE_VIDEO_OVERLAY:
194 case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
195 return put_v4l2_window32(&p64->fmt.win, &p32->fmt.win);
196 case V4L2_BUF_TYPE_VBI_CAPTURE:
197 case V4L2_BUF_TYPE_VBI_OUTPUT:
198 return copy_to_user(&p32->fmt.vbi, &p64->fmt.vbi,
199 sizeof(p64->fmt.vbi)) ? -EFAULT : 0;
200 case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
201 case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
202 return copy_to_user(&p32->fmt.sliced, &p64->fmt.sliced,
203 sizeof(p64->fmt.sliced)) ? -EFAULT : 0;
204 case V4L2_BUF_TYPE_SDR_CAPTURE:
205 case V4L2_BUF_TYPE_SDR_OUTPUT:
206 return copy_to_user(&p32->fmt.sdr, &p64->fmt.sdr,
207 sizeof(p64->fmt.sdr)) ? -EFAULT : 0;
208 case V4L2_BUF_TYPE_META_CAPTURE:
209 case V4L2_BUF_TYPE_META_OUTPUT:
210 return copy_to_user(&p32->fmt.meta, &p64->fmt.meta,
211 sizeof(p64->fmt.meta)) ? -EFAULT : 0;
217 static int put_v4l2_create32(struct v4l2_create_buffers *p64,
218 struct v4l2_create_buffers32 __user *p32)
220 if (copy_to_user(p32, p64,
221 offsetof(struct v4l2_create_buffers32, format)) ||
222 put_user(p64->capabilities, &p32->capabilities) ||
223 put_user(p64->flags, &p32->flags) ||
224 copy_to_user(p32->reserved, p64->reserved, sizeof(p64->reserved)))
226 return put_v4l2_format32(&p64->format, &p32->format);
229 struct v4l2_standard32 {
233 struct v4l2_fract frameperiod; /* Frames, not fields */
238 static int get_v4l2_standard32(struct v4l2_standard *p64,
239 struct v4l2_standard32 __user *p32)
241 /* other fields are not set by the user, nor used by the driver */
242 return get_user(p64->index, &p32->index);
245 static int put_v4l2_standard32(struct v4l2_standard *p64,
246 struct v4l2_standard32 __user *p32)
248 if (put_user(p64->index, &p32->index) ||
249 put_user(p64->id, &p32->id) ||
250 copy_to_user(p32->name, p64->name, sizeof(p32->name)) ||
251 copy_to_user(&p32->frameperiod, &p64->frameperiod,
252 sizeof(p32->frameperiod)) ||
253 put_user(p64->framelines, &p32->framelines) ||
254 copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
259 struct v4l2_plane32 {
264 compat_long_t userptr;
272 * This is correct for all architectures including i386, but not x32,
273 * which has different alignment requirements for timestamp
275 struct v4l2_buffer32 {
277 __u32 type; /* enum v4l2_buf_type */
280 __u32 field; /* enum v4l2_field */
285 struct v4l2_timecode timecode;
288 /* memory location */
289 __u32 memory; /* enum v4l2_memory */
292 compat_long_t userptr;
293 compat_caddr_t planes;
301 #ifdef CONFIG_COMPAT_32BIT_TIME
302 struct v4l2_buffer32_time32 {
304 __u32 type; /* enum v4l2_buf_type */
307 __u32 field; /* enum v4l2_field */
308 struct old_timeval32 timestamp;
309 struct v4l2_timecode timecode;
312 /* memory location */
313 __u32 memory; /* enum v4l2_memory */
316 compat_long_t userptr;
317 compat_caddr_t planes;
326 static int get_v4l2_plane32(struct v4l2_plane *p64,
327 struct v4l2_plane32 __user *p32,
328 enum v4l2_memory memory)
330 struct v4l2_plane32 plane32;
331 typeof(p64->m) m = {};
333 if (copy_from_user(&plane32, p32, sizeof(plane32)))
337 case V4L2_MEMORY_MMAP:
338 case V4L2_MEMORY_OVERLAY:
339 m.mem_offset = plane32.m.mem_offset;
341 case V4L2_MEMORY_USERPTR:
342 m.userptr = (unsigned long)compat_ptr(plane32.m.userptr);
344 case V4L2_MEMORY_DMABUF:
349 memset(p64, 0, sizeof(*p64));
350 *p64 = (struct v4l2_plane) {
351 .bytesused = plane32.bytesused,
352 .length = plane32.length,
354 .data_offset = plane32.data_offset,
360 static int put_v4l2_plane32(struct v4l2_plane *p64,
361 struct v4l2_plane32 __user *p32,
362 enum v4l2_memory memory)
364 struct v4l2_plane32 plane32;
366 memset(&plane32, 0, sizeof(plane32));
367 plane32 = (struct v4l2_plane32) {
368 .bytesused = p64->bytesused,
369 .length = p64->length,
370 .data_offset = p64->data_offset,
374 case V4L2_MEMORY_MMAP:
375 case V4L2_MEMORY_OVERLAY:
376 plane32.m.mem_offset = p64->m.mem_offset;
378 case V4L2_MEMORY_USERPTR:
379 plane32.m.userptr = (uintptr_t)(p64->m.userptr);
381 case V4L2_MEMORY_DMABUF:
382 plane32.m.fd = p64->m.fd;
386 if (copy_to_user(p32, &plane32, sizeof(plane32)))
392 static int get_v4l2_buffer32(struct v4l2_buffer *vb,
393 struct v4l2_buffer32 __user *arg)
395 struct v4l2_buffer32 vb32;
397 if (copy_from_user(&vb32, arg, sizeof(vb32)))
400 memset(vb, 0, sizeof(*vb));
401 *vb = (struct v4l2_buffer) {
404 .bytesused = vb32.bytesused,
407 .timestamp.tv_sec = vb32.timestamp.tv_sec,
408 .timestamp.tv_usec = vb32.timestamp.tv_usec,
409 .timecode = vb32.timecode,
410 .sequence = vb32.sequence,
411 .memory = vb32.memory,
412 .m.offset = vb32.m.offset,
413 .length = vb32.length,
414 .request_fd = vb32.request_fd,
417 switch (vb->memory) {
418 case V4L2_MEMORY_MMAP:
419 case V4L2_MEMORY_OVERLAY:
420 vb->m.offset = vb32.m.offset;
422 case V4L2_MEMORY_USERPTR:
423 vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr);
425 case V4L2_MEMORY_DMABUF:
426 vb->m.fd = vb32.m.fd;
430 if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
431 vb->m.planes = (void __force *)
432 compat_ptr(vb32.m.planes);
437 #ifdef CONFIG_COMPAT_32BIT_TIME
438 static int get_v4l2_buffer32_time32(struct v4l2_buffer *vb,
439 struct v4l2_buffer32_time32 __user *arg)
441 struct v4l2_buffer32_time32 vb32;
443 if (copy_from_user(&vb32, arg, sizeof(vb32)))
446 *vb = (struct v4l2_buffer) {
449 .bytesused = vb32.bytesused,
452 .timestamp.tv_sec = vb32.timestamp.tv_sec,
453 .timestamp.tv_usec = vb32.timestamp.tv_usec,
454 .timecode = vb32.timecode,
455 .sequence = vb32.sequence,
456 .memory = vb32.memory,
457 .m.offset = vb32.m.offset,
458 .length = vb32.length,
459 .request_fd = vb32.request_fd,
461 switch (vb->memory) {
462 case V4L2_MEMORY_MMAP:
463 case V4L2_MEMORY_OVERLAY:
464 vb->m.offset = vb32.m.offset;
466 case V4L2_MEMORY_USERPTR:
467 vb->m.userptr = (unsigned long)compat_ptr(vb32.m.userptr);
469 case V4L2_MEMORY_DMABUF:
470 vb->m.fd = vb32.m.fd;
474 if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
475 vb->m.planes = (void __force *)
476 compat_ptr(vb32.m.planes);
482 static int put_v4l2_buffer32(struct v4l2_buffer *vb,
483 struct v4l2_buffer32 __user *arg)
485 struct v4l2_buffer32 vb32;
487 memset(&vb32, 0, sizeof(vb32));
488 vb32 = (struct v4l2_buffer32) {
491 .bytesused = vb->bytesused,
494 .timestamp.tv_sec = vb->timestamp.tv_sec,
495 .timestamp.tv_usec = vb->timestamp.tv_usec,
496 .timecode = vb->timecode,
497 .sequence = vb->sequence,
498 .memory = vb->memory,
499 .m.offset = vb->m.offset,
500 .length = vb->length,
501 .request_fd = vb->request_fd,
504 switch (vb->memory) {
505 case V4L2_MEMORY_MMAP:
506 case V4L2_MEMORY_OVERLAY:
507 vb32.m.offset = vb->m.offset;
509 case V4L2_MEMORY_USERPTR:
510 vb32.m.userptr = (uintptr_t)(vb->m.userptr);
512 case V4L2_MEMORY_DMABUF:
513 vb32.m.fd = vb->m.fd;
517 if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
518 vb32.m.planes = (uintptr_t)vb->m.planes;
520 if (copy_to_user(arg, &vb32, sizeof(vb32)))
526 #ifdef CONFIG_COMPAT_32BIT_TIME
527 static int put_v4l2_buffer32_time32(struct v4l2_buffer *vb,
528 struct v4l2_buffer32_time32 __user *arg)
530 struct v4l2_buffer32_time32 vb32;
532 memset(&vb32, 0, sizeof(vb32));
533 vb32 = (struct v4l2_buffer32_time32) {
536 .bytesused = vb->bytesused,
539 .timestamp.tv_sec = vb->timestamp.tv_sec,
540 .timestamp.tv_usec = vb->timestamp.tv_usec,
541 .timecode = vb->timecode,
542 .sequence = vb->sequence,
543 .memory = vb->memory,
544 .m.offset = vb->m.offset,
545 .length = vb->length,
546 .request_fd = vb->request_fd,
548 switch (vb->memory) {
549 case V4L2_MEMORY_MMAP:
550 case V4L2_MEMORY_OVERLAY:
551 vb32.m.offset = vb->m.offset;
553 case V4L2_MEMORY_USERPTR:
554 vb32.m.userptr = (uintptr_t)(vb->m.userptr);
556 case V4L2_MEMORY_DMABUF:
557 vb32.m.fd = vb->m.fd;
561 if (V4L2_TYPE_IS_MULTIPLANAR(vb->type))
562 vb32.m.planes = (uintptr_t)vb->m.planes;
564 if (copy_to_user(arg, &vb32, sizeof(vb32)))
571 struct v4l2_framebuffer32 {
587 static int get_v4l2_framebuffer32(struct v4l2_framebuffer *p64,
588 struct v4l2_framebuffer32 __user *p32)
590 if (get_user(p64->capability, &p32->capability) ||
591 get_user(p64->flags, &p32->flags) ||
592 copy_from_user(&p64->fmt, &p32->fmt, sizeof(p64->fmt)))
599 static int put_v4l2_framebuffer32(struct v4l2_framebuffer *p64,
600 struct v4l2_framebuffer32 __user *p32)
602 if (put_user((uintptr_t)p64->base, &p32->base) ||
603 put_user(p64->capability, &p32->capability) ||
604 put_user(p64->flags, &p32->flags) ||
605 copy_to_user(&p32->fmt, &p64->fmt, sizeof(p64->fmt)))
611 struct v4l2_input32 {
612 __u32 index; /* Which input */
613 __u8 name[32]; /* Label */
614 __u32 type; /* Type of input */
615 __u32 audioset; /* Associated audios (bitfield) */
616 __u32 tuner; /* Associated tuner */
624 * The 64-bit v4l2_input struct has extra padding at the end of the struct.
625 * Otherwise it is identical to the 32-bit version.
627 static inline int get_v4l2_input32(struct v4l2_input *p64,
628 struct v4l2_input32 __user *p32)
630 if (copy_from_user(p64, p32, sizeof(*p32)))
635 static inline int put_v4l2_input32(struct v4l2_input *p64,
636 struct v4l2_input32 __user *p32)
638 if (copy_to_user(p32, p64, sizeof(*p32)))
643 struct v4l2_ext_controls32 {
649 compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
652 struct v4l2_ext_control32 {
659 compat_caddr_t string; /* actually char * */
661 } __attribute__ ((packed));
663 /* Return true if this control is a pointer type. */
664 static inline bool ctrl_is_pointer(struct file *file, u32 id)
666 struct video_device *vdev = video_devdata(file);
667 struct v4l2_fh *fh = NULL;
668 struct v4l2_ctrl_handler *hdl = NULL;
669 struct v4l2_query_ext_ctrl qec = { id };
670 const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
672 if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
673 fh = file->private_data;
675 if (fh && fh->ctrl_handler)
676 hdl = fh->ctrl_handler;
677 else if (vdev->ctrl_handler)
678 hdl = vdev->ctrl_handler;
681 struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id);
683 return ctrl && ctrl->is_ptr;
686 if (!ops || !ops->vidioc_query_ext_ctrl)
689 return !ops->vidioc_query_ext_ctrl(file, fh, &qec) &&
690 (qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
693 static int get_v4l2_ext_controls32(struct v4l2_ext_controls *p64,
694 struct v4l2_ext_controls32 __user *p32)
696 struct v4l2_ext_controls32 ec32;
698 if (copy_from_user(&ec32, p32, sizeof(ec32)))
701 *p64 = (struct v4l2_ext_controls) {
704 .error_idx = ec32.error_idx,
705 .request_fd = ec32.request_fd,
706 .reserved[0] = ec32.reserved[0],
707 .controls = (void __force *)compat_ptr(ec32.controls),
713 static int put_v4l2_ext_controls32(struct v4l2_ext_controls *p64,
714 struct v4l2_ext_controls32 __user *p32)
716 struct v4l2_ext_controls32 ec32;
718 memset(&ec32, 0, sizeof(ec32));
719 ec32 = (struct v4l2_ext_controls32) {
722 .error_idx = p64->error_idx,
723 .request_fd = p64->request_fd,
724 .reserved[0] = p64->reserved[0],
725 .controls = (uintptr_t)p64->controls,
728 if (copy_to_user(p32, &ec32, sizeof(ec32)))
736 * x86 is the only compat architecture with different struct alignment
737 * between 32-bit and 64-bit tasks.
739 struct v4l2_event32 {
755 static int put_v4l2_event32(struct v4l2_event *p64,
756 struct v4l2_event32 __user *p32)
758 if (put_user(p64->type, &p32->type) ||
759 copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) ||
760 put_user(p64->pending, &p32->pending) ||
761 put_user(p64->sequence, &p32->sequence) ||
762 put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) ||
763 put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) ||
764 put_user(p64->id, &p32->id) ||
765 copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
772 #ifdef CONFIG_COMPAT_32BIT_TIME
773 struct v4l2_event32_time32 {
781 struct old_timespec32 timestamp;
786 static int put_v4l2_event32_time32(struct v4l2_event *p64,
787 struct v4l2_event32_time32 __user *p32)
789 if (put_user(p64->type, &p32->type) ||
790 copy_to_user(&p32->u, &p64->u, sizeof(p64->u)) ||
791 put_user(p64->pending, &p32->pending) ||
792 put_user(p64->sequence, &p32->sequence) ||
793 put_user(p64->timestamp.tv_sec, &p32->timestamp.tv_sec) ||
794 put_user(p64->timestamp.tv_nsec, &p32->timestamp.tv_nsec) ||
795 put_user(p64->id, &p32->id) ||
796 copy_to_user(p32->reserved, p64->reserved, sizeof(p32->reserved)))
810 static int get_v4l2_edid32(struct v4l2_edid *p64,
811 struct v4l2_edid32 __user *p32)
815 if (copy_from_user(p64, p32, offsetof(struct v4l2_edid32, edid)) ||
816 get_user(edid, &p32->edid))
819 p64->edid = (void __force *)compat_ptr(edid);
823 static int put_v4l2_edid32(struct v4l2_edid *p64,
824 struct v4l2_edid32 __user *p32)
826 if (copy_to_user(p32, p64, offsetof(struct v4l2_edid32, edid)))
832 * List of ioctls that require 32-bits/64-bits conversion
834 * The V4L2 ioctls that aren't listed there don't have pointer arguments
835 * and the struct size is identical for both 32 and 64 bits versions, so
836 * they don't need translations.
839 #define VIDIOC_G_FMT32 _IOWR('V', 4, struct v4l2_format32)
840 #define VIDIOC_S_FMT32 _IOWR('V', 5, struct v4l2_format32)
841 #define VIDIOC_QUERYBUF32 _IOWR('V', 9, struct v4l2_buffer32)
842 #define VIDIOC_G_FBUF32 _IOR ('V', 10, struct v4l2_framebuffer32)
843 #define VIDIOC_S_FBUF32 _IOW ('V', 11, struct v4l2_framebuffer32)
844 #define VIDIOC_QBUF32 _IOWR('V', 15, struct v4l2_buffer32)
845 #define VIDIOC_DQBUF32 _IOWR('V', 17, struct v4l2_buffer32)
846 #define VIDIOC_ENUMSTD32 _IOWR('V', 25, struct v4l2_standard32)
847 #define VIDIOC_ENUMINPUT32 _IOWR('V', 26, struct v4l2_input32)
848 #define VIDIOC_G_EDID32 _IOWR('V', 40, struct v4l2_edid32)
849 #define VIDIOC_S_EDID32 _IOWR('V', 41, struct v4l2_edid32)
850 #define VIDIOC_TRY_FMT32 _IOWR('V', 64, struct v4l2_format32)
851 #define VIDIOC_G_EXT_CTRLS32 _IOWR('V', 71, struct v4l2_ext_controls32)
852 #define VIDIOC_S_EXT_CTRLS32 _IOWR('V', 72, struct v4l2_ext_controls32)
853 #define VIDIOC_TRY_EXT_CTRLS32 _IOWR('V', 73, struct v4l2_ext_controls32)
854 #define VIDIOC_DQEVENT32 _IOR ('V', 89, struct v4l2_event32)
855 #define VIDIOC_CREATE_BUFS32 _IOWR('V', 92, struct v4l2_create_buffers32)
856 #define VIDIOC_PREPARE_BUF32 _IOWR('V', 93, struct v4l2_buffer32)
858 #ifdef CONFIG_COMPAT_32BIT_TIME
859 #define VIDIOC_QUERYBUF32_TIME32 _IOWR('V', 9, struct v4l2_buffer32_time32)
860 #define VIDIOC_QBUF32_TIME32 _IOWR('V', 15, struct v4l2_buffer32_time32)
861 #define VIDIOC_DQBUF32_TIME32 _IOWR('V', 17, struct v4l2_buffer32_time32)
862 #define VIDIOC_DQEVENT32_TIME32 _IOR ('V', 89, struct v4l2_event32_time32)
863 #define VIDIOC_PREPARE_BUF32_TIME32 _IOWR('V', 93, struct v4l2_buffer32_time32)
866 unsigned int v4l2_compat_translate_cmd(unsigned int cmd)
873 case VIDIOC_TRY_FMT32:
874 return VIDIOC_TRY_FMT;
875 case VIDIOC_G_FBUF32:
876 return VIDIOC_G_FBUF;
877 case VIDIOC_S_FBUF32:
878 return VIDIOC_S_FBUF;
879 #ifdef CONFIG_COMPAT_32BIT_TIME
880 case VIDIOC_QUERYBUF32_TIME32:
881 return VIDIOC_QUERYBUF;
882 case VIDIOC_QBUF32_TIME32:
884 case VIDIOC_DQBUF32_TIME32:
886 case VIDIOC_PREPARE_BUF32_TIME32:
887 return VIDIOC_PREPARE_BUF;
889 case VIDIOC_QUERYBUF32:
890 return VIDIOC_QUERYBUF;
895 case VIDIOC_CREATE_BUFS32:
896 return VIDIOC_CREATE_BUFS;
897 case VIDIOC_G_EXT_CTRLS32:
898 return VIDIOC_G_EXT_CTRLS;
899 case VIDIOC_S_EXT_CTRLS32:
900 return VIDIOC_S_EXT_CTRLS;
901 case VIDIOC_TRY_EXT_CTRLS32:
902 return VIDIOC_TRY_EXT_CTRLS;
903 case VIDIOC_PREPARE_BUF32:
904 return VIDIOC_PREPARE_BUF;
905 case VIDIOC_ENUMSTD32:
906 return VIDIOC_ENUMSTD;
907 case VIDIOC_ENUMINPUT32:
908 return VIDIOC_ENUMINPUT;
909 case VIDIOC_G_EDID32:
910 return VIDIOC_G_EDID;
911 case VIDIOC_S_EDID32:
912 return VIDIOC_S_EDID;
914 case VIDIOC_DQEVENT32:
915 return VIDIOC_DQEVENT;
917 #ifdef CONFIG_COMPAT_32BIT_TIME
918 case VIDIOC_DQEVENT32_TIME32:
919 return VIDIOC_DQEVENT;
925 int v4l2_compat_get_user(void __user *arg, void *parg, unsigned int cmd)
930 case VIDIOC_TRY_FMT32:
931 return get_v4l2_format32(parg, arg);
933 case VIDIOC_S_FBUF32:
934 return get_v4l2_framebuffer32(parg, arg);
935 #ifdef CONFIG_COMPAT_32BIT_TIME
936 case VIDIOC_QUERYBUF32_TIME32:
937 case VIDIOC_QBUF32_TIME32:
938 case VIDIOC_DQBUF32_TIME32:
939 case VIDIOC_PREPARE_BUF32_TIME32:
940 return get_v4l2_buffer32_time32(parg, arg);
942 case VIDIOC_QUERYBUF32:
945 case VIDIOC_PREPARE_BUF32:
946 return get_v4l2_buffer32(parg, arg);
948 case VIDIOC_G_EXT_CTRLS32:
949 case VIDIOC_S_EXT_CTRLS32:
950 case VIDIOC_TRY_EXT_CTRLS32:
951 return get_v4l2_ext_controls32(parg, arg);
953 case VIDIOC_CREATE_BUFS32:
954 return get_v4l2_create32(parg, arg);
956 case VIDIOC_ENUMSTD32:
957 return get_v4l2_standard32(parg, arg);
959 case VIDIOC_ENUMINPUT32:
960 return get_v4l2_input32(parg, arg);
962 case VIDIOC_G_EDID32:
963 case VIDIOC_S_EDID32:
964 return get_v4l2_edid32(parg, arg);
969 int v4l2_compat_put_user(void __user *arg, void *parg, unsigned int cmd)
974 case VIDIOC_TRY_FMT32:
975 return put_v4l2_format32(parg, arg);
977 case VIDIOC_G_FBUF32:
978 return put_v4l2_framebuffer32(parg, arg);
979 #ifdef CONFIG_COMPAT_32BIT_TIME
980 case VIDIOC_QUERYBUF32_TIME32:
981 case VIDIOC_QBUF32_TIME32:
982 case VIDIOC_DQBUF32_TIME32:
983 case VIDIOC_PREPARE_BUF32_TIME32:
984 return put_v4l2_buffer32_time32(parg, arg);
986 case VIDIOC_QUERYBUF32:
989 case VIDIOC_PREPARE_BUF32:
990 return put_v4l2_buffer32(parg, arg);
992 case VIDIOC_G_EXT_CTRLS32:
993 case VIDIOC_S_EXT_CTRLS32:
994 case VIDIOC_TRY_EXT_CTRLS32:
995 return put_v4l2_ext_controls32(parg, arg);
997 case VIDIOC_CREATE_BUFS32:
998 return put_v4l2_create32(parg, arg);
1000 case VIDIOC_ENUMSTD32:
1001 return put_v4l2_standard32(parg, arg);
1003 case VIDIOC_ENUMINPUT32:
1004 return put_v4l2_input32(parg, arg);
1006 case VIDIOC_G_EDID32:
1007 case VIDIOC_S_EDID32:
1008 return put_v4l2_edid32(parg, arg);
1009 #ifdef CONFIG_X86_64
1010 case VIDIOC_DQEVENT32:
1011 return put_v4l2_event32(parg, arg);
1013 #ifdef CONFIG_COMPAT_32BIT_TIME
1014 case VIDIOC_DQEVENT32_TIME32:
1015 return put_v4l2_event32_time32(parg, arg);
1021 int v4l2_compat_get_array_args(struct file *file, void *mbuf,
1022 void __user *user_ptr, size_t array_size,
1023 unsigned int cmd, void *arg)
1027 memset(mbuf, 0, array_size);
1030 #ifdef CONFIG_COMPAT_32BIT_TIME
1031 case VIDIOC_QUERYBUF32_TIME32:
1032 case VIDIOC_QBUF32_TIME32:
1033 case VIDIOC_DQBUF32_TIME32:
1034 case VIDIOC_PREPARE_BUF32_TIME32:
1036 case VIDIOC_QUERYBUF32:
1038 case VIDIOC_DQBUF32:
1039 case VIDIOC_PREPARE_BUF32: {
1040 struct v4l2_buffer *b64 = arg;
1041 struct v4l2_plane *p64 = mbuf;
1042 struct v4l2_plane32 __user *p32 = user_ptr;
1044 if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {
1045 u32 num_planes = b64->length;
1047 if (num_planes == 0)
1050 while (num_planes--) {
1051 err = get_v4l2_plane32(p64, p32, b64->memory);
1060 case VIDIOC_G_EXT_CTRLS32:
1061 case VIDIOC_S_EXT_CTRLS32:
1062 case VIDIOC_TRY_EXT_CTRLS32: {
1063 struct v4l2_ext_controls *ecs64 = arg;
1064 struct v4l2_ext_control *ec64 = mbuf;
1065 struct v4l2_ext_control32 __user *ec32 = user_ptr;
1068 for (n = 0; n < ecs64->count; n++) {
1069 if (copy_from_user(ec64, ec32, sizeof(*ec32)))
1072 if (ctrl_is_pointer(file, ec64->id)) {
1075 if (get_user(p, &ec32->string))
1077 ec64->string = compat_ptr(p);
1085 if (copy_from_user(mbuf, user_ptr, array_size))
1093 int v4l2_compat_put_array_args(struct file *file, void __user *user_ptr,
1094 void *mbuf, size_t array_size,
1095 unsigned int cmd, void *arg)
1100 #ifdef CONFIG_COMPAT_32BIT_TIME
1101 case VIDIOC_QUERYBUF32_TIME32:
1102 case VIDIOC_QBUF32_TIME32:
1103 case VIDIOC_DQBUF32_TIME32:
1104 case VIDIOC_PREPARE_BUF32_TIME32:
1106 case VIDIOC_QUERYBUF32:
1108 case VIDIOC_DQBUF32:
1109 case VIDIOC_PREPARE_BUF32: {
1110 struct v4l2_buffer *b64 = arg;
1111 struct v4l2_plane *p64 = mbuf;
1112 struct v4l2_plane32 __user *p32 = user_ptr;
1114 if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {
1115 u32 num_planes = b64->length;
1117 if (num_planes == 0)
1120 while (num_planes--) {
1121 err = put_v4l2_plane32(p64, p32, b64->memory);
1130 case VIDIOC_G_EXT_CTRLS32:
1131 case VIDIOC_S_EXT_CTRLS32:
1132 case VIDIOC_TRY_EXT_CTRLS32: {
1133 struct v4l2_ext_controls *ecs64 = arg;
1134 struct v4l2_ext_control *ec64 = mbuf;
1135 struct v4l2_ext_control32 __user *ec32 = user_ptr;
1138 for (n = 0; n < ecs64->count; n++) {
1139 unsigned int size = sizeof(*ec32);
1141 * Do not modify the pointer when copying a pointer
1142 * control. The contents of the pointer was changed,
1143 * not the pointer itself.
1144 * The structures are otherwise compatible.
1146 if (ctrl_is_pointer(file, ec64->id))
1147 size -= sizeof(ec32->value64);
1149 if (copy_to_user(ec32, ec64, size))
1158 if (copy_to_user(user_ptr, mbuf, array_size))
1167 * v4l2_compat_ioctl32() - Handles a compat32 ioctl call
1169 * @file: pointer to &struct file with the file handler
1170 * @cmd: ioctl to be called
1171 * @arg: arguments passed from/to the ioctl handler
1173 * This function is meant to be used as .compat_ioctl fops at v4l2-dev.c
1174 * in order to deal with 32-bit calls on a 64-bits Kernel.
1176 * This function calls do_video_ioctl() for non-private V4L2 ioctls.
1177 * If the function is a private one it calls vdev->fops->compat_ioctl32
1180 long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
1182 struct video_device *vdev = video_devdata(file);
1183 long ret = -ENOIOCTLCMD;
1185 if (!file->f_op->unlocked_ioctl)
1188 if (!video_is_registered(vdev))
1191 if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE)
1192 ret = file->f_op->unlocked_ioctl(file, cmd,
1193 (unsigned long)compat_ptr(arg));
1194 else if (vdev->fops->compat_ioctl32)
1195 ret = vdev->fops->compat_ioctl32(file, cmd, arg);
1197 if (ret == -ENOIOCTLCMD)
1198 pr_debug("compat_ioctl32: unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
1199 _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
1202 EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);