zoukankan      html  css  js  c++  java
  • 初识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); }

    通过简单的分析函数的调用过程,与上图我们猜测的过程刚好对应起来,本篇文章先让我们感性的来认识一下,摄像头驱动程序的框架。

  • 相关阅读:
    PAT甲级——A1091 Acute Stroke【30】
    PAT甲级——A1090 Highest Price in Supply Chain
    PAT甲级——A1089 Insert or Merge
    PAT甲级——A1088 Rational Arithmetic
    PAT甲级——A1087 All Roads Lead to Rome【30】
    【php中的curl】php中curl的详细解说
    【php中的curl】使用curl完成POST数据给飞信接口
    【php中的curl】php中curl的使用
    【socket】php实现socket
    【socket】用PHP的socket实现客户端到服务端的通信
  • 原文地址:https://www.cnblogs.com/-glb/p/10292198.html
Copyright © 2011-2022 走看看