UVC 驱动调用过程与驱动框架的简单分析 v4l2

UVC 驱动整体调用流程:

/* 打开设备描述符 */
1. open:
        uvc_v4l2_open
/* 查询设备属性 */
2. VIDIOC_QUERYCAP
		if (video->streaming->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
			cap->capabilities = V4L2_CAP_VIDEO_CAPTURE
					  | V4L2_CAP_STREAMING;
		else
			cap->capabilities = V4L2_CAP_VIDEO_OUTPUT
					  | V4L2_CAP_STREAMING;
/* 枚举设备支持的格式 */
3. VIDIOC_ENUM_FMT
        format = &video->streaming->format[fmt->index];
/* 得到设备当前所使用的 format 与 frame */
4. VIDIOC_G_FMT
        uvc_v4l2_get_format
        	struct uvc_format *format = video->streaming->cur_format;
        	struct uvc_frame *frame = video->streaming->cur_frame;
/* Check if the hardware supports the requested format. */
5. VIDIOC_TRY_FMT
        uvc_v4l2_try_format
/* 设置数据,此时并没有真正的设置,而是在启动视频流时将数据发送给设备 */
6. VIDIOC_S_FMT
        uvc_v4l2_set_format
            uvc_v4l2_try_format
        	video->streaming->cur_format = format;
        	video->streaming->cur_frame = frame;
/* 分配视频缓冲区 */
7. VIDIOC_REQBUFS
        uvc_alloc_buffers
           	for (; nbuffers > 0; --nbuffers) {
        		mem = vmalloc_32(nbuffers * bufsize);
        		if (mem != NULL)
        			break;
        	}
/* 查询并获取到分配的缓冲区信息 */
8. VIDIOC_QUERYBUF
        uvc_query_buffer
            __uvc_query_buffer
/* 映射缓冲区地址到用户空间 */
9. mmap
        uvc_v4l2_mmap
/* 将 V4L2 信息块放入队列 */
10. VIDIOC_QBUF
        uvc_queue_buffer
            list_add_tail(&buf->queue, &queue->irqqueue);
        	list_add_tail(&buf->stream, &queue->mainqueue);
/* 设置设备并启动视频流 */
11. VIDIOC_STREAMON
        uvc_video_enable(video, 1)
            /* Commit the streaming parameters. */
            uvc_commit_video
                /* 设置 format, frame */
                uvc_set_video_ctrl  
            /* 启动:Initialize isochronous/bulk URBs and allocate transfer buffers. */
            uvc_init_video(video, GFP_KERNEL);
                    uvc_init_video_isoc / uvc_init_video_bulk
                    usb_submit_urb    
/* 休眠等待数据 */
12. poll
        uvc_v4l2_poll
            uvc_queue_poll
                poll_wait(file, &buf->wait, wait);
/* 取出信息块 */
13. VIDIOC_DQBUF
        uvc_dequeue_buffer
        	list_del(&buf->stream);
/* 关闭视频流 */
14. VIDIOC_STREAMOFF
        uvc_video_enable(video, 0);
    		usb_kill_urb(urb);
    		usb_free_urb(urb);

驱动分析,首先找到 UVC 驱动的入口点:

struct uvc_driver uvc_driver = {
	.driver = {
		.name		= "uvcvideo",
		.probe		= uvc_probe,
		.disconnect	= uvc_disconnect,
		.suspend	= uvc_suspend,
		.resume		= uvc_resume,
		.reset_resume	= uvc_reset_resume,
		.id_table	= uvc_ids,
		.supports_autosuspend = 1,
	},
};
usb_register(&uvc_driver.driver);

版权声明:本文为qq_26690505原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。