OpenHarmony系统HDF驱动开发介绍(补充)
一、HDF驱动简介
HDF(Hardware Driver Foundation)驱动框架,为驱动开发者提供驱动框架能力,包括驱动加载、驱动服务管理、驱动消息机制和配置管理。
简单来说:HDF框架的驱动和Linux的驱动比较相似都是由配置文件和驱动源码组成。
HDF驱动:配置文件HCS + 驱动源码。
Linux驱动:配置文件DTS + 驱动源码。
二、HCS文件简介
HCS(HDF Configuration Source)是HDF驱动框架的配置描述源码,内容以Key-Value为主要形式。它实现了配置代码与驱动代码解耦,便于开发者进行配置管理。HC-GEN(HDF Configuration Generator)是HCS配置转换工具,可以将HDF配置文件转换为软件可读取的文件格式:
在弱性能环境中,转换为配置树源码或配置树宏定义,驱动可直接调用C代码或宏式APIs获取配置。
在高性能环境中,转换为HCB(HDF Configuration Binary)二进制文件,驱动可使用HDF框架提供的配置解析接口获取配置。
HCS文件示例:
root {device_info {match_attr = "hdf_manager";template host {hostName = "";priority = 100;template device {template deviceNode {policy = 0;priority = 100;preload = 0;permission = 0664;moduleName = "";serviceName = "";deviceMatchAttr = "";}}}base :: host {hostName = "base_host";priority = 50;device_support :: device {device0 :: deviceNode {policy = 2;priority = 10;permission = 0644;moduleName = "HDF_KEVENT";serviceName = "hdf_kevent";}}}}
}
上面是我从一个HCS文件中截取了一点内容,HCS子定义了一套格式。
三、HCS语法说明
下面是从官网的一个截图:
HCS经过HC-GEN编译生成HCB文件,HDF驱动框架中的HCS Parser模块会从HCB文件中重建配置树,HDF驱动模块使用HCS Parser提供的配置读取接口获取配置内容。
表3 HCS配置语法保留关键字
|关键字 | 用途 |说明|
关键字 | 用途 | 说明 |
---|---|---|
root | 配置根节点 | - |
include | 引用其他HCS配置文件 | - |
delete | 删除节点或属性 | 只能用于操作include导入的配置树 |
template | 定义模板节点 | - |
match_attr | 用于标记节点的匹配查找属性 | 解析配置时可以使用该属性的值查找到对应节点 |
HCS主要分为属性(Attribute)和节点(Node)两种结构。
详细语法说明参考:https://gitee.com/openharmony/docs/blob/master/zh-cn/device-dev/driver/driver-hdf-manage.md
上面的示例代码中有:moduleName = “HDF_KEVENT”;
这块的 moduleName 和 DTS文件中驱动节点的 compatible 功能相同,用来匹配对应的驱动代码。
上面的示例代码中有:serviceName = “hdf_kevent”;
当驱动匹配成功后最终在/dev路径下面生成的节点名称 “hdf_kevent”。但是是否在/dev下面生成节点信息和policy的属性有关。
只有policy = 2时,在/dev下面才能看到节点信息。
typedef enum {/* 驱动不提供服务 */SERVICE_POLICY_NONE = 0,/* 驱动对内核态发布服务 */SERVICE_POLICY_PUBLIC = 1,/* 驱动对内核态和用户态都发布服务 */SERVICE_POLICY_CAPACITY = 2,/* 驱动服务不对外发布服务,但可以被订阅 */SERVICE_POLICY_FRIENDLY = 3,/* 驱动私有服务不对外发布服务,也不能被订阅 */SERVICE_POLICY_PRIVATE = 4,/* 错误的服务策略 */SERVICE_POLICY_INVALID
} ServicePolicy;
四、驱动代码介绍
驱动实现包含驱动业务代码实现和驱动入口注册,具体写法如下:
- 驱动业务代码
#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 = "HDF_KEVENT",.Bind = HdfSampleDriverBind,.Init = HdfSampleDriverInit,.Release = HdfSampleDriverRelease,
};// 调用HDF_INIT将驱动入口注册到HDF框架中。在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动;当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。
HDF_INIT(g_sampleDriverEntry);
只要驱动代码中的moduleName配置和HCS文件中moduleName配置内容相同就会执行驱动中的Bind函数,Bind函数执行成功后就会执行Init函数。如果Bind和Init函数有一个执行失败会立刻执行Release函数。
五、其他
今天就介绍到这里,我最近几年一直从事音频开发,主要做Linux、Open Harmony系统的音频开发。做过RK系列、海思和展锐的音频适配,大家有什么问题可以留言咨询。