RK3568驱动指南|第九篇 设备模型-第108章 驱动注册流程分析实验

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568 支持安卓 11 和 linux 系统,主要面向物联网网关、NVR 存储、工控平板、工业检测、工控盒、卡拉 OK、云终端、车载中控等行业。


【公众号】迅为电子

【粉丝群】824412014(加群获取驱动文档+例程)

【视频观看】嵌入式学习之Linux驱动(第九期_设备模型_全新升级)_基于RK3568

【购买链接】迅为RK3568开发板瑞芯微Linux安卓鸿蒙ARM核心板人工智能AI主板


第108章 驱动注册流程分析实验

在上一章节中,我们学习了设备注册到自定义总线下,并进行了实验。在本章节中,我们将继续探讨驱动是如何注册到总线上的。

一旦驱动程序的结构体和匹配信息准备就绪,我们就可以调用 driver_register() 函数将驱动程序注册到总线上。

108.1 driver_register函数解析

driver_register函数实现如下所示:

int driver_register(struct device_driver *drv)
{
	int ret;
	struct device_driver *other;

	// 检查总线是否已初始化
	if (!drv->bus->p) {
		pr_err("Driver '%s' was unable to register with bus_type '%s' because the bus was not initialized.\n",
			   drv->name, drv->bus->name);
		return -EINVAL;
	}

	// 检查驱动程序的方法是否需要更新
	if ((drv->bus->probe && drv->probe) ||
	    (drv->bus->remove && drv->remove) ||
	    (drv->bus->shutdown && drv->shutdown))
		printk(KERN_WARNING "Driver '%s' needs updating - please use "
			"bus_type methods\n", drv->name);

	// 检查驱动程序是否已被注册
	other = driver_find(drv->name, drv->bus);
	if (other) {
		printk(KERN_ERR "Error: Driver '%s' is already registered, "
			"aborting...\n", drv->name);
		return -EBUSY;
	}

	ret = bus_add_driver(drv);  // 将驱动程序添加到总线
	if (ret)
		return ret;
	ret = driver_add_groups(drv, drv->groups);  // 添加驱动程序的组属性
	if (ret) {
		bus_remove_driver(drv);  // 移除已添加的驱动程序
		return ret;
	}
	kobject_uevent(&drv->p->kobj, KOBJ_ADD);  // 发送内核对象事件,通知驱动程序添加成功

	return ret;  // 返回注册结果
}

driver_register函数用于注册设备驱动程序并将其添加到总线中。以下是该函数的功能解释:

  • 第5~11行代码 检查总线是否已初始化:
  • 首先,通过 drv->bus访问设备驱动程序结构体中的总线信息。如果总线的 p成员为 NULL,表示总线未初始化。如果总线未初始化,则打印错误消息,并返回 -EINVAL错误码表示无效的参数。
  • 第13行~19行代码 检查驱动程序的方法是否需要更新:
  •  通过检查驱动程序结构体中的 bus->probe和 drv->probe、bus->remove 和 drv->remove、bus->shutdown 和 drv->shutdown 成员是否同时存在来判断。如果存在需要更新的方法组合,说明驱动程序需要更新。在这种情况下,打印警告消息,建议使用 bus_type 方法进行更新。
  • 第21行~26行 检查驱动程序是否已被注册:
  • 调用 driver_find函数来查找是否已经注册了同名的驱动程序。如果找到同名驱动程序,表示驱动程序已经注册过。在这种情况下,打印错误消息,并返回 -EBUSY错误码表示设备忙。
  • 第28行代码 添加驱动程序到总线:
  • 调用 bus_add_driver 函数将驱动程序添加到总线。如果添加失败,则返回相应的错误码。
  • 第31行代码 添加驱动程序的组属性:

调用 driver_add_groups函数将驱动程序的组属性添加到驱动程序中。如果添加失败,则调用 bus_remove_driver函数移除已添加的驱动程序,并返回相应的错误码。

  • 第36行代码 发送内核对象事件:

 调用 kobject_uevent函数向驱动程序的内核对象发送事件,通知驱动程序已成功添加到系统中。

