【V4L2】 v4l2框架分析之v4l2_device

news2025/2/13 12:45:35

👀👉本系列文章基于linux内核版本4.1.15分析media子系统下的V4L2。先分析组成V4L2的核心数据结构以及各组成元素的含义和作用。相关文章:


❤(1)《【V4L2】v4l2框架分析之video_device》
❤(2)《V4L2-PCI驱动程序样例分析(一)》

文章目录

    • 🔺一、v4l2_device简介
    • 🔺二、注册v4l2_device
    • 🔺三、移除v4l2_device
    • 🔺四、引用计数

🔺一、v4l2_device简介

相关源码文件:

  • /drivers/media/v4l2-core/v4l2-device.h
  • /drivers/media/v4l2-core/v4l2-device.c

对于想要接入V4L2子系统的设备,每个设备实例都由一个struct v4l2_device表示。对于简单的设备可以只分配这个结构,但大多数情况下,可以把这个结构嵌入到更大的结构中。v4l2_device定义如下(/include/media/v4l2-device.h):

struct v4l2_device {
	struct device *dev;    //指向struct device的指针。
#if defined(CONFIG_MEDIA_CONTROLLER)
	struct media_device *mdev; //指向struct media_device的指针,值可以为NULL。struct media_device表示一个媒体设备。
#endif
	struct list_head subdevs;  //用来跟踪注册的子设备。
	spinlock_t lock;  //自旋锁。用于锁定这个结构体;如果这个结构体被嵌入到一个更大的结构体中,也可以被驱动程序使用。
	char name[V4L2_DEVICE_NAME_SIZE]; //唯一的设备名称,默认是驱动程序名称+总线ID
	void (*notify)(struct v4l2_subdev *sd,
			unsigned int notification, void *arg);  //被一些子设备调用,可用于执行通知操作。
	struct v4l2_ctrl_handler *ctrl_handler;  //control处理程序,可以为NULL。
	struct v4l2_prio_state prio;  //设备优先级状态。
	struct mutex ioctl_lock; //互斥锁。
	struct kref ref; //用于跟踪对这个结构体的引用。
	void (*release)(struct v4l2_device *v4l2_dev); //当ref的计数值变为0时调用这个函数。
};

🔺二、注册v4l2_device

在实际开发中,需使用下列函数:

v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);

注册v4l2_device设备实例。

函数实现如下:

该函数会初始化v4l2_device结构。如果dev->driver_data字段是NULL,他将被连接到v4l2_dev。如果驱动程序想要与媒体设备框架集成,则需要手动设置dev->driver_data,用于指向v4l2_device实例的驱动程序的特定设备结构。这是通过在注册V4L2设备实例之前调用dev_set_drvdata()实现的。还必须设置v4l2_device结构的mdev字段,用于指向初始化和注册的媒体设备实例。

如果v4l2_dev->name为空,那么它将被设置为派生自dev的值,如果在调用v4l2_device_register()之前已经设置了v4l2_dev->name,那么它将不受到影响。如果dev为NULL,那么在调用v4l2_device_register之前,则必须设置v4l2_dev->name参数。

对于v4l2_device_register()函数,第一个’dev’参数通常是指向pci_devusb_interfaceplatform_device的设备指针。dev很少为NULL,但是ISA设备或一个设备创建多个PCI设备时会出现dev为NULL的情况,因此不可能将v4l2_dev与特定的父设备进行关联。

在实际驱动程序设计中,可以提供一个notify()回调函数,子设备可以调用它来通知事件。是否需要设置notify回调函数取决于子设备。子设备支持的任何通知都必须在include/media/subdevice.h的头文件中定义。

🔺三、移除v4l2_device

在驱动程序设计中,使用:

v4l2_device_unregister(struct v4l2_device *v4l2_dev);

来移除注册的设备。如果dev->driver_data字段指向v4l2_dev,那么dev->driver_data将被重置为NULL。移除操作也会自动从设备上移除所有子设备。

如果有一个可热插拔的设备(例如USB设备),那么当断开连接时,父设备就会失效。因为v4l2_device有一个指向父设备的指针,所以它也必须被清除,以标记父设备已经消失。这时候需要调用:

v4l2_device_disconnect(struct v4l2_device *v4l2_dev);

该函数不会取消注册的子设备,所以仍然需要调用v4l2_device_unregister()函数。如果驱动程序不可以热插拔,则不需要调用v4l2_device_disconnect()

有时需要遍历由特定驱动程序注册的所有设备。如果多个设备驱动程序使用相同的硬件,通常会出现这种情况:例如,ivtvfb驱动程序是一个使用ivtv硬件的帧缓冲区驱动程序。同样的情况也适用于alsa驱动。

可以使用下列所示的代码遍历所有已经注册的设备:

static int callback(struct device *dev, void *p)
{
  struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);

  /* 检测该设备是否已经被初始化 */
  if (v4l2_dev == NULL)
  	return 0;
  ...
  return 0;
}

int iterate(void *p)
{
  struct device_driver *drv;
  int err;

  /* Find driver 'ivtv' on the PCI bus.
     pci_bus_type is a global. For USB busses use usb_bus_type. */
  drv = driver_find("ivtv", &pci_bus_type);
  /* iterate over all ivtv device instances */
  err = driver_for_each_device(drv, NULL, p, callback);
  put_driver(drv);
  return err;
}

🔺四、引用计数

如果有多个设备节点,那么很难知道何时为可热插拔设备注销v4l2_device是安全的操作。因此,v4l2_device支持引用计数:在video_register_device()被调用时增加引用计数值,在设备节点被释放时减少引用计数值,当引用计数值达到零时,则会调用v4l2_devicerelease()回调。在实际驱动程序设计中,则可以在这个回调函数中执行最后的清理操作。

如果创建了其他设备节点(例如ALSA),那么也可以通过调用:

void v4l2_device_get(struct v4l2_device *v4l2_dev);

或者:

int v4l2_device_put(struct v4l2_device *v4l2_dev);

手动增加、减少引用计数。

由于初始引用计数是1,所以还需要在disconnect()remove()回调函数(例如PCI设备)中调用v4l2_device_put(),否则引用计数将不会达到0。

参考资料:
https://docs.kernel.org/driver-api/media/v4l2-device.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/639547.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

30分钟了解并学会git的使用(绝对干货)

概述: 在programmer行业有一句流传许久的话:不会用git的程序员,不是真的程序员!!! 足以看出来git在业界的认可度有多高,所以我们混这行的都应该学会这个由Linux之父林纳斯开发 的第二大发明&a…

【QT/OpenCV】Qt创建并发布OpenCV dll项目

文章目录 01、开发版本02、QT创建dll项目03、dll项目配置说明04、dll动态库测试 01、开发版本 以下所有源码与软件都是基于下面的版本。 1、QT: Based on Qt 5.12.2 (MSVC 2017, 32 bit) 2、OpenCV: OpenCV – 4.5.1 tips: OpenCV的版本不一…

web漏洞-逻辑越权之登录脆弱支付篡改(34)

这节课是这两个内容,登录的内容会讲不完,会有一小点部分,在别的课将, #登录应用功能点产生的安全问题 只要有登录功能都可以检测(排除之前讲过的) 1.登陆点的暴力破口(很好理解 2.http/http…

【第三节】列表

上一节介绍了最常见的两种数据类型 字符串和数字 这一节将介绍列表 列表 首先,什么是列表?列表是由一系列按照特定顺序排列的元素组成,在python中由中括号[ ]定义 首先列表是一系列的元素,这些元素的种类可以不同,一…

python3 爬虫相关学习9:BeautifulSoup 官方文档学习

目录 1 BeautifulSoup 官方文档 2 用bs 和 requests 打开 本地html的区别:代码里的一段html内容 2.1 代码和运行结果 2.2 用beautiful 打开 本地 html 文件 2.2.1 本地html文件 2.2.2 soup1BeautifulSoup(html1,"lxml") 2.3 用requests打开 本地 h…

微服务治理【注册发现】Nacos

目录 Nacos是什么? Nacos有什么用? 使用 Nacos 服务发现的流程图 Nacos是什么? Nacos是阿里巴巴开源的一个服务发现、配置管理和服务管理平台,是一种基于云原生架构的动态服务发现和配置管理工具。 Nacos有什么用&#xff…

什么是API测试?开发必知的8种API自动化测试类型

API测试 API自动化测试在产品质量控制和CI/CD流程检测中扮演着非常重要的角色。与GUI测试不同,API测试可以更灵活应地适应发布周期短和频繁变更的需求或产品,而且也不会破坏测试输出结果。 什么是API测试? API是应用程序编程接口的首字母缩…

jetLinks协议开发对接真实设备方式

jetLinks协议开发对接真实设备方式 拿到设备确定设备的SDKSDK调用流程梳理SDK集成JetLinks 拿到设备 首先拿到设备,确认设备型号 然后登入海康威视官网,下载 https://www.hikvision.com/cn/support/tools/hitools/ 连接设备修改其对应的IP地址使得本…

