v4l2_ioctl调用过程
应用层:
ioctl(dev->fd, VIDIOC_DQBUF, &buf))
ioctl(dev->fd, VIDIOC_QBUF, &buf)
驱动层:
v4L2_fops.unlocked_ioctl
-->.v4L2_ioctl
-->vdev = video_devdata(filp);
vdev->fops->unlocked_ioctl(filp, cmd, arg);//调用设备提供的unlocked_ioctl 如果是uvc则指向.unlocked_ioctl= video_ioctl2
video_ioctl2//函数位置为kernel\drivers\media\v4l2-core\v4l2-ioctl.c
-->video_usercopy(file, cmd, arg, __video_do_ioctl)//__video_do_ioctl为一个回调函数,在video_usercopy中调用
-->__video_do_ioctl
video_usercopy
函数定义如下:
long video_usercopy(struct file *file, unsigned int cmd, unsigned long arg, v4l2_kioctl func)
{
......
if (v4l2_is_known_ioctl(cmd)) {
//检查cmd是否支持
u32 flags = v4l2_ioctls[_IOC_NR(cmd)].flags;
if (flags & INFO_FL_CLEAR_MASK)
n = (flags & INFO_FL_CLEAR_MASK) >> 16;
}
if (copy_from_user(parg, (void __user *)arg, n))//从用户空间拷贝数据到内核空间
goto out;
/* Handles IOCTL */
err = func(file, cmd, parg);//执行对应的ioctl操作就对应到__video_do_ioctl
if (err == -ENOTTY || err == -ENOIOCTLCMD) {
err = -ENOTTY;
goto out;
}
if (has_array_args) {
*kernel_ptr = (void __force *)user_ptr;
if (copy_to_user(user_ptr, mbuf, array_size))//将数据拷贝回到用户空间
err = -EFAULT;
goto out_array_args;
}
......
}
回调函数__video_do_ioctl
定义如下:
static long __video_do_ioctl(struct file *file,
unsigned int cmd, void *arg)
{
......
if (ops == NULL) {
pr_warn("%s: has no ioctl_ops.\n",
video_device_node_name(vfd));
return ret;
}
if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags))
vfh = file->private_data;
if (v4l2_is_known_ioctl(cmd)) {
//这个函数没啥好讲的,看着就是判定cmd是否在当前所有支持的里面。
info = &v4l2_ioctls[_IOC_NR(cmd)];//获取对应cmd的info参数
if (!test_bit(_IOC_NR(cmd), vfd->valid_ioctls) &&
!((