/* * Per-ioctl data copy handlers. * * Those come in pairs, with a get_v4l2_foo() and a put_v4l2_foo() routine, * where "v4l2_foo" is the name of the V4L2 struct. * * They basically get two __user pointers, one with a 32-bits struct that * came from the userspace call and a 64-bits struct, also allocated as * userspace, but filled internally by do_video_ioctl(). * * For ioctls that have pointers inside it, the functions will also * receive an ancillary buffer with extra space, used to pass extra * data to the routine.
*/
/** * struct v4l2_create_buffers32 - VIDIOC_CREATE_BUFS32 argument * @index: on return, index of the first created buffer * @count: entry: number of requested buffers, * return: number of created buffers * @memory: buffer memory type * @format: frame format, for which buffers are requested * @capabilities: capabilities of this buffer type. * @flags: additional buffer management attributes (ignored unless the * queue has V4L2_BUF_CAP_SUPPORTS_MMAP_CACHE_HINTS capability and * configured for MMAP streaming I/O). * @max_num_buffers: if V4L2_BUF_CAP_SUPPORTS_MAX_NUM_BUFFERS capability flag is set * this field indicate the maximum possible number of buffers * for this queue. * @reserved: future extensions
*/ struct v4l2_create_buffers32 {
__u32 index;
__u32 count;
__u32 memory; /* enum v4l2_memory */ struct v4l2_format32 format;
__u32 capabilities;
__u32 flags;
__u32 max_num_buffers;
__u32 reserved[5];
};
staticint get_v4l2_standard32(struct v4l2_standard *p64, struct v4l2_standard32 __user *p32)
{ /* other fields are not set by the user, nor used by the driver */ return get_user(p64->index, &p32->index);
}
/* * The 64-bit v4l2_input struct has extra padding at the end of the struct. * Otherwise it is identical to the 32-bit version.
*/ staticinlineint get_v4l2_input32(struct v4l2_input *p64, struct v4l2_input32 __user *p32)
{ if (copy_from_user(p64, p32, sizeof(*p32))) return -EFAULT; return 0;
}
/* * List of ioctls that require 32-bits/64-bits conversion * * The V4L2 ioctls that aren't listed there don't have pointer arguments * and the struct size is identical for both 32 and 64 bits versions, so * they don't need translations.
*/
unsignedint v4l2_compat_translate_cmd(unsignedint cmd)
{ switch (cmd) { case VIDIOC_G_FMT32: return VIDIOC_G_FMT; case VIDIOC_S_FMT32: return VIDIOC_S_FMT; case VIDIOC_TRY_FMT32: return VIDIOC_TRY_FMT; case VIDIOC_G_FBUF32: return VIDIOC_G_FBUF; case VIDIOC_S_FBUF32: return VIDIOC_S_FBUF; #ifdef CONFIG_COMPAT_32BIT_TIME case VIDIOC_QUERYBUF32_TIME32: return VIDIOC_QUERYBUF; case VIDIOC_QBUF32_TIME32: return VIDIOC_QBUF; case VIDIOC_DQBUF32_TIME32: return VIDIOC_DQBUF; case VIDIOC_PREPARE_BUF32_TIME32: return VIDIOC_PREPARE_BUF; #endif case VIDIOC_QUERYBUF32: return VIDIOC_QUERYBUF; case VIDIOC_QBUF32: return VIDIOC_QBUF; case VIDIOC_DQBUF32: return VIDIOC_DQBUF; case VIDIOC_CREATE_BUFS32: return VIDIOC_CREATE_BUFS; case VIDIOC_G_EXT_CTRLS32: return VIDIOC_G_EXT_CTRLS; case VIDIOC_S_EXT_CTRLS32: return VIDIOC_S_EXT_CTRLS; case VIDIOC_TRY_EXT_CTRLS32: return VIDIOC_TRY_EXT_CTRLS; case VIDIOC_PREPARE_BUF32: return VIDIOC_PREPARE_BUF; case VIDIOC_ENUMSTD32: return VIDIOC_ENUMSTD; case VIDIOC_ENUMINPUT32: return VIDIOC_ENUMINPUT; case VIDIOC_G_EDID32: return VIDIOC_G_EDID; case VIDIOC_S_EDID32: return VIDIOC_S_EDID; #ifdef CONFIG_X86_64 case VIDIOC_DQEVENT32: return VIDIOC_DQEVENT; #endif #ifdef CONFIG_COMPAT_32BIT_TIME case VIDIOC_DQEVENT32_TIME32: return VIDIOC_DQEVENT; #endif
} return cmd;
}
int v4l2_compat_get_user(void __user *arg, void *parg, unsignedint cmd)
{ switch (cmd) { case VIDIOC_G_FMT32: case VIDIOC_S_FMT32: case VIDIOC_TRY_FMT32: return get_v4l2_format32(parg, arg);
case VIDIOC_S_FBUF32: return get_v4l2_framebuffer32(parg, arg); #ifdef CONFIG_COMPAT_32BIT_TIME case VIDIOC_QUERYBUF32_TIME32: case VIDIOC_QBUF32_TIME32: case VIDIOC_DQBUF32_TIME32: case VIDIOC_PREPARE_BUF32_TIME32: return get_v4l2_buffer32_time32(parg, arg); #endif case VIDIOC_QUERYBUF32: case VIDIOC_QBUF32: case VIDIOC_DQBUF32: case VIDIOC_PREPARE_BUF32: return get_v4l2_buffer32(parg, arg);
case VIDIOC_G_EXT_CTRLS32: case VIDIOC_S_EXT_CTRLS32: case VIDIOC_TRY_EXT_CTRLS32: return get_v4l2_ext_controls32(parg, arg);
case VIDIOC_CREATE_BUFS32: return get_v4l2_create32(parg, arg);
case VIDIOC_ENUMSTD32: return get_v4l2_standard32(parg, arg);
case VIDIOC_ENUMINPUT32: return get_v4l2_input32(parg, arg);
case VIDIOC_G_EDID32: case VIDIOC_S_EDID32: return get_v4l2_edid32(parg, arg);
} return 0;
}
int v4l2_compat_put_user(void __user *arg, void *parg, unsignedint cmd)
{ switch (cmd) { case VIDIOC_G_FMT32: case VIDIOC_S_FMT32: case VIDIOC_TRY_FMT32: return put_v4l2_format32(parg, arg);
case VIDIOC_G_FBUF32: return put_v4l2_framebuffer32(parg, arg); #ifdef CONFIG_COMPAT_32BIT_TIME case VIDIOC_QUERYBUF32_TIME32: case VIDIOC_QBUF32_TIME32: case VIDIOC_DQBUF32_TIME32: case VIDIOC_PREPARE_BUF32_TIME32: return put_v4l2_buffer32_time32(parg, arg); #endif case VIDIOC_QUERYBUF32: case VIDIOC_QBUF32: case VIDIOC_DQBUF32: case VIDIOC_PREPARE_BUF32: return put_v4l2_buffer32(parg, arg);
case VIDIOC_G_EXT_CTRLS32: case VIDIOC_S_EXT_CTRLS32: case VIDIOC_TRY_EXT_CTRLS32: return put_v4l2_ext_controls32(parg, arg);
case VIDIOC_CREATE_BUFS32: return put_v4l2_create32(parg, arg);
case VIDIOC_ENUMSTD32: return put_v4l2_standard32(parg, arg);
case VIDIOC_ENUMINPUT32: return put_v4l2_input32(parg, arg);
case VIDIOC_G_EDID32: case VIDIOC_S_EDID32: return put_v4l2_edid32(parg, arg); #ifdef CONFIG_X86_64 case VIDIOC_DQEVENT32: return put_v4l2_event32(parg, arg); #endif #ifdef CONFIG_COMPAT_32BIT_TIME case VIDIOC_DQEVENT32_TIME32: return put_v4l2_event32_time32(parg, arg); #endif
} return 0;
}
int v4l2_compat_get_array_args(struct file *file, void *mbuf, void __user *user_ptr, size_t array_size, unsignedint cmd, void *arg)
{ int err = 0;
memset(mbuf, 0, array_size);
switch (cmd) { #ifdef CONFIG_COMPAT_32BIT_TIME case VIDIOC_QUERYBUF32_TIME32: case VIDIOC_QBUF32_TIME32: case VIDIOC_DQBUF32_TIME32: case VIDIOC_PREPARE_BUF32_TIME32: #endif case VIDIOC_QUERYBUF32: case VIDIOC_QBUF32: case VIDIOC_DQBUF32: case VIDIOC_PREPARE_BUF32: { struct v4l2_buffer *b64 = arg; struct v4l2_plane *p64 = mbuf; struct v4l2_plane32 __user *p32 = user_ptr;
if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {
u32 num_planes = b64->length;
if (num_planes == 0) return 0;
while (num_planes--) {
err = get_v4l2_plane32(p64, p32, b64->memory); if (err) return err;
++p64;
++p32;
}
} break;
} case VIDIOC_G_EXT_CTRLS32: case VIDIOC_S_EXT_CTRLS32: case VIDIOC_TRY_EXT_CTRLS32: { struct v4l2_ext_controls *ecs64 = arg; struct v4l2_ext_control *ec64 = mbuf; struct v4l2_ext_control32 __user *ec32 = user_ptr; int n;
for (n = 0; n < ecs64->count; n++) { if (copy_from_user(ec64, ec32, sizeof(*ec32))) return -EFAULT;
if (ctrl_is_pointer(file, ec64->id)) {
compat_uptr_t p;
int v4l2_compat_put_array_args(struct file *file, void __user *user_ptr, void *mbuf, size_t array_size, unsignedint cmd, void *arg)
{ int err = 0;
switch (cmd) { #ifdef CONFIG_COMPAT_32BIT_TIME case VIDIOC_QUERYBUF32_TIME32: case VIDIOC_QBUF32_TIME32: case VIDIOC_DQBUF32_TIME32: case VIDIOC_PREPARE_BUF32_TIME32: #endif case VIDIOC_QUERYBUF32: case VIDIOC_QBUF32: case VIDIOC_DQBUF32: case VIDIOC_PREPARE_BUF32: { struct v4l2_buffer *b64 = arg; struct v4l2_plane *p64 = mbuf; struct v4l2_plane32 __user *p32 = user_ptr;
if (V4L2_TYPE_IS_MULTIPLANAR(b64->type)) {
u32 num_planes = b64->length;
if (num_planes == 0) return 0;
while (num_planes--) {
err = put_v4l2_plane32(p64, p32, b64->memory); if (err) return err;
++p64;
++p32;
}
} break;
} case VIDIOC_G_EXT_CTRLS32: case VIDIOC_S_EXT_CTRLS32: case VIDIOC_TRY_EXT_CTRLS32: { struct v4l2_ext_controls *ecs64 = arg; struct v4l2_ext_control *ec64 = mbuf; struct v4l2_ext_control32 __user *ec32 = user_ptr; int n;
for (n = 0; n < ecs64->count; n++) { unsignedint size = sizeof(*ec32); /* * Do not modify the pointer when copying a pointer * control. The contents of the pointer was changed, * not the pointer itself. * The structures are otherwise compatible.
*/ if (ctrl_is_pointer(file, ec64->id))
size -= sizeof(ec32->value64);
if (copy_to_user(ec32, ec64, size)) return -EFAULT;
/** * v4l2_compat_ioctl32() - Handles a compat32 ioctl call * * @file: pointer to &struct file with the file handler * @cmd: ioctl to be called * @arg: arguments passed from/to the ioctl handler * * This function is meant to be used as .compat_ioctl fops at v4l2-dev.c * in order to deal with 32-bit calls on a 64-bits Kernel. * * This function calls do_video_ioctl() for non-private V4L2 ioctls. * If the function is a private one it calls vdev->fops->compat_ioctl32 * instead.
*/ long v4l2_compat_ioctl32(struct file *file, unsignedint cmd, unsignedlong arg)
{ struct video_device *vdev = video_devdata(file); long ret = -ENOIOCTLCMD;
if (!file->f_op->unlocked_ioctl) return ret;
if (!video_is_registered(vdev)) return -ENODEV;
if (_IOC_TYPE(cmd) == 'V' && _IOC_NR(cmd) < BASE_VIDIOC_PRIVATE)
ret = file->f_op->unlocked_ioctl(file, cmd,
(unsignedlong)compat_ptr(arg)); elseif (vdev->fops->compat_ioctl32)
ret = vdev->fops->compat_ioctl32(file, cmd, arg);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.