从应用调用vivi驱动分析v4l2 -- select

本文详细介绍了Linux V4L2架构下使用select进行数据读取的过程,包括select调用流程、vivi_poll和vb2_poll的具体实现,并分析了vb2_core_poll中如何判断是否有数据可读。

Linux v4l2架构学习总链接

vivi代码

v4l2测试代码

step 7 : 读取数据

1,poll或者select

这里使用select,对应代码如下

		fd_set fds;
		struct timeval tv;
		int r;

		FD_ZERO (&fds);
		FD_SET(fd, &fds);
		tv.tv_sec = 5;
		tv.tv_usec = 0;

		r = select (fd + 1, &fds, NULL, NULL, &tv);

		if (-1 == r) 
		{
			if (EINTR == errno)
				continue;
			printf ("select err\n");
		}
		if (0 == r) 
		{
			fprintf (stderr, "select timeout\n");
			exit (EXIT_FAILURE);
		}
                //ok

对于select其调用过程如下

SYSCALL_DEFINE5(select  -- kernel/fs/select.c
    kern_select
        core_sys_select
            do_select
                vfs_poll
                    file->f_op->poll 
                        ...
                            vivi_poll

具体过程不分析,这里看vivi_poll

vivi_poll(struct file *file, struct poll_table_struct *wait)
{
	struct vivi_dev *dev = video_drvdata(file);
	struct vb2_queue *q = &dev->vb_vidq;

	dprintk(dev, 1, "%s\n", __func__);
	return vb2_poll(q, file, wait);
}

__poll_t vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
{
	struct video_device *vfd = video_devdata(file);
	__poll_t req_events = poll_requested_events(wait);
	__poll_t res = 0;


        /*
         * 对于V4L2_FL_USES_V4L2_FH
         * 具体的作用没有看明白
         */



	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {struct v4l2_fh *fh = file->private_data;


                /*
                 * 对于pending
                 * 就是判断fh->navailable的值
                 * 这里以后分析
                 */

		if (v4l2_event_pending(fh))
			res = EPOLLPRI;
		else if (req_events & EPOLLPRI)
                    
                        /*
                         * 对于poll_wait这个暂时没有追着看
                         * 应用poll的时候走不到这里
                         * 只有select的时候才会走到
                         */
			poll_wait(file, &fh->wait, wait);
	}
        
        /*
         * 分析 vb2_core_poll
         */

	return res | vb2_core_poll(q, file, wait);
}

vivi_poll
    vb2_poll
        vb2_core_poll

__poll_t vb2_core_poll(struct vb2_queue *q, struct file *file,
		poll_table *wait)
{
	...

        /*
         * 之前分析过vivi stream_on后就会开始产生数据
         * 产生数据后会调用vb2_buffer_done做2件事
         * 1.将填充了数据的buffer挂载到done_list链表上
         * 2.wake_up(&q->done_wq);
         *
         * 所以说如果if条件满足,说明还没有帧数据产生
         * 那么就在这里等着就行
         */


	if (list_empty(&q->done_list)) {
		/*
		 * If the last buffer was dequeued from a capture queue,
		 * return immediately. DQBUF will return -EPIPE.
		 */
		if (q->last_buffer_dequeued)
			return EPOLLIN | EPOLLRDNORM;

		poll_wait(file, &q->done_wq, wait);
	}

	/*
	 * Take first buffer available for dequeuing.
	 */
	spin_lock_irqsave(&q->done_lock, flags);


        /*
         * 发现done_list上不为空,说明有数据
         * 那么就取链表靠前的buffer
         * 这里取buffer的目的只是判断当前buffer是不是有效的
         * 如果无效,那么应用select继续等待
         */


	if (!list_empty(&q->done_list))
		vb = list_first_entry(&q->done_list, struct vb2_buffer,
					done_entry);
	spin_unlock_irqrestore(&q->done_lock, flags);

	if (vb && (vb->state == VB2_BUF_STATE_DONE
			|| vb->state == VB2_BUF_STATE_ERROR)) {
		return (q->is_output) ?
				EPOLLOUT | EPOLLWRNORM :
				EPOLLIN | EPOLLRDNORM;
	}
	return 0;
}

select的应用代码这里先不编写,和后面的一起配合使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

dianlong_lee

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

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

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

打赏作者

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

抵扣说明:

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

余额充值