时间:2021-09-02 14:27
人气:
作者:admin
HDI接口概述
回顾之前的文章,HDF 驱动框架的一个重要功能是为系统提供稳定的统一的硬件接口,这样才能保证系统服务可以运行在不同硬件上而不需要额外的适配工作,HDI(Hardware Device Interfaces)正是为了实现该目的而设计。
HDI 是对硬件功能的较高层次抽象接口,各类外设完成 HDI 接口定义后便只会在 HDI 的兼容性规则下进行变更,从而保证接口的稳定性。具体的驱动实现不需要再重复定义 HDI 接口,只需要按需实现即可接入系统功能。
在不同量级的 OpenHarmony 系统上,HDI 存在两种部署形态,IPC 模式和直通模式。
在轻量级 OpenHarmony 系统上,出于减小系统性能负载考虑,HDI 实现为用户态共享库,由系统服务直接加载 HDI 实现到自己进程中函数调用使用。HDI 实现封装具体的用户态-内核态交互过程,当需要访问驱动程序时使用 IO Service 请求将消息通过 system call 方式调用到内核驱动实现。
在标准 OpenHarmony 系统上,HDI 以独立服务进程方式部署,系统服务只加载 HDI 客户端实现到自己进程中,实际业务运行在独立进程中,客户端通过 IPC 与服务端交互,便于架构解耦、权限管理。
HDI接口实现
直通模式为函数实现方式,无论调用还是实现都不需要其他组件支持即可实现,这里将重点分析 IPC 模式的实现。
HDI发布
HDI IPC 模式基于 OpenHarmony 系统通信框架的通用模型,但是因为驱动很多时候涉及到底层操作和多系统迁移的场景而使用C语言编写,所以驱动框架还提供了 HDI 服务的 C 语言实现的基础组件,C++实现则主要使用系统通信框架组件。
HDI 服务发布基于 UHDF(用户态 HDF 驱动框架)实现,通用的服务发布实现如下。
1.实现驱动入口
int SampleDriverBind(struct HdfDeviceObject *deviceObject){ HDF_LOGE("SampleDriverBind enter!"); static struct IDeviceIoService testService = { .Dispatch = SampleServiceDispatch, // 服务回调接口 }; deviceObject->service = &testService; return HDF_SUCCESS;} int SampleDriverInit(struct HdfDeviceObject *deviceObject){ HDF_LOGE("SampleDriverInit enter"); return HDF_SUCCESS;} void SampleDriverRelease(struct HdfDeviceObject *deviceObject){ HDF_LOGE("SampleDriverRelease enter"); return;} struct HdfDriverEntry g_sampleDriverEntry = { .moduleVersion = 1, .moduleName = "sample_driver", .Bind = SampleDriverBind, .Init = SampleDriverInit, .Release = SampleDriverRelease,}; HDF_INIT(g_sampleDriverEntry);
首先要添加一个 UHDF 驱动用于发布 IoService 服务,IoService 设备服务即为 HDI 服务实体。实现方式与 KHDF 驱动一致。
2.实现服务响应接口
int32_t SampleServiceOnRemoteRequest(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply){ switch (cmdId) { case SAMPLE_SERVICE_PING: return SampleServiceStubPing(client, data, reply); … … default: HDF_LOGE("SampleServiceDispatch: not support cmd %d", cmdId); return HDF_ERR_INVALID_PARAM; }}static int32_t SampleServiceDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply){ return SampleServiceOnRemoteRequest(client, cmdId, data, reply);}
当收到 HDI 调用时,服务响应接口"SampleServiceDispatch"将会被调用。
client 调用者对象,在用户态驱动中暂时未支持
cmdId 调用命令字,用于区分调用的 API
data 调用入参序列化对象,在 IPC 调用场景为 parcel 对象的 C 语言封装,入参需要使用序列化接口从 data 对象中获取后再使用
reply 调用出参对象,需要返回给调用的信息写入该序列化对象
如果 C++实现客户端可以使用下面接口将 sbuf 对象转换为 parcel 对象后操作:
int32_t SbufToParcel(struct HdfSBuf *sbuf, OHOS::MessageParcel **parcel);3.UHDF 驱动配置
platform :: host { hostName = "sample_host"; priority = 50; sample_device :: device { device0 :: deviceNode { policy = 2; priority = 100; moduleName = "libsample_driver.z.so"; serviceName = "sample_driver_service"; } }}
参数说明:
host 一个 host 节点即为一个独立进程,如果需要独立进程,新增属于自己的 host 节点
policy 服务发布策略,HDI 服务设置为 2
moduleName 驱动实现库名
serviceName 服务名称,请保持全局唯一性
因为 HDI 服务 C 和 C++实现使用的 IPC 组件不一样,面向对象实现也不一致,所以在具体实现上存在一些差异。
HDI基础组件UHDF 框架为了支持 HDI 实现,提供了以下基础组件(仅用于 C 语言 HDI 实现):
SBuf
SBuf 是同时支持 KHDF 和 UHDF 驱动 IoService 消息序列化的工具对象。在 UHDF IPC 通信场景中,SBuf 可以与系统 IPC 框架序列化对象 MessageParcel 对象(仅支持 C++)相互转换,从而实现 C 和 C++实现的 IPC 互通。
常用 API 如下:
struct HdfSBuf;struct HdfSbufImpl;struct HdfRemoteService; /** * @brief HdfSBuf类型定义。 * * @since 1.0 */enum HdfSbufType { SBUF_RAW = 0, /* 用于用户态内核态通信的sbuf类型 */ SBUF_IPC, /* 用于跨进程通信的sbuf类型 */ SBUF_IPC_HW, /* 用于扩展的预留类型 */ SBUF_TYPE_MAX, /* sbuf类型最大值 *
上一篇:什么是接口定义 有哪些特点
从profibusDP转ModbusTCP,一网打尽转换技巧!