v4l2 学习笔记2--v4l2 framework简介

由于作者水平有限,错误之出,欢迎指正。

v4l2简易框架(引用)

 2.1 video_device

  (1)用于创建和管理 v4l2 设备节点。首要任务:在 /dev/ 下创建设备文件。 

  (2).fops: 指向video 设备的struct v4l2_file_operations 结构体的指针

  (3)sysfs 相关成员:

    1).dev:video 设备的struct device 结构体

    2).cdev:指向代表字符设备的 struct cdev 结构的指针

  (4)

    1).v4l2_dev:指向struct v4l2_device 结构的父设备的指针

    2).dev_parent:指向struct device 父设备的指针

    3).ctrl_handler:指向这个设备节点关联的控制处理程序的指针

    4).queue:指向这个设备节点关联的struct vb2_queue 结构的指针

    5).prio:指向含有设备优先级状态的struct v4l2_prio_state 结构的指针

  (4).release:video 设备release() callback

  (5).ioctl_ops:指向含有 ioctl callback 的struct v4l2_ioctl_ops 结构的指针

 

2.1.1 创建及销毁

  (1)静态分配:嵌入到其他结构体中

    一般不用释放空间,为release指定空函数video_device_release_empty()

  (2)动态分配:video_device_alloc()

      必须为video_device 指定release函数,该函数在video_device 的最后一个用户退出后被调用,释放所申请的空间。