综上所述,driver_register函数的功能是注册设备驱动程序并将其添加到总线中,同时进行各种检查和错误处理操作。

在上面代码中,调用 bus_add_driver 函数将驱动程序添加到总线。我们来详细分析下bus_add_driver 函数。

int bus_add_driver(struct device_driver *drv)
{
	struct bus_type *bus;
	struct driver_private *priv;
	int error = 0;

	// 获取总线对象
	bus = bus_get(drv->bus);
	if (!bus)
		return -EINVAL;  // 返回无效参数错误码

	pr_debug("bus: '%s': add driver %s\n", bus->name, drv->name);

	// 分配并初始化驱动程序私有数据
	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (!priv) {
		error = -ENOMEM;
		goto out_put_bus;
	}
	klist_init(&priv->klist_devices, NULL, NULL);
	priv->driver = drv;
	drv->p = priv;
	priv->kobj.kset = bus->p->drivers_kset;
	// 初始化并添加驱动程序的内核对象
	error = kobject_init_and_add(&priv->kobj, &driver_ktype, NULL,
				     "%s", drv->name);
	if (error)
		goto out_unregister;

	// 将驱动程序添加到总线的驱动程序列表
	klist_add_tail(&priv->knode_bus, &bus->p->klist_drivers);
	// 如果总线启用了自动探测,则尝试自动探测设备
	if (drv->bus->p->drivers_autoprobe) {
		error = driver_attach(drv);
		if (error)
			goto out_unregister;
	}
	// 将驱动程序添加到模块
	module_add_driver(drv->owner, drv);

	// 创建驱动程序的uevent属性文件
	error = driver_create_file(drv, &driver_attr_uevent);
	if (error) {
		printk(KERN_ERR "%s: uevent attr (%s) failed\n",
			__func__, drv->name);
	}
	// 添加驱动程序的组属性
	error = driver_add_groups(drv, bus->drv_groups);
	if (error) {
		/* How the hell do we get out of this pickle? Give up */
		printk(KERN_ERR "%s: driver_create_groups(%s) failed\n",
			__func__, drv->name);
	}

	// 如果驱动程序不禁止绑定属性文件,则添加绑定属性文件
	if (!drv->suppress_bind_attrs) {
		error = add_bind_files(drv);
		if (error) {
			/* Ditto */
			printk(KERN_ERR "%s: add_bind_files(%s) failed\n",
				__func__, drv->name);
		}
	}

	return 0;  // 返回成功

out_unregister:
	kobject_put(&priv->kobj);
	/* drv->p is freed in driver_release()  */
	drv->p = NULL;
out_put_bus:
	bus_put(bus);
	return error;  // 返回错误码
}

bus_add_driver该函数用于将设备驱动程序添加到总线中。以下是功能的详细解释:

  • 第8行代码获取总线对象:
  • 通过 drv->bus 访问设备驱动程序结构体中的总线信息。通过调用 bus_get 函数获取总线对象。如果总线对象不存在,则返回 -EINVAL 错误码表示无效的参数。
  • 第15行~23行代码分配并初始化驱动程序私有数据:
  • 调用 kzalloc 函数为驱动程序的私有数据结构体 priv 分配内存,并使用 GFP_KERNEL 标志进行内存分配。如果内存分配失败,则返回 -ENOMEM 错误码表示内存不足。使用 klist_init 函数初始化 priv 结构体中的设备列表。设置 priv 结构体中的驱动程序指针,并将其赋值为当前的驱动程序。将 drv->p 指向 priv 结构体,以便后续的释放操作。
  • 第25行代码初始化并添加驱动程序的内核对象:
  • 设置 priv->kobj.kset 成员为总线对象的 drivers_kset。调用 kobject_init_and_add 函数初始化并添加驱动程序的内核对象。如果初始化或添加失败,则跳转到 out_unregister 进行错误处理。
  • 第31行代码将驱动程序添加到总线的驱动程序列表:
  • 使用 klist_add_tail 函数将驱动程序的节点添加到总线的驱动程序列表中。

