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(一)的更多相关文章

  1. 初识V4l2(二)-------浅析video_register_device

    在V4l2初识(一)中,我们已经知道当插上一个摄像头的时候,在uvc_driver.c中最终会调用函数video_register_device函数.接下来我们就简要分析这个函数做了哪些事情,揭开其神 ...

  2. 初识v4l2(五)-------v4l2_ioctl浅析

    上一篇文章中,已经介绍了v4l2_open.v4l2_read.v4l2_write的调用过程,相对于v4l2_ioctl,它们是比较简单的.下面来分析v4l2_ioctl.注意在这里还是分析以viv ...

  3. 初识V4L2(三)-------分析vivi.c 虚拟视频驱动

    1.分配video_device结构体 2.设置 3.注册  video_register_device 分析vivi.c: vivi_init( )//入口函数 vivi_create_instan ...

  4. 初识v4l2(四)-------v4l2_open、v4l2_read、v4l2_write浅析

    原文:https://blog.csdn.net/leesagacious/article/details/49995729 1.app:     open("/dev/video0&quo ...

  5. V4l2初识(七)-----------浅析app获取虚拟摄像头数据的过程

    继续分析数据的获取过程: 1.请求分配的缓冲区: ioctl(4,VIDIOC_REQBUFS) vidioc_reqbufs 2.查询和映射缓冲区   ioctl(4,VIDIOC_QUERYBUF ...

  6. Android动画效果之初识Property Animation(属性动画)

    前言: 前面两篇介绍了Android的Tween Animation(补间动画) Android动画效果之Tween Animation(补间动画).Frame Animation(逐帧动画)Andr ...

  7. 初识Hadoop

    第一部分:              初识Hadoop 一.             谁说大象不能跳舞 业务数据越来越多,用关系型数据库来存储和处理数据越来越感觉吃力,一个查询或者一个导出,要执行很长 ...

  8. python学习笔记(基础四:模块初识、pyc和PyCodeObject是什么)

    一.模块初识(一) 模块,也叫库.库有标准库第三方库. 注意事项:文件名不能和导入的模块名相同 1. sys模块 import sys print(sys.path) #打印环境变量 print(sy ...

  9. 初识IOS,Label控件的应用。

    初识IOS,Label控件的应用. // // ViewController.m // Gua.test // // Created by 郭美男 on 16/5/31. // Copyright © ...

随机推荐

  1. 高频Python面试题分享

    一.Python语言中你用过哪些方式来实现进程间通信1.队列Queue 2.Pipe管道 只适用于两个进程之间的通信, pipe的效率高于queue 3.共享内存 4.socket套接字(UDP即可) ...

  2. (转)SpringMVC表单多对象传递小技巧——@InitBinder

    转:https://www.jianshu.com/p/59771cbf373d 1.问题情景 项目中前端后台的数据传递是必不可少的,比如说我们要在一张表单中提交对象,如果只是一个对象就就很好做,因为 ...

  3. node.js是用来做什么的?这是我看到最好的解释了

    一种JavaScript的运行环境,能够使得JavaScript脱离浏览器运行. 参考链接:https://www.cnblogs.com/suhaihong/p/6598308.html https ...

  4. django-订单并发处理--悲观锁和乐观锁

    冲突比较少的时候,使用乐观锁. 冲突比较多的时候,使用悲观锁. (1)     悲观锁 select * from df_goods_sku where id=17 for update; 悲观锁获取 ...

  5. Vue.js 创建第一个应用

    VUE官网下载Vue.js文件或者用Vue的CDN地址 在项目中引入Vue.js文件 代码: <!doctype html> <html lang="en"> ...

  6. 【django json.dumps 报错】 datetime.datetime is not JSON serializable

    django 中,json.dumps 无法直接转译 datetime 类型的值. 找了无数方法,找到一个最优.最简洁的解决办法: json.dumps(results, indent=4, sort ...

  7. 【前端知识体系-JS相关】对移动端和Hybrid开发的理解?

    1.hybrid是什么,为何使用hybrid呢? 概念: hybrid就是前端和客户端的混合开发 需要前端开发人员和客户端开发人员配合完成 某些环节也可能会涉及到server端 大前端:网页.APP. ...

  8. tensorflow之tf.shape()

    tf.shape()这个方法就相当于numpy当中shape属性. 下面通过列子来了解: 具体而言,tf.shape是用来获取张量的维度(shape).

  9. 区分 JVM 内存结构、 Java 内存模型 以及 Java 对象模型 三个概念

    本文由 简悦 SimpRead 转码, 原文地址 https://www.toutiao.com/i6732361325244056072/ 作者:Hollis 来源:公众号Hollis Java 作 ...

  10. hive on spark 释放session资源

    背景 启动hive时,可以看到2.0以后的版本,将要弃用mr引擎,官方建议使用spark,tez等引擎. spark同时支持批式流式处理,可以减少学习成本.所以选用了spark作为执行引擎. hive ...