2.1.2 初始化

  (1)必须要初始化的成员:

    1).v4l2_dev

    2).name

    3).fops

    4).ioctl_ops

    5).lock

    6).prio:优先级,用来实现VIDIOC_G/S_PRIORITY。若为NULL,会使用v4l2_device的优先级。

 

  (2)互斥锁 :lock

     当lock不为NULL时,V4L2框架会使用此mutex确保操作的互斥性。

  (3)优先级:prio

    1)struc v4l2_prio_state 结构体,其实现为含有4个atomic_t 类型元素的数组prios。

    3)在enum v4l2_priority 中以枚举的方式定义3个优先级

      1> V4L2_PRIORITY_BACKGROUND:最低优先级,主要用于后台处理。

      2> V4L2_PRIORITY_INTERACTIVE : 默认优先级。 

      3> V4L2_PRIORITY_RECORD :最高优先级。

     4)如何操作v4l2_prio_stat结构体中的4个atomic_t变量,实现优先级管理?  

      1> 若这四个变量中的任何一个不为零,则表示该变量所对应的优先级有效。比如若prios[V4L2_PRIORITY_BACKGROUND]不为零,则程序处于V4L2_PRIORITY_BACKGROUND优先级。

      2> 优先级的确定过程:从数组(atomic_t prios[4])末尾依次查询,返回第一个不为零的变量的位置。此位置即为程序的优先级。

 

    5)优先级相关函数:

      1> v4l2_prio_init   清零所有的优先级变量

      2> v4l2_prio_change  设置指定的优先级(new)变量的值为1,并将以前的优先级(local)变量设置为0.

      3> v4l2_prio_open  设置程序的优先级为V4L2_PRIORITY_DEFAULT

      4> v4l2_prio_close  设置当前优先级变量的值为0

      5> v4l2_prio_max  查询程序的优先级

      6> v4l2_prio_check  查询以确定程序是否能在指定的优先级下工作

        对于ioctl类的函数,读取操作一般不需要调用v4l2_prio_check检查优先级;但是写操作(更改设备状态的操作)则必须检查优先级。

 

    (4)ioctl_ops 和 fops 成员

      实现将用户的操作(函数调用)映射到实际的驱动代码中。

       1)如何实现映射的?

       1> 首先,使用fops将用户的ioctl操作映射到V4L2自己的__video_do_ioctl函数中,

       2> 然后,通过ioctl_ops将具体的cmd传递给驱动中的相关函数。

 

        

    v4l2在注册字符设备时,将该字符设备的file_operations赋值为v4l2_fops。vdev->cdev->ops 指向v4l2_fops,v4l2_fops的 .unlocked_ioctl 成员实现为v4l2_ioctl。

    v4l2_ioctl的中:

      1> 检查vdev->fops->unlocked_ioctl 是否初始化。

      2> 已初始化(非NULL),调用v4l2_ioctl_get_lock()获得lock变量,并调用mutex_lock_interruptible()上锁, 

      3> 调用 video_is_registered() 检查video是否被注册; 如果已被注册,调用vdev->fops->unlocked_ioctl。

      4> 释放互斥锁,mutex_unlock()

     vdev->fops 指向soc_camera_fops对象,soc_camera_fops的unlocked_ioctl 成员实现为 video_ioctl2. video_ioctl2函数中仅仅调用video_usercopy()函数,video_usercopy函数会对用户传递过来的参数检查,将用户空间的数据拷贝到内核空间,调用指定的__video_do_ioctl函数,并将内核空间的数据拷贝到用户空间。

     video_usercopy(file, cmd, arg, __video_do_ioctl);

     __video_do_ioctl 是关键函数:

      处理 IOCTL //待补充。。

      struct v4l2_ioctl_info ??

 2.1.3 注册

  //这几个结构体是如何注册进去的?注册顺序?//待补充

  (1)video_device 是如何被注册的?

    在哪里调用?硬件相关具体驱动实现调用?

    调用video_register_device 函数,这个函数直接调用__video_register_device。

    在__video_register_device中会对 video_device 结构进行初始化,然后:

      1)vdev 添加到 video_device 数组中次设备号对应的下标位置。

        video_device 数组是static struct video_device * 类型的数组,定义在v4l2-dev.c文件中,数组大小为256。注册时没一个video_device struct 对象的指针都保存在这个数组中。

      2)向系统中添加一个字符设备vdev->cdev

      3)注册设备vdev->dev到sysfs系统中

      4)注册实体vdev

    最后会激活这个次设备,字符设备就能被使用了。

     video_device 数组作用,获得struct video_device * 的指针:

    在字符设备的ops 接口中,v4l2_open 等接口的实现,首先通过调用video_devdata()函数,得到对应的video_device 设备指针,进而进行针对v4l2设备相关的操作。

     

    内存中每个file对象的f_inode字段指向的inode struct 的i_rdev成员是对应设备号,MINOR宏取其低20位即次设备号

  (2)注册本质做了什么?为什么注册的接口是video core层来提供?

    1)cdev_add

    2)device_register

      只调用两个函数: device_initialize 和 device_add

    3)video_register_media_controller

 

2.2 v4l2 文件句柄

  (1)file handle: 便于存储和管理文件相关的数据结构

    1)比如,v4l2的event事件依托在v4l2 file handle上。

    2)实现文件的多次打开。每个应用打开文件时,v4l2都会创建一个新file handle,并将文件相关的数据保存到其中,可以隔离不同的应用程序。

  (2)struct v4l2_fh

    1)每次通过 open 函数打开文件时,都会分配一个文件句柄。这个句柄的private_data 指向v4l2_fh结构体。

    2)video_device 保存一个v4l2_fh的列表。

 

  (3)驱动如何使用这个结构体? 

    //待补充

2.3 v4l2_device

  (1)每一个 v4l2 device 必须创建一个 v4l2_device stuct , 可以是独立的或者是嵌入到一个更大的struct 中。

  (2)注意:

    1)该结构中的dev->driver_data 指向该结构

    2)如果没有父设备,dev  可以是NULL

  (3)v4l2 设备注册

    v4l2_device_register()

2.4 v4l2子设备

 

2.5 v4l2 control handler 机制

 

2.6 v4l2 event机制

 

 

******************

references:

  1. 第二章 v4l2 framework简介

  2. v4l2中的file hande

  分析基于 linux kernel v4.9

posted on 2017-12-15 16:20  sky8336  阅读(618)  评论(0编辑  收藏  举报

导航