樹莓派4B編寫HDF驅動示例
前言
前段時間已經在樹莓派4B成功加入了HDF驅動框架,帖子鏈接。得用HDF編寫個自己的驅動來測試下移植的效果。不說了代碼最實在,看代碼吧。

1.內核態驅動代碼
一個簡單的測試驅動,可以認為是串口驅動。因為在linux內核下,所以驅動放置在linux\platform\uart目錄下。
drivers\adapter\khdf\linux\platform\uart\my_hdf_uart.c
- #include "hdf_device_desc.h" // HDF框架對驅動開發相關能力接口的頭文件
- #include "hdf_log.h" // HDF 框架提供的日志接口頭文件
- #define HDF_LOG_TAG "my_hdf_uart" // 打印日志所包含的標簽,如果不定義則用默認定義的HDF_TAG標簽
- // 【3.1驅動消息機制管理】Dispatch是用來處理用戶態發下來的消息
- 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.驅動開發】驅動對外提供的服務能力,將相關的服務接口綁定到HDF框架
- int32_t MyHdfUartDriverBind(struct HdfDeviceObject *deviceObject)
- {
- HDF_LOGE("%s::enter", __func__);
- // 【2.驅動服務管理】deviceObject為HDF框架給每一個驅動創建的設備對象,用來保存設備相關的私有數據和服務接口
- if (deviceObject == NULL) {
- HDF_LOGE("My Uart device object is null!");
- return HDF_FAILURE;
- }
- static struct IDeviceIoService testService = {
- .Dispatch = MyUartDriverDispatch, // 【3.2驅動消息機制管理】在服務實現過程中,實現服務基類成員IDeviceIoService中的Dispatch方法
- .Open = NULL, // 【2.驅動服務管理】驅動提供的其他服務。
- .Release = NULL,
- // .ServiceA = SampleDriverServiceA,
- };
- deviceObject->service = &testService;
- return HDF_SUCCESS;
- }
- // 【1.驅動開發】驅動自身業務初始的接口
- 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.驅動開發】驅動資源釋放的接口
- void MyHdfUartDriverRelease(struct HdfDeviceObject *deviceObject)
- {
- HDF_LOGE("%s::enter", __func__);
- return;
- }
- // 【1.驅動開發】定義驅動入口的對象,必須為HdfDriverEntry(在hdf_device_desc.h中定義)類型的全局變量
- struct HdfDriverEntry g_myhdfUartDriverEntry = {
- .moduleVersion = 1,
- .moduleName = "my_hdf_uart",
- .Bind = MyHdfUartDriverBind,
- .Init = MyHdfUartDriverInit,
- .Release = MyHdfUartDriverRelease,
- };
- // 【1.驅動開發】調用HDF_INIT將驅動入口注冊到HDF框架中,在加載驅動時HDF框架會先調用Bind函數,再調用Init函數加載該驅動,當Init調用異常時,HDF框架會調用Release釋放驅動資源并退出。
- HDF_INIT(g_myhdfUartDriverEntry);
drivers\adapter\khdf\linux\platform\uart\Makefile:將驅動加入內核編譯
- - uart_adapter.o
- + uart_adapter.o \
- + my_hdf_uart.o
2.添加驅動配置文件
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.用戶態HDF驅動交互驗證
applications\standard\app\myuarttest.c:用戶態主程序,主要代碼已經添加注釋了。
- #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 // 【驅動消息機制管理】讀寫操作碼,驅動定義消息處理函數中的cmd類型
- int main()
- {
- HDF_LOGE("%s::enter", __func__);
- int ret = 0;
- // 用戶態獲取驅動的服務,獲取該服務之后通過服務中的Dispatch方法向驅動發送消息。
- struct HdfIoService *serv = HdfIoServiceBind(SAMPLE_SERVICE_NAME); // 【3驅動消息機制管理】用戶態(通過服務名)獲取服務接口
- if (serv == NULL) {
- HDF_LOGE("fail to get service %s", SAMPLE_SERVICE_NAME);
- return HDF_FAILURE;
- }
- char *sendData = "";
- struct HdfSBuf *data = HdfSBufObtainDefaultSize(); // 存放要發送的數據
- if (!HdfSbufWriteString(data, sendData)) { // 發送的內容賦值
- HDF_LOGE("fail to write sbuf");
- ret = HDF_FAILURE;
- }
- struct HdfSBuf *reply = HdfSBufObtainDefaultSize(); // 存放返回的數據
- ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply); // 發送消息到驅動
- if (ret != HDF_SUCCESS) {
- HDF_LOGE("fail to send service call");
- }
- HdfIoServiceRecycle(serv);
- return HDF_SUCCESS;
- }
applications\standard\app\BUILD.gn:編寫構建腳本
- 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.測試
最后執行用戶態的myuarttest程序,就可以測試驅動是否添加成功了。

用戶態只需要發送cmdId比如1001,然后內核驅動程序根據cmdID執行相應的操作即可。