OpenHarmony驱动服务管理开发

驱动服务管理的开发包括驱动服务的编写、绑定、获取或者订阅,详细步骤如下。

驱动服务编写

// 驱动服务结构的定义
struct ISampleDriverService {
    struct IDeviceIoService ioService;       // 服务结构的首个成员必须是IDeviceIoService类型的成员。
    int32_t (*ServiceA)(void);               // 驱动的第一个服务接口。
    int32_t (*ServiceB)(uint32_t inputCode); // 驱动的第二个服务接口,有多个可以依次往下累加。
};
// 驱动服务接口的实现
int32_t SampleDriverServiceA(void)
{
    // 驱动开发者实现业务逻辑
    return HDF_SUCCESS;
}

int32_t SampleDriverServiceB(uint32_t inputCode)
{
    // 驱动开发者实现业务逻辑
    return HDF_SUCCESS;
}

驱动服务绑定

开发者实现HdfDriverEntry中的Bind指针函数,如下的SampleDriverBind,把驱动服务绑定到HDF框架中。

int32_t SampleDriverBind(struct HdfDeviceObject *deviceObject)
{
    // deviceObject为HDF框架给每一个驱动创建的设备对象,用来保存设备相关的私有数据和服务接口。
    if (deviceObject == NULL) {
        HDF_LOGE("Sample device object is null!");
        return HDF_FAILURE;
    }
    static struct ISampleDriverService sampleDriverA = {
        .ServiceA = SampleDriverServiceA,
        .ServiceB = SampleDriverServiceB,
    };
    deviceObject->service = &sampleDriverA.ioService;
    return HDF_SUCCESS;
}

驱动服务获取

应用程序开发者获取驱动服务有两种方式:通过HDF接口直接获取和通过HDF提供的订阅机制获取。

通过HDF接口直接获取

当驱动服务获取者明确驱动已经加载完成时,获取该驱动的服务可以通过HDF框架提供的能力接口直接获取,如下所示:

const struct ISampleDriverService *sampleService =
        (const struct ISampleDriverService *)DevSvcManagerClntGetService("sample_driver");
if (sampleService == NULL) {
    return HDF_FAILURE;
}
sampleService->ServiceA();
sampleService->ServiceB(5);

通过HDF提供的订阅机制获取

当内核态驱动服务获取者对驱动(同一个host)加载的时机不感知时,可以通过HDF框架提供的订阅机制来订阅该驱动服务。当该驱动加载完成时,HDF框架会将被订阅的驱动服务发布给订阅者(驱动服务获取者),实现方式如下所示:

// 订阅回调函数的编写,当被订阅的驱动加载完成后,HDF框架会将被订阅驱动的服务发布给订阅者,通过这个回调函数给订阅者使用。
// object为订阅者的私有数据,service为被订阅的服务对象。
int32_t TestDriverSubCallBack(struct HdfDeviceObject *deviceObject, const struct HdfObject *service)
{
    const struct ISampleDriverService *sampleService =
        (const struct ISampleDriverService *)service;
    if (sampleService == NULL) {
        return HDF_FAILURE;
    }
    sampleService->ServiceA();
    sampleService->ServiceB(5);
}
// 订阅过程的实现
int32_t TestDriverInit(struct HdfDeviceObject *deviceObject)
{
    if (deviceObject == NULL) {
        HDF_LOGE("Test driver init failed, deviceObject is null!");
        return HDF_FAILURE;
    }
    struct SubscriberCallback callBack;
    callBack.deviceObject = deviceObject;
    callBack.OnServiceConnected = TestDriverSubCallBack;
    int32_t ret = HdfDeviceSubscribeService(deviceObject, "sample_driver", callBack);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("Test driver subscribe sample driver failed!");
    }
    return ret;
}

HDF开发实例

下面基于HDF框架,提供一个完整的样例,包含配置文件的添加,驱动代码的实现以及用户态程序和驱动交互的流程。

添加配置

在HDF框架的配置文件(例如vendor/hisilicon/xxx/hdf_config/device_info)中添加该驱动的配置信息,如下所示:

root {
    device_info {
        match_attr = "hdf_manager";
        template host {
            hostName = "";
            priority = 100;
            template device {
                template deviceNode {
                    policy = 0;
                    priority = 100;
                    preload = 0;
                    permission = 0664;
                    moduleName = "";
                    serviceName = "";
                    deviceMatchAttr = "";
                }
            }
        }
        sample_host :: host {
            hostName = "sample_host";
            sample_device :: device {
                device0 :: deviceNode {
                    policy = 2;
                    priority = 100;
                    preload = 1;
                    permission = 0664;
                    moduleName = "sample_driver";
                    serviceName = "sample_service";
                }
            }
        }
    }
}

