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

背景

  • 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 123static 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 herereturn;
}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.mkMODULE_NAME := sample_driverLOCAL_CFLAGS += $(HDF_INCLUDE)LOCAL_SRCS += sample_driver.cLOCAL_CFLAGS += -fstack-protector-strong -Wextra -Wall -Werror -fsigned-char -fno-strict-aliasing -fno-commoninclude $(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 123int 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. ……

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/607131.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASP.NET中小型超市管理系统源码

ASP.NET中小型超市管理系统源码 超市管理系统是专门为中小型超市打造的管理系统&#xff0c;可以方便管理时更加准确清晰的查看商品信息&#xff0c; 仓库出售与进货的信息&#xff0c;还有每一个部门员工的信息&#xff0c;也更加直观的体现出每一阶段的商品销售情况&#xf…

【VUE】无法加载文件 \node\vue.ps1,因为在此系统上禁止运行脚本。问题解决

问题描述 在VS Code中输入vue create -p dcloudio/uni-preset-vue uniapp-demo命令时报错 无法加载文件 D:\address\node\vue.ps1&#xff0c;因为在此系统上禁止运行脚本。有关详细信息&#xff0c;请参阅 https:/go.microsoft.com/fwlink/?LinkID135170 中的 about_Executi…

(aiohttp-asyncio-FFmpeg-Docker-SRS)实现异步摄像头转码服务器

1. 背景介绍 在先前的博客文章中&#xff0c;我们已经搭建了一个基于SRS的流媒体服务器。现在&#xff0c;我们希望通过Web接口来控制这个服务器的行为&#xff0c;特别是对于正在进行的 RTSP 转码任务的管理。这将使我们能够在不停止整个服务器的情况下&#xff0c;动态地启动…

UE5 使用动画模板创建多个动画蓝图

我们制作游戏的时候&#xff0c;角色会根据不同的武器表现出来不同的攻击动画&#xff0c;待机动画以及移动动画。如果我们在UE里面实现这个需求&#xff0c;是通过复制粘贴的方式修改&#xff0c;还是有更好的方式。 这里就需要介绍一下动画模板&#xff0c;我们可以将动画蓝图…

pycharm调整漂亮的颜色主题

主题样式&#xff1a; 一、设置主题为白色 二、pycharm 如何设置字体颜色 打开pycharm编辑器&#xff0c;file > settings > editor > color scheme > python > 你也可以直接用我资源中的配置好的文件

探索C语言中的水仙花数及其计算方法

在计算机科学与数学的交叉领域中&#xff0c;有一种特殊的整数被称为“水仙花数”&#xff0c;它是指一个三位数&#xff0c;其各位数字立方和等于该数本身。例如&#xff0c;153是一个典型的水仙花数&#xff0c;因为1 5 3 1 125 27 153。 下面&#xff0c;我们通过一段…

1.7数算PPT选择汇总,PTA选择汇总,计算后缀表达式,中缀转后缀、前缀、快速排序

PTA选择汇总 在第一个位置后插入&#xff0c;注意是在后面插入&#xff0c;而不是前面&#xff1b;要移动49&#xff0c;为50-I&#xff0c;第25个的话&#xff0c;移25个 如果是插在前面&#xff0c;就移动50&#xff0c;N-I1&#xff0c;注意是插在前面还是后面 删第一个&a…

虾皮上传产品软件:如何使用虾皮平台上传产品

在虾皮&#xff08;Shopee&#xff09;平台上&#xff0c;卖家可以通过多种方法来上传产品&#xff0c;以简化商品上架过程。本文将介绍一些常用的产品上传方法&#xff0c;帮助卖家选择最适合自己的方式。 先给大家推荐一款shopee知虾数据运营工具 知虾免费体验地址&#xff…

【Axure高保真原型】日期天数加减计算器

今天和大家分享日期天数加减计算器的原型模板&#xff0c;我们通过这个模板选择指定日期&#xff0c;然后填写需要增加或者减少的天数&#xff0c;点击确认按钮后&#xff0c;就可以计算出对应的结束日期&#xff0c;本案例提供中继器版的日期选择器&#xff0c;以及JS版的日期…

在docker中搭建部署clickhouse

因需要给网关日志拉取并存储供数据分析师分析&#xff0c;由于几十个项目的网关请求数量很大&#xff0c;放在mysql不合适&#xff0c;MongoDB不适合分析&#xff0c;于是准备存放在clickhouse&#xff0c;clickhouse对于读写支持也比较友好&#xff0c;说干就干 1、在服务器中…

LUT预设.cube格式PR/达芬奇/FCP/剪映等视频电影调色预设LUTs

对于将标准镜头转换为让人想起高端电影的视觉冲击场景至关重要。这些LUT经过专业设计&#xff0c;以模仿电影行业中的电影质量、深度和情感&#xff0c;使其成为电影制作人、摄像师和内容创作者的理想选择&#xff0c;希望为你的作品带来专业的电影色彩。 电影LUT的类别&#…

STL标准库与泛型编程(侯捷)笔记4

STL标准库与泛型编程&#xff08;侯捷&#xff09; 本文是学习笔记&#xff0c;仅供个人学习使用。如有侵权&#xff0c;请联系删除。 参考链接 Youbute: 侯捷-STL标准库与泛型编程 B站: 侯捷 - STL Github:STL源码剖析中源码 https://github.com/SilverMaple/STLSourceCo…

【Electron】 Vite项目 初始配置 scss

pnpm add -D sasssrc下面创建 styles/main.scss 文件 mian.ts 内引入 ./styles.scss 文件 import ./styles/main.scss 测试scss是否生效&#xff1a; styles/mian.scss :root{--mian:red; } App.vue <template><div>你好</div> </template><s…

红队打靶练习:EVM: 1

目录 信息收集 1、arp 2、netdiscover 3、nmap 4、nikto 5、whatweb 目录探测 1、gobuster 2、dirsearch WEB wpscan get username get password MSF get shell 提权 get root get flag 信息收集 1、arp ┌──(root㉿ru)-[~/kali] └─# arp-scan -l Interf…

基于zookeeper实现服务节点HA主备自动切换

文章目录 前言一、架构图和流程图二、流程说明1.服务启动初始化ZK、注册所有服务节点信息-MasterRegister2.创建、运行服务节点&#xff0c;并管理服务节点-LeaderSelectorZkClient。3.典型场景-调度服务单体执行-DigitalEmpTask 总结参考 前言 Spring Boot 主备切换可以采用数…

一文读懂「多模态大模型」

​ 学习资源 5-多模态大模型一统NLP和CV 1.多模态大模型的基本原理 2.常见的多模态大模型 https://www.bilibili.com/video/BV1NN41177Zp?p5&vd_sourcef27f081fc77389ca006fcebf41bede2d 3.多模态大模型如_哔哩哔哩_bilibili 强强联手&#xff01;科大讯飞和中科院终于把【…

模型 ECRS分析原则

系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。效能优化。 1 ECRS分析原则的应用 1.1 ECRS分析原则在企业管理中的应用-麦当劳的服务流程优化 取消&#xff08;Eliminate&#xff09;&#xff1a;麦当劳作为全球知名的快餐连锁企业&#…

一起来了解综合能源服务认证

首先&#xff0c;综合能源服务认证是有国家政策支持的&#xff0c; 《能源生产和消费革命战略&#xff08;2016-2030&#xff09;》中指出:1、能源生产端要以绿色低碳为方向&#xff0c;推动能源集中式和分布式开发并举&#xff0c;大幅提高新能源和可再生能源比重&#xff1b…

Redis黑马点评业务总结(含mac m1pro | windows11 wsl2 ubuntu环境配置 持续更新中~)

redis黑马点评项目分析业务学习笔记 含项目配置教学mac m1pro windows mac M1pro环境配置windows11 wsl2 ubuntu 环境配置一.短信登录1. 1发送验证码1.2短信登录注册1.3登录校验拦截器补缺Cookie Session Token1.4基于redistoken认证实现短信登陆1.5完善token认证的刷新机制 二…

STM32F103C8T6(HAL库函数 - 内部Flash操作)

简介 STM32F103C8T6 内部Flash 为 64KB&#xff0c;本次将对他多余空间进行读写。 介绍 数据手册下载 STM32F103x8/STM32F103xB 数据手册 包含Flash Memory Page分布 STM32F设备命名 设备容量类型 中容量类型 内部空间介绍 64 KBytes大小Flash Memory 从 0x0800 0000 ~…