//xia仔k:鸿蒙系统实战短视频App 从0到1掌握HarmonyOS
开发指导
场景引见
关于驱动的开发我们主要目的是完成驱动代码的编写,但是驱动开发过程中需求效劳管理、音讯机制管理,才干使驱动在代码编译过程中停止加载。以下开发步骤中引见了驱动开发、驱动音讯机制管理开发、驱动效劳管理开发的步骤。
驱动开发实例
基于HDF框架的驱动开发主要分为三个局部:驱动完成、驱动编译脚本编写和驱动配置。细致开发流程如下所示:
驱动完成
驱动完成包含驱动业务代码完成和驱动入口注册,详细写法如下:
驱动业务代码
#include "hdf_device_desc.h" // HDF框架对驱动开发相关才能接口的头文件
#include "hdf_log.h" // HDF框架提供的日志接口头文件
#define HDF_LOG_TAG sample_driver // 打印日志所包含的标签,假如不定义则用默许定义的HDF_TAG标签。
// 将驱动对外提供的效劳才能接口绑定到HDF框架。
int32_t HdfSampleDriverBind(struct HdfDeviceObject *deviceObject)
{
HDF_LOGD("Sample driver bind success");
return HDF_SUCCESS;
}
// 驱动本身业务初始化的接口
int32_t HdfSampleDriverInit(struct HdfDeviceObject *deviceObject)
{
HDF_LOGD("Sample driver Init success");
return HDF_SUCCESS;
}
// 驱动资源释放的接口
void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject)
{
HDF_LOGD("Sample driver release success");
return;
}
驱动入口注册到HDF框架
// 定义驱动入口的对象,必需为HdfDriverEntry(在hdf_device_desc.h中定义)类型的全局变量。
struct HdfDriverEntry g_sampleDriverEntry = {
.moduleVersion = 1,
.moduleName = "sample_driver",
.Bind = HdfSampleDriverBind,
.Init = HdfSampleDriverInit,
.Release = HdfSampleDriverRelease,
};
// 调用HDF_INIT将驱动入口注册到HDF框架中。在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动;当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
HDF_INIT(g_sampleDriverEntry);
驱动编译脚本编写
LiteOS
触及Makefile和BUILD.gn修正:
Makefile局部:
驱动代码的编译必需要运用HDF框架提供的Makefile模板停止编译。
include $(LITEOSTOPDIR)/../../drivers/hdf_core/adapter/khdf/liteos/lite.mk # 【必需】导入hdf预定义内容
MODULE_NAME := #生成的结果文件
LOCAL_INCLUDE := #本驱动的头文件目录
LOCAL_SRCS := #本驱动的源代码文件
LOCAL_CFLAGS := #自定义的编译选项
include $(HDF_DRIVER) #导入Makefile模板完成编译
编译结果文件链接到内核镜像,添加到drivers/hdf_core/adapter/khdf/liteos目录下的hdf_lite.mk里面,示例如下:
LITEOS_BASELIB += -lxxx #链接生成的静态库
LIB_SUBDIRS += #驱动代码Makefile的目录
BUILD.gn局部:
添加模块BUILD.gn,可参考如下示例:
import("//build/lite/config/component/lite_component.gni")
import("//drivers/hdf_core/adapter/khdf/liteos/hdf.gni")
module_switch = defined(LOSCFG_DRIVERS_HDF_xxx)
module_name = "xxx"
hdf_driver(module_name) {
sources = [
"xxx/xxx/xxx.c", #模块要编译的源码文件
]
public_configs = [ ":public" ] #运用依赖的头文件配置
}
config("public") { #定义依赖的头文件配置
include_dirs = [
"xxx/xxx/xxx", #依赖的头文件目录
]
}
把新增模块的BUILD.gn所在的目录添加到/drivers/hdf_core/adapter/khdf/liteos/BUILD.gn里面:
group("liteos") {
public_deps = [ ":$module_name" ]
deps = [
"xxx/xxx",#新增模块BUILD.gn所在的目录,/drivers/hdf_core/adapter/khdf/liteos
]
}
Linux
假如需求定义模块控制宏,需求在模块目录xxx里面添加Kconfig文件,并把Kconfig文件途径添加到drivers/hdf_core/adapter/khdf/linux/Kconfig里面:
source "drivers/hdf/khdf/xxx/Kconfig" #目录为hdf模块软链接到kernel里面的目录
添加模块目录到drivers/hdf_core/adapter/khdf/linux/Makefile:
obj-$(CONFIG_DRIVERS_HDF) += xxx/
在模块目录xxx里面添加Makefile文件,在Makefile文件里面添加模块代码编译规则:
obj-y += xxx.o
驱动配置
HDF运用HCS作为配置描绘源码,HCS细致引见配置管理。
驱动配置包含两局部,HDF框架定义的驱动设备描绘和驱动的私有配置信息,详细写法如下:
驱动设备描绘(必选)
HDF框架加载驱动所需求的信息来源于HDF框架定义的驱动设备描绘,因而基于HDF框架开发的驱动必需要在HDF框架定义的device_info.hcs配置文件中添加对应的设备描绘。驱动的设备描绘填写如下所示:
root {
device_info {
match_attr = "hdf_manager";
template host { // host模板,继承该模板的节点(如下sample_host)假如运用模板中的默许值,则节点字段能够缺省。
hostName = "";
priority = 100;
uid = ""; // 用户态进程uid,缺省为空,会被配置为hostName的定义值,即普通用户。
gid = ""; // 用户态进程gid,缺省为空,会被配置为hostName的定义值,即普通用户组。
caps = [""]; // 用户态进程Linux capabilities配置,缺省为空,需求业务模块依照业务需求停止配置。
template device {
template deviceNode {
policy = 0;
priority = 100;
preload = 0;
permission = 0664;
moduleName = "";
serviceName = "";
deviceMatchAttr = "";
}
}
}
sample_host :: host{
hostName = "host0"; // host称号,host节点是用来寄存某一类驱动的容器。
priority = 100; // host启动优先级(0-200),值越大优先级越低,倡议默许配100,优先级相同则不保证host的加载次第。
caps = ["DAC_OVERRIDE", "DAC_READ_SEARCH"]; // 用户态进程Linux capabilities配置。
device_sample :: device { // sample设备节点
device0 :: deviceNode { // sample驱动的DeviceNode节点
policy = 1; // policy字段是驱动效劳发布的战略,在驱动效劳管理章节有细致引见。
priority = 100; // 驱动启动优先级(0-200),值越大优先级越低,倡议默许配100,优先级相同则不保证device的加载次第。
preload = 0; // 驱动按需加载字段。
permission = 0664; // 驱动创立设备节点权限
moduleName = "sample_driver"; // 驱动称号,该字段的值必需和驱动入口构造的moduleName值分歧。
serviceName = "sample_service"; // 驱动对外发布效劳的称号,必需独一。
deviceMatchAttr = "sample_config"; // 驱动私有数据匹配的关键字,必需和驱动私有数据配置表中的match_attr值相等。
}
}
}
}
}
阐明:
uid、gid、caps等配置项是用户态驱动的启动配置,内核态不用配置。
依据进程权限最小化设计准绳,业务模块uid、gid不用配置,如上面的sample_host,运用普通用户权限,即uid和gid被定义为hostName的定义值。
假如普通用户权限不能满足业务请求,需求把uid、gid定义为system或者root权限时,请找平安专家停止评审。
进程的uid在文件base/startup/init/services/etc/passwd中配置,进程的gid在文件base/startup/init/services/etc/group中配置,进程uid和gid配置参考:系统效劳用户组添加办法。
caps值:格式为caps = ["xxx"],假如要配置CAP_DAC_OVERRIDE,此处需求填写caps = ["DAC_OVERRIDE"],不能填写为caps = ["CAP_DAC_OVERRIDE"]。
preload:驱动按需加载字段。
驱动私有配置信息(可选)
假如驱动有私有配置,则能够添加一个驱动的配置文件,用来填写一些驱动的默许配置信息。HDF框架在加载驱动的时分,会将对应的配置信息获取并保管在HdfDeviceObject中的property里面,驱动的配置信息示例如下:
root {
SampleDriverConfig {
sample_version = 1;
sample_bus = "I2C_0";
match_attr = "sample_config"; // 该字段的值必需和device_info.hcs中的deviceMatchAttr值分歧
}
}
配置信息定义之后,需求将该配置文件添加到板级配置入口文件hdf.hcs,示例如下:
<button type="button" class="btn btn-dark rounded-0 sflex-center copyCode" data-toggle="tooltip" data-placement="top" data-clipboard-text="#include "device_info/device_info.hcs" #include "sample/sample_config.hcs"" aria-label="复制" data-bs-original-title="复制">
#include "device_info/device_info.hcs"
#include "sample/sample_config.hcs"