编写驱动代码

基于HDF框架编写的sample驱动代码如下:

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include "hdf_log.h"
#include "hdf_base.h"
#include "hdf_device_desc.h"

#define HDF_LOG_TAG sample_driver

#define SAMPLE_WRITE_READ 123

static int32_t HdfSampleDriverDispatch(
    struct HdfDeviceIoClient *client, int id, struct HdfSBuf *data, struct HdfSBuf *reply)
{
    HDF_LOGI("%{public}s: received cmd %{public}d", __func__, id);
    if (id == SAMPLE_WRITE_READ) {
        const char *readData = HdfSbufReadString(data);
        if (readData != NULL) {
            HDF_LOGE("%{public}s: read data is: %{public}s", __func__, readData);
        }
        if (!HdfSbufWriteInt32(reply, INT32_MAX)) {
            HDF_LOGE("%{public}s: reply int32 fail", __func__);
        }
        return HdfDeviceSendEvent(client->device, id, data);
    }
    return HDF_FAILURE;
}

static void HdfSampleDriverRelease(struct HdfDeviceObject *deviceObject)
{
    // release resources here
    return;
}

static int HdfSampleDriverBind(struct HdfDeviceObject *deviceObject)
{
    if (deviceObject == NULL) {
        return HDF_FAILURE;
    }
    static struct IDeviceIoService testService = {
        .Dispatch = HdfSampleDriverDispatch,
    };
    deviceObject->service = &testService;
    return HDF_SUCCESS;
}

static int HdfSampleDriverInit(struct HdfDeviceObject *deviceObject)
{
    if (deviceObject == NULL) {
        HDF_LOGE("%{public}s::ptr is null!", __func__);
        return HDF_FAILURE;
    }
    HDF_LOGI("Sample driver Init success");
    return HDF_SUCCESS;
}

static struct HdfDriverEntry g_sampleDriverEntry = {
    .moduleVersion = 1,
    .moduleName = "sample_driver",
    .Bind = HdfSampleDriverBind,
    .Init = HdfSampleDriverInit,
    .Release = HdfSampleDriverRelease,
};

HDF_INIT(g_sampleDriverEntry);

编写用户程序和驱动交互代码

基于HDF框架编写的用户态程序和驱动交互的代码如下(代码可以放在目录drivers/hdf_core/adapter/uhdf下面编译,BUILD.gn可以参考drivers/hdf_core/framework/sample/platform/uart/dev/BUILD.gn):

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "hdf_log.h"
#include "hdf_sbuf.h"
#include "hdf_io_service_if.h"

#define HDF_LOG_TAG sample_test
#define SAMPLE_SERVICE_NAME "sample_service"

#define SAMPLE_WRITE_READ 123

int g_replyFlag = 0;

static int OnDevEventReceived(void *priv,  uint32_t id, struct HdfSBuf *data)
{
    const char *string = HdfSbufReadString(data);
    if (string == NULL) {
        HDF_LOGE("fail to read string in event data");
        g_replyFlag = 1;
        return HDF_FAILURE;
    }
    HDF_LOGI("%{public}s: dev event received: %{public}u %{public}s",  (char *)priv, id, string);
    g_replyFlag = 1;
    return HDF_SUCCESS;
}

static int SendEvent(struct HdfIoService *serv, char *eventData)
{
    int ret = 0;
    struct HdfSBuf *data = HdfSbufObtainDefaultSize();
    if (data == NULL) {
        HDF_LOGE("fail to obtain sbuf data");
        return 1;
    }

    struct HdfSBuf *reply = HdfSbufObtainDefaultSize();
    if (reply == NULL) {
        HDF_LOGE("fail to obtain sbuf reply");
        ret = HDF_DEV_ERR_NO_MEMORY;
        goto out;
    }

    if (!HdfSbufWriteString(data, eventData)) {
        HDF_LOGE("fail to write sbuf");
        ret = HDF_FAILURE;
        goto out;
    }

    ret = serv->dispatcher->Dispatch(&serv->object, SAMPLE_WRITE_READ, data, reply);
    if (ret != HDF_SUCCESS) {
        HDF_LOGE("fail to send service call");
        goto out;
    }

    int replyData = 0;
    if (!HdfSbufReadInt32(reply, &replyData)) {
        HDF_LOGE("fail to get service call reply");
        ret = HDF_ERR_INVALID_OBJECT;
        goto out;
    }
    HDF_LOGI("Get reply is: %{public}d", replyData);
out:
    HdfSbufRecycle(data);
    HdfSbufRecycle(reply);
    return ret;
}