信号都是如何产生的,干货满满

目录 一、哪三大阶段 二、产生信号 1、通过键盘产生信号 2、系统调用 3、软件条件产生信号 4、硬件异常产生信号 三、Term和core是什么 一、信号一生三大阶段 1、产生信号:由通过键盘、系统调用、软件条件、硬件异常产生这几种方法产生信号。 2、信号储存&a…

JMeter必知必会系列 —— JMeter基础

1.1 JMeter概述 JMeter简介 Apache JMeter™是Apache组织开发的一款开源软件,是典型的纯Java开发的应用程序,可以在不同平台比如Windows、Linux或macOS系统上进行软件测试。JMeter主要用于应用程序的功能负载测试以度量软件的性能,也可以用于…

项目使用tensorflow2会出错,下载并使用tensorflow1

背景:使用pycharm安装总显示安装失败,使用pip安装也不行,只能使用conda配置虚拟环境手动安装 1、下载安装anaconda 官网下载,双击安装。用anaconda就是想使用虚拟环境,万一没弄好直接删了重新搞就行。 2、创建虚拟环境…

Kendo UI R2 2023 crack

Kendo UI R2 2023 crack 新组件:角度PDFViewer 直接在Angular应用程序中查看PDF文件,无需第三方软件或附加组件。 凭借直观的分页机制、强大的搜索功能和灵活的缩放选项,用户可以轻松导航和浏览PDF内容。 角度16支架 Angular 16引入了一系列改…

AWS CodeWhisperer(代码辅助工具)使用体验

工具 1.vscode 2.AWS Toolkit插件 CodeWhisperer插件的功能 1.自动优化代码:CodeWhisperer插件可以通过代码分析来自动优化代码,从而提高代码的质量和效率。 2.智能代码提示:CodeWhisperer插件可以根据代码上下文提供智能代码提示&#x…

C语言之数组详解(1)(更新前面数组博客的不足)

目录 一、一维数组 1.一维数组的创建和初始化 (1).数组的创建 (2).数组的初始化 2.一维数组的使用 3.一维数组在内存中的存储 二、二维数组 1.二维数组的创建和初始化 (1).二维数组的创建 (2).二维数组的初始化 2.二维数组的使用 3.二维数组在内存中的存储 三、数组作为函数参…

尚硅谷大数据技术Spark教程-笔记08【SparkSQL(介绍、特点、数据模型、核心编程、案例实操、总结)】

尚硅谷大数据技术-教程-学习路线-笔记汇总表【课程资料下载】视频地址:尚硅谷大数据Spark教程从入门到精通_哔哩哔哩_bilibili 尚硅谷大数据技术Spark教程-笔记01【SparkCore(概述、快速上手、运行环境、运行架构)】尚硅谷大数据技术Spark教程…

14.一天搞定主流小程序按分类列表显示文章1

小程序按分类列表显示文章1 (视频对应无13) 本教程均在第一节中项目启动下操作 小程序按分类列表显示文章1 (视频对应无13)前言一、新增分类界面:![在这里插入图片描述](https://img-blog.csdnimg.cn/1dffd20abc8f47d3961dee59426f3a8f.png)二.新增接口apiflex布局组件数据表绑…

Cocos creator常驻节点使用方式addPersistRootNode

最近在做小游戏的时候,遇到了进入result场景时候的传值问题。 场景加载传值,通过常驻节点实现。 在game_scene中添加常驻节点GameResultData空节点。 创建脚本GameResultData.ts,声明要传递的值的内容。 const {ccclass, property} cc._de…

vscode配置格式化

安装好插件 : Vetur 打开vscode --> 文件 --> 首选项 --> 设置 --> 扩展 --> vetur 点击: 写入以下代码 // { // "files.autoSave": "onFocusChange", // "explorer.confirmDelete": false, // "editor.…

南大通用GBase 8c 多模多态分布式数据库系列一之基本介绍、核心技术、架构演进

前言 随着传统的关系型SQL数据库(Oracle,MySQL,PostgreSQL等)难以满足日益增长的高数据量、快速数据处理要求、高数据库安全及强容灾能力要求(RPO,RTO)等挑战,尽管NoSQL非关系型数据…

【超详细练气篇】STL之string类---常见接口函数(1)

个人主页:平行线也会相交💪 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创 收录于专栏【C之路】💌 本专栏旨在记录C的学习路线,望对大家有所帮助🙇‍ 希望我们一起努力、成长&…