从应用调用vivi驱动分析v4l2 -- 应用open过程分析

Linux v4l2架构学习总链接

v4l2测试代码

vivi驱动分析如下:

从vivi虚拟摄像头驱动分析v4l2

step 1 : 打开设备节点

int fd = open("/dev/video0", flag);

应用层的open函数最后会对应到驱动的fops的open函数

vivi驱动中配置如下

video_device[vdev->minor] = vdev;
vdev->cdev->ops = &v4l2_fops;
vdev->cdev->owner = owner;

static const struct file_operations v4l2_fops = {
	.owner = THIS_MODULE,
	.open = v4l2_open,
        ...
};

接下来分析 v4l2_open

static int v4l2_open(struct inode *inode, struct file *filp)
{
	struct video_device *vdev;
	int ret = 0;

	/* Check if the video device is available */
	mutex_lock(&videodev_lock);

        /*
         * 这里从filp中得到vdev
         * 原理是获取filp的inode,然后从inode->i_rdev中获取次设备号
         * 以次设备号为下标从数组video_device中获取vdev
         * 注册video节点的时候保存方式是 video_device[vdev->minor] = vdev;
         */

	vdev = video_devdata(filp);

        /*
         * video_is_registered通过判断 vdev->flags中是否置位 V4L2_FL_REGISTERED
         * 驱动中注册video的时候置位代码 
         * set_bit(V4L2_FL_REGISTERED, &vdev->flags);
         */

	/* return ENODEV if the video device has already been removed. */
	if (vdev == NULL || !video_is_registered(vdev)) {
		mutex_unlock(&videodev_lock);
		return -ENODEV;
	}
	/* and increase the device refcount */
	video_get(vdev);
	mutex_unlock(&videodev_lock);

        /*
         * vdev->fops->open
         * vivi驱动中有这句代码 
         * *vfd = vivi_template;
         * 所以可以知道 open就是 vivi_template的fops的open函数
         * 也就是 v4l2_fh_open
         */

	if (vdev->fops->open) {
		if (video_is_registered(vdev))
			ret = vdev->fops->open(filp);
		else
			ret = -ENODEV;
	}

	if (vdev->dev_debug & V4L2_DEV_DEBUG_FOP)
		printk(KERN_DEBUG "%s: open (%d)\n",
			video_device_node_name(vdev), ret);
	/* decrease the refcount in case of an error */
	if (ret)
		video_put(vdev);
	return ret;
}

跟进分析 v4l2_fh_open

这里的fh是file handler的缩写


void v4l2_fh_add(struct v4l2_fh *fh)
{
	unsigned long flags;


        /*
         * fh->vdev->prio 是 global全局的,是一个数组记录prio值
         * fh->prio       是 local本地的prio值
         * v4l2_prio_open的操作就是
         * 1. fh->vdev->prios[V4L2_PRIORITY_DEFAULT]++
         * 2. local值 fh->prio = V4L2_PRIORITY_DEFAULT
         */


	v4l2_prio_open(fh->vdev->prio, &fh->prio);
	spin_lock_irqsave(&fh->vdev->fh_lock, flags);


        /*
         * fh通过list挂载到链表vdev->fh_list上
         */


	list_add(&fh->list, &fh->vdev->fh_list);
	spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
}

void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
{
	fh->vdev = vdev;


        /*
         * 这里的ctrl_handler很重要,后面调用handler ctrl的时候需要它
         * 后面会专门分析 handler ctrl
         */


	/* Inherit from video_device. May be overridden by the driver. */
	fh->ctrl_handler = vdev->ctrl_handler;
	INIT_LIST_HEAD(&fh->list);
        

        /*
         * V4L2_FL_USES_V4L2_FH标志位置位
         * 后面处理handler ctrl的时候应该会用到,遇到再分析
         */


	set_bit(V4L2_FL_USES_V4L2_FH, &fh->vdev->flags);
	/*
	 * determine_valid_ioctls() does not know if struct v4l2_fh
	 * is used by this driver, but here we do. So enable the
	 * prio ioctls here.
	 */

        
        /*
         * VIDIOC_G_PRIORITY 和 VIDIOC_S_PRIORITY 
         * 同样遇到再分析
         */
        

	set_bit(_IOC_NR(VIDIOC_G_PRIORITY), vdev->valid_ioctls);
	set_bit(_IOC_NR(VIDIOC_S_PRIORITY), vdev->valid_ioctls);

	fh->prio = V4L2_PRIORITY_UNSET;

	init_waitqueue_head(&fh->wait);
	INIT_LIST_HEAD(&fh->available);
	INIT_LIST_HEAD(&fh->subscribed);
	fh->sequence = -1;
}

int v4l2_fh_open(struct file *filp)
{

        /*
         * vdev的获取方法见上面的分析
         */

	struct video_device *vdev = video_devdata(filp);
	struct v4l2_fh *fh = kzalloc(sizeof(*fh), GFP_KERNEL);

	filp->private_data = fh;
	if (fh == NULL)
		return -ENOMEM;
	v4l2_fh_init(fh, vdev);
	v4l2_fh_add(fh);
	return 0;
}

总体来看,vivi的open操作主要就是操作了fh,这个fh的作用暂时看不出来。

后面遇到的时候再分析。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

dianlong_lee

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值