mirror of
https://github.com/Fishwaldo/Star64_linux.git
synced 2025-07-06 06:21:31 +00:00
[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
1 changed files with 11 additions and 98 deletions
|
@ -294,101 +294,6 @@ void v4l_printk_ioctl(unsigned int cmd)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(v4l_printk_ioctl);
|
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,
|
static void dbgbuf(unsigned int cmd, struct video_device *vfd,
|
||||||
struct v4l2_buffer *p)
|
struct v4l2_buffer *p)
|
||||||
{
|
{
|
||||||
|
@ -2332,8 +2237,9 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
long video_ioctl2(struct file *file,
|
long
|
||||||
unsigned int cmd, unsigned long arg)
|
video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
|
||||||
|
v4l2_kioctl func)
|
||||||
{
|
{
|
||||||
char sbuf[128];
|
char sbuf[128];
|
||||||
void *mbuf = NULL;
|
void *mbuf = NULL;
|
||||||
|
@ -2395,7 +2301,7 @@ long video_ioctl2(struct file *file,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handles IOCTL */
|
/* Handles IOCTL */
|
||||||
err = __video_do_ioctl(file, cmd, parg);
|
err = func(file, cmd, parg);
|
||||||
if (err == -ENOIOCTLCMD)
|
if (err == -ENOIOCTLCMD)
|
||||||
err = -EINVAL;
|
err = -EINVAL;
|
||||||
|
|
||||||
|
@ -2422,4 +2328,11 @@ out:
|
||||||
kfree(mbuf);
|
kfree(mbuf);
|
||||||
return err;
|
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);
|
EXPORT_SYMBOL(video_ioctl2);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue