linux V4L2子系统——v4l2架构(2)之v4l2_device

备注:
  1. Kernel版本:5.4
  2. 使用工具:Source Insight 4.0
  3. 参考博客:
(1)Linux V4L2子系统分析(一)
(2)linux v4l2 学习之-v4l2设备注册过程及各个设备之间的联系
(3)V4L2框架-v4l2 device

文章目录

  • linux V4L2子系统——v4l2架构(2)之v4l2_device
    • v4l2_device结构体概述
    • 主要函数解析
      • v4l2_device_register函数
      • 其他相关函数

v4l2_device结构体概述

详见:
linux V4L2子系统——v4l2的结构体(1)之v4l2_device

V4L2主设备实例使用struct v4l2_device结构体表示,v4l2_device是V4L2子系统的入口,管理着V4L2子系统的主设备和从设备。简单设备可以仅分配这个结构体,但在大多数情况下,都会将这个结构体嵌入到一个更大的结构体中。需要与媒体框架整合的驱动必须手动设置dev->driver_data,指向包含v4l2_device结构体实例的驱动特定设备结构体。这可以在注册V4L2设备实例前通过dev_set_drvdata()函数完成。同时必须设置v4l2_device结构体的mdev域,指向适当的初始化并注册过的media_device实例。

在文件 drivers/media/platform/sunxi/sun6i-csi/sun6i-csi.c 中的 sun6i_csi_probe 函数将调用 sun6i_csi_v4l2_init 函数中的第一个参数为 struct sun6i_csi ,此为驱动自定义的结构体,那就是它了,那么它的定义如下:

// 源码:drivers/media/platform/sunxi/sun6i-csi/sun6i-csi.c
struct sun6i_csi {struct device         *dev;struct v4l2_ctrl_handler   ctrl_handler;struct v4l2_device     v4l2_dev;struct media_device        media_dev;struct v4l2_async_notifier    notifier;/* video port settings */struct v4l2_fwnode_endpoint   v4l2_ep;struct sun6i_csi_config     config;struct sun6i_video       video;
};

主要函数解析

// 源码:include/media/v4l2-device.h// 注册v4l2_device结构体,并初始化v4l2_device结构体// dev-父设备结构体指针,若为NULL,在注册之前设备名称name必须被设置,// v4l2_dev-v4l2_device结构体指针// 返回值-0成功,小于0-失败int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)// 卸载注册的v4l2_device结构体// v4l2_dev-v4l2_device结构体指针void v4l2_device_unregister(struct v4l2_device *v4l2_dev)// 设置设备名称,填充v4l2_device结构体中的name成员// v4l2_dev-v4l2_device结构体指针// basename-设备名称基本字符串// instance-设备计数,调用v4l2_device_set_name后会自加1// 返回值-返回设备计数自加1的值int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename, atomic_t *instance)// 热插拔设备断开时调用此函数// v4l2_dev-v4l2_device结构体指针void v4l2_device_disconnect(struct v4l2_device *v4l2_dev);

v4l2_device_register函数

// 源码:drivers/media/platform/sunxi/sun6i-csi/sun6i-csi.c
static int sun6i_csi_v4l2_init(struct sun6i_csi *csi)
{int ret;......ret = v4l2_ctrl_handler_init(&csi->ctrl_handler, 0);if (ret) {dev_err(csi->dev, "V4L2 controls handler init failed (%d)\n",ret);goto clean_media;}csi->v4l2_dev.mdev = &csi->media_dev;csi->v4l2_dev.ctrl_handler = &csi->ctrl_handler;ret = v4l2_device_register(csi->dev, &csi->v4l2_dev);if (ret) {dev_err(csi->dev, "V4L2 device registration failed (%d)\n",ret);goto free_ctrl;}......
}

v4l2的设备注册其实没有注册设备或者设备驱动,只是将v4l2的大结构体与其他设备进行捆绑,
并保存v4l2设备对象到当前设备的driverdata中。此函数的作用就是将当前设备驱动和v4l2对象进行捆绑,便于挂接子设备

如下面是v4l2注册设备的过程。

