From 5db6f3f30125e7eaa5d5f2944b7835c48abde911 Mon Sep 17 00:00:00 2001 From: chenchong Date: Tue, 26 Jul 2022 11:53:32 +0800 Subject: [PATCH] Add Motion Development Guide Signed-off-by: chenchong --- .../driver/driver-peripherals-motion-des.md | 252 ++++++++++++++++++ ...1\345\212\250\346\241\206\346\236\266.png" | Bin 0 -> 12017 bytes ...0\350\277\220\350\241\214\345\233\276.png" | Bin 0 -> 22193 bytes 3 files changed, 252 insertions(+) create mode 100644 zh-cn/device-dev/driver/driver-peripherals-motion-des.md create mode 100644 "zh-cn/device-dev/driver/figures/\346\211\213\345\212\277\350\257\206\345\210\253\351\251\261\345\212\250\346\241\206\346\236\266.png" create mode 100644 "zh-cn/device-dev/driver/figures/\346\211\213\345\212\277\350\257\206\345\210\253\351\251\261\345\212\250\350\277\220\350\241\214\345\233\276.png" diff --git a/zh-cn/device-dev/driver/driver-peripherals-motion-des.md b/zh-cn/device-dev/driver/driver-peripherals-motion-des.md new file mode 100644 index 0000000000..3d3608cbdf --- /dev/null +++ b/zh-cn/device-dev/driver/driver-peripherals-motion-des.md @@ -0,0 +1,252 @@ +# 手势识别 + +## 概述 + +### 功能简介 + +手势识别模块作为端侧设备不可或缺的一部分,为用户提供手势识别控制能力。当前支持的手势识别类型有拿起、翻转、摇一摇、旋转屏等。 + +基于HDF(Hardware Driver Foundation)驱动框架开发的手势识别驱动,能够屏蔽硬件器件差异,为上层MSDP(Multimodal Sensor +Data Platform)服务层提供稳定的手势识别控制能力接口,包括手势识别使能/去使能、手势识别订阅/去订阅等。 + +手势识别驱动框架如图1所示,上层为Framework层,提供MSDP服务,通过DAL层的Motion HDI Client与Motion HDI Server进行交互;而Motion HDI Server可调用Motion HDI实现类接口,从而实现上层服务的手势识别使能/去使能、手势识别订阅/去订阅等能力。 + +**图1** 手势识别驱动框架 + +![1660105057660](figures/手势识别驱动框架.png) + +### 运作机制 + +通过介绍手势识别驱动模型的加载以及运行流程,对模型内部关键组件以及关联组件之间的关系进行了划分,整体加载流程如图2所示: + +**图 2** 手势识别驱动运行图 + +![1660122293156](figures/手势识别驱动运行图.png) + +1. MSDP:上层综合传感信息处理平台服务层,当HDI接口服务实例获取成功后可以直接调用Motion HDI接口。 +2. IDL:接口抽象层。MSDP服务层首先从Motion Proxy获取到Motion HDI接口服务实例。而Motion Proxy获取到的接口实例是由IService Manager进行分配。当MSDP服务层成功获取到Motion HDI接口服务实例后,MSDP服务层就可以直接调用Motion Proxy中的HDI接口,然后通过IPC(Inter-Process Communication)调用到Motion Stub,从而调用到Motion Service的接口。这部分是由工具自动生成的代码,不用器件厂商自己开发。 +3. HD IService:HDI Service中包括Motion Interface Driver、Motion Service和Motion Impl三个部分。其中Motion Interface Driver为手势识别接口的驱动代码,在这部分驱动代码中通过定义一个struct HdfDriverEntry类型的结构体变量,实现此变量中的的Init、Bind和Release函数描述驱动能力,函数内部通过HDF_INIT宏加载驱动。Motion Service为手势识别服务接口类,具体的实现在Motion Impl中描述。此部分代码需要器件厂商根据自己器件来开发。 + +## 开发指导 + +### 场景介绍 + +手势识别驱动的主要工作是为上层MSDP服务提供稳定的使能/去使能手势识别服务,订阅/取消订阅手势识别数据回调函数的功能。可应用于拿起、翻转、摇一摇、旋转屏等手势识别场景。 + +### 接口说明 + +**表1** 接口功能介绍 + +| 接口名 | 功能介绍 | +| ------------------------------------------------------------ | ---------------------------- | +| int32_t EnableMotion(int32_t motionType) | 使能一种手势识别类型,只有数据订阅者使能手势识别后,才能获取订阅的手势识别数据。 | +| int32_t DisableMotion(int32_t motionType) | 去使能手势识别。 | +| int32_t Register(const sptr\ &callbackObj) | 订阅者成功注册手势识别数据回调函数,系统会将获取到的手势识别数据上报给订阅者。 | +| int32_t Unregister(const sptr\ &callbackObj) | 取消订阅手势识别数据回调函数。 | + +### 开发步骤 + +开发步骤分为两个大步骤。 + +1. 基于HDF驱动框架,完成手势识别用户态驱动开发。 +2. 厂商实现EnableMotion、DisableMotion、Register和Unregister接口功能。 + +手势识别目录结构及各部分功能简介。 + +```undefined +/drivers/peripheral/motion # 此目录具体实现需要厂商根据自己的器件进行开发 +├── hdi_service # 手势识别模块对上层MSDP服务提供的驱动能力 +├── test # 手势识别模块测试代码 +│ └── unittest\hdi # 手势识别模块HDI单元测试代码 +``` + +下面结合DEMO实例,介绍如何基于HDF驱动框架,手势识别用户态驱动开发。具体实现请参考 [motion_interface_driver.cpp](https://gitee.com/openharmony/drivers_peripheral/blob/master/motion/hdi_service/motion_interface_driver.cpp)。 + +手势识别用户态驱动开发, 主要完成Bind、Init、Release、Dispatch函数接口实现。其中Bind函数为驱动对外提供的服务能力,Init函数为系统加载驱动前需要的一些初始化的操作,Release函数的主要作用为当系统加载驱动调用Init函数失败时对资源进行回收操作。 + +```c++ +// 自定义的HdfMotionInterfaceHost对象 +struct HdfMotionInterfaceHost { + struct IDeviceIoService ioService; + OHOS::sptr stub; +}; + +// 服务接口调用响应接口 +static int32_t MotionInterfaceDriverDispatch(struct HdfDeviceIoClient *client, int cmdId, struct HdfSBuf *data, + struct HdfSBuf *reply) +{ + auto *hdfMotionInterfaceHost = CONTAINER_OF(client->device->service, struct HdfMotionInterfaceHost, ioService); + + OHOS::MessageParcel *dataParcel = nullptr; + OHOS::MessageParcel *replyParcel = nullptr; + OHOS::MessageOption option; + + if (SbufToParcel(data, &dataParcel) != HDF_SUCCESS) { + HDF_LOGE("%{public}s: invalid data sbuf object to dispatch", __func__); + return HDF_ERR_INVALID_PARAM; + } + if (SbufToParcel(reply, &replyParcel) != HDF_SUCCESS) { + HDF_LOGE("%{public}s: invalid reply sbuf object to dispatch", __func__); + return HDF_ERR_INVALID_PARAM; + } + + return hdfMotionInterfaceHost->stub->SendRequest(cmdId, *dataParcel, *replyParcel, option); +} + +// 初始化接口 +int HdfMotionInterfaceDriverInit(struct HdfDeviceObject *deviceObject) +{ + HDF_LOGI("HdfMotionInterfaceDriverInit enter"); + return HDF_SUCCESS; +} + +// Motion驱动对外提供的服务绑定到HDF框架 +int HdfMotionInterfaceDriverBind(struct HdfDeviceObject *deviceObject) +{ + HDF_LOGI("HdfMotionInterfaceDriverBind enter"); + + auto *hdfMotionInterfaceHost = new (std::nothrow) HdfMotionInterfaceHost; + if (hdfMotionInterfaceHost == nullptr) { + HDF_LOGE("%{public}s: failed to create HdfMotionInterfaceHost object", __func__); + return HDF_FAILURE; + } + + hdfMotionInterfaceHost->ioService.Dispatch = MotionInterfaceDriverDispatch; + hdfMotionInterfaceHost->ioService.Open = NULL; + hdfMotionInterfaceHost->ioService.Release = NULL; + + auto serviceImpl = IMotionInterface::Get(true); + if (serviceImpl == nullptr) { + HDF_LOGE("%{public}s: failed to get of implement service", __func__); + return HDF_FAILURE; + } + + hdfMotionInterfaceHost->stub = OHOS::HDI::ObjectCollector::GetInstance().GetOrNewObject(serviceImpl, + IMotionInterface::GetDescriptor()); + if (hdfMotionInterfaceHost->stub == nullptr) { + HDF_LOGE("%{public}s: failed to get stub object", __func__); + return HDF_FAILURE; + } + + deviceObject->service = &hdfMotionInterfaceHost->ioService; + return HDF_SUCCESS; +} + +// 释放Motion驱动中的资源 +void HdfMotionInterfaceDriverRelease(struct HdfDeviceObject *deviceObject) +{ + HDF_LOGI("HdfMotionInterfaceDriverRelease enter"); + auto *hdfMotionInterfaceHost = CONTAINER_OF(deviceObject->service, struct HdfMotionInterfaceHost, ioService); + delete hdfMotionInterfaceHost; + hdfMotionInterfaceHost = nullptr; +} + +// 注册Motion驱动入口数据结构体对象 +struct HdfDriverEntry g_motioninterfaceDriverEntry = { + .moduleVersion = 1, + .moduleName = "motion_service", + .Bind = HdfMotionInterfaceDriverBind, + .Init = HdfMotionInterfaceDriverInit, + .Release = HdfMotionInterfaceDriverRelease, +}; + +// 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出。 +HDF_INIT(g_userAuthInterfaceDriverEntry); +``` + + +### 调测验证 + +测试代码开发步骤: + +1. 通过调用IMotionInterface::Get()获取到手势识别实例,并赋给IMotionInterface类型的智能指针对象g_motionInterface。 + +2. 通过g_motionInterface实例调用Register接口注册回调,回调函数需要根据自己的需求来设计。 + +3. 通过g_motionInterface实例调用EnableMotion接口使能Motion类型,当前支持拿起(HDF_MOTION_TYPE_PICKUP)、翻转(HDF_MOTION_TYPE_FLIP)、摇一摇(HDF_MOTION_TYPE_SHAKE)、旋转(HDF_MOTION_TYPE_ROTATION)等手势识别类型。 + +4. 通过g_motionInterface实例调用DisableMotion接口去使能手势识别类型。 + +5. 通过g_motionInterface实例调用Unregister取消订阅Motion数据回调函数。注意取消订阅必须先调用Register接口注册回调,否则Unregister会返回失败。 + + 测试代码实例如下: + + ```c++ + using namespace OHOS::HDI::Motion::V1_0; + using namespace testing::ext; + + namespace { + sptr g_motionInterface = nullptr; + sptr g_motionCallback = new MotionCallbackService(); + sptr g_motionCallbackUnregistered = new MotionCallbackService(); + } + + class HdfMotionTest : public testing::Test { + public: + static void SetUpTestCase(); + static void TearDownTestCase(); + void SetUp(); + void TearDown(); + }; + + void HdfMotionTest::SetUpTestCase() + { + // 1.获取手势识别实例 + g_motionInterface = IMotionInterface::Get(); + } + + void HdfMotionTest::TearDownTestCase() + { + } + + void HdfMotionTest::SetUp() + { + } + + void HdfMotionTest::TearDown() + { + } + + HWTEST_F(HdfMotionTest, EnableMotion_001, TestSize.Level1) + { + if (g_motionInterface == nullptr) { + ASSERT_NE(nullptr, g_motionInterface); + return; + } + + vector vec; + vec.push_back(HDF_MOTION_TYPE_PICKUP); + vec.push_back(HDF_MOTION_TYPE_FLIP); + vec.push_back(HDF_MOTION_TYPE_SHAKE); + vec.push_back(HDF_MOTION_TYPE_ROTATION); + + // 2.订阅手势识别数据回调函数 + int32_t ret = g_motionInterface->Register(g_motionCallback); + EXPECT_EQ(HDF_SUCCESS, ret); + + for (int i = 0; i < vec.size(); i++) { + // 3.使能手势识别 + ret = g_motionInterface->EnableMotion(vec[i]); + if (ret == HDF_SUCCESS) { + printf("Motion %d enabled successfully\n", vec[i]); + } else { + printf("Motion %d enable failed\n", vec[i]); + } + EXPECT_EQ(HDF_SUCCESS, ret); + OsalSleep(15); + // 4.去使能手势识别 + ret = g_motionInterface->DisableMotion(vec[i]); + if (ret == HDF_SUCCESS) { + printf("Motion %d disabled successfully\n", vec[i]); + } else { + printf("Motion %d disable failed\n", vec[i]); + } + EXPECT_EQ(HDF_SUCCESS, ret); + OsalSleep(2); + } + // 5.取消订阅手势识别数据回调函数 + ret = g_motionInterface->Unregister(g_motionCallback); + EXPECT_EQ(HDF_SUCCESS, ret); + } + ``` + \ No newline at end of file diff --git "a/zh-cn/device-dev/driver/figures/\346\211\213\345\212\277\350\257\206\345\210\253\351\251\261\345\212\250\346\241\206\346\236\266.png" "b/zh-cn/device-dev/driver/figures/\346\211\213\345\212\277\350\257\206\345\210\253\351\251\261\345\212\250\346\241\206\346\236\266.png" new file mode 100644 index 0000000000000000000000000000000000000000..2369adacb1beb70cf7aabbfd9705098d9c18a006 GIT binary patch literal 12017 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 literal 0 HcmV?d00001 -- GitLab