1、分配video_device结构体

2、设置

3、注册  video_register_device

分析vivi.c:

vivi_init( )//入口函数

 vivi_create_instance()

  ret = v4l2_device_register(NULL, &dev->v4l2_dev);

  /*注意dev->v4l2_dev在该函数v4l2_device_registe中被设置,这个结构体在后边将被用到。

  ,这个函数只是做了某些初始化的工作,并没有什么注册

  */

   vfd = video_device_alloc(); 

    1、设置 

    *vfd = vivi_template;

    vivi_template结构体中主要有成员变量:

    .fops = &vivi_fops,

    .ioctl_ops = &vivi_ioctl_ops,

    .release = video_device_release,

    2、
    vfd->v4l2_dev = &dev->v4l2_dev;

    v4l2_dev是在v4l2_device_register()中设置的

    3、设置"ctrl"(用于app的ioctl)。在应用程序中ioctl中可以做什么事情,就是在vivi.c这个地方设置的。(注意本文是分析vivi.c,对于其他的也是一样的)  

      hdl = &dev->ctrl_handler;
      v4l2_ctrl_handler_init(hdl, 11);//初始化一个ctrl_handler

      /*v4l2_ctrl_new_std 添加一个新的标准的ctrl

        v4l2_ctrl_new_custom添加一个客户自定义的ctrl*/
      dev->volume = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
      dev->brightness = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
      dev->button = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_button, NULL);
      dev->int32 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int32, NULL);
      dev->int64 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int64, NULL);

   video_register_device()

    __video_register_device()//在上一篇博客中,这个函数已经简要的分析,在此不再赘述。

vivi 的入口函数:vivi_init()

  static int __init vivi_init(void)

  {   

    for (i = 0; i < n_devs; i++) { /n_devs=1
      ret = vivi_create_instance(i);//调用该函数来创建设备
    }
  }

vivi_create_instance(int inst)

{

  struct video_device *vfd; //这是一个核心的结构,对应视频视频设备节点

  .........

  vfd = video_device_alloc(); //动态分配了一个video_device

  /*这里的vfd被设置成了vivi_template,在后面的代码中会以次设备号为索引把vfd放入到video_device[]中,在其它函数中根据次设备号从video_device[]数组中获取的video_deice就是vivi_template*/

  *vfd = vivi_template;

  ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);

}

如何写v4l2驱动

(1)分配/设置/注册 v4l2_device

  v4l2_device并不重要,里面只是提供了一些辅助的信息,比如自旋锁、引用计数等,目的是给以后的video_device使用

  利用函数v4l2_device_register得到一个结构体v4l2_device结构体

(2)分配video_device

  利用函数video_device_alloc得到结构体video_device

(3)设置

  得到的video_device称为vfd

  a、vfd->v4l2_dev就让该结构体的v4L2_dev指向v4L2_device_register函数得到的结构体v4l2_device

  b、

    *vfd = vivi_template;

    static struct video_device vivi_template = {
      .name = "vivi",
      .fops = &vivi_fops,
      .ioctl_ops = &vivi_ioctl_ops,
      .release = video_device_release,

    }; 

    static const struct v4l2_file_operations vivi_fops = {
      .owner = THIS_MODULE,
      .open = v4l2_fh_open,
      .release = vivi_close,
      .read = vivi_read,
      .poll = vivi_poll,
      .unlocked_ioctl = video_ioctl2, /* V4L2 ioctl handler */
      .mmap = vivi_mmap,
    };   

    static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
      .vidioc_querycap = vidioc_querycap,
      .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
      .vidioc_g_fmt_vid_cap = vidioc_g_fmt_vid_cap,
      .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
      .vidioc_s_fmt_vid_cap = vidioc_s_fmt_vid_cap,
      .vidioc_reqbufs = vidioc_reqbufs,
      .vidioc_querybuf = vidioc_querybuf,
      .vidioc_qbuf = vidioc_qbuf,
      .vidioc_dqbuf = vidioc_dqbuf,
      .vidioc_s_std = vidioc_s_std,
      .vidioc_enum_input = vidioc_enum_input,
      .vidioc_g_input = vidioc_g_input,
      .vidioc_s_input = vidioc_s_input,
      .vidioc_streamon = vidioc_streamon,
      .vidioc_streamoff = vidioc_streamoff,
      .vidioc_log_status = v4l2_ctrl_log_status,
      .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
      .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
    };

  可以用下面这幅图简要说明其中的关系:

    

  c、app可以通过ioctl来设置、获得亮度等信息

    驱动程序里面谁来接收、存储、设置到硬件或提供信息给硬件

    在驱动程序里面抽象出一个结构体v4l2_ctrl,称为属性。每个v4l2_ctrl对应一项,比如说亮度、音量等信息。

    用v4l2_ctrl_handler来管理v4l2_ctrl。v4l2_ctrl_handler就像一个链表一样,里面需要填充各个属性,也可理解为设置各个属性。

     (1)v4L2_ctrl_handler_init  初始化一个ctrl_handler

     (2)v4L2_ctrl_new_std     v4L2_ctrl_new_custom

        创建v4L2_ctrl,并且放入链表v4L2_ctrl_handler中

     (3)与video_dev关联

        v4L2_dev.ctrl_handler = hdl //将上面两步创建出来的v4L2_ctrl_handler赋给v4L2_dev中的ctrl_handler

        video_dev->v4L2_dev = v4L2_dev  //video_dev是我们的核心。

      

