更多内容请访问:Harmonyos.51cto.comHDI接口概述回顾上一篇文章,HDF驱动框架的一个重要功能是为系统提供稳定统一的硬件接口,从而保证系统服务可以运行在不同的硬件上,而不需要额外的适配工作。HDI(HardwareDeviceInterfaces)就是为了达到这个目的而设计的。HDI是硬件功能的高层抽象接口。各种外设的HDI接口定义完成后,只会在HDI的兼容规则下进行更改,以保证接口的稳定性。具体的驱动实现不需要重复定义HDI接口,只需要按需实现即可访问系统功能。在不同规模的OpenHarmony系统上,HDI有两种部署形式,IPC模式和透传模式。在轻量级的OpenHarmony系统上,为了降低系统性能负载,将HDI实现为用户态共享库,系统服务直接将HDI实现加载到自己的进程中进行函数调用。HDI实现了对具体用户态和内核态交互过程的封装,在需要访问驱动时,通过系统调用,通过IOService请求调用消息给内核驱动实现。在标准的OpenHarmony系统上,HDI被部署为一个独立的服务进程。系统服务只将HDI客户端加载到它自己的进程中。实际业务运行在一个独立的进程中。客户端通过IPC与服务端进行交互,便于架构解耦和授权。管理。HDI接口将透传模式作为一种功能实现方式来实现,无论是调用还是实现,都可以在没有其他组件支持的情况下实现。这里重点分析IPC模式的实现。HDI发布了基于OpenHarmony系统通信框架通用模型的HDIIPC模式,但由于驱动常涉及底层操作和多系统迁移场景,且采用C语言编写,因此驱动框架也提供了基础组件HDI服务的C语言实现,C++实现主要使用系统通信框架组件。HDI服务发布基于UHDF(UserModeHDFDriverFramework)实现,通用服务发布实现如下。1.实现驱动入口intSampleDriverBind(structHdfDeviceObject*deviceObject){HDF_LOGE("SampleDriverBinenter!");staticstructIDeviceIoServicetestService={.Dispatch=SampleServiceDispatch,//服务回调接口};deviceObject->service=&testService;returnHDF_SUCCESS;}intSampleDriverInit(structObjectHdfDeviceObject){HDF_LOGE("SampleDriverInitenter");returnHDF_SUCCESS;}voidSampleDriverRelease(structHdfDeviceObject*deviceObject){HDF_LOGE("SampleDriverReleaseenter");返回;}structHdfDriverEntryg_sampleDriverEntry={.SammoduleVersion=1,.moduleName="sample.DriverBind="sample.DriverBindInit=SampleDriverInit,.Release=SampleDriverRelease,};HDF_INIT(g_sampleDriverEntry);首先添加UHDF驱动,发布IoService服务,IoService设备服务为HDI服务实体。实现与KHDF驱动一致。2.实现服务响应接口int32_tSampleServiceOnRemoteRequest(structHdfDeviceIoClient*client,intcmdId,structHdfSBuf*data,structHdfSBuf*reply){switch(cmdId){caseSAMPLE_SERVICE_PING:returnSampleServiceStubPing(Dclient,Data,Reply);……default("%HD:"%Fd",cmdId);returnHDF_ERR_INVALID_PARAM;}}staticint32_tSampleServiceDispatch(structHdfDeviceIoClient*client,intcmdId,structHdfSBuf*data,structHdfSBuf*reply){returnSampleServiceOnRemoteRequest(client,cmdId,data,reply)收到服务响应时"DI接口调用;}SampleServiceDispatch"将被调用。client调用者对象,用户态驱动暂时不支持cmdId调用命令字,用于区分callAPI数据调用入参序列化对象,在IPC调用场景下,为C语言parcel对象的封装,入参需要使用序列化从data对象中获取接口后,使用reply调用参数对象。调用需要返回的信息写入到序列化对象中。如果C++实现客户端可以使用如下接口将sbuf对象转换为parcel对象,则操作:int32_tSbufToParcel(structHdfSBuf*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主机节点是一个独立进程,如果需要独立进程,添加自己的主机节点policy服务发布策略,HDI服务设置为2moduleName驱动实现库名serviceName服务名,请保留全局唯一性因为HDI服务C和C++实现使用不同的IPC组件,面向对象的实现也不一致,所以在具体实现上存在一些差异。HDI基础组件UHDF框架为了支持HDI实现,提供了以下基础组件(仅针对C语言HDI实现):SBufSBuf是一个同时支持KHDF和UHDF驱动IoService消息序列化的工具对象。在UHDFIPC通信场景下,SBuf可以与系统IPC框架序列化对象MessageParcel对象相互转换(仅支持C++),从而实现C和C++实现的IPC互通。常用的API如下:structHdfSBuf;结构体HdfSbufImpl;structHdfRemoteService;/***@briefHdfSBuf类型定义。**@since1.0*/enumHdfSbufType{SBUF_RAW=0,/*sbuftypeforuser-modekernelmodecommunication*/SBUF_IPC,/*sbuftypeforcross-processcommunication*/SBUF_IPC_HW,/*forextendedReservedtype*/SBUF_TYPE_MAX,/*sbuf类型的最大值*/};以上接口都有对应的写入接口,就不一一列举了,可以参考官网的API参考文档。RemoteServiceRemoteService对象对应并可以转换为系统IPC框架中的IRemoteObject对象(仅支持C++),代表一个IPC对象。相关API说明://消息分发器,用于服务端响应调用或在客户端发起调用callbackstructHdfDeathRecipient{void(*OnRemoteDied)(structHdfDeathRecipient*,structHdfRemoteService*);};structHdfRemoteService{structHdfObjectobject_;structHdfObject*target;structHdfRemoteDispatcher*dispatcher;boolisHw;};//以自定义的消息分发器实例化一个RemoteServicestructHdfRemoteService*HdfRemoteServiceObtain(structHdfObject*object,structHdfRemoteDispatcher*dispatcher);//回收RemoteService对象voidHdfRemoteServiceRecycle(structHdfRemoteService*service);//添加RemoteService的死亡通知,如果RemoteService对应的进程异常退出,会调用HdfDeathRecipient的回调接口voidHdfRemoteServiceAddDeathRecipient(structServiceHdfRemoteH*服务,strserviceHdfRemoteH*f*收件人);基于RemoteService实现服务器的例子:intSampleServiceStubDispatch(structHdfRemoteService*service,intcode,structHdfSBuf*data,structHdfSBuf*reply){//IPC调用响应接口intret=HDF_FAILURE;switch(code){caseSAMPLE_IF_0:{//dosomethingbreak;}default:{ret=HDF_ERR_INVALID_PARAM;}}returnret;}boolSampleStubConstruct(){//构造消息分发器并实现消息处理回调staticstructHdfRemoteDispatcherdispatcher={.Dispatch=SampleServiceStubDispatch};//实例化RemoteServiceinst->remote=HdfRemoteServiceObtain((structHdfObject*)inst,&dispatcher);if(inst->remote==NULL){HDF_LOGE("Deviceservicemanagerfailedtoobtainremoteservice");returnfalse;}...直接基于RemoteService实现server只适合实现匿名IPC服务的话,要发布基于UHDF的HDI服务,只需要实现Driver绑定的IoService即可。RemoteService客户端对象只能从SBufHdfSBufReadRemoteService接口获取。HDI实现Driver是HDI服务的驱动入口,IoService是HDI服务的服务入口实现。IoService的Dispatch方法调用了ServiceStub中真正的服务响应接口(OnRemoteRequest)。ServiceStub是服务端实现对象,主要处理IPC相关的业务逻辑,这里完成参数反序列化后,调用的是真正的Service实现接口,即ServiceImpl接口ServiceImpl是HDI接口的真正实现。这里不关心IPC流程,只实现函数接口。驱动框架提供示例代码实现,请参考gitee驱动代码库。HDI接口调用HDI驱动框架HDI接口。HDI服务管理功能由驱动框架DeviceManager实现,因此驱动框架提供与HDI服务管理相关的HDI接口。C++实现:namespaceOHOS{namespaceHDI{namespaceServiceManager{namespaceV1_0{structIServiceManager:publicIRemoteBroker{public:DECLARE_INTERFACE_DESCRIPTOR(u"HDI.IServiceManager.V1_0");//get()静态方法用于获取IServiceManager对象实例static::OHOS::sptr