int main()
{
    char *sendData = "default event info";
    struct HdfIoService *serv = HdfIoServiceBind(SAMPLE_SERVICE_NAME);
    if (serv == NULL) {
        HDF_LOGE("fail to get service %s", SAMPLE_SERVICE_NAME);
        return HDF_FAILURE;
    }

    static struct HdfDevEventlistener listener = {
        .callBack = OnDevEventReceived,
        .priv ="Service0"
    };

    if (HdfDeviceRegisterEventListener(serv, &listener) != HDF_SUCCESS) {
        HDF_LOGE("fail to register event listener");
        return HDF_FAILURE;
    }
    if (SendEvent(serv, sendData)) {
        HDF_LOGE("fail to send event");
        return HDF_FAILURE;
    }

    while (g_replyFlag == 0) {
        sleep(1);
    }

    if (HdfDeviceUnregisterEventListener(serv, &listener)) {
        HDF_LOGE("fail to  unregister listener");
        return HDF_FAILURE;
    }

    HdfIoServiceRecycle(serv);
    return HDF_SUCCESS;
}

为了节省大家一些查找的时间,这边联合几位行业大佬,为大家准备了一份《OpenHarmony4.0&Next》的学习导图,从入门到进阶再到南北向开发实战的一整套完整体系,想要学习了解更多鸿蒙开发的相关知识可以借鉴:《做鸿蒙应用开发到底学习些啥?

除了上面整理的思维导图以外,这里还特别整理的一份《鸿蒙 (Harmony OS)开发学习手册》给大家进行参考学习:《鸿蒙基础入门开发宝典!

一、入门必看

  1. 应用开发导读(ArkTS)

  2. ......

二、HarmonyOS 概念

  1. 系统定义

  2. 技术架构

  3. 技术特性

  4. 系统安全

5........

三、如何快速入门?

  1. 基本概念

  2. 构建第一个ArkTS应用

  3. 构建第一个JS应用

  4. ......

四、开发基础知识

  1. 应用基础知识

  2. 配置文件

  3. 应用数据管理

  4. 应用安全管理

  5. 应用隐私保护

  6. 三方应用调用管控机制

  7. 资源分类与访问

  8. 学习ArkTS语言

  9. ......

五、基于ArkTS 开发

  1. Ability开发

  2. UI开发

  3. 公共事件与通知

  4. 窗口管理

  5. 媒体

  6. 安全

  7. 网络与链接

  8. 电话服务

  9. 数据管理

  10. 后台任务(Background Task)管理

  11. 设备管理

  12. 设备使用信息统计

  13. DFX

  14. 国际化开发

  15. 折叠屏系列

  16. ......

更多了解更多鸿蒙开发的相关知识可以参考:《鸿蒙开发学习指南

相关推荐
小懒编程日记39 分钟前
【数据结构与算法】B树
java·数据结构·b树·算法
Beginner_bml43 分钟前
C语言---链表
c语言·数据结构
闫铁娃1 小时前
二分解题的奇技淫巧都有哪些,你还不会吗?
c语言·数据结构·c++·算法·leetcode
Y_3_71 小时前
【回溯数独】有效的数独(medium)& 解数独(hard)
java·数据结构·windows·算法·dfs·回溯
小码狐2 小时前
并查集【数据结构与算法】【C语言版-笔记】
数据结构·笔记·并查集·c语言版
一切皆是定数2 小时前
Linux驱动开发——LED驱动开发
linux·驱动开发·b树
问道飞鱼2 小时前
每日学习一个数据结构-默克尔树(Merkle Tree)
数据结构·学习·默克尔树
CV工程师小林2 小时前
【算法】DFS 系列之 穷举/暴搜/深搜/回溯/剪枝(下篇)
数据结构·c++·算法·leetcode·深度优先·剪枝
-$_$-4 小时前
【LeetCode HOT 100】详细题解之二叉树篇
数据结构·算法·leetcode
尘心cx4 小时前
数据结构-栈
数据结构