前言
前段时间已经在树莓派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执行相应的操作即可。