//源码:drivers/media/v4l2-core/v4l2-device.c// 注册v4l2_device结构体,并初始化v4l2_device结构体
// dev-父设备结构体指针,若为NULL,在注册之前设备名称name必须被设置,
// v4l2_dev-v4l2_device结构体指针
// 返回值-0成功,小于0-失败
int v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev)
{if (v4l2_dev == NULL)return -EINVAL;INIT_LIST_HEAD(&v4l2_dev->subdevs);   //初始化subdev链表spin_lock_init(&v4l2_dev->lock);v4l2_prio_init(&v4l2_dev->prio);kref_init(&v4l2_dev->ref);            //初始化v4l2_dev计数值为1// 上面都是做一些初始化工作get_device(dev);// 下面将当前设备的对象,赋值给v4l2_dev->dev中,// 这样的话当前的设备就成了v4l2设备,// 由于当前设备已经注册过了设备文件,// 所以后续不需要在重新注册设备文件。v4l2_dev->dev = dev;if (dev == NULL) {      // 条件检查/* If dev == NULL, then name must be filled in by the caller */if (WARN_ON(!v4l2_dev->name[0]))return -EINVAL;return 0;}/* Set name to driver name + device name if it is empty. *//* 如果v4l2设备的名字为空,则会将当前设备的名字拷贝为v4l2设备中。*/if (!v4l2_dev->name[0])snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s",dev->driver->name, dev_name(dev));// 下面是非常重要的一步,即将v4l2设备对象,保存到dev设备中,// 这个dev可以是platform、char、block等设,// 我们可以使用dev_get_drvdata(dev)获取到v4l2对象。if (!dev_get_drvdata(dev))dev_set_drvdata(dev, v4l2_dev);return 0;
}

使用v4l2_device_register注册v4l2_device结构体。如果v4l2_dev->name为空,则它将被设置为从dev中衍生出的值(为了更加精确,形式为驱动名后跟bus_id)。如果在调用v4l2_device_register前已经设置好了,则不会被修改。如果dev为NULL,则必须在调用v4l2_device_register前设置v4l2_dev->name。可以基于驱动名和驱动的全局atomic_t类型的实例编号,通过 v4l2_device_set_name() 设置name。这样会生成类似ivtv0、ivtv1等名字。若驱动名以数字结尾,则会在编号和驱动名间插入一个破折号,如:cx18-0、cx18-1等。dev参数通常是一个指向pci_dev、usb_interface或platform_device的指针,很少使其为NULL,除非是一个ISA设备或者当一个设备创建了多个PCI设备,使得v4l2_dev无法与一个特定的父设备关联。

使用v4l2_device_unregister卸载v4l2_device结构体。如果dev->driver_data域指向 v4l2_dev,将会被重置为NULL。主设备注销的同时也会自动注销所有子设备。如果你有一个热插拔设备(如USB设备),则当断开发生时,父设备将无效。由于v4l2_device有一个指向父设备的指针必须被清除,同时标志父设备
已消失,所以必须调用v4l2_device_disconnect函数清理v4l2_device中指向父设备的dev指针。

v4l2_device_disconnect 并不注销主设备,因此依然要调用 v4l2_device_unregister 函数注销主设备。

其他相关函数

//源码:drivers/media/v4l2-core/v4l2-device.c// 设置设备名称,填充v4l2_device结构体中的name成员
// v4l2_dev-v4l2_device结构体指针
// basename-设备名称基本字符串
// instance-设备计数,调用v4l2_device_set_name后会自加1
// 返回值-返回设备计数自加1的值
int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename,atomic_t *instance)
{int num = atomic_inc_return(instance) - 1;int len = strlen(basename);if (basename[len - 1] >= '0' && basename[len - 1] <= '9')snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),"%s-%d", basename, num);elsesnprintf(v4l2_dev->name, sizeof(v4l2_dev->name),"%s%d", basename, num);return num;
}
//源码:drivers/media/v4l2-core/v4l2-device.c// 热插拔设备断开时调用此函数 // v4l2_dev-v4l2_device结构体指针
void v4l2_device_disconnect(struct v4l2_device *v4l2_dev)
{if (v4l2_dev->dev == NULL)return;if (dev_get_drvdata(v4l2_dev->dev) == v4l2_dev)dev_set_drvdata(v4l2_dev->dev, NULL);put_device(v4l2_dev->dev);v4l2_dev->dev = NULL;
}
EXPORT_SYMBOL_GPL(v4l2_device_disconnect);
//源码:drivers/media/v4l2-core/v4l2-device.c// 卸载注册的v4l2_device结构体
// v4l2_dev-v4l2_device结构体指针
void v4l2_device_unregister(struct v4l2_device *v4l2_dev)
{struct v4l2_subdev *sd, *next;/* Just return if v4l2_dev is NULL or if it was already* unregistered before. */if (v4l2_dev == NULL || !v4l2_dev->name[0])return;v4l2_device_disconnect(v4l2_dev);/* Unregister subdevs */list_for_each_entry_safe(sd, next, &v4l2_dev->subdevs, list) {v4l2_device_unregister_subdev(sd);if (sd->flags & V4L2_SUBDEV_FL_IS_I2C)v4l2_i2c_subdev_unregister(sd);else if (sd->flags & V4L2_SUBDEV_FL_IS_SPI)v4l2_spi_subdev_unregister(sd);}/* Mark as unregistered, thus preventing duplicate unregistrations */v4l2_dev->name[0] = '\0';
}
EXPORT_SYMBOL_GPL(v4l2_device_unregister);

