OpenHarmony基于HDF简单驱动开发实例

2024-01-09

背景

  • OpenHarmony-3.0-LTS
  • qemu_small_system_demo
  • liteos_a
  • qemu

添加配置

device/qemu/arm_virt/liteos_a/hdf_config/device_info/device_info.hcs

device_info 新增:

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";
        }
    }
}

添加驱动代码

目录:device/qemu/arm_virt/liteos_a/drivers

新建驱动实现

mkdir sample_driver

vim sample_driver/sample_driver.c

#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);

新建Makefile和BUILD.gn

新建Makefile和BUILD.gn,可参考其他平台,例如 device/hisilicon/drivers/rtc/

Makefile:

include $(LITEOSTOPDIR)/config.mk
include $(LITEOSTOPDIR)/../../drivers/adapter/khdf/liteos/lite.mk

MODULE_NAME := sample_driver

LOCAL_CFLAGS += $(HDF_INCLUDE)

LOCAL_SRCS += sample_driver.c

LOCAL_CFLAGS += -fstack-protector-strong -Wextra -Wall -Werror -fsigned-char -fno-strict-aliasing -fno-common

include $(HDF_DRIVER)

BUILD.gn:

import("//drivers/adapter/khdf/liteos/hdf.gni")

#module_switch = defined(LOSCFG_DRIVERS_HDF_PLATFORM_RTC)
module_name = "sample_driver"
hdf_driver(module_name) {
  sources = [ "sample_driver.c" ]
}

修改上层BUILD.gn

import("//drivers/adapter/khdf/liteos/hdf.gni")

group("drivers") {
  public_deps = [ "../../../drivers" ]

  #新增
  deps = [
    "sample_driver",
  ]

}

config("public") {
  configs = [ "../../../drivers:public" ]
}

编写驱动交互代码

目录:vendor/ohemu/qemu_small_system_demo/

新建用户代码实现

mkdir hdf_test

vim hdf_test/sample_service.c

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include "hdf_log.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";

    HDF_LOGI(SAMPLE_SERVICE_NAME "start");

    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;
}

新建BUILD.gn

vim sample_service/BUILD.gn,可参考huawei/hdf/sample/platform/uart/dispatch/BUILD.gn

import("//build/lite/config/component/lite_component.gni")
HDF_FRAMEWORKS = "//drivers/framework"

lite_component("hdf_test") {
  features = [ ":sample_service" ]
}

executable("sample_service") {
  sources = [ "sample_service.c" ]

  include_dirs = [
    "$HDF_FRAMEWORKS/ability/sbuf/include",
    "$HDF_FRAMEWORKS/core/shared/include",
    "$HDF_FRAMEWORKS/core/host/include",
    "$HDF_FRAMEWORKS/core/master/include",
    "$HDF_FRAMEWORKS/include/core",
    "$HDF_FRAMEWORKS/include/utils",
    "$HDF_FRAMEWORKS/utils/include",
    "$HDF_FRAMEWORKS/include/osal",
    "//drivers/adapter/uhdf/posix/include",
    "//third_party/bounds_checking_function/include",
    "//base/hiviewdfx/hilog_lite/interfaces/native/innerkits",
  ]

  deps = [
    "//base/hiviewdfx/hilog_lite/frameworks/featured:hilog_shared",
    "//drivers/adapter/uhdf/manager:hdf_core",
    "//drivers/adapter/uhdf/posix:hdf_posix_osal",
  ]

  public_deps = [ "//third_party/bounds_checking_function:libsec_shared" ]
  defines = [ "__USER__" ]

  cflags = [
    "-Wall",
    "-Wextra",
    "-Wno-format",
    "-Wno-format-extra-args",
  ]

}

说明: 用户态应用程序使用了HDF框架中的消息发送接口,因此在编译用户态程序的过程中需要依赖HDF框架对外提供的hdf_core和osal的动态库,在gn编译文件中添加如下依赖项:

deps = [
​ "//drivers/hdf_core/adapter/uhdf/manager:hdf_core",
​ "//drivers/hdf_core/adapter/uhdf/posix:hdf_posix_osal",
]

修改上层BUILD.gn

group("qemu_small_system_demo") {
  deps = [
    "apps",
    "init_configs",
    "hdf_test",  #新增
  ]
}

以上都是趟过了许多坑后再跑通的

编译测试

使用 hb 重新编译镜像,会生成对应带新增驱动的内核和带用户程序的镜像


  
#编译
hb clean
hb build

运行新编译的镜像


#运行qemu
./vendor/ohemu/qemu_small_system_demo/patches/qemu-run

注: 需要修改上述脚本中的 rebuild=yes,让其每次都重新生成qemu镜像

开机log有如下打印,说明驱动已加载成功,并且在/dev/hdf/下面会生成 sample_service的节点:

...

