初识V4L2(一)
V4L2驱动框架概述
V4L2(video for linux two)是linux为视频设备提供的一套标准接口。它也属于字符设备驱动程序。
首先回顾普通字符设备驱动程序的写法:
app : open read write
----------------------------------------------------------------------------
内核: drv_open drv_read drv_write
----------------------------------------------------------------------------
相关的硬件设备
1、如何写简单的字符设备驱动程序
(1)构造file_operations结构
.open =drv_open
.read =drv_read
.write =drv_write
(2)告诉内核
(3)入口函数
(4)出口函数
2、如何写复杂的字符设备驱动程序
以LCD驱动程序为例,进行简要说明。在LCD驱动程序里面引入了分层的概念,分为上下两层
(1)fbmem.c。注意这里面的内容内核已经帮我们做好了
构造file_operations结构体
.open/.read/.write
告诉内核
入口函数
出口函数
(2)硬件相关的内容,这部分内容需要我们自己来做
分配fb_info结构体
设置fb_info结构体
硬件相关的操作
注册
所谓注册,就是把fb_info结构体告诉fbmem.c。这样当应用程序调用open、read、write等函数来操作LCD时,首先会调用fbmem.c的file_operations结构体中的open、read、write等函数,进而调用fb_info结构体提供的open、read、write等函数。分层的好处在于:在写驱动程序的时候专注于硬件相关的那部分就可以了。其他通用的比如说fbmem.c中的内容,内核已经帮我们做好了。
前面已经说过,摄像头驱动程序也是一种字符设备驱动程序,它的结构框图如下:

当我们插入一个usb摄像头的时候,过程是怎样的?接下来简要分析一下:
在uvc_driver.c中
首先看一下入口函数:
static int __init uvc_init(void)
{
int ret;
ret = usb_register(&uvc_driver.driver);
}
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,
/*假设我们接上了一个usb摄像头,这个摄像头在 uvc_ids里面,那么内核就会调用uvc_probe函数*/
.id_table = uvc_ids,
.supports_autosuspend = 1,
},
};
接下来再看一下uvc_probe这个函数:
/* -------------------------------------------------------------
* USB probe, disconnect, suspend and resume
*/
static int uvc_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
/*v4l2_device_register这个函数不重要,只是做了某些初始化的工作*/
if (v4l2_device_register(&intf->dev, &dev->vdev) < 0)
goto error;
/* Register video device nodes. */
if (uvc_register_chains(dev) < 0)
goto error;
}
接下来看一下函数uvc_register_chains做了什么事情?
static int uvc_register_chains(struct uvc_device *dev)
{
struct uvc_video_chain *chain;
int ret; list_for_each_entry(chain, &dev->chains, list) { ret = uvc_register_terms(dev, chain);
if (ret < 0)
return ret;
}
接下来分析uvc_register_terms:
/*
* Register all video devices in all chains.
*/
static int uvc_register_terms(struct uvc_device *dev,
struct uvc_video_chain *chain)
{
ret = uvc_register_video(dev, stream);
if (ret < 0)
return ret;
}
static int uvc_register_video(struct uvc_device *uvc)
{
struct usb_composite_dev *cdev = uvc->func.config->cdev;
struct video_device *video;
/* TODO reference counting. */
video = video_device_alloc();
if (video == NULL)
return -ENOMEM;
video->parent = &cdev->gadget->dev;
video->minor = -1;
video->fops = &uvc_v4l2_fops;
video->release = video_device_release;
strncpy(video->name, cdev->gadget->name, sizeof(video->name));
uvc->vdev = video;
video_set_drvdata(video, uvc);
return video_register_device(video, VFL_TYPE_GRABBER, -1);
}
通过简单的分析函数的调用过程,与上图我们猜测的过程刚好对应起来,本篇文章先让我们感性的来认识一下,摄像头驱动程序的框架。
初识V4L2(一)的更多相关文章
- 初识V4l2(二)-------浅析video_register_device
在V4l2初识(一)中,我们已经知道当插上一个摄像头的时候,在uvc_driver.c中最终会调用函数video_register_device函数.接下来我们就简要分析这个函数做了哪些事情,揭开其神 ...
- 初识v4l2(五)-------v4l2_ioctl浅析
上一篇文章中,已经介绍了v4l2_open.v4l2_read.v4l2_write的调用过程,相对于v4l2_ioctl,它们是比较简单的.下面来分析v4l2_ioctl.注意在这里还是分析以viv ...
- 初识V4L2(三)-------分析vivi.c 虚拟视频驱动
1.分配video_device结构体 2.设置 3.注册 video_register_device 分析vivi.c: vivi_init( )//入口函数 vivi_create_instan ...
- 初识v4l2(四)-------v4l2_open、v4l2_read、v4l2_write浅析
原文:https://blog.csdn.net/leesagacious/article/details/49995729 1.app: open("/dev/video0&quo ...
- V4l2初识(七)-----------浅析app获取虚拟摄像头数据的过程
继续分析数据的获取过程: 1.请求分配的缓冲区: ioctl(4,VIDIOC_REQBUFS) vidioc_reqbufs 2.查询和映射缓冲区 ioctl(4,VIDIOC_QUERYBUF ...
- Android动画效果之初识Property Animation(属性动画)
前言: 前面两篇介绍了Android的Tween Animation(补间动画) Android动画效果之Tween Animation(补间动画).Frame Animation(逐帧动画)Andr ...
- 初识Hadoop
第一部分: 初识Hadoop 一. 谁说大象不能跳舞 业务数据越来越多,用关系型数据库来存储和处理数据越来越感觉吃力,一个查询或者一个导出,要执行很长 ...
- python学习笔记(基础四:模块初识、pyc和PyCodeObject是什么)
一.模块初识(一) 模块,也叫库.库有标准库第三方库. 注意事项:文件名不能和导入的模块名相同 1. sys模块 import sys print(sys.path) #打印环境变量 print(sy ...
- 初识IOS,Label控件的应用。
初识IOS,Label控件的应用. // // ViewController.m // Gua.test // // Created by 郭美男 on 16/5/31. // Copyright © ...
随机推荐
- 【Eureka篇三】Eureka比Zookeeper好在哪里?(8)
Eureka遵守AP,Zookeeper遵守CP RDBMS(oracle/mysql.sqlServer) ====> ACID, 关系型数据库遵循ACID原则 NoSQL(redis/mon ...
- insertAdjacentHTML和insertAdjacentText的使用(在指定位置插入代码或者文字)
insertAdjacentText方法与insertAdjacentHTML方法类似,只不过只能插入纯文本,参数相同.
- 记录几篇PM文章
今日阅读了几篇关于 PM 的文章感觉还不错,整理.摘录于此: 1.[项目经理和产品经理:https://www.cnblogs.com/joylee/p/3541141.html] ——关于二者的异同 ...
- PDF文件添加二维码水印教程
maven配置iText的jar,主要不是所有私服都有iText的jar,maven仓库没有的,可以去https://mvnrepository.com/artifact/com.itextpdf/i ...
- pymysql 读取大数据内存卡死的解决方案
背景:目前表中只有5G(后期持续增长),但是其中一个字段(以下称为detail字段)存了2M(不一定2M,部分为0,平均下来就是2M),字段中存的是一个数组,数组中存N个json数据.这个字段如下: ...
- Vue.js 源码分析(二十一) 指令篇 v-pre指令详解
该指令会跳过所在元素和它的子元素的编译过程,也就是把这个节点及其子节点当作一个静态节点来处理,例如: <!DOCTYPE html> <html lang="en" ...
- redis命令之 ----SortedSed(有序集合)
ZADD ZADD key score member [[score member] [score member] ...] 将一个或多个 member 元素及其 score 值加入到有序集 key ...
- 阿里云 CDN 业务基于边缘容器的云原生转型实践
导读:本文基于边缘容器的阿里云 CDN 云原生实践, 涵盖了边缘容器的背景和趋势,边缘托管集群 ACK Managed Edge K8s(文中简称“Edge@ACK”) 的能力.架构,以及基于边缘容器 ...
- selenium简单使用
简介 Selenium是一个用于Web应用程序测试的工具.Selenium可以直接运行在浏览器中,就像真正的用户在操作一样.支持的浏览器包括IE(7, 8, 9, 10, 11),Mozilla Fi ...
- python调用时间装饰器检测函数运行时间
用一个装饰器,监控程序的运行时间 import time def count_time(func): def int_time(*args, **kwargs): start_time = time. ...