HDF 驅動框架是 OpenAtom OpenHarmony(簡稱“OpenHarmony”)系統(tǒng)硬件生態(tài)開放的基礎,為驅動開發(fā)者提供了驅動加載、驅動服務管理和驅動消息機制等驅動框架能力,同時還為開發(fā)者提供了規(guī)范的HDI硬件設備接口,讓開發(fā)者能屏蔽南向設備差異,提供更好的硬件。本文將為大家?guī)?HDI 硬件設備接口的介紹。
一、HDI介紹
HDI(Hardware Device Interface,硬件設備接口)是 HDF 驅動框架為開發(fā)者提供的硬件規(guī)范化描述性接口。在 OpenHarmony 分層結構中,HDI 位于 “基礎系統(tǒng)服務層”和“設備抽象層(DAL)”之間。硬件設備通過 DAL 抽象化,并基于 IDL(Interface Description Language)接口描述語言描述后,為上層應用或服務提供了規(guī)范的硬件設備接口。
圖2 OpenHarmony 分層結構
HDI 支持“IPC 模式”及“直通模式”兩種調用方式。其中,IPC 模式即跨進程通信模式,基于 binder 機制實現(xiàn),調用端通過 Proxy 代理庫調用 HDI 接口,具備良好的解耦性和安全性,是標準系統(tǒng)的默認部署方式。直通模式,將 HDI 實現(xiàn)為共享庫,調用端使用 dlopen 加載 HDI 實現(xiàn)庫并直接調用 HDI 接口,是小型系統(tǒng)的默認部署方式,同時還適用于對性能有特殊需求的標準系統(tǒng)模塊。
圖3 兩種調用方式
HDI 硬件設備接口的優(yōu)點用一句話總結就是:為硬件的接入提供了統(tǒng)一的實現(xiàn)通路。屏蔽了硬件接口的具體實現(xiàn),實現(xiàn)系統(tǒng)軟件與硬件的架構解耦。讓開發(fā)者專注于硬件接口的使用,從而簡化開發(fā)過程,提升開發(fā)效率。
二、HDI實現(xiàn)
通過上文的介紹,相信很多小伙伴會有疑問,HDI 接口是怎么實現(xiàn)的呢?下面我們將為你介紹 IPC 模式下基于 C/S(Client-Server 客戶端與服務端)結構的 HDI 接口實現(xiàn)。
2.1 IDL接口描述語言
為方便后文的理解,我們先簡單了解一下 IDL 接口描述語言。
IDL(Interface Description Language)是一類用來描述接口的語言,通過一種中立的方式來定義客戶端與服務端均認可的編程接口,可以實現(xiàn)在二者間的跨進程通信(IPC)。跨進程通信意味著可以在一個進程訪問另一個進程的數據,或調用另一個進程的方法。通常把應用接口提供方(供調用)稱為服務端,調用方稱為客戶端。
IDL 先把需要傳遞的對象分解成操作系統(tǒng)能夠理解的基本類型,然后根據接口聲明編譯,生成 IPC/RPC代理(Proxy)和樁(Stub)的 C/C++ 代碼,從而為調用者提供一致的接口和調用方式。
圖4 IDL IPC模式通信模型
2.2 基于IDL語言實現(xiàn)HDI接口
首先,使用 IDL 語法描述 HDI 接口并保存為.idl文件,然后編寫 .idl 文件的編譯腳本 BUILD.gn 文件,最后編譯 .idl 文件即可。下面我們將為大家演示電源子系統(tǒng)的 HDI 接口的實現(xiàn)過程。
(1)使用IDL語法編寫 .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;
[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 相關過程代碼,開發(fā)者只需要基于生成的 power.h 函數接口實現(xiàn)具體服務功能即可。
編譯后生成代碼在 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
Get() ;static sptr
GetInstance(const std::string& serviceName) ;virtual int32_t RegisterCallback(const sptr
& 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)實現(xiàn)HDI接口
● 實現(xiàn) UHDF Driver,用于將 HDI 實現(xiàn)加載為獨立進程,并基于 HDF 驅動框架發(fā)布設備服務。
static int32_t PowerInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data,
struct HdfSBuf *reply)
{
......
return hdfPowerInterfaceHost->service->OnRemoteRequest(cmdId, *dataParcel, *replyParcel, option); // 將接口調用轉發(fā)到stub實現(xiàn)
}
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,
};
● 實現(xiàn) HDI 接口
/* 繼承PowerInterfaceStub并實現(xiàn)IPowerInterface 中的接口*/
class PowerInterfaceImpl : public PowerInterfaceStub {
public:
virtual ~PowerInterfaceImpl() {}
int32_t RegisterCallback(const sptr
& 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中對相關接口進行實現(xiàn),其中調用了內核相關接口,實現(xiàn)了具體功能
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 語言來展示電源子系統(tǒng) HDI 的調用。
3.1 調用原理
在 IPC 模式下,當系統(tǒng)服務調用 HDI 接口時,通過 proxy 庫將函數調用轉換為 IPC 請求,將接口調用的參數進行序列化;IPC 請求通過 IPC 框架發(fā)送到服務端,請求將被 stub 庫先處理,然后對接口調用的參數進行反序列化,再轉換成對服務實現(xiàn)的函數調用,從而實現(xiàn)接口調用過程。
圖5 HDI調用過程
3.2 基于CPP語言的使用
上文已經編譯生成了電源子系統(tǒng)的 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 = [
"http://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)在實現(xiàn)電源子系統(tǒng)的代碼中調用 HDI 接口,代碼如下:
using namespace OHOS::V1_0; //使用HDI接口命名空間
namespace OHOS {
namespace PowerMgr {
sptr
powerInterface = nullptr; SystemSuspendController::SystemSuspendController()
{
sptr
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接口的實現(xiàn)思路及使用,對于廣大南向開發(fā)者,我們還在社區(qū)提供了詳細的HDI接口實現(xiàn)指導,歡迎大家在gitee社區(qū)參與更多討論。
社區(qū)鏈接:
https://gitee.com/openharmony/drivers_interface
審核編輯 :李倩
-
接口
+關注
關注
33文章
8447瀏覽量
150724 -
HDI
+關注
關注
6文章
191瀏覽量
21262
原文標題:OpenHarmony 3.1 Release版本關鍵特性解析——HDI硬件設備接口介紹
文章出處:【微信號:gh_e4f28cfa3159,微信公眾號:OpenAtom OpenHarmony】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論