概述
HDF(Hardware Driver Foundation)驱动框架,为驱动开发者提供驱动框架能力,包括驱动加载、驱动服务管理、驱动消息机制和配置管理。并以组件化驱动模型作为核心设计思路,让驱动开发和部署更加规范,旨在构建统一的驱动架构平台,为驱动开发者提供更精准、更高效的驱动管理的开发环境,力求做到一次开发,多系统部署。
驱动加载
HDF驱动框架提供把和配置的设备列表匹配成功的驱动程序加载起来的功能。
驱动服务管理
HDF框架可以集中管理驱动服务,开发者可直接通过HDF框架对外提供的能力接口获取驱动相关的服务。
驱动消息机制
HDF框架提供统一的驱动消息机制,支持用户态应用向内核态驱动发送消息,也支持内核态驱动向用户态应用发送消息。
配置管理
HCS(HDF Configuration Source)是HDF驱动框架的配置描述源码,内容以Key-Value为主要形式。它实现了配置代码与驱动代码解耦,便于开发者进行配置管理。
驱动模型
HDF框架将一类设备驱动放在同一个Host(设备容器)里面,用于管理一组设备的启动加载等过程。在划分Host时,驱动程序是部署在一个Host还是部署在不同的Host,主要考虑驱动程序之间是否存在耦合性,如果两个驱动程序之间存在依赖,可以考虑将这部分驱动程序部署在一个Host里面,否则部署到独立的Host中是更好的选择。Device对应一个真实的物理设备。DeviceNode是设备的一个部件,Device至少有一个DeviceNode。每个DeviceNode可以发布一个设备服务。驱动即驱动程序,每个DevicdNode唯一对应一个驱动,实现和硬件的功能交互。HDF驱动模型如下图所示:
图1 HDF驱动模型
功能描述
驱动加载
HDF驱动框架提供把和配置的设备列表匹配成功的驱动程序加载起来的功能,支持按需加载和按序加载两种策略,具体设备的加载策略由配置文件中的preload字段来控制,配置值参考如下:
typedef enum {
DEVICE_PRELOAD_ENABLE = 0,
DEVICE_PRELOAD_ENABLE_STEP2 = 1,
DEVICE_PRELOAD_DISABLE = 2,
DEVICE_PRELOAD_INVALID
} DevicePreload;
c
按需加载
- preload字段配置为0(DEVICE_PRELOAD_ENABLE),则系统启动过程中默认加载。
- preload字段配置为1(DEVICE_PRELOAD_ENABLE_STEP2),当系统支持快速启动的时候,则在系统完成之后再加载这一类驱动,否则和DEVICE_PRELOAD_ENABLE含义相同。
- preload字段配置为2(DEVICE_PRELOAD_DISABLE),则系统启动过程中默认不加载,支持后续动态加载,当用户态获取驱动服务 消息机制 时,如果驱动服务不存在,HDF框架会尝试动态加载该驱动。
按序加载(默认加载策略)
配置文件中的priority(取值范围为整数0到200)是用来表示host(驱动容器)和驱动的优先级的。不同的host内的驱动,host的priority值越小,驱动加载优先级越高;同一个host内驱动的priority值越小,加载优先级越高。
异常恢复(用户态驱动)
当驱动服务异常退出时,恢复策略如下:
- preload字段配置为0(DEVICE_PRELOAD_ENABLE)或1(DEVICE_PRELOAD_ENABLE_STEP2)的驱动服务,由启动模块拉起host并重新加载服务。
- preload字段配置为2(DEVICE_PRELOAD_DISABLE)的驱动服务,需业务模块注册HDF的服务状态监听器,当收到服务退出消息时,业务模块调用LoadDevice重新加载服务。
驱动服务管理
驱动服务是HDF驱动设备对外提供能力的对象,由HDF框架统一管理。驱动服务管理主要包含驱动服务的发布和获取。HDF框架定义了驱动对外发布服务的策略,由配置文件中的policy字段来控制,policy字段的取值范围以及含义如下:
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;
c
使用场景
当驱动需要以接口的形式对外提供能力时,可以使用HDF框架的驱动服务管理能力。
接口说明
针对驱动服务管理功能,HDF框架开放了以下接口供开发者调用,如下表所示:
表1 服务管理接口
方法 | 描述 |
---|---|
int32_t (*Bind)(struct HdfDeviceObject *deviceObject) | 需要驱动开发者实现Bind函数,将自己的服务接口绑定到HDF框架中。 |
const struct HdfObject *DevSvcManagerClntGetService(const char *svcName) | 获取驱动的服务。 |
int HdfDeviceSubscribeService( struct HdfDeviceObject *deviceObject, const char *serviceName, struct SubscriberCallback callback) | 订阅驱动的服务。 |
驱动消息机制管理
使用场景
当用户态应用和内核态驱动需要交互时,可以使用HDF框架的消息机制来实现。
接口说明
消息机制的功能主要有以下两种:
- 用户态应用发送消息到驱动。
- 用户态应用接收驱动主动上报事件。
表2 消息机制接口
方法 | 描述 |
---|---|
struct HdfIoService *HdfIoServiceBind(const char *serviceName); | 用户态获取驱动的服务,获取该服务之后通过服务中的Dispatch方法向驱动发送消息。 |
void HdfIoServiceRecycle(struct HdfIoService *service); | 释放驱动服务。 |
int HdfDeviceRegisterEventListener(struct HdfIoService *target, struct HdfDevEventlistener *listener); | 用户态程序注册接收驱动上报事件的操作方法。 |
int32_t HdfDeviceSendEvent(const struct HdfDeviceObject *deviceObject, uint32_t id, const struct HdfSBuf *data) | 驱动主动上报事件接口。 |
配置管理
配置概述
HCS(HDF Configuration Source)是HDF驱动框架的配置描述源码,内容以Key-Value为主要形式。它实现了配置代码与驱动代码解耦,便于开发者进行配置管理。HC-GEN(HDF Configuration Generator)是HCS配置转换工具,可以将HDF配置文件转换为软件可读取的文件格式:
- 在弱性能环境中,转换为配置树源码或配置树宏定义,驱动可直接调用C代码或宏式APIs获取配置。
- 在高性能环境中,转换为HCB(HDF Configuration Binary)二进制文件,驱动可使用HDF框架提供的配置解析接口获取配置。
以下是使用HCB模式的典型应用场景:
图2 配置使用流程图
HCS经过HC-GEN编译生成HCB文件,HDF驱动框架中的HCS Parser模块会从HCB文件中重建配置树,HDF驱动模块使用HCS Parser提供的配置读取接口获取配置内容。
配置语法
HCS的语法介绍如下:
关键字
HCS配置语法保留了以下关键字。
表3 HCS配置语法保留关键字
关键字 | 用途 | 说明 |
---|---|---|
root | 配置根节点 | - |
include | 引用其他HCS配置文件 | - |
delete | 删除节点或属性 | 只能用于操作include导入的配置树 |
template | 定义模板节点 | - |
match_attr | 用于标记节点的匹配查找属性 | 解析配置时可以使用该属性的值查找到对应节点 |
基本结构
HCS主要分为属性(Attribute)和节点(Node)两种结构。
属性
属性即最小的配置单元,是一个独立的配置项。语法如下:
attribute_name = value;
- attribute_name是字母、数字、下划线的组合且必须以字母或下划线开头,字母区分大小写。
- value的可用格式如下:
- 数字常量,支持二进制、八进制、十进制、十六进制数,具体 数据类型 章节。
- 字符串,内容使用双引号(“”)引用。
- 节点引用。
- attribute必须以分号(;)结束且必须属于一个node。
节点
节点是一组属性的集合,语法如下:
node_name {
module = "sample";
...
}
- node_name是字母、数字、下划线的组合且必须以字母或下划线开头,字母区分大小写。
- 大括号后无需添加结束符“;”。
- root为保留关键字,用于声明