初识V4L2(三)-------分析vivi.c 虚拟视频驱动的更多相关文章

  1. 彻底分析虚拟视频驱动vivi(三)

    在Ubuntu系统中接上usb摄像头设备时,系统会自动安装对应的usb设备驱动程序.我们现在要使用自己编译的vivi驱动,该怎么办呢? 1.先安装系统自带的vivi驱动和它所依赖的所有驱动:sudo ...

  2. 2.2 vivi虚拟视频驱动测试

    学习目标:在linux终端安装xawtv,并测试vivi.ko驱动程序. 一.安装xawtv 1)ubuntu能上网情况下,使用命令:# sudo apt-get install xawtv 2)如果 ...

  3. 摄像头驱动——V4L2框架分析

    一.概述 Video for Linux 2,简称V4l2,是Linux内核中关于视频设备的内核驱动框架,为上层的访问底层的视频设备提供了统一的接口. 摄像头驱动是属于字符设备驱动程序.(分析linu ...

  4. 二十四、V4L2框架主要结构体分析和虚拟摄像头驱动编写

    一.V4L2框架主要结构体分析 V4L2(video for linux version 2),是内核中视频设备的驱动框架,为上层访问视频设备提供统一接口. V4L2整体框架如下图: 图中主要包括两层 ...

  5. V4L2(二)虚拟摄像头驱动vivi深入分析【转】

    转自:http://www.cnblogs.com/tureno/articles/6694463.html 转载于: http://blog.csdn.net/lizuobin2/article/d ...

  6. DAVINCI DM6446 开发攻略——V4L2视频驱动和应用分析

     针对DAVINCI DM6446平台,网络上也有很多网友写了V4L2的驱动,但只是解析Montavista linux-2.6.10 V4L2的原理.结构和函数,深度不够.本文决定把Montavis ...

  7. V4L2学习(五)VIVI虚拟摄像头驱动

    概述 前面简单分析了内核中虚拟摄像头驱动 vivi 的框架与实现,本文参考 vivi 来写一个虚拟摄像头驱动,查询.设置视频格式相对简单,难点在于 vb2_buf 的处理过程. 数据采集流程分析 在我 ...

  8. 8、摄像头驱动_Linux的V4L2架构分析

    V4L2架构可以参考  linux-3.4.2\Documentation\video4linux\v4l2-framework.txt V4L2全名为Video For Linux 2,它是针对Li ...

  9. 【原创】Linux v4l2框架分析

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...

随机推荐

  1. Hyper-V与VirtualBox或VMware虚拟机软件冲突的解决方法(VirtualBox只能创建32位虚拟机)

    Hyper-V与VirtualBox或VMware虚拟机软件冲突的解决方法 Hyper-V是微软的虚拟化软件,功能类似VirtualBox.VMware,可以用来创建虚拟机. 虚拟化软件都是基于CPU ...

  2. CentOS7 安装 anaconda

    Anaconda是一个开源的Python发行版本,可以帮助我们更方便地配置Python环境. 如果只需要某些包,或者需要节省带宽或存储空间,也可以使用Miniconda这个较小的发行版 0. 开始前 ...

  3. Centos7防火墙添加端口

    添加 firewall-cmd --zone=public --add-port=80/tcp --permanent   (--permanent永久生效,没有此参数重启后失效) 重新载入 fire ...

  4. RPC调用和HTTP调用的区别

    很长时间以来都没有怎么好好搞清楚RPC(即Remote Procedure Call,远程过程调用)和HTTP调用的区别,不都是写一个服务然后在客户端调用么?这里请允许我迷之一笑~Naive!本文简单 ...

  5. WIFI Portal登录

    开头 关于 ANDROID 5.0-7.1.2 网络图标上的感叹号及其解决办法-狐狸的小小窝 HTTP状态码之204 No Content 原理 访问generate_204地址,如果得到状态码是20 ...

  6. Vue+Element UI 实现视频上传

    一.前言 项目中需要提供一个视频介绍,使用户能够快速.方便的了解如何使用产品以及注意事项. 前台使用Vue+Element UI中的el-upload组件实现视频上传及进度条展示,后台提供视频上传AP ...

  7. 物联网架构成长之路(43)-k8s从入门到放弃

    0. 前言 这段时间要入门一下CI/CD了,以前简单的了解过Jenkins,现在要把以下的这个图的架构搭建起来.国外可能一两个命令就安装完成的事情,我折腾了2天多,真的差点放弃了. 1. 安装Virt ...

  8. (三十二)golang--面向对象之封装

    封装:把抽象出来的字段和对字段的操作封装在一起,数据被保护在内部,程序的其它包只有通过被授权的操作(方法),才能对字段进行操作. 封装的好处: (1)隐藏实际的细节: (2)可以对数据进行验证,保证安 ...

  9. DataTable 转List

    忘了出处   ,这个是转别人的 public class DataToList<T> where T : new() { /// <summary> /// 利用反射和泛型 / ...

  10. Winform中设置ZedGraph的曲线为散点图

    场景 Winform中设置ZedGraph的曲线符号Symbol以及对应关系: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10 ...