1.HDF 驱动框架
OpenHarmony 系统 HDF 驱动框架主要由驱动管理框架、驱动程序、驱动配置文件和驱动接口这四个部分组成。
1)HDF 驱动管理框架由 Device Manager 和 Device Host 组成,提供统一的硬件资源管理,驱动加载管理以及设备节点管理等功能。驱动框架采用的是主从模式设计。Device Manager 提供了统一的驱动管理,Device Manager 启动时根据 Device Information 驱动配置文件提供的驱动设备信息加载相应的驱动 Device Host,并控制 Host 完成驱动的加载。Device Host 提供驱动运行的环境,同时预置 Host Framework 与 Device Manager 进行协同,完成驱动加载和调用。根据业务的需求 Device Host 可以有多个实例。
2)驱动程序 Driver 实现驱动具体的功能,每个驱动由一个或者多个驱动程序组成,每个驱动程序都对应着一个 Driver Entry。Driver Entry 主要完成驱动的初始化和驱动接口绑定功能。
3)驱动配置文件主要由设备信息(Device Information)和设备资源(Device Resource)组成,分别对应 deviceInfo.hcs 和 deviceRes.hcs 两个配置文件。Device Information 完成设备信息的配置。如配置接口发布策略,驱动加载的方式等。Device Resource 完成设备资源的配置。如 GPIO 管脚、寄存器等资源信息的配置。另外还可以通过 deviceMatchAttr 来指定自定义参数配置文件。
4)驱动接口 HDI(Hardware Driver interface )提供标准化的接口定义和实现,驱动框架提供 IO Service 和 IO Dispatcher 机制,使得不同部署形态下驱动接口趋于形式一致。具体的驱动实现不需要再重复定义 HDI 接口,只需要按 HDI 接口实现即可将设备接入系统,从而保证了上层调用者无需改动即可访问操作新适配的设备。
HDF 框架以组件化的驱动模型作为核心设计思路,通过 HCS 配置文件为开发者提供更精细化的驱动管理,让驱动开发和部署更加规范。HDF 框架将一类设备驱动放在同一个 host 里面,一个驱动可包含多个驱动程序,HDF 驱动模型的配置文件以及对应结构图示如下所示:
distributed_camera_host :: host {
hostName = "dcamera_host";
priority = 50;
distributed_camera_device :: device {
device0 :: deviceNode {
policy = 2;
priority = 100;
preload = 2;
moduleName = "libdistributed_camera_host_config.z.so";
serviceName = "distributed_camera_service";
}
device1 :: deviceNode {
policy = 2;
priority = 100;
preload = 2;
moduleName = "libdistributed_camera_provider_config.z.so";
serviceName = "distributed_camera_provider_service";
}
}
}
codec :: host {
hostName = "codec_host";
priority = 50;
gid = ["codec_host", "uhdf_driver", "vendor_mpp_driver"];
codec_omx_device :: device {
device0 :: deviceNode {
policy = 2;
priority = 100;
moduleName = "libcodec_hdi_omx_server.z.so";
serviceName = "codec_hdi_omx_service";
deviceMatchAttr = "media_codec_capabilities";
}
}
}
2.HDF 驱动开发
基于 HDF 框架进行驱动的开发主要分为两个部分,驱动实现和驱动配置,详细开发流程如下所示:
2.1 驱动实现
驱动实现包含驱动业务代码和驱动入口注册。
2.1.1 驱动业务代码
#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;
}
2.1.2 驱动入口注册到 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);
2.2 驱动配置
驱动配置的实现以驱动配置文件作为载体,为开发者提供更精细化的驱动管理。HDF 使用 HCS 文件作为配置描述源码,内容以 Key-Value 键值对为主要形式。它实现了配置代码与驱动代码解耦,便于开发者进行配置管理。HC-GEN (全称 HDF Configuration Generator) 是 HCS 配置转换工具,可以将 HDF 配置文件转换为软件可读取的文件格式:在弱性能环境中,转换为配置树源码,驱动可直接调用 C 代码获取配置;在高性能环境中,转换为 HCB(HDF Configuration Binary)二进制文件,驱动可使用 HDF 框架提供的配置解析接口获取配置。
HCS 经过 HC-GEN 编译生成 HCB 文件,HDF 驱动框架中的 HCS Parser 模块会从 HCB 文件中重建配置树,HDF 驱动模块使用 HCS Parser 提供的配置读取接口获取配置内容。驱动配置过程的原理图如下所示:
2.2.1 驱动设备描述(必选)
HDF 框架加载驱动所需要的信息来源于 HDF 框架定义的 device_info.hcs 配置文件,因此需要在其中添加对应的设备描述,驱动的设备描述填写如下所示:
sample_host :: host{
hostName = "host0"; //host名称,host节点是用来存放某一类驱动的容器。
priorit