共计 6709 个字符,预计需要花费 17 分钟才能阅读完成。
HDF 驱动框架是 OpenAtom OpenHarmony(简称“OpenHarmony”)零碎硬件生态凋谢的根底,为驱动开发者提供了驱动加载、驱动服务治理和驱动音讯机制等驱动框架能力,同时还为开发者提供了标准的 HDI 硬件设施接口,让开发者能屏蔽南向设施差别,提供更好的硬件。本文将为大家带来 HDI 硬件设施接口的介绍。
一、HDI 介绍
HDI(Hardware Device Interface,硬件设施接口)是 HDF 驱动框架为开发者提供的硬件规范化描述性接口。在 OpenHarmony 分层构造中,HDI 位于“根底零碎服务层”和“设施形象层(DAL)”之间。硬件设施通过 DAL 抽象化,并基于 IDL(Interface Description Language)接口描述语言形容后,为下层利用或服务提供了标准的硬件设施接口。
HDI 反对“IPC 模式”及“直通模式”两种调用形式。其中,IPC 模式即跨过程通信模式,基于 binder 机制实现,调用端通过 Proxy 代理库调用 HDI 接口,具备良好的解耦性和安全性,是规范零碎的默认部署形式。直通模式,将 HDI 实现为共享库,调用端应用 dlopen 加载 HDI 实现库并间接调用 HDI 接口,是小型零碎的默认部署形式,同时还实用于对性能有非凡需要的规范零碎模块。
HDI 硬件设施接口的长处用一句话总结就是:为硬件的接入提供了对立的实现通路。屏蔽了硬件接口的具体实现,实现系统软件与硬件的架构解耦。让开发者专一于硬件接口的应用,从而简化开发过程,晋升开发效率。
二、HDI 实现
通过上文的介绍,置信很多小伙伴会有疑难,HDI 接口是怎么实现的呢?上面咱们将为你介绍 IPC 模式下基于 C/S(Client-Server 客户端与服务端)构造的 HDI 接口实现。
2.1 IDL 接口描述语言
为不便后文的了解,咱们先简略理解一下 IDL 接口描述语言。
IDL(Interface Description Language)是一类用来形容接口的语言,通过一种中立的形式来定义客户端与服务端均认可的编程接口,能够实现在二者间的跨过程通信(IPC)。跨过程通信意味着能够在一个过程拜访另一个过程的数据,或调用另一个过程的办法。通常把利用接口提供方(供调用)称为服务端,调用方称为客户端。
IDL 先把须要传递的对象分解成操作系统可能了解的根本类型,而后依据接口申明编译,生成 IPC/RPC 代理(Proxy)和桩(Stub)的 C/C++ 代码,从而为调用者提供统一的接口和调用形式。
2.2 基于 IDL 语言实现 HDI 接口
首先,应用 IDL 语法形容 HDI 接口并保留为.idl 文件,而后编写 .idl 文件的编译脚本 BUILD.gn 文件,最初编译 .idl 文件即可。上面咱们将为大家演示电源子系统的 HDI 接口的实现过程。
(1)应用 IDL 语法编写 .idl 文件
● 定义电源接口 IPowerInterface.idl
package ohos.hdi.power.v1_0;
import ohos.hdi.power.v1_0.IPowerHdiCallback;
import ohos.hdi.power.v1_0.PowerTypes;
interface IPowerInterface {RegisterCallback([in] IPowerHdiCallback ipowerHdiCallback);
StartSuspend();
StopSuspend();
ForceSuspend();
SuspendBlock([in] String name);
SuspendUnblock([in] String name);
PowerDump([out] String info);
}
● 如果须要从服务端回调,能够定义 callback 接口类 IPowerHdiCallback.idl
package ohos.hdi.power.v1_0;
[callback] interface IPowerHdiCallback {OnSuspend();
OnWakeup();}
● 如果 interface 中用到了自定义数据类型,将自定义类型定义到 powerTypes.idl
package ohos.hdi.power.v1_0;
enum PowerHdfCmd {
CMD_REGISTER_CALLBCK = 0,
CMD_START_SUSPEND,
CMD_STOP_SUSPEND,
CMD_FORCE_SUSPEND,
CMD_SUSPEND_BLOCK,
CMD_SUSPEND_UNBLOCK,
CMD_DUMP,
};
enum PowerHdfCallbackCmd {
CMD_ON_SUSPEND = 0,
CMD_ON_WAKEUP,
};
enum PowerHdfState {
AWAKE = 0,
INACTIVE,
SLEEP,
};
(2)编写 .idl 文件的编译脚本 BUILD.gn
import("//drivers/adapter/uhdf2/hdi.gni")
if (defined(ohos_lite)) {group("libpower_proxy_1.0") {deps = []
public_configs = []}
} else {hdi("power") {
module_name = "power_interface_service"
sources = [
"IPowerHdiCallback.idl",
"IPowerInterface.idl",
"PowerTypes.idl",
]
language = "cpp" subsystem_name = "hdf" part_name = "power_device_driver" }
}
(3)编译 .idl 文件
应用编译工具 hdi-gen 编译 IDL 文件,IDL 文件在编译过程中转换为 C/C++ 语言的函数接口申明、客户端与服务端 IPC 相干过程代码,开发者只须要基于生成的 power.h 函数接口实现具体服务性能即可。
编译后生成代码在 out/product/gen/drivers/interface/power 中,接口代码如下:
namespace OHOS {
namespace HDI {
namespace Power {
namespace V1_0 {
using namespace OHOS;
enum {
CMD_POWER_INTERFACE_REGISTER_CALLBACK,
CMD_POWER_INTERFACE_START_SUSPEND,
CMD_POWER_INTERFACE_STOP_SUSPEND,
CMD_POWER_INTERFACE_FORCE_SUSPEND,
CMD_POWER_INTERFACE_SUSPEND_BLOCK,
CMD_POWER_INTERFACE_SUSPEND_UNBLOCK,
CMD_POWER_INTERFACE_POWER_DUMP,
CMD_POWER_INTERFACE_GET_VERSION,
};
class IPowerInterface : public IRemoteBroker {
public:
DECLARE_INTERFACE_DESCRIPTOR(u"ohos.hdi.power.v1_0.IPowerInterface");
virtual ~IPowerInterface() = default;
static sptr<IPowerInterface> Get();
static sptr<IPowerInterface> GetInstance(const std::string& serviceName);
virtual int32_t RegisterCallback(const sptr<IPowerHdiCallback>& ipowerHdiCallback) = 0;
virtual int32_t StartSuspend() = 0;
virtual int32_t StopSuspend() = 0;
virtual int32_t ForceSuspend() = 0;
virtual int32_t SuspendBlock(const std::string& name) = 0;
virtual int32_t SuspendUnblock(const std::string& name) = 0;
virtual int32_t PowerDump(std::string& info) = 0;
virtual int32_t GetVersion(uint32_t& majorVer, uint32_t& minorVer) = 0;
};
} // V1_0
} // Power
} // HDI
} // OHOS
(4)实现 HDI 接口
● 实现 UHDF Driver,用于将 HDI 实现加载为独立过程,并基于 HDF 驱动框架公布设施服务。
static int32_t PowerInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data,
struct HdfSBuf *reply)
{
......
return hdfPowerInterfaceHost->service->OnRemoteRequest(cmdId, *dataParcel, *replyParcel, option); // 将接口调用转发到 stub 实现
}
static int HdfPowerInterfaceDriverBind(struct HdfDeviceObject *deviceObject)
{
......
hdfPowerInterfaceHost->ioservice.Dispatch = PowerInterfaceDriverDispatch;
hdfPowerInterfaceHost->ioservice.Open = NULL;
hdfPowerInterfaceHost->ioservice.Release = NULL;
hdfPowerInterfaceHost->service = new PowerInterfaceImpl();
deviceObject->service = &hdfPowerInterfaceHost->ioservice;
return HDF_SUCCESS;
}
......
struct HdfDriverEntry g_powerinterfaceDriverEntry = {
.moduleVersion = 1,
.moduleName = "power_interface_service",
.Bind = HdfPowerInterfaceDriverBind,
.Init = HdfPowerInterfaceDriverInit,
.Release = HdfPowerInterfaceDriverRelease,
};
● 实现 HDI 接口
#include "v1_0/power_interface_stub.h"
/* 继承 PowerInterfaceStub 并实现 IPowerInterface 中的接口 */
class PowerInterfaceImpl : public PowerInterfaceStub {
public:
virtual ~PowerInterfaceImpl() {}
int32_t RegisterCallback(const sptr<IPowerHdiCallback>& ipowerHdiCallback) override;
int32_t StartSuspend() override;
int32_t StopSuspend() override;
int32_t ForceSuspend() override;
int32_t SuspendBlock(const std::string& name) override;
int32_t SuspendUnblock(const std::string& name) override;
int32_t PowerDump(std::string& info) override;
};
// 在 cpp 中对相干接口进行实现,其中调用了内核相干接口,实现了具体性能
int32_t PowerInterfaceImpl::StopSuspend()
{
suspendRetry_ = false;
return HDF_SUCCESS;
}
int32_t PowerInterfaceImpl::ForceSuspend()
{
suspendRetry_ = false;
NotifyCallback(CMD_ON_SUSPEND);
DoSuspend();
NotifyCallback(CMD_ON_WAKEUP);
return HDF_SUCCESS;
}
int32_t PowerInterfaceImpl::SuspendBlock(const std::string& name)
{std::lock_guard<std::mutex> lock(mutex_);
if (name.empty()) {return HDF_ERR_INVALID_PARAM;}
UniqueFd fd(TEMP_FAILURE_RETRY(open(LOCK_PATH, O_RDWR | O_CLOEXEC)));
bool ret = SaveStringToFd(fd, name);
if (!ret) {return HDF_FAILURE;}
return HDF_SUCCESS;
}
三、HDI 应用
通过上文的介绍,置信大家曾经对 HDI 有了肯定的理解,上面咱们将为大家介绍 HDI 的应用,在直通模式下,对 HDI 接口调用为同一过程空间函数调用,过程较为间接,这里咱们重点论述 IPC 模式下的调用原理,而后通过 CPP 语言来展现电源子系统 HDI 的调用。
3.1 调用原理
在 IPC 模式下,当零碎服务调用 HDI 接口时,通过 proxy 库将函数调用转换为 IPC 申请,将接口调用的参数进行序列化;IPC 申请通过 IPC 框架发送到服务端,申请将被 stub 库先解决,而后对接口调用的参数进行反序列化,再转换成对服务实现的函数调用,从而实现接口调用过程。
3.2 基于 CPP 语言的应用
上文曾经编译生成了电源子系统的 HDI 接口,上面咱们来看看如何应用 CPP 语言来调用 HDI 接口吧。
(1)客户端在 BUILD.gn 中减少依赖://drivers/interface/foo/v1.0:libfoo_proxy_1.0″
ohos_executable("call_foo_hdi") {
sources = ["src/call_foo_hdi.cpp",]
deps = ["//drivers/interface/foo/v1.0:libfoo_proxy_1.0",]
external_deps = [
"hiviewdfx_hilog_native:libhilog",
"ipc:ipc_core",
"utils_base:utils",
]
part_name = "bar"
subsystem_name = "bar_subsystem"
}
(2)在实现电源子系统的代码中调用 HDI 接口,代码如下:
#include "v1_0/power_interface.h" // 蕴含 Power HDI 接口头文件
using namespace OHOS::HDI::Power::V1_0; // 应用 HDI 接口命名空间
namespace OHOS {
namespace PowerMgr {
sptr<IPowerInterface> powerInterface = nullptr;
SystemSuspendController::SystemSuspendController()
{sptr<IPowerHdiCallback> g_callback = new PowerHdiCallbackImpl();
powerInterface = IPowerInterface::Get(); // 调用接口实例化接口获取客户端实例
if (powerInterface == nullptr) {POWER_HILOGE(COMP_SVC, "The hdf interface is null");
return;
}
powerInterface->RegisterCallback(g_callback); // 调用 HDI 接口注册电源事件回调
}
四、结语
以上就是本文全部内容,咱们在这里简略介绍了 HDI 接口的实现思路及应用,对于宽广南向开发者,咱们还在社区提供了具体的 HDI 接口实现领导,欢送大家在 gitee 社区参加更多探讨。
社区链接:https://gitee.com/openharmony…