linux V4L2子系统——v4l2架构(2)之v4l2_device相关推荐

  1. linux V4L2子系统——v4l2架构(3)之video_device

    linux V4L2子系统--v4l2架构(3)之video_device 备注:   1. Kernel版本:5.4   2. 使用工具:Source Insight 4.0   3. 参考博客: ...

  2. 视频驱动V4L2子系统驱动架构 - 驱动框架

    文章系列 视频驱动V4L2子系统驱动架构 - 驱动框架 视频驱动V4L2子系统驱动架构 - ioctl 基于linux4.6.3 V4L2驱动框架 v4l2驱动架构如图所示,v4l2也就是video ...

  3. 视频驱动V4L2子系统驱动架构-框架

    V4L2驱动框架 v4l2驱动架构如图所示,v4l2也就是video for linux two,那么也就是说还有One了,v4l2前面还有v4l 图中芯片模块对应Soc的各个子模块,video_de ...

  4. 视频驱动V4L2子系统驱动架构

    1 概述 Video4 for Linux 2是Linux内核中关于视频设备的内核驱动框架,为上层的访问底层的视频设备提供了统一的接口.凡是内核中的子系统都是有抽象硬件的差异,为上层提供统一的接口和提 ...

  5. 视频驱动V4L2子系统驱动架构 - ioctl

    基于linux4.6.3,最后会附上一张ioctl调用总图,分析代码还是要用图来说明,这样更清晰一点,我就是这么分析的,不过平时分析的图很随便,而且很大,所以就不能在这里呈现,我在这里会贴出一个简略图 ...

  6. linux显示子系统-framebuffer架构分析

    目录 简介 驱动层 时序数据流 架构 应用层 实例 fb架构优劣势 参考文件 简介 FrameBuffer,帧缓冲,简称fb,也叫显存,下文以fb代表framebuffer.该子系统是内核针对显示系统 ...

  7. Linux V4L2子系统分析(一)

    1.概述 Linux系统上的Video设备多种多样,如通过Camera Host控制器接口连接的摄像头,通过USB总线连接的摄像头等.为了兼容更多的硬件,Linux内核抽象了V4L2(Video fo ...

  8. Linux V4L2子系统-Video设备框架分析(二)

    1.概述 在V4L2子系统中,Video设备是一个字符设备,设备节点为/dev/videoX,主设备号为81,次设备号范围为0-63.在用户空间,应用可以通过open/close/ioctl/mmap ...

  9. Linux V4L2子系统-应用层访问video设备(四)

    1.概述 V4L2子系统向上提供了很多访问Video设备的接口,应用程序可以通过系统调用访问Video设备.但由于Video设备千差万别,很少有设备驱动程序能支持所有的接口功能,因此在使用之前,需要了 ...

  10. Linux ARM平台开发系列讲解(摄像头V4L2子系统) 2.12.5 V4L2 control的原理和实现

    1. 概述 既然涉及到视频输入,就会有很多与 ISP 相关的效果,比如对比度.饱和度.色温.白平衡等等,这些都是通用的.必须的控制项,并且大多数仅需要设置一个整数值即可.Linux 内核中V4L2已经 ...

最新文章

  1. traceback异常打印
  2. 【玩转cocos2d-x之九】动作类CCAction
  3. 前端学习(1208):vue常用特性
  4. T-SQL 字符串前加 N 是什么意思
  5. oracle性能优化之awr分析
  6. 人工智能系统Google开源的TensorFlow官方文档中文版
  7. python学习第六天运算符总结大全
  8. win10 android 手机驱动下载,win10手机刷机包驱动
  9. 系统迁移到ssd 开启哪些服务器,如何使用分区助手完美迁移系统到SSD固态硬盘...
  10. [01.14]主题之家精美主题每日更新【雪豹】
  11. 谷歌地图 经纬加密_Google开始加密搜索
  12. makefile是如何自动生成的
  13. 今日头条网页数据采集接口
  14. 重读《从菜鸟到测试架构师》-- 构建的过程
  15. C语言实现url的编码和解码
  16. 渴望成长的工程师-你了解一万小时定律吗
  17. 也说说ADC以及ADC的主要技术参数及分类介绍
  18. 面试心得与总结---BAT、网易、蘑菇街
  19. 【读书分享】精益企业——高效能组织如何规模化创新?
  20. 操作DOM对象(重点)

热门文章

  1. EUI学习之DataGroup与List
  2. 数字媒体技术 计算机类 专业大学排名,2019年全国数字媒体技术专业大学排名(20强)...
  3. HC-SR501人体红外传感器
  4. pyecharts之参透神剧人物关系
  5. android adb 模拟长按,adb 模拟长按电源键
  6. 利用canvas画一个钟表
  7. 大数据:增量采集、处理、导出
  8. h5微信f分享链接给对方获取对方手机号_「技巧 分享」微信辅助验证次数及微信被封号后如何解封...
  9. unity3d 为什么要烘焙/unity3d 烘焙作用是为了什么【2020】
  10. 计算机网络 可靠数据传输原理——从rdt协议到GBN到SR