摄像头驱动——V4L2框架分析
一、概述
Video for Linux 2,简称V4l2,是Linux内核中关于视频设备的内核驱动框架,为上层的访问底层的视频设备提供了统一的接口。
摄像头驱动是属于字符设备驱动程序。(分析linux3.4.2内核)
二、如何写字符设备驱动
1、对于简单的驱动:
1).构造一个file_operations:.open=drv_open .read=drv_read
2).告诉内核:register_chrdev(主设备号,名字,&file_operations)
3).入口函数:调用register_chrdev
4).出口函数:卸载
一般采用register_chrdev的代替方法:分配、设置cdev,cdev_add
2、对于稍复杂的驱动程序采用分层思想
例如LCD驱动中分为两层:上层通用的核心层内核已经帮我们做好,即在fbmem.c
1.构造file_operations(open/ read /write ...)
2.注册
3.入口、出口
我们做的是硬件相关层,供上层file_operations调用
1.分配一个fb_info 结构体
2.设置
3.注册
4.硬件相关的操作
三、分析V4L2框架
把usb设备接到系统前台,会有打印信息,根据打印信息在内核里找出驱动,用dmsg命令查看;
grep "Found UVC" * -nR 搜索 在uvc_driver.c里,这是个硬件相关的驱动。
分析代码,猜测V4L2 框架 肯定也是分为至少两层 。
应用层:
/*调用 open read write -->调用 v4l2_fops 里的 open read write->调用硬件相关层的video_device 里提供的函数*/
----------------------------------------------------------------------------------------------------------
核心层:v4l2-dev.c __video_register_device
构造:v4l2_fops(
.read = v4l2_read,
.write = v4l2_write,
.open = v4l2_open, ...)
注册:
vdev->cdev = cdev_alloc(); //1.字符设备cdev_alloc
vdev->cdev->ops = &v4l2_fops; //2.设置fops
cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1); //3.cdev_add
----------------------------------------------------------------------------------------------------------
硬件相关层:如uvc_driver.c Found UVC
->v4l2_device_register(这个不重要)
->video_device_alloc->video_register_device(向核心层注册)
->v4l2-dev.h->__video_register_device(v4l2-dev.c)
---------------------------------------------------------------------------------------------------------
即分配结构体 video_device (里面的函数供上层v4l2_fops调用)
设置 注册video_register_device
四、通过vivi.c分析v4l2核心驱动框架
(virtual video driver )虚拟视频驱动
分析如下:
vivi_init (入口函数)
vivi_create_instance(i);
v4l2_device_register //非主要,仅初始化一些锁等,实际未注册啥
spin_lock_init(&v4l2_dev->lock);
...
get_device(dev);
v4l2_dev->dev = dev;
vfd = video_device_alloc(); //分配video_device
//设置
.*vfd = vivi_template; //内容设置为vivi_template
/*最底层的vivi 操作函数*/
static struct video_device vivi_template = {
.name = "vivi",
.fops = &vivi_fops,
.ioctl_ops = &vivi_ioctl_ops,
...
}; .vfd->v4l2_dev = &dev->v4l2_dev; .设置“Ctrl属性”(用于APP的ioctl),音量、亮度、增益等
dev->volume = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
V4L2_CID_AUDIO_VOLUME, , , , );
dev->brightness = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
V4L2_CID_BRIGHTNESS, , , , );
dev->contrast = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
V4L2_CID_CONTRAST, , , , );
...
// 结构体vfd 类型 number
video_register_device(video_device, VFL_TYPE_GRABBER, nr); //向上注册
__video_register_device
/* Part 1: check device type */ 检验设备类型
...
/* Part 2: find a free minor, device node number and device index. */
... 互斥锁相关
/* Part 3: Initialize the character device */ 初始化字符设备
vdev->cdev = cdev_alloc();
vdev->cdev->ops = &v4l2_fops;
cdev_add
...
/* Part 6: Activate this minor. The char device can now be used. */
video_device[vdev->minor] = vdev; //以次设备号为下标,将vdev存入数组 ************************************************************************************
分析vivi.c的open、read、write、ioctl过程
. open
app: open ("/dev/video0",...)
----------------------------------------------
drv: v4l2_open
vdev = video_devdata(filp); //根据次设备号从数组中得到video_device
ret = vdev->fops->open(filp);//调用open函数
调用vivi.c 里的v4l2_fh_open . read
app: read...
----------------------------------------------
drv: v412_read
struct video_device *vdev = video_devdata(filp);
ret = vdev->fops->read(filp, buf, sz, off); . ioctl
app: ioctl
----------------------------------------------
drv: v4l2_fops.unlocked_ioctl
v4l2_ioctl
struct video_device *vdev = video_devdata(filp);
ret = vdev->fops->unlocked_ioctl(filp, cmd, arg);
调用vivi.c 里的video_ioctl2
/*把用户空间的参数复制进来,然后调用__video_do_ioctl*/
video_usercopy(file, cmd, arg, __video_do_ioctl);
__video_do_ioctl
*vdev = video_devdata(filp)
根据APP传入的cmd来获得、设置某些属性
/*在vivi.c 里一开始的vivi_create_instance里设置*/
由上分析可知vivi.c主要完成了以下工作:
1 、初始化 v4l2_device结构体(代表一个 v4l2设备)
v4l2_device_register、 v4l2_device
2、分配video_device结构体
vfd = video_device_alloc()
3、设置video_device结构
a、 .vfd->v4l2_dev
b、vfd:
.fops 设置vfd的fops 里的open、read、write 被上层调用
.ioctl_ops 最终会调用到ioctl(设置属性被上层调用 )
4、 注册video_device结构体
(video_device 是内核对 v4l2_device的官方封装,用于管理v4l2_device数据),向上层用户提供访问接口
video_register_device
问:APP可以通过ioctl来设置(获得)亮度等信息,在驱动程序里,谁来接收、存储、设置到硬件(提供这些信息)?
答:在驱动程序中抽象出来一个结构体v4l2_ctrl, 每个Ctrl对应其中的一项(音量、亮度等等);
由v4l2_ctrl_handler来管理他们
1.初始化
v4l2_ctrl_handler_init
2.设置
v4l2_ctrl_new_std
v4l2_ctrl_new_custom
这些函数就是创建各个属性,并且放入v4l2_ctrl_handler的链表
3.跟vdev关联
dev->v4l2_dev.ctrl_handler = hdl;
小结:
v4l2框架并未脱离字符设备驱动框架,只是ioctl的实现较为复杂。
摄像头驱动——V4L2框架分析的更多相关文章
- v4l2框架分析
参考:https://www.cnblogs.com/fengong/p/4424823.html http://www.cnblogs.com/fengong/p/4424895.html 一 ...
- 2.3 摄像头驱动_vivi驱动程序分析
学习目标:熟悉vivi的调用过程,分析vivi程序源码的ioctl函数: 一.vivi虚拟视频驱动测试方法 当我们接上usb摄像头设备时,系统会自动给我们安装对应的usb设备驱动程序.如果下次直接测试 ...
- 【原创】Linux v4l2框架分析
背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...
- V4L2(二)虚拟摄像头驱动vivi深入分析【转】
转自:http://www.cnblogs.com/tureno/articles/6694463.html 转载于: http://blog.csdn.net/lizuobin2/article/d ...
- camera驱动框架分析(上)【转】
转自:https://www.cnblogs.com/rongpmcu/p/7662738.html 前言 camera驱动框架涉及到的知识点比较多,特别是camera本身的接口就有很多,有些是直接连 ...
- camera驱动框架分析(上)
前言 camera驱动框架涉及到的知识点比较多,特别是camera本身的接口就有很多,有些是直接连接到soc的camif口上的,有些是通过usb接口导出的,如usb camera.我这里主要讨论前者, ...
- 2.1 摄像头V4L2驱动框架分析
学习目标:学习V4L2(V4L2:vidio for linux version 2)摄像头驱动框架,分析vivi.c(虚拟视频硬件相关)驱动源码程序,总结V4L2硬件相关的驱动的步骤: 一.V4L ...
- 二十四、V4L2框架主要结构体分析和虚拟摄像头驱动编写
一.V4L2框架主要结构体分析 V4L2(video for linux version 2),是内核中视频设备的驱动框架,为上层访问视频设备提供统一接口. V4L2整体框架如下图: 图中主要包括两层 ...
- Linux摄像头驱动学习之:(一)V4L2_框架分析
这段时间开始搞安卓camera底层驱动了,把以前的的Linux视频驱动回顾一下,本篇主要概述一下vfl2(video for linux 2). 一. V4L2框架: video for linux ...
随机推荐
- 数学之路-python计算实战(6)-numpy-ndarray
>>>> mya=np.zeros(shape=(2,2)) >>>> mya array([[ 0., 0.], [ 0., 0.]]) > ...
- 捕捉到来自宇宙深空的神奇X-射线信号
请看下图: 这是专门用于捕捉X-射线信号的航天望远镜,约有5吨重,执行轨道距离地面大约有5万多公里.6月24日,美国宇航局NASA宣布,这台航天望远镜从银河系深处捕捉到一种波长非常特殊的神奇X-射线信 ...
- 关于MAVEN找不到JDK的那点事
自从SUN被Oracle收购以后.JDK就由Oracle来提供了. 在新版本号之中,假设你下载安装JDK以后,又选择了JRE安装(当然,如今JRE直接叫做Java了),那么,恭喜你,在 C:\wind ...
- 可变对象 vs 不可变对象(Python)
Python 在 heap 中分配的对象分成两类:可变对象和不可变对象.所谓可变对象是指,对象的内容是可变的,例如 list.而不可变的对象则相反,表示其内容不可变. 不可变对象:int,string ...
- []HAOI2008] 硬币购物 解题报告 ( 完全背包+容斥原理)
题目链接:https://www.luogu.org/problemnew/show/P1450 题目描述: 题解: 如果去掉限制的话,这就是一个完全背包. 我们可以考虑先去掉限制,把这个完全背包做出 ...
- ASP.NET Identity 角色管理(Roles)
当我们使用ASP.NET 4.5创建模板项目时,会发现模板只提供了ApplicationUserManager用于用户的登录注册.修改.设置等,而没有提供与用户角色相关的代码,对此就需要我们自己手动的 ...
- 继承—Monkey
public class Monkey { public void Monkey(String s){ } public void speak(){ System.out.println(" ...
- ASP.NET Core学习日志1
1.ASP.NET进行了结构化的优化,使框架更为精简,模块化更加明显. 2.ASP.NET Core不再基于System.Web.dll,而是基于细粒度.分解的NuGet包. 3.基础特性: 1.We ...
- <Sicily>数字反转
一.题目描述 给定一个整数,请将该数各个位上数字反转得到一个新数.新数也应满足整数的常见形式,即除非给定的原数为零,否则反转后得到的新数的最高位数字不应为零(参见样例2). 二.输入 输入共 1 行, ...
- 创建支持SSH服务的镜像
一.基于commit命令创建 docker commit CONTAINER [REPOSITORY [:TAG]] 1.使用ubuntu镜像创建一个容器 docker run -it ubuntu ...