电子产业一站式赋能平台

PCB联盟网

搜索
查看: 1151|回复: 0
收起左侧

【HarmonyOS HiSpark AI Camera试用连载 】第七次眷恋-鸿蒙OS驱动服务的订阅机制

[复制链接]

2607

主题

2607

帖子

7472

积分

高级会员

Rank: 5Rank: 5

积分
7472
发表于 2021-1-14 23:55:59 | 显示全部楼层 |阅读模式
【HarmonyOS HiSpark AI Camera试用连载 】第七次眷恋-鸿蒙OS驱动服务的订阅机制,   
本帖最后由 瑟寒凌风 于 2021-1-14 23:10 编辑



谁? 我! 是你? 是我! 你终于来了! 我终于来了! 你终究是来了? 我终究是来了! 你来干什么! 我来写服务订阅!

鸿蒙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;
      
  • }
      


复制代码

这个函数就是简单的两个服务函数的调用。主要函数就是这样。

图1.jpg (121.04 KB, 下载次数: 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_sbuf.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 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_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;
      
  • }
      

  •   


复制代码
回复

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则


联系客服 关注微信 下载APP 返回顶部 返回列表