从vivi学习V4L2架构(三):VIDIOC_QUERYCAP流程分析

6 篇文章 0 订阅
5 篇文章 0 订阅

ioctl VIDIOC_QUERYCAP流程分析

int result = ioctl(fd, VIDIOC_QUERYCAP, &caps);

第一步根据ioctl会调用到video_device的cdev结构的ops的unlocked_ioctl,也就是v4l2_ioctl

static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{
	struct video_device *vdev = video_devdata(filp);
	int ret = -ENODEV;

	if (vdev->fops->unlocked_ioctl) { //unlocked_ioctl定义了,所以走这里
		if (vdev->lock && mutex_lock_interruptible(vdev->lock))
			return -ERESTARTSYS;
		if (video_is_registered(vdev))
			ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);//调用vivi_template的fops中的unlocked_ioctrl
		if (vdev->lock)
			mutex_unlock(vdev->lock);
	} else if (vdev->fops->ioctl) {
    ... ...
    }
    ... ...
}

也就是在vivi驱动probe时赋值的如下:

static struct video_device vivi_template = {
	.name		= "vivi",
	.fops           = &vivi_fops,
	.ioctl_ops 	= &vivi_ioctl_ops,
	.release	= video_device_release,
	.tvnorms              = V4L2_STD_525_60,
	.current_norm         = V4L2_STD_NTSC_M,
};



最终会调用vivi_fops中的video_ioctl2

static const struct v4l2_file_operations vivi_fops = {
	.owner		= THIS_MODULE,
	.open		= v4l2_fh_open,
	.release        = vivi_close,
	.read           = vivi_read,
	.poll		= vivi_poll,
	.unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */ 
	.mmap           = vivi_mmap,
};

long video_ioctl2(struct file *file,
	       unsigned int cmd, unsigned long arg)
{
    //video_usercopy中会对arg进行一些判断后调用__video_do_ioctl函数
	return video_usercopy(file, cmd, arg, __video_do_ioctl);
}
static long __video_do_ioctl(struct file *file,
		unsigned int cmd, void *arg)
{
	struct video_device *vfd = video_devdata(file);
	const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
	void *fh = file->private_data;
	struct v4l2_fh *vfh = NULL;
	struct v4l2_format f_copy;
	int use_fh_prio = 0;
	long ret = -EINVAL;
... ...
	switch (cmd) {

	/* --- capabilities ------------------------------------------ */
	case VIDIOC_QUERYCAP:
	{
		struct v4l2_capability *cap = (struct v4l2_capability *)arg;

		if (!ops->vidioc_querycap)
			break;
        //下面是直接调用video_device的ioctl_ops
		ret = ops->vidioc_querycap(file, fh, cap);
		if (!ret)
			dbgarg(cmd, "driver=%s, card=%s, bus=%s, "
					"version=0x%08x, "
					"capabilities=0x%08x\n",
					cap->driver, cap->card, cap->bus_info,
					cap->version,
					cap->capabilities);
		break;
	}
... ...
}

video_device的ioctl_ops也是在vivi_template里面赋值为vidioc_quercap

//这函数其实就填充了一些信息返回给应用层,driver,card, version, 能力 
static int vidioc_querycap(struct file *file, void  *priv,
					struct v4l2_capability *cap)
{
	struct vivi_dev *dev = video_drvdata(file);

	strcpy(cap->driver, "vivi");
	strcpy(cap->card, "vivi");
	strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
	cap->version = VIVI_VERSION;
	cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING | \
			    V4L2_CAP_READWRITE;
	return 0;
}

总的来说调用流程如下:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值