01-01 00:00:00.119 2 4 W 02500/driver_loader: failed to load node, property is null, match attr is: 
01-01 00:00:00.119 2 4 I 02500/sample_driver: Sample driver Init success
01-01 00:00:00.119 2 4 I 02500/osal_cdev: OsalRegisterCdev:register /dev/hdf/sample_service
01-01 00:00:00.119 2 4 D 02500/devmgr_service: DevmgrServiceUpdateStatus host:sample_host 0 device:sample_service 0 status:1

...
OHOS:/$ ls /dev/hdf/                                                           
dev_mgr  event2  hdf_input_event1  input_dev_manager  sample_service 

运行测试应用 sample_service,会有如下打印:

OHOS:/$ sample_service                                                         
01-01 00:00:59.059 10 44 I 02500/sample_test: sample_servicestart
01-01 00:00:59.063 10 44 I 02500/sample_driver: HdfSampleDriverDispatch: received cmd 123
01-01 00:00:59.063 10 44 E 02500/sample_driver: HdfSampleDriverDispatch: read data is: default event info
01-01 00:00:59.064 10 44 I 02500/sample_test: Get reply is: 2147483647
01-01 00:00:59.068 10 45 I 02500/sample_test: Service0: dev event received: 123 default event info
01-01 00:01:00.065 10 44 D 02500/hdf_syscall_adapter: ioctl send poll thread(4) exit event, ret=0
OHOS:/$ 01-01 00:01:00.066 10 45 I 02500/hdf_syscall_adapter: event listener task received exit event
01-01 00:01:00.066 10 45 I 02500/hdf_syscall_adapter: event listener task exit
01-01 00:01:00.067 10 44 I 02500/hdf_syscall_adapter: poll thread exited
^C
OHOS:/$ ^C

总结

以上的内容主要简单介绍了OpenHarmony基于HDF简单驱动开发实例

要想成为一名鸿蒙高级开发,以上知识点是必须要掌握的,除此之外,还需要掌握一些鸿蒙应用开发相关的一些技术,需要我们共同去探索。

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

除了以上的知识内容,我还为大家整理了一份 《鸿蒙 (Harmony OS)开发学习手册》都是整理成PDF文档方式,分享给大家参考学习:《 鸿蒙开发学习指南

《鸿蒙 (Harmony OS)开发学习手册》

一、入门必看

1. 应用开发导读(ArkTS)

2. 应用开发导读(Java)

3.......

二、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. ……

更多了解更多鸿蒙开发的相关知识可以参考:《 做鸿蒙应用开发到底学习些啥?

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenHarmony基于HDF简单驱动开发实例 的相关文章

  • 进程间通信

    进程间通信 进程间通信介绍 进程间通信目的 数据传输 一个进程需要将它的数据发送给另一个进程 资源共享 多个进程之间共享同样的资源 通知事件 一个进程需要向另一个或一组进程发送消息 通知它 它们 发生了某种事件 如进程终止 时要通知父进程