到此,如何在总线下注册驱动流程已经分析完毕。


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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

计算机创新协会冬令营——暴力枚举题目04

说句实话,单纯的暴力枚举题目太难找了┭┮﹏┭┮,接招吧~~ 题目 2094. 找出 3 位偶数 - 力扣(LeetCode) 给你一个整数数组 digits ,其中每个元素是一个数字(0 - 9)。数组中可能存在重复元素。…

光伏效果图是用什么软件建模设计的?

光伏效果图是展示光伏系统在建筑或地面上的外观和效果的图像。要创建这样的效果图,需要使用专业的建模和设计软件。那么,光伏效果图是用什么软件建模设计的呢? 鹧鸪云光伏设计软件:鹧鸪云是一款集开发、设计和施工为一体的设计软…

【每日一题】被列覆盖的最多行数

文章目录 Tag题目来源解题思路方法一:二进制枚举 写在最后 Tag 【二进制枚举】【矩阵】【2024-01-04】 题目来源 2397. 被列覆盖的最多行数 解题思路 方法一:二进制枚举 思路 使用二进制枚举所有选中列的集合,对于集合中的每一个二进制数…

whistle+SwitchyOmega前端api代理调试

1、whistle介绍 whistle官网whistle githubwhistle主要用于查看、修改HTTP、HTTPS、Websocket的请求、响应,也可以作为HTTP代理服务器,功能很强大 2、安装教程 官方安装文档 // 全局安装whistle npm install -g whistle// 安装whistle的inspect插件&a…

three.js gltf后处理颜色异常(伽马校正)

效果&#xff1a; 应用了伽马校正&#xff0c;好像效果不明显 代码&#xff1a; <template><div><el-container><el-main><div class"box-card-left"><div id"threejs" style"border: 1px solid red"><…

Apache 网页优化

技能目标&#xff1a; 掌握 Apache 网页压缩掌握 Apache 网页缓存掌握Apache 隐藏版本信息掌握 Apache 网页防盗链 1.1网页压缩与缓存 在使用 Apache 作为 Web 服务器的过程中&#xff0c;只有对 Apache 服务器进行适当的优化配 置才能让 Apache 发挥出更好的性能。反过来说&…

快速打通 Vue 3(二):响应式对象基础

很激动进入了 Vue 3 的学习&#xff0c;作为一个已经上线了三年多的框架&#xff0c;很多项目都开始使用 Vue 3 来编写了 这一组文章主要聚焦于 Vue 3 的新技术和新特性 如果想要学习基础的 Vue 语法可以看我专栏中的其他博客 Vue&#xff08;一&#xff09;&#xff1a;Vue 入…

Java 变量与运算符

初识变量 内存中的一个存储区域&#xff0c;该区域的数据可以在同一类型范围内不断变化变量的构成包含三个要素&#xff1a;数据类型、变量名、存储的值Java 中变量声明的格式&#xff1a;数据类型 变量名 变量值 变量的数据类型 Java中变量的数据类型分为两大类&#xff1…

不会代码(零基础)学语音开发(语音控制板载双电机)

电机&#xff0c;可以说是在生活中无处不见。有句话形容它&#xff1a;只要动的地方就有电机的身影。 比方说&#xff1a;空调、冰箱、洗衣机、油烟机、电扇、吸尘器、电动剃须刀、电吹风、豆浆机、破壁机、空气净化器、洗碗机、电动牙刷等种种电器产品&#xff0c;无一不是使…

检测和缓解僵尸网络

僵尸网络源自“机器人网络”一词&#xff0c;是感染了恶意软件的网络或机器集群&#xff0c;允许黑客控制并发起一系列攻击。僵尸网络的强度完全取决于它所包含的受感染机器的数量。攻击者接管这些设备的操作&#xff0c;以使用僵尸网络命令和控制模型进行远程控制。 什么是僵…

