Linux摄像头驱动学习之:(四)UVC-摄像头驱动框架分析
UVC: USB Video Class
UVC驱动:drivers\media\video\uvc\
uvc_driver.c分析:
1. usb_register(&uvc_driver.driver);
2. uvc_probe
uvc_register_video
vdev = video_device_alloc();
vdev->fops = &uvc_fops;
video_register_device
在www.usb.org下载 uvc specification,
UVC 1.5 Class specification.pdf : 有详细描述
USB_Video_Example 1.5.pdf : 有示例
通过VideoControl Interface来控制,
通过VideoStreaming Interface来读视频数据,
VC里含有多个Unit/Terminal等功能模块,可以通过访问这些模块进行控制,比如调亮度
分析UVC驱动调用过程:
const struct v4l2_file_operations uvc_fops = {
.owner = THIS_MODULE,
.open = uvc_v4l2_open,
.release = uvc_v4l2_release,
.ioctl = uvc_v4l2_ioctl,
.read = uvc_v4l2_read,
.mmap = uvc_v4l2_mmap,
.poll = uvc_v4l2_poll,
};
1. open:
uvc_v4l2_open
2. VIDIOC_QUERYCAP // video->streaming->type 应该是在设备被枚举时分析描述符时设置的
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数组应是在设备被枚举时设置的
format = &video->streaming->format[fmt->index];
4. VIDIOC_G_FMT
uvc_v4l2_get_format // USB摄像头支持多种格式fromat, 每种格式下有多种frame(比如分辨率)
struct uvc_format *format = video->streaming->cur_format;
struct uvc_frame *frame = video->streaming->cur_frame;
5. VIDIOC_TRY_FMT
uvc_v4l2_try_format
/* Check if the hardware supports the requested format. */
/* Find the closest image size. The distance between image sizes is
* the size in pixels of the non-overlapping regions between the
* requested size and the frame-specified size.
*/
6. VIDIOC_S_FMT // 只是把参数保存起来,还没有发给USB摄像头
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
memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf); // 复制参数
9. mmap
uvc_v4l2_mmap
10. VIDIOC_QBUF
uvc_queue_buffer
list_add_tail(&buf->stream, &queue->mainqueue);
list_add_tail(&buf->queue, &queue->irqqueue);
11. VIDIOC_STREAMON
uvc_video_enable(video, 1) // 把所设置的参数发给硬件,然后启动摄像头
/* Commit the streaming parameters. */
uvc_commit_video
uvc_set_video_ctrl /* 设置格式fromat, frame */
ret = __uvc_query_ctrl(video->dev /* 哪一个USB设备 */, SET_CUR, 0,
video->streaming->intfnum /* 哪一个接口: VS */,
probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size,
uvc_timeout_param);
/* 启动:Initialize isochronous/bulk URBs and allocate transfer buffers. */
uvc_init_video(video, GFP_KERNEL);
uvc_init_video_isoc / uvc_init_video_bulk
urb->complete = uvc_video_complete; (收到数据后此函数被调用,它又调用video->decode(urb, video, buf); ==> uvc_video_decode_isoc/uvc_video_encode_bulk => uvc_queue_next_buffer => wake_up(&buf->wait);)
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);
分析设置亮度过程:
ioctl: VIDIOC_S_CTRL
uvc_ctrl_set
uvc_ctrl_commit
__uvc_ctrl_commit(video, 0);
uvc_ctrl_commit_entity(video->dev, entity, rollback);
ret = uvc_query_ctrl(dev /* 哪一个USB设备 */, SET_CUR, ctrl->entity->id /* 哪一个unit/terminal */,
dev->intfnum /* 哪一个接口: VC interface */, ctrl->info->selector,
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
ctrl->info->size);
总结:
1. UVC设备有2个interface: VideoControl Interface, VideoStreaming Interface
2. VideoControl Interface用于控制,比如设置亮度。它内部有多个Unit/Terminal(在程序里Unit/Terminal都称为entity)
可以通过类似的函数来访问:
ret = uvc_query_ctrl(dev /* 哪一个USB设备 */, SET_CUR, ctrl->entity->id /* 哪一个unit/terminal */,
dev->intfnum /* 哪一个接口: VC interface */, ctrl->info->selector,
uvc_ctrl_data(ctrl, UVC_CTRL_DATA_CURRENT),
ctrl->info->size);
3. VideoStreaming Interface用于获得视频数据,也可以用来选择fromat/frame(VS可能有多种format, 一个format支持多种frame, frame用来表示分辨率等信息)
可以通过类似的函数来访问:
ret = __uvc_query_ctrl(video->dev /* 哪一个USB设备 */, SET_CUR, 0,
video->streaming->intfnum /* 哪一个接口: VS */,
probe ? VS_PROBE_CONTROL : VS_COMMIT_CONTROL, data, size,
uvc_timeout_param);
4. 我们在设置FORMAT时只是简单的使用video->streaming->format[fmt->index]等数据,
这些数据哪来的?
应是设备被枚举时设置的,也就是分析它的描述符时设置的。
5. UVC驱动的重点在于:
描述符的分析
属性的控制: 通过VideoControl Interface来设置
格式的选择:通过VideoStreaming Interface来设置
数据的获得:通过VideoStreaming Interface的URB来获得
(---end---)
Linux摄像头驱动学习之:(四)UVC-摄像头驱动框架分析的更多相关文章
- Linux内核驱动学习(四)Platform设备驱动模型
Linux platform设备驱动模型 文章目录 Linux platform设备驱动模型 前言 框架 设备与驱动的分离 设备(device) 驱动(driver) 匹配(match) 参考 前言 ...
- Linux内核驱动学习(八)GPIO驱动模拟输出PWM
文章目录 前言 原理图 IO模拟输出PWM 设备树 驱动端 调试信息 实验结果 附录 前言 上一篇的学习中介绍了如何在用户空间直接操作GPIO,并写了一个脚本可以产生PWM.本篇的学习会将写一个驱动操 ...
- Linux音频驱动学习之:(1)ASOC分析
一.音频架构概述 (1)ALSA是Advanced Linux Sound Architecture 的缩写,目前已经成为了linux的主流音频体系结构,想了解更多的关于ALSA的这一开源项目的信息和 ...
- linux驱动学习(八) i2c驱动架构(史上最全) davinc dm368 i2c驱动分析【转】
转自:http://blog.csdn.net/ghostyu/article/details/8094049 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 预备知识 lin ...
- 嵌入式Linux驱动学习之路(十一)按键驱动-中断机制
轮询方式: 和led驱动不同的是在配置IO引脚的时候,把LED的输出引脚换成输入,在read函数中向外发送io的状态.必须由应用程序不断的来查询当前IO口的状态来判断. 中断方式: /* file n ...
- Linux运维学习第四周记
古木阴中系短篷 杖藜扶我过桥东 沾衣欲湿杏花雨 吹面不寒杨柳风 *不要辜负绵绵春意 第四周学记 第四周主要学习了文件查找和打包压缩的相关工具,以及软件包管理工具 文件查找相关命令 1.locate 在 ...
- 嵌入式Linux驱动学习之路(十三)按键驱动-异步通知
之前的按键方式: 查询: 极度占用CPU资源 中断: 在读的时候产生休眠,在没有信号的时候永远不会返回. poll机制: 在中断的基础上加上超时时间. 异步通知就是通过信号来传送. 首先在应用程序中有 ...
- 嵌入式Linux驱动学习之路(五)u-boot启动流程分析
这里说的u-boot启动流程,值得是从上电开机执行u-boot,到u-boot,到u-boot加载操作系统的过程.这一过程可以分为两个过程,各个阶段的功能如下. 第一阶段的功能: 硬件设备初始化. 加 ...
- linux基础命令学习(四)计划任务
一.计划任务 crond服务简介 linux任务调度的工作主要分为以下两类: *系统执行的工作:系统周期性所要执行的工作,如备份系统数据.清理缓存 *个人执行的工作:某个用户定期要做的工作,例如每隔1 ...
- 鸟哥的linux私房菜学习-(四)linux命令的基本概念
一.命令格式及使用方式 注意到上面的说明当中,『第一个被输入的数据绝对是命令或者是可运行的文件』! 这个是很重要的概念喔!还有,按下[Enter]键表示要开始运行此一命令的意思. 如下效果一样: 二. ...
随机推荐
- Monkey之环境搭建完全版
图文版将在后期补充. 如果想要搭建好Monkey的测试环境,首先几个必要的步骤和环境不能少,分别是java相关环境.Android SDK环境,启动android虚拟机或连接真机.执行monkey测试 ...
- LoadRunner脚本设计、场景设计和结果分析
本次笔记主要记录LoadRunner脚本设计.场景设计和结果分析 1. 脚本设计 录制模式 手工模式:插入步骤.手动编写 1.1 脚本增强: ...
- innodb的表最大限制
相信大多数人都不知道,innodb的表最大限制为64TB,但是why? Each space is divided into pages, normally 16 kib each (this can ...
- mysql出现“SELECT list is not in GROUP BY clause and contains nonaggregated column [duplicate]”错误提示
项目跨平台时由于mysql设置的问题,原代码运行出现这个错误,此时把mysql设置改下就好了 sql_mode='NO_ENGINE_SUBSTITUTION'
- javascript,jQuery,trim()
JavaScript trim() Syntax string.trim() The trim() method removes whitespace from both sides of a str ...
- servlet定义
. 运行在服务器上的java类
- sql函数PadLeft与PadRight代码实例
1.PadLeft函数向已知字符串左边补充字符,使整个字符串到达指定长度 CREATE FUNCTION PadLeft ( ),/*原始字符*/ @TotalLength int,/*总长度*/ ) ...
- CSSOM之getComputedStyle,currentStyle,getPropertyValue,getAttribute
js关于CSSOM编程的样式相关几个常用的方法 webkit:getComputedStyle,getPropertyValue IE:currentStyle,getAttribute 前言 jqu ...
- MDK的一些设置(尤其是部分代码无法断点问题的解决)
转自http://www.cnblogs.com/worldsing/p/3412323.html
- Windows 10:解决开机显示C:\WINDOWS\system32\config\systemprofile\Desktop不可用的方法
开机显示C:\WINDOWS\system32\config\systemprofile\Desktop不可用应该是不少网友都遇到过. 近日在使用Windows 10 Build 9926中,也出 ...