樹(shù)莓派4B編寫(xiě)HDF驅(qū)動(dòng)示例
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
前言
前段時(shí)間已經(jīng)在樹(shù)莓派4B成功加入了HDF驅(qū)動(dòng)框架,帖子鏈接。得用HDF編寫(xiě)個(gè)自己的驅(qū)動(dòng)來(lái)測(cè)試下移植的效果。不說(shuō)了代碼最實(shí)在,看代碼吧。

1.內(nèi)核態(tài)驅(qū)動(dòng)代碼
一個(gè)簡(jiǎn)單的測(cè)試驅(qū)動(dòng),可以認(rèn)為是串口驅(qū)動(dòng)。因?yàn)樵趌inux內(nèi)核下,所以驅(qū)動(dòng)放置在linux\platform\uart目錄下。
drivers\adapter\khdf\linux\platform\uart\my_hdf_uart.c
- #include "hdf_device_desc.h" // HDF框架對(duì)驅(qū)動(dòng)開(kāi)發(fā)相關(guān)能力接口的頭文件
- #include "hdf_log.h" // HDF 框架提供的日志接口頭文件
- #define HDF_LOG_TAG "my_hdf_uart" // 打印日志所包含的標(biāo)簽,如果不定義則用默認(rèn)定義的HDF_TAG標(biāo)簽
- // 【3.1驅(qū)動(dòng)消息機(jī)制管理】Dispatch是用來(lái)處理用戶(hù)態(tài)發(fā)下來(lái)的消息
- int32_t MyUartDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
- {
- HDF_LOGE("%s::enter", __func__);
- HDF_LOGE("get cmdId::%d",cmdId);
- return HDF_SUCCESS;
- }
- // 【1.驅(qū)動(dòng)開(kāi)發(fā)】驅(qū)動(dòng)對(duì)外提供的服務(wù)能力,將相關(guān)的服務(wù)接口綁定到HDF框架
- int32_t MyHdfUartDriverBind(struct HdfDeviceObject *deviceObject)
- {
- HDF_LOGE("%s::enter", __func__);
- // 【2.驅(qū)動(dòng)服務(wù)管理】deviceObject為HDF框架給每一個(gè)驅(qū)動(dòng)創(chuàng)建的設(shè)備對(duì)象,用來(lái)保存設(shè)備相關(guān)的私有數(shù)據(jù)和服務(wù)接口
- if (deviceObject == NULL) {
- HDF_LOGE("My Uart device object is null!");
- return HDF_FAILURE;
- }
- static struct IDeviceIoService testService = {
- .Dispatch = MyUartDriverDispatch, // 【3.2驅(qū)動(dòng)消息機(jī)制管理】在服務(wù)實(shí)現(xiàn)過(guò)程中,實(shí)現(xiàn)服務(wù)基類(lèi)成員IDeviceIoService中的Dispatch方法
- .Open = NULL, // 【2.驅(qū)動(dòng)服務(wù)管理】驅(qū)動(dòng)提供的其他服務(wù)。
- .Release = NULL,
- // .ServiceA = SampleDriverServiceA,
- };
- deviceObject->service = &testService;
- return HDF_SUCCESS;
- }
- // 【1.驅(qū)動(dòng)開(kāi)發(fā)】驅(qū)動(dòng)自身業(yè)務(wù)初始的接口
- int32_t MyHdfUartDriverInit(struct HdfDeviceObject *deviceObject)
- {
- HDF_LOGE("%s::enter", __func__);
- HDF_LOGD("Uart driver bind success");
- return 0;
- }
- static int32_t MyUartParseAndInit(struct HdfDeviceObject *device, const struct DeviceResourceNode *node)
- {
- HDF_LOGE("%s::enter", __func__);
- return 0;
- }
- // 【1.驅(qū)動(dòng)開(kāi)發(fā)】驅(qū)動(dòng)資源釋放的接口
- void MyHdfUartDriverRelease(struct HdfDeviceObject *deviceObject)
- {
- HDF_LOGE("%s::enter", __func__);
- return;
- }
- // 【1.驅(qū)動(dòng)開(kāi)發(fā)】定義驅(qū)動(dòng)入口的對(duì)象,必須為HdfDriverEntry(在hdf_device_desc.h中定義)類(lèi)型的全局變量
- struct HdfDriverEntry g_myhdfUartDriverEntry = {
- .moduleVersion = 1,
- .moduleName = "my_hdf_uart",
- .Bind = MyHdfUartDriverBind,
- .Init = MyHdfUartDriverInit,
- .Release = MyHdfUartDriverRelease,
- };
- // 【1.驅(qū)動(dòng)開(kāi)發(fā)】調(diào)用HDF_INIT將驅(qū)動(dòng)入口注冊(cè)到HDF框架中,在加載驅(qū)動(dòng)時(shí)HDF框架會(huì)先調(diào)用Bind函數(shù),再調(diào)用Init函數(shù)加載該驅(qū)動(dòng),當(dāng)Init調(diào)用異常時(shí),HDF框架會(huì)調(diào)用Release釋放驅(qū)動(dòng)資源并退出。
- HDF_INIT(g_myhdfUartDriverEntry);
drivers\adapter\khdf\linux\platform\uart\Makefile:將驅(qū)動(dòng)加入內(nèi)核編譯
- - uart_adapter.o
- + uart_adapter.o \
- + my_hdf_uart.o
2.添加驅(qū)動(dòng)配置文件
vendor\raspberrypi\RPI4B\hdf_config\khdf\device_info\device_info.hcs
- # device_uart :: device 下添加
- device2 :: deviceNode {
- policy = 2;
- permission = 0644;
- priority = 40;
- moduleName = "my_hdf_uart";
- serviceName = "my_hdf_uart_service";
- }
3.用戶(hù)態(tài)HDF驅(qū)動(dòng)交互驗(yàn)證
applications\standard\app\myuarttest.c:用戶(hù)態(tài)主程序,主要代碼已經(jīng)添加注釋了。
- #include <utils/hdf_log.h>
- #include <core/hdf_io_service_if.h>
- #include "hdf_sbuf.h"
- #define HDF_LOG_TAG "my_hdf_uart"
- #define SAMPLE_SERVICE_NAME "my_hdf_uart_service"
- #define SAMPLE_WRITE_READ 1001 // 【驅(qū)動(dòng)消息機(jī)制管理】讀寫(xiě)操作碼,驅(qū)動(dòng)定義消息處理函數(shù)中的cmd類(lèi)型
- int main()
- {
- HDF_LOGE("%s::enter", __func__);
- int ret = 0;
- // 用戶(hù)態(tài)獲取驅(qū)動(dòng)的服務(wù),獲取該服務(wù)之后通過(guò)服務(wù)中的Dispatch方法向驅(qū)動(dòng)發(fā)送消息。
- struct HdfIoService *serv = HdfIoServiceBind(SAMPLE_SERVICE_NAME); // 【3驅(qū)動(dòng)消息機(jī)制管理】用戶(hù)態(tài)(通過(guò)服務(wù)名)獲取服務(wù)接口
- if (serv == NULL) {
- HDF_LOGE("fail to get service %s", SAMPLE_SERVICE_NAME);
- return HDF_FAILURE;
- }
- char *sendData = "";
- struct HdfSBuf *data = HdfSBufObtainDefaultSize(); // 存放要發(fā)送的數(shù)據(jù)
- if (!HdfSbufWriteString(data, sendData)) { // 發(fā)送的內(nèi)容賦值
- HDF_LOGE("fail to write sbuf");
- ret = HDF_FAILURE;
- }
- struct HdfSBuf *reply = HdfSBufObtainDefaultSize(); // 存放返回的數(shù)據(jù)
- ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply); // 發(fā)送消息到驅(qū)動(dòng)
- if (ret != HDF_SUCCESS) {
- HDF_LOGE("fail to send service call");
- }
- HdfIoServiceRecycle(serv);
- return HDF_SUCCESS;
- }
applications\standard\app\BUILD.gn:編寫(xiě)構(gòu)建腳本
- import("//build/ohos.gni")
- import("//drivers/adapter/uhdf2/uhdf.gni")
- ohos_executable("myuarttest") {
- sources = [
- "myuarttest.c"
- ]
- include_dirs = [
- "//drivers/framework/include", # <utils/hdf_log.h> <core/hdf_io_service_if.h>
- "//drivers/adapter/uhdf2/osal/include", # hdf_log_adapter.h
- "//base/hiviewdfx/hilog/interfaces/native/innerkits/include", # <hilog/log.h>
- "//drivers/framework/ability/sbuf/include", # hdf_sbuf.h
- "//drivers/framework/include/utils", # hdf_base.h
- ]
- deps = [
- "//drivers/adapter/uhdf2/osal:libhdf_utils", # hdf_log_adapter.h
- "//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog" # <hilog/log.h>
- ]
- subsystem_name = "applications"
- part_name = "prebuilt_hap"
- }
applications\standard\hap\ohos.build:最后將app加入編譯框架
- + "//applications/standard/app:myuarttest",
4.測(cè)試
最后執(zhí)行用戶(hù)態(tài)的myuarttest程序,就可以測(cè)試驅(qū)動(dòng)是否添加成功了。

用戶(hù)態(tài)只需要發(fā)送cmdId比如1001,然后內(nèi)核驅(qū)動(dòng)程序根據(jù)cmdID執(zhí)行相應(yīng)的操作即可。
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)