UVC 驱动调用过程与驱动框架的简单分析
内核:Linux-3.4.2
驱动:drivers\media\video\uvc\uvc_driver.c
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);
注册了 usb 驱动,如果系统中出现了与其 id_table 匹配的设备,则驱动会与它建立关系并调用 probe 函数:
我们选择比较重要的函数进行分析,在 probe 中的函数调用:
uvc_register_chains -> uvc_register_terms -> uvc_register_video(对类型为 UVC_TT_STREAMING 的video调用本函数)
uvc_register_video 函数如下:
static int uvc_register_video(struct uvc_device *dev,
struct uvc_streaming *stream)
{
struct video_device *vdev;
int ret;
/* 对 video 做一些初始化 */
ret = uvc_video_init(stream);
if (ret < 0) {
uvc_printk(KERN_ERR, "Failed to initialize the device "
"(%d).\n", ret);
return ret;
}
uvc_debugfs_init_stream(stream);
/* 分配一个 video device */
vdev = video_device_alloc();
if (vdev == NULL) {
uvc_printk(KERN_ERR, "Failed to allocate video device (%d).\n",
ret);
return -ENOMEM;
}
/* 配置 video device */
vdev->v4l2_dev = &dev->vdev;
vdev->fops = &uvc_fops;
vdev->release = uvc_release;
strlcpy(vdev->name, dev->name, sizeof vdev->name);
stream->vdev = vdev;
video_set_drvdata(vdev, stream);
/* 注册 video device */
ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
if (ret < 0) {
uvc_printk(KERN_ERR, "Failed to register video device (%d).\n",
ret);
stream->vdev = NULL;
video_device_release(vdev);
return ret;
}
atomic_inc(&dev->nstreams);
return 0;
}
在这里面有个重要的结构,即:
const struct v4l2_file_operations uvc_fops = {
.owner = THIS_MODULE,
.open = uvc_v4l2_open,
.release = uvc_v4l2_release,
.unlocked_ioctl = uvc_v4l2_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl32 = uvc_v4l2_compat_ioctl32,
#endif
.read = uvc_v4l2_read,
.mmap = uvc_v4l2_mmap,
.poll = uvc_v4l2_poll,
#ifndef CONFIG_MMU
.get_unmapped_area = uvc_v4l2_get_unmapped_area,
#endif
};
uvc_v4l2_ioctl 就是实现 V4L2 操作的函数集。
这个 unlocked_ioctl 属性的赋值需要注意一下,当它为 uvc_v4l2_ioctl(当前内核所使用)时,调用的是 uvc_v4l2.c 中现有的函数; 但如果将它赋值为 video_ioctl2 时,内核将调用我们在驱动中 vdev 的 ioctl_ops 属性所赋给的函数集进行操作。
__video_do_ioctl 中:
const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops; 之后就调用 ops 中的一系列函数来操作 video
所以这一系列的函数可以由我们自己来编写。
UVC 驱动调用过程与驱动框架的简单分析的更多相关文章
- go微服务框架go-micro深度学习(五) stream 调用过程详解
上一篇写了一下rpc调用过程的实现方式,简单来说就是服务端把实现了接口的结构体对象进行反射,抽取方法,签名,保存,客户端调用的时候go-micro封请求数据,服务端接收到请求时,找到需要调用调 ...
- Spring源码分析之`BeanFactoryPostProcessor`调用过程
前文传送门: Spring源码分析之预启动流程 Spring源码分析之BeanFactory体系结构 本文内容: AbstractApplicationContext#refresh前部分的一点小内容 ...
- Linux Framebuffer驱动剖析之二—驱动框架、接口实现和使用
深入分析LinuxFramebuffer子系统的驱动框架.接口实现和使用. 一.LinuxFramebuffer的软件需求 上一篇文章详细阐述了LinuxFramebuffer的软件需求(请先理解第一 ...
- Linux驱动之USB总线驱动程序框架简析
通用串行总线(USB)是主机和外围设备之间的一种连接.USB总线规范有1.1版和2.0版,当然现在已经有了3.0版本.USB1.1支持两种传输速度:低速为1.5Mbps,高速为12Mbps.USB2. ...
- ARM-Linux S5PV210 UART驱动(4)----串口驱动初始化过程
对于S5PV210 UART驱动来说,主要关心的就是drivers/serial下的samsung.c和s5pv210.c连个文件. 由drivers/serial/Kconfig: config S ...
- 【驱动】DM9000A网卡驱动框架源码分析
Linux网络设备结构 首先看一下Linux网络设备的结构,如下图: 网络协议接口层向网络层协议提供提供统一的数据包收发接口,不论上层协议为ARP还是IP,都通过dev_queue_xmit()函数发 ...
- ARM Linux驱动篇 学习温度传感器ds18b20的驱动编写过程
ARM Linux驱动篇 学习温度传感器ds18b20的驱动编写过程 原文地址:http://www.cnblogs.com/NickQ/p/9026545.html 一.开发板与ds18b20的入门 ...
- Linux驱动修炼之道-SPI驱动框架源码分析(上)【转】
转自:http://blog.csdn.net/lanmanck/article/details/6895318 SPI驱动架构,以前用过,不过没这个详细,跟各位一起分享: 来自:http://blo ...
- 荣品RP4412开发板摄像头驱动调用及对焦控制
1.关于更换不同摄像头驱动调用问题. 问:RP4412开发板,我用的摄像头640*480图像预览时OK的,但是我调用1280*720的初始化预览,摄像头没有图像了,是不是camera程序也需要修改? ...
随机推荐
- eclipse中设置python的版本
(mac系统)由于系统的python是内置的,无法直接查找到安装文件,则可在eclipse偏好设置-PyDev - Interpreters-Python Interpreter其右边选择Quick ...
- 从今天开始慢慢阅读java9源码决心的声明。
我从很早的时候就好奇java的源码了,因为有使用者就有制作者. 在校期间使用了java两年多的我却不知道java里面的任何东西. 这个寒假前我无意之间看到了java9出现的新闻,网上查询到原来源码就隐 ...
- 学习Python第六天
今天我们讲讲数据类型中的集合,博客写得有点糙,后续应该要进行优化优化了........ 集合:无序,不重复的数据组合,主要作用:去重,把一个列表变成集合,就自动去重了 基本语法:S = {1}类型为集 ...
- C++的IO处理中的头文件以及类理解(2)<sstream>头文件
C++的IO处理中的头文件以及类理解(2)<sstream>头文件 头文件<sstream>中定义的类型都继承iostream头文件中定义的类型.除了继承得来的操作,sstre ...
- MyBatis在非Spring环境下第三方DataSource设置-Druid篇
首先在ITEye上面看到一个同标题文章,在此说明,此文并非转载自 http://iintothewind.iteye.com/blog/2069522 ,因为这篇文章根本就是错误的,照着上面做,工程可 ...
- Android WebView 加载超长 JS 数据
在之前的文章里面,我总结过WebView如何与网页交互,也就是Java如何和JS交互 —— Android WebView 总结 —— Java和JavaScript交互. 基于这篇文章,我们基本上能 ...
- 微信小程序信息展示列表
微信小程序信息展示列表 效果展示: 代码展示: wxml <view class="head"> <view class="head_item" ...
- webpack入门-个人学习资源收集
本来是想自己写哈个人学习webpack心德的,不过网上现在已经有各种比较好的,详细的入门或者深入资源了. 所以我就简单总结了一下,我在入门webpack时看的一些博客和文档,以及顺道看到的一些觉得也应 ...
- Tools - 正版Windows7系统的下载与安装
下载 微软原版系统下载地址:https://msdn.itellyou.cn/ 根据系统类型.语言和版本,下载合适的系统ISO文件. 例如: Windows 7 Professional with S ...
- C++11实现一个轻量级的AOP框架
AOP介绍 AOP(Aspect-Oriented Programming,面向方面编程),可以解决面向对象编程中的一些问题,是OOP的一种有益补充.面向对象编程中的继承是一种从上而下的关系,不适合定 ...