排除启动类故障----三大实验

目录 一、模拟破坏mbr和分区表然后修复 二、修复grub引导故障 三、遗忘root用户密码 一、模拟破坏mbr和分区表然后修复 1、mbr处于第一块磁盘的第一个物理扇区&#xff0c;总共512个字节&#xff0c;前446个字节是grub程序&#xff0c;后面64个字节是分区表 2、故障原因&a…

实现中文jieba分词

目录 问题描述&#xff1a; 代码实现&#xff1a; 问题描述&#xff1a; 使用中文分词库jieba从给定的文本中提取指定范围内的前后词语。 特殊的&#xff0c;如果前面是‘的’即再向前取一位&#xff0c;这个可根据自己的实际需求做出更改。 代码实现&#xff1a; import j…

如何获取完整的中国DEM高程数据

地形数据&#xff0c;也叫dem数据&#xff0c;是我们在各项研究中最常使用的数据之一&#xff0c;通过地形数据我们可以分析地表的高程、坡度、坡向等信息&#xff01; 地形数据&#xff0c;也叫dem数据&#xff0c;是我们在各项研究中最常使用的数据之一&#xff0c;通过地形…

企业无法处理海量的大文件,FTP不可靠该如何进行替代?

FTP是一项标准协议&#xff0c;用于在网络中进行文件传输&#xff0c;最早于1971年问世&#xff0c;被认为是互联网的基石之一。FTP可在不同操作系统和网络环境下实现文件上传和下载&#xff0c;具备方便、迅速和高效的特性&#xff0c;广泛应用于网站建设、软件更新、数据备份…

frp配置内网穿透访问家里的nas

frp配置内网穿透访问家里的nas 需求 家里局域网内有台nas&#xff0c;在去公司的路上想访问它 其内网地址为&#xff1a; http://192.168.50.8:6002 工具 1.frp版本v0.53.2 下载地址&#xff1a; https://github.com/fatedier/frp/releases/download/v0.53.2/frp_0.53.2_li…

万界星空科技低代码平台:制造业数字化转型的捷径

低代码MES系统&#xff1a;制造业数字化转型的捷径 随着制造业的数字化转型&#xff0c;企业对生产管理系统的需求逐渐提高。传统的MES系统实施过程复杂、成本高昂&#xff0c;已经无法满足现代企业的快速发展需求。而低代码搭建MES系统的出现&#xff0c;为企业提供了一种高…

大创项目推荐 深度学习卫星遥感图像检测与识别 -opencv python 目标检测

文章目录 0 前言1 课题背景2 实现效果3 Yolov5算法4 数据处理和训练5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; **深度学习卫星遥感图像检测与识别 ** 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐…

Android 相机库CameraView源码解析 (四) : 带滤镜预览

1. 前言 这段时间&#xff0c;在使用 natario1/CameraView 来实现带滤镜的预览、拍照、录像功能。 由于CameraView封装的比较到位&#xff0c;在项目前期&#xff0c;的确为我们节省了不少时间。 但随着项目持续深入&#xff0c;对于CameraView的使用进入深水区&#xff0c;逐…

借助开源自定义表单,实现流程化办公

实现流程化办公已经成为众多企业的发展目的和愿望&#xff0c;因为可以为企业提质增效、创造良好效益&#xff0c;因此在现代化职场办公中&#xff0c;流程化办公是众多客户追求的发展目的。开源自定义表单拥有较为突出的优势和特点&#xff0c;可以发挥其应有的市场价值和作用…

DBSCAN聚类算法

DBSCAN读作&#xff1a;DB Scan&#xff0c;是英语基于密度的噪声应用空间聚类&#xff08;Density-Based Spatial Clustering of Applications with Noise&#xff09;的简写。在理解K-means聚类算法之后再来理解DBSCAN就容易多了。 DBSCAN的步骤如下&#xff1a; 随机从一个…