谁?
我!
是你?
是我!
你终于来了!
我终于来了!
你终究是来了?
我终究是来了!
你来干什么!
我来写服务订阅!
鸿蒙lite-a的驱动开发,我们其实就是为了实现HdfDriverEntry结构体,驱动框架完成大部分驱动加载的动作,用户只需注册自己所需的接口和配置,然后驱动框架就会根据解析,完成驱动加载和初始化动作。
开发者基于HDF驱动框架开发的驱动主要包含三大部分:
1、驱动程序部分 - 完成驱动的功能逻辑
2、驱动配置信息 - 指示驱动的加载信息内容
3、驱动资源配置 - 配置驱动的硬件配置信息。
驱动程序主要是完成驱动功能的开发部分:
对于开发者首先看到的是驱动入口部分,驱动入口部分通过DriverEntry对齐进行描述。
其中主要包含bind, init 和release三个接口。
本文主要说的是驱动订阅服务。
要实现订阅,需要在device_info.hcs文件中修改policy字段,该字段policy是驱动服务发布的策略
- typedef enum {
- /* 驱动不提供服务 */
- SERVICE_POLICY_NONE = 0,
- /* 驱动对内核态发布服务 */
- SERVICE_POLICY_PUBLIC = 1,
- /* 驱动对内核态和用户态都发布服务 */
- SERVICE_POLICY_CAPACITY = 2,
- /* 驱动服务不对外发布服务,但可以被订阅 */
- SERVICE_POLICY_FRIENDLY = 3,
- /* 驱动私有服务不对外发布服务,也不能被订阅 */
- SERVICE_POLICY_PRIVATE = 4,
- /* 错误的服务策略 */
- SERVICE_POLICY_INVALID
- } ServicePolicy;
复制代码
当对驱动(同一个host)加载的时机不感知时,可以通过HDF框架提供的订阅机制来订阅该驱动,当该驱动加载完成时,HDF框架会将被订阅的驱动服务发布给订阅者,我们先实现一个自定义结构体
- struct ILedService {
- struct IDeviceIoService ioService; // 服务结构的首个成员必须是IDeviceIoService类型的成员
- int32_t (*LedServiceA)(void); // 驱动的第一个服务接口
- int32_t (*LedServiceB)(uint32_t inputCode); // 驱动的第二个服务接口,有多个可以依次往下累加
- };
复制代码
在驱动的绑定程序中,实现服务函数的初始化
- static struct ILedService ledDriver = {
- .ioService.object = {0},
- .ioService.Dispatch = led_dispatch,
- .LedServiceA = service_funA,
- .LedServiceB = service_funB,
- };
- object->service = &ledDriver.ioService;
复制代码
然后可以来实现service_funA和service_funB函数,我的函数如下
- int32_t service_funA()
- {
- HDF_LOGE("%s: serviceA ok", __func__);
- int i = 5;
- while(i--)
- {
- GpioWrite(gpio, 1);
- OsalSleep(1);
- GpioWrite(gpio, 0);
- OsalSleep(1);
-
- }
- return 0;
- }
- int32_t service_funB(uint32_t inputCode)
- {
- HDF_LOGE("%s: serviceB ok", __func__);
- HDF_LOGE("inputCode: %d",inputCode);
- return 0;
- }
复制代码
通过回调函数可以调用这两个服务函数,我的回调函数如下
- int32_t TestDriverSubCallBack(struct HdfDeviceObject *deviceObject, const struct HdfObject *service)
- {
- (void)*deviceObject;
- const struct ILedService *sampleService =
- (const struct ILedService *)service;
- if (sampleService == NULL) {
- return -1;
- }
- sampleService->LedServiceA();
- sampleService->LedServiceB(5);
- return 0;
- }
复制代码
这个函数就是简单的两个服务函数的调用。主要函数就是这样。
Test.c如下
- /*
- * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved.
- * Description: ft6236 touch driver implement.
- * Author: zhaihaipeng
- * Create: 2020-07-25
- */
- #include <stdlib.h>
- #include <asm/io.h>
- #include <fs/fs.h>
- #include <fs_poll_pri.h>
- #include <los_queue.h>
- #include <poll.h>
- #include <user_copy.h>
- #include <securec.h>
- #include "gpio_if.h"
- #include "hdf_device_desc.h"
- #include "hdf_log.h"
- #include "osal_irq.h"
- #include "osal_mem.h"
- #include "osal_time.h"
- #include "led_dev.h"
- #define LED_WRITE_READ 123
- uint16_t gpio = 19; /*待测试的GPIO管脚号 */
- #define HDF_LOG_TAG led_driver // 打印日志所包含的标签,如果不定义则用默认定义的HDF_TAG标签
- struct ILedService {
- struct IDeviceIoService ioService; // 服务结构的首个成员必须是IDeviceIoService类型的成员
- int32_t (*LedServiceA)(void); // 驱动的第一个服务接口
- int32_t (*LedServiceB)(uint32_t inputCode); // 驱动的第二个服务接口,有多个可以依次往下累加
- };
- int32_t led_dispatch(struct HdfDeviceIoClient *deviceObject, int cmdId, struct HdfSBuf *data, struct HdfSBuf *reply)
- {
- HDF_LOGE("%s:Dispatch,cmd:%d", __func__,cmdId);
- if(cmdId == LED_WRITE_READ)
- {
- const char *readData = HdfSbufReadString(data);
- if (readData != NULL) {
- HDF_LOGE("%s: read data is: %s", __func__, readData);
- }
- if (!HdfSbufWriteInt32(reply, INT32_MAX)) {
- HDF_LOGE("%s: reply int32 fail", __func__);
- }
- return HdfDeviceSendEvent(deviceObject->device, cmdId, data);
- }
-
- return HDF_FAILURE;
- }
- int32_t service_funA()
- {
- HDF_LOGE("%s: serviceA ok", __func__);
- int i = 5;
- while(i--)
- {
- GpioWrite(gpio, 1);
- OsalSleep(1);
- GpioWrite(gpio, 0);
- OsalSleep(1);
-
- }
- return 0;
- }
- int32_t service_funB(uint32_t inputCode)
- {
- HDF_LOGE("%s: serviceB ok", __func__);
- HDF_LOGE("inputCode: %d",inputCode);
- return 0;
- }
- int32_t led_bind(struct HdfDeviceObject *object)
- {
- HDF_LOGI("%s: led_bind", __func__);
- if (object == NULL) {
- HDF_LOGE("%s: param is null", __func__);
- return HDF_ERR_INVALID_PARAM;
- }
- static struct ILedService ledDriver = {
- .ioService.object = {0},
- .ioService.Dispatch = led_dispatch,
- .LedServiceA = service_funA,
- .LedServiceB = service_funB,
- };
- object->service = &ledDriver.ioService;
- return HDF_SUCCESS;
- }
- // 订阅回调函数的编写,当被订阅的驱动加载完成后,HDF框架会将被订阅驱动的服务发布给订阅者,通过这个回调函数给订阅者使用
- // object为订阅者的私有数据,service为被订阅的服务对象
- int32_t TestDriverSubCallBack(struct HdfDeviceObject *deviceObject, const struct HdfObject *service)
- {
- (void)*deviceObject;
- const struct ILedService *sampleService =
- (const struct ILedService *)service;
- if (sampleService == NULL) {
- return -1;
- }
- sampleService->LedServiceA();
- sampleService->LedServiceB(5);
- return 0;
- }
- int led_init(struct HdfDeviceObject *deviceObject)
- {
- HDF_LOGI("%s: led_init", __func__);
- GpioSetDir(gpio, GPIO_DIR_OUT);//设置GPIO管脚方向,输出
- if (deviceObject == NULL) {
- HDF_LOGE("Test driver init failed, deviceObject is null!");
- return -1;
- }
- struct SubscriberCallback callBack;
- callBack.deviceObject = deviceObject;
- callBack.OnServiceConnected = TestDriverSubCallBack;
- int32_t ret = HdfDeviceSubscribeService(deviceObject, "HDF_PLATFORM_LED", callBack);
- if (ret != 0) {
- HDF_LOGE("Test driver subscribe led driver failed!");
- }
- return ret;
- }
- void led_release(struct HdfDeviceObject *deviceObject)
- {
- HDF_LOGD("led driver release success");
- return;
- }
- struct HdfDriverEntry g_ledDevEntry = {
- .moduleVersion = 1,
- .moduleName = "HDF_PLATFORM_LED",
- .Bind = led_bind,
- .Init = led_init,
- .Release = led_release,
- };
- HDF_INIT(g_ledDevEntry);
复制代码
main.c如下
- #include "hdf_log.h"
- #include "osal_mem.h"
- #include "hdf_io_service_if.h"
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include <string.h>
- #include <unistd.h>
- #include "osal_time.h"
- // #include "hdf_device_desc.h"
- //#include "hdf_device_section.h"
- #include <stdlib.h>
- // #include <asm/io.h>
- // #include <fs/fs.h>
- // #include <fs_poll_pri.h>
- // #include <los_queue.h>
- #include <poll.h>
- // #include <user_copy.h>
- // #include <securec.h>
- // #include "gpio_if.h"
- #include "hdf_device_desc.h"
- // #include "hdf_log.h"
- #include "osal_irq.h"
- // #include "osal_mem.h"
- // #include "osal_time.h"
- #include <sys/ioctl.h>
- #include "hdf_***uf.h"
- #include "led_dev.h"
- #define SAMPLE_WRITE_READ 123 // 读写操作码1
- int g_replyFlag = 0;
- struct ILedService {
- struct IDeviceIoService ioService; // 服务结构的首个成员必须是IDeviceIoService类型的成员
- int32_t (*LedServiceA)(void); // 驱动的第一个服务接口
- int32_t (*LedServiceB)(uint32_t inputCode); // 驱动的第二个服务接口,有多个可以依次往下累加
- };
- static int SendEvent(struct HdfIoService *serv, char *eventData)
- {
- int ret = 0;
- struct HdfSBuf *data = HdfSBufObtainDefaultSize();
- if (data == NULL) {
- HDF_LOGE("fail to obtain ***uf data");
- return 1;
- }
-
- struct HdfSBuf *reply = HdfSBufObtainDefaultSize();
- if (reply == NULL) {
- HDF_LOGE("fail to obtain ***uf reply");
- ret = HDF_DEV_ERR_NO_MEMORY;
- goto out;
- }
-
- if (!HdfSbufWriteString(data, eventData)) {
- HDF_LOGE("fail to write ***uf");
- 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_LOGE("Get reply is: %d", replyData);
- out:
- HdfSBufRecycle(data);
- HdfSBufRecycle(reply);
- return ret;
- }
- static int OnDevEventReceived(void *priv, uint32_t id, struct HdfSBuf *data)
- {
- HDF_LOGE("%s: OnDevEventReceived", __func__);
- const char *string = HdfSbufReadString(data);
- if (string == NULL) {
- HDF_LOGE("fail to read string in event data");
- g_replyFlag = 1;
- return HDF_FAILURE;
- }
- HDF_LOGE("%s: dev event received: %u %s", (char *)priv, id, string);
- g_replyFlag = 1;
- return HDF_SUCCESS;
- }
- int main()
- {
- char *sendData = "default event info";
- struct HdfIoService *serv = HdfIoServiceBind("HDF_PLATFORM_LED", 0);
- if (serv == NULL) {
- HDF_LOGE("fail to get service %s", "HDF_PLATFORM_LED");
- 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;
- }
-
- /* wait for event receive event finishing */
- while (g_replyFlag == 0) {
- sleep(1);
- }
- if (HdfDeviceUnregisterEventListener(serv, &listener)) {
- HDF_LOGE("fail to unregister listener");
- return HDF_FAILURE;
- }
- HdfIoServiceRecycle(serv);
- return HDF_SUCCESS;
- }
复制代码