mirror of https://gitee.com/openkylin/linux.git
[media] v4l: Share code between video_usercopy and video_ioctl2
The two functions are mostly identical. They handle the copy_from_user and copy_to_user operations related with V4L2 ioctls and call the real ioctl handler. Create a __video_usercopy function that implements the core of video_usercopy and video_ioctl2, and call that function from both. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Acked-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
parent
9f00edaef8
commit
fc0a807985
|
@ -294,101 +294,6 @@ void v4l_printk_ioctl(unsigned int cmd)
|
|||
}
|
||||
EXPORT_SYMBOL(v4l_printk_ioctl);
|
||||
|
||||
/*
|
||||
* helper function -- handles userspace copying for ioctl arguments
|
||||
* Obsolete usercopy function - Should be removed soon
|
||||
*/
|
||||
long
|
||||
video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
|
||||
v4l2_kioctl func)
|
||||
{
|
||||
char sbuf[128];
|
||||
void *mbuf = NULL;
|
||||
void *parg = NULL;
|
||||
long err = -EINVAL;
|
||||
int is_ext_ctrl;
|
||||
size_t ctrls_size = 0;
|
||||
void __user *user_ptr = NULL;
|
||||
|
||||
is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
|
||||
cmd == VIDIOC_TRY_EXT_CTRLS);
|
||||
|
||||
/* Copy arguments into temp kernel buffer */
|
||||
switch (_IOC_DIR(cmd)) {
|
||||
case _IOC_NONE:
|
||||
parg = NULL;
|
||||
break;
|
||||
case _IOC_READ:
|
||||
case _IOC_WRITE:
|
||||
case (_IOC_WRITE | _IOC_READ):
|
||||
if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
|
||||
parg = sbuf;
|
||||
} else {
|
||||
/* too big to allocate from stack */
|
||||
mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
|
||||
if (NULL == mbuf)
|
||||
return -ENOMEM;
|
||||
parg = mbuf;
|
||||
}
|
||||
|
||||
err = -EFAULT;
|
||||
if (_IOC_DIR(cmd) & _IOC_WRITE)
|
||||
if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
if (is_ext_ctrl) {
|
||||
struct v4l2_ext_controls *p = parg;
|
||||
|
||||
/* In case of an error, tell the caller that it wasn't
|
||||
a specific control that caused it. */
|
||||
p->error_idx = p->count;
|
||||
user_ptr = (void __user *)p->controls;
|
||||
if (p->count) {
|
||||
ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
|
||||
/* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
|
||||
mbuf = kmalloc(ctrls_size, GFP_KERNEL);
|
||||
err = -ENOMEM;
|
||||
if (NULL == mbuf)
|
||||
goto out_ext_ctrl;
|
||||
err = -EFAULT;
|
||||
if (copy_from_user(mbuf, user_ptr, ctrls_size))
|
||||
goto out_ext_ctrl;
|
||||
p->controls = mbuf;
|
||||
}
|
||||
}
|
||||
|
||||
/* call driver */
|
||||
err = func(file, cmd, parg);
|
||||
if (err == -ENOIOCTLCMD)
|
||||
err = -EINVAL;
|
||||
if (is_ext_ctrl) {
|
||||
struct v4l2_ext_controls *p = parg;
|
||||
|
||||
p->controls = (void *)user_ptr;
|
||||
if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
|
||||
err = -EFAULT;
|
||||
goto out_ext_ctrl;
|
||||
}
|
||||
if (err < 0)
|
||||
goto out;
|
||||
|
||||
out_ext_ctrl:
|
||||
/* Copy results into user buffer */
|
||||
switch (_IOC_DIR(cmd)) {
|
||||
case _IOC_READ:
|
||||
case (_IOC_WRITE | _IOC_READ):
|
||||
if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
|
||||
err = -EFAULT;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
kfree(mbuf);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(video_usercopy);
|
||||
|
||||
static void dbgbuf(unsigned int cmd, struct video_device *vfd,
|
||||
struct v4l2_buffer *p)
|
||||
{
|
||||
|
@ -2332,8 +2237,9 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
|
|||
return ret;
|
||||
}
|
||||
|
||||
long video_ioctl2(struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
long
|
||||
video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
|
||||
v4l2_kioctl func)
|
||||
{
|
||||
char sbuf[128];
|
||||
void *mbuf = NULL;
|
||||
|
@ -2395,7 +2301,7 @@ long video_ioctl2(struct file *file,
|
|||
}
|
||||
|
||||
/* Handles IOCTL */
|
||||
err = __video_do_ioctl(file, cmd, parg);
|
||||
err = func(file, cmd, parg);
|
||||
if (err == -ENOIOCTLCMD)
|
||||
err = -EINVAL;
|
||||
|
||||
|
@ -2422,4 +2328,11 @@ long video_ioctl2(struct file *file,
|
|||
kfree(mbuf);
|
||||
return err;
|
||||
}
|
||||
EXPORT_SYMBOL(video_usercopy);
|
||||
|
||||
long video_ioctl2(struct file *file,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
return video_usercopy(file, cmd, arg, __video_do_ioctl);
|
||||
}
|
||||
EXPORT_SYMBOL(video_ioctl2);
|
||||
|
|
Loading…
Reference in New Issue