随机推荐

  • 搜索二叉树(BSTree)

    一 搜索二叉树的概念 二叉搜索树又称为做二叉排序树 二叉查找树 其要么是一棵空树 要么是一个满足以下性质的二叉树 若它的左子树不空 则左子树上所有结点的关键字均小于根结点关键字 若它的右子树不空 则右子树上所有结点的关键字均大于根结点关键字
  • 9个最受欢迎的开源自动化测试框架盘点

    2024软件测试面试刷题 这个小程序 永久刷题 靠它快速找到工作了 刷题APP的天花板 自动化测试框架可以帮助测试人员评估多个Web和移动应用程序的功能 安全性 可用性和可访问性 尽管团队可以自己构建复杂的自动化测试框架 但是当他们可以使用
  • 深入了解鸿鹄电子招投标系统:Java版企业电子招标采购系统的核心功能

    随着市场竞争的加剧和企业规模的扩大 招采管理逐渐成为企业核心竞争力的重要组成部分 为了提高招采工作的效率和质量 我们提出了一种基于电子化平台的解决方案 该方案旨在通过电子化招投标 使得招标采购的质量更高 速度更快 同时节约招标成本 提升企业
  • 游戏被攻击了要怎么办

    有客户反馈刚上线新款游戏 没两天就被攻击了 导致用户无法登录 来咨询到我们这边能不能帮他解决 今天就来分享下 怎么预防游戏攻击和已经被攻击的游戏服务器该怎么处理 服务器不管是个人还是企业 被攻击的都有 在所难免 特别是新上线时候要承受住外来
  • 985毕业,我依然过不好这一生?(大厂java开发2年被裁)

    前言 看到标题 可能很多读者朋友恐怕又要骂我了 985这个特殊的字眼也确实异常晃眼 实际上现在985 211也越来越多 它能代表你能够进入到更高的平台 拿到 高级工厂 的入场券 但并不意味着你会成为赢家 或者说也不代表着你会站在金字塔的顶端
  • 前端如何处理大量数据。

    理论就是分割后台数据 然后通过定时器将数据加载到虚拟dom上 加载完成后渲染一部分 在项目中经常会碰到大量数据需要在前端页面渲染 很多时候会使用分页的功能 但是数据量过大的时候比如10万条这种的 一直滑动列表后面会出现卡顿 滑不动的现象 这
  • HarmonyOS鸿蒙开发指南:容器组建 dialog开发指导

    目录 创建Dialog组件 设置弹窗响应 场景示例 创建Dialog组件 在pages index目录下的hml文件中创建一个Dialog组件 并添加Button组件来触发Dialog Dialog组件仅支持width height mar
  • 工作五年,一年内我靠这系列java面试宝典从13K到大厂30K

    我认为对于面试以及进阶最佳的学习方法莫过于 刷题 博客 书籍 总结 前三者我将淋漓尽致地挥毫于这篇文章中 至于总结要靠个人 实际上越到后面你越会发现面试并不难 其次就是在刷题的过程中有没有去思考 刷题只是次之 这又是一个层次了 这里暂时不提
  • 如何处理不稳定的自动化测试?

    2024软件测试面试刷题 这个小程序 永久刷题 靠它快速找到工作了 刷题APP的天花板 abluecolor 在解决这个问题之前 请停止编写更多测试 因为这将花费你较高的测试维护成本 你需要尽快行动起来对不稳定的原因进行深入研究 找到不稳定
  • HarmonyOS鸿蒙开发指南:容器组建 tabs开发指导

    目录 创建Tabs 设置Tabs方向 设置样式 显示页签索引 场景示例 创建Tabs 在pages index目录下的hml文件中创建一个Tabs组件 div class container div
  • 阿里巴巴大神发布的Java零基础笔记,实战教程多到手软,跪了

    前言 现值金九银十之际 是面试高峰季 很多学校开始校招 也是跳槽转行的最佳时机 根据数据显示 程序员是金九银十里最热门的行业 也是需求量最大的行业 但是程序员是个门槛低 但金字塔顶峰比较高的行业 意味着你的付出要比别人多才能拔尖 我们都知道
  • 987页的Java面试宝典,看完才发现,应届生求职也没那么难

    前言 现在已经九月底 金九银十也已经过去了一大半 很明显今年的面试季明显不如往年火热 对于求职者来说 也更难了一些 马上迎来国庆节 假期一过 十月份又过去了三分之一 综合来看今年确实不是面试的最佳时期 不过趁今年所剩的时间来好好准备 明年的
  • 基于Java ssm美容院管理系统的设计与实现

    一 技术介绍 Java语言 SSM框架 SpringBoot框架 JSP页面 Mysql数据库 IDEA Eclipse开发 有需要的同学 源代码和配套文档领取 加文章最下方的名片哦 二 资料介绍 完整源代码 前后端源代码 SQL脚本 配套
  • 鸿蒙Ability开发-Stage模型下Ability的创建和使用

    创建Ability和Page页面 创建两个Ability EntryAbility DetailsAbility 其中EntryAbility是由工程默认创建的 这里我们只讲如何创建DetailsAbility 使用DevEco Studi
  • 基于Java ssm教资考前指导系统的设计与实现

    一 技术介绍 Java语言 SSM框架 SpringBoot框架 JSP页面 Mysql数据库 IDEA Eclipse开发 有需要的同学 源代码和配套文档领取 加文章最下方的名片哦 二 资料介绍 完整源代码 前后端源代码 SQL脚本 配套
  • Airtest常用API介绍

    2024软件测试面试刷题 这个小程序 永久刷题 靠它快速找到工作了 刷题APP的天花板 今天就继续给大家介绍一下Airtest框架常用的核心API用法 这也是熟悉使用Airtest框架的必备手册之一 一 官方文档 官方文档 https ai
  • 各大厂急招鸿蒙开发员,争抢鸿蒙工程师

    去年9月 余承东宣布鸿蒙原生应用全面启动 华为开始了全面抛弃安卓的进程 多家互联网公司也发布了鸿蒙OS的App开发工程师的岗位 开启了抢人大战 有的企业开出了近百万的年薪招聘鸿蒙OS工程师 而华为甚至为鸿蒙OS资深架构师开出了100万 16
  • 2024年一套超详细Java面试精华资料,让进大厂少走弯路

    在座的诸位有没有是自学Java的 有的话评论区给我扣个1看看 但凡自学过的同学都知道有多难 虽说现在互联网非常发达 不明白的上网一搜就有很多资料 不过大多质量不高 而且非常碎片化 实在很难梳理成一个可持续成长的体系 所以有了这篇文章 我结合
  • 基于Java ssm考研助手系统的设计与实现

    一 技术介绍 Java语言 SSM框架 SpringBoot框架 JSP页面 Mysql数据库 IDEA Eclipse开发 有需要的同学 源代码和配套文档领取 加文章最下方的名片哦 二 资料介绍 完整源代码 前后端源代码 SQL脚本 配套
  • OpenHarmony基于HDF简单驱动开发实例

    背景 OpenHarmony 3 0 LTS qemu small system demo liteos a qemu 添加配置 device qemu arm virt liteos a hdf config device info de