您现在的位置是:亿华云 > IT科技类资讯

HDF驱动框架探路(三):基于3516配置一套可以打通的HDF驱动程序

亿华云2025-10-02 16:33:33【IT科技类资讯】1人已围观

简介想了解更多内容,请访问:和华为官方合作共建的鸿蒙技术社区https://harmonyos.51cto.com老规矩还是将最终希望跑出来的效果放出来。如下:前言大家如果有读过第二篇文章的话,可能发现了

想了解更多内容,驱F驱请访问:

和华为官方合作共建的动框动程鸿蒙技术社区

https://harmonyos.51cto.com

老规矩还是将最终希望跑出来的效果放出来。如下:

前言

大家如果有读过第二篇文章的架探话,可能发现了在该文中内核态的于配驱动程序是直接引用了源码中已经存在的一个HDF驱动模块。所以本文的置套就是着重解决这个问题,也就是可打自己去配置一个HDF驱动模块。

本文是驱F驱基于3516的小型系统去验证的。

本文框架图

观察上图,云服务器提供商动框动程其实本文是架探将上文的流程进一步细化,上文中的于配驱动程序细分成了三个部分,分别是置套:HCS文件配置、内核态代码、可打liteos_a配置编译进内核。驱F驱这三个部分合起来就是动框动程自己搭建HDF驱动程序的步骤。

1. HDF配置

这里的架探HDF配置是按照源码中已经存在的sample_driver模块来的

打开文件vendor/hisilicon/hispark_taurus/hdf_config/hdf_test/hdf_test_manager/device_info.hcs,然后加入下述代码中的device2。

device1 :: deviceNode {                  policy = 2;                 priority = 10;                 preload = 0;                 permission = 0644;                 moduleName = "sample_driver";                 serviceName = "sample_service";             }             device2 :: deviceNode {              // DeviceNode of the sample driver           policy = 2;                     // Driver service release policy. For details, see section Driver Service Management.           priority= 10;                  // Driver startup priority (0-200). A larger value indicates a lower priority. The default value 100 is recommended. If the priorities are the same, the device loading sequence is random.           preload = 0;                    // On-demand loading of the driver. For details, see "NOTE" at the end of this section.           permission = 0664;              // Permission for the driver to create device nodes.           moduleName = "talkweb_driver";       // Driver name. The value of this field must be the same as the value of moduleName in the driver entry structure.           serviceName = "talkweb_service";     // Name of the service released by the driver. The name must be unique.       }         }         device_platform_test :: device {              platform_test:: deviceNode {                  policy = 1;                 priority = 150;                 preload = 0;                 permission = 0644;                 moduleName = "PLATFORM_TEST_DRIVER";                 serviceName = "PLATFORM_TEST";                 deviceMatchAttr = "platform_test";             }         } 

2. liteos_a编译配置

该步骤的网站模板作用是将第三步中的驱动程序编译进入内核。

2.1 在BUILD.gn文件中配置

打开drivers/adapter/khdf/liteos/test/BUILD.gn文件

--- a/khdf/liteos/test/BUILD.gn +++ b/khdf/liteos/test/BUILD.gn @@ -37,6 +37,7 @@ hdf_driver(module_name) {     sources = [      "$HDF_TEST_FRAMWORK_ROOT/common/hdf_main_test.c",      "$HDF_TEST_FRAMWORK_ROOT/manager/sample_driver_test.c", +    "$HDF_TEST_FRAMWORK_ROOT/talkwebtest/talkweb.c",      "$HDF_TEST_FRAMWORK_ROOT/osal/osal_all_test.c",      "$HDF_TEST_FRAMWORK_ROOT/osal/osal_file_test.c",      "$HDF_TEST_FRAMWORK_ROOT/osal/osal_get_case_test.c", 

2.2 在Makefile中进行添加配置

drivers/adapter/khdf/liteos/test/Makefile

--- a/khdf/liteos/test/Makefile +++ b/khdf/liteos/test/Makefile @@ -34,6 +34,7 @@ HDF_TEST_FRAMWORK_ROOT = $(LITEOSTOPDIR)/../../drivers/framework/test/unittest  LOCAL_SRCS := $(HDF_TEST_FRAMWORK_ROOT)/common/hdf_main_test.c \                $(HDF_TEST_FRAMWORK_ROOT)/manager/sample_driver_test.c \ +              $(HDF_TEST_FRAMWORK_ROOT)/talkwebtest/talkweb.c \                $(HDF_TEST_FRAMWORK_ROOT)/osal/osal_test_entry.c \                $(HDF_TEST_FRAMWORK_ROOT)/osal/osal_all_test.c \                $(HDF_TEST_FRAMWORK_ROOT)/osal/osal_file_test.c \ 

3. 驱动程序

进入drivers/framework/test/unittest目录下,新建talkwebtest目录

3.1 在上述目录下新建talkweb.h文件,将下述代码放入

#ifndef HDF_SAMPLE_DRIVER_H #define HDF_SAMPLE_DRIVER_H #include "hdf_object.h" #define SAMPLE_SERVICE "sample_service" typedef enum {      SAMPLE_DRIVER_REGISTER_DEVICE = 0,     SAMPLE_DRIVER_UNREGISTER_DEVICE,     SAMPLE_DRIVER_SENDEVENT_SINGLE_DEVICE,     SAMPLE_DRIVER_SENDEVENT_BROADCAST_DEVICE,     SAMPLE_DRIVER_PM_STATE_INJECT, } SAMPLE_DRIVER_CMDID; struct HdfDeviceObject *GetDeviceObject(void); #endif // HDF_MAIN_TEST_H 

3.2 在上述目录下新建talkweb.c文件,将下述代码放入

/*  * Copyright (c) 2020-2021 Huawei Device Co., Ltd.  *  * HDF is dual licensed: you can use it either under the terms of  * the GPL, or the BSD license, at your option.  * See the LICENSE file in the root of this repository for complete details.  */ #include "talkweb.h" #include "devsvc_manager_clnt.h" #include "devmgr_service.h" #include "hdf_log.h" #include "hdf_device_desc.h" #include "hdf_pm.h" #include "device_resource_if.h" #include "osal_io.h" #include "osal_mem.h" #include "gpio_if.h" #include "osal_irq.h" #include "osal_time.h"  //#define HDF_LOG_TAG led_driver // 打印日志所包含的标签,如果不定义则用默认>    定义的HDF_TAG标签 #define LED_WRITE_READ 88   #define HDF_LOG_TAG sample_driver_test #ifndef INT32_MAX #define INT32_MAX 0x7fffffff #endif void HdftalkwebDriverRelease(struct HdfDeviceObject *deviceObject) {      (void)deviceObject;     return; } int32_t talkwebDriverRegisterDevice(struct HdfSBuf *data) {      const char *moduleName = NULL;     const char *serviceName = NULL;     struct HdfDeviceObject *devObj = NULL;     if (data == NULL) {          return HDF_FAILURE;     }     moduleName = HdfSbufReadString(data);     if (moduleName == NULL) {          return HDF_FAILURE;     }     serviceName = HdfSbufReadString(data);     if (serviceName == NULL) {          return HDF_FAILURE;     }     devObj = HdfRegisterDevice(moduleName, serviceName, NULL);     if (devObj == NULL) {          return HDF_FAILURE;     }     return HDF_SUCCESS; } int32_t talkwebDriverUnregisterDevice(struct HdfSBuf *data) {      const char *moduleName = NULL;     const char *serviceName = NULL;     if (data == NULL) {          return HDF_FAILURE;     }     moduleName = HdfSbufReadString(data);     if (moduleName == NULL) {          return HDF_FAILURE;     }     serviceName = HdfSbufReadString(data);     if (serviceName == NULL) {          return HDF_FAILURE;     }     HdfUnregisterDevice(moduleName, serviceName);     return HDF_SUCCESS; } int32_t talkwebDriverSendEvent(struct HdfDeviceIoClient *client, int id, struct HdfSBuf *data, bool broadcast) {      return broadcast ? HdfDeviceSendEvent(client->device, id, data) : HdfDeviceSendEventToClient(client, id, data); } int32_t talkwebDriverPowerStateInject(uint32_t powerState) {      int ret;     struct IDevmgrService *devmgrService = DevmgrServiceGetInstance();     if (devmgrService == NULL || devmgrService->PowerStateChange == NULL) {          return HDF_ERR_INVALID_OBJECT;     }     ret = devmgrService->PowerStateChange(devmgrService, powerState);     HDF_LOGI("%s: inject power state(%d) done, ret = %d", __func__, powerState, ret);     return ret; } static int32_t CtlLED(int mode) {      int32_t ret;     uint16_t valRead;     /* LED的GPIO管脚号 */     uint16_t gpio = 5 * 8 + 1;  // 红外补光灯     // uint16_t gpio = 2 * 8 + 3;  // 绿色指示灯     // uint16_t gpio = 3 * 8 + 4;  // 红色指示灯     /* 将GPIO管脚配置为输出 */     ret = GpioSetDir(gpio, GPIO_DIR_OUT);     if (ret != 0)     {             HDF_LOGE("GpioSerDir: failed, ret %d\n", ret);         return ret;     }        if (mode == -1)      {             // 翻转输出口         (void)GpioRead(gpio, &valRead);         ret = GpioWrite(gpio, (valRead == GPIO_VAL_LOW) ? GPIO_VAL_HIGH : GPIO_VAL_LOW);     }        else     {             ret = GpioWrite(gpio, mode);     }        if (ret != 0)     {             HDF_LOGE("GpioWrite: failed, ret %d\n", ret);         return ret;     }        return ret; } int32_t talkwebDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply) {          HDF_LOGD("%s::qzk-enter", __func__);     uint32_t powerState = 0;     int32_t ret = HDF_SUCCESS;     if (reply == NULL || client == NULL) {          return HDF_FAILURE;     }     int32_t result = HDF_FAILURE;     switch (cmdId) {          case LED_WRITE_READ:             const char *recv = HdfSbufReadString(data);             if (recv != NULL)             {                  //HDF_LOGI("recv: %s", recv);                 result = CtlLED(-1);                 // CtlLED(GPIO_VAL_HIGH);                 if (!HdfSbufWriteInt32(reply, result)){                      //HDF_LOGE("replay is fail");                 }                 return HdfDeviceSendEvent(client->device, cmdId, data);             }             break;         case SAMPLE_DRIVER_REGISTER_DEVICE: {              ret = talkwebDriverRegisterDevice(data);             HdfSbufWriteInt32(reply, ret);             break;         }         case SAMPLE_DRIVER_UNREGISTER_DEVICE:             ret = talkwebDriverUnregisterDevice(data);             HdfSbufWriteInt32(reply, ret);             break;         case SAMPLE_DRIVER_SENDEVENT_SINGLE_DEVICE:             ret =  talkwebDriverSendEvent(client, cmdId, data, false);             HdfSbufWriteInt32(reply, INT32_MAX);             break;         case SAMPLE_DRIVER_SENDEVENT_BROADCAST_DEVICE:             ret = talkwebDriverSendEvent(client, cmdId, data, true);             HdfSbufWriteInt32(reply, INT32_MAX);             break;         case SAMPLE_DRIVER_PM_STATE_INJECT:             HdfSbufReadUint32(data, &powerState);             return talkwebDriverPowerStateInject(powerState);         default:             break;     }     return ret; } int HdftalkwebDriverBind(struct HdfDeviceObject *deviceObject) {      static struct IDeviceIoService testService = {          .Dispatch = talkwebDriverDispatch,         .Open = NULL,         .Release = NULL,     };     HDF_LOGD("%s::enter", __func__);     if (deviceObject == NULL) {          return HDF_FAILURE;     }     deviceObject->service = &testService;     return HDF_SUCCESS; } int HdftalkwebDozeResume(struct HdfDeviceObject *deviceObject) {      HDF_LOGI("%s:called", __func__);     return HDF_SUCCESS; } int HdftalkwebDozeSuspend(struct HdfDeviceObject *deviceObject) {      HDF_LOGI("%s:called", __func__);     return HDF_SUCCESS; } int HdftalkwebResume(struct HdfDeviceObject *deviceObject) {      HDF_LOGI("%s:called", __func__);     return HDF_SUCCESS; } int HdftalkwebSuspend(struct HdfDeviceObject *deviceObject) {      HDF_LOGI("%s:called", __func__);     return HDF_SUCCESS; } struct talkwebDriverPmListener {      struct IPowerEventListener powerListener;     void *p; }; int HdftalkwebDriverInit(struct HdfDeviceObject *deviceObject) {      static struct talkwebDriverPmListener pmListener = { 0};     int ret;     HDF_LOGI("%s::enter!", __func__);     if (deviceObject == NULL) {          HDF_LOGE("%s::ptr is null!", __func__);         return HDF_FAILURE;     }     HDF_LOGD("%s:Init success", __func__);     pmListener.powerListener.DozeResume = HdftalkwebDozeResume;     pmListener.powerListener.DozeSuspend = HdftalkwebDozeSuspend;     pmListener.powerListener.Resume = HdftalkwebResume;     pmListener.powerListener.Suspend = HdftalkwebSuspend;     ret = HdfPmRegisterPowerListener(deviceObject, &pmListener.powerListener);     HDF_LOGI("%s:register power listener, ret = %d", __func__, ret);     return HDF_SUCCESS; } struct HdfDriverEntry g_talkwebDriverEntry = {      .moduleVersion = 1,     .moduleName = "talkweb_driver",     .Bind = HdftalkwebDriverBind,     .Init = HdftalkwebDriverInit,     .Release = HdftalkwebDriverRelease, }; HDF_INIT(g_talkwebDriverEntry); 

4. 应用态程序

这里的应用态程序的代码和编译方法,直接可以采用上文的就可以。

这里只需要修改SAMPLE_SERVICE_NAME这个宏。

#define SAMPLE_SERVICE_NAME "talkweb_service" 

想了解更多内容,请访问:

和华为官方合作共建的鸿蒙技术社区

https://harmonyos.51cto.com

很赞哦!(94)