driver-peripherals-vibrator-des.md 23.8 KB
Newer Older
Mr-YX's avatar
Mr-YX 已提交
1 2 3 4 5 6
# Vibrator

## 概述

### 功能简介

7
为了快速开发马达驱动,基于HDF(Hardware Driver Foundation)驱动框架开发了马达(Vibrator)驱动模型。马达驱动模型,屏蔽设备驱动与系统交互的实现,为硬件服务层提供统一稳定的驱动接口能力,为驱动开发者提供开放的接口和解析接口的能力,用于不同操作系统马达设备部件的部署指导和马达设备部件驱动的开发。马达驱动模型如图1所示:
Mr-YX's avatar
Mr-YX 已提交
8 9 10 11 12 13 14

**图 1** 马达驱动模型图

![Vibrator驱动模型图](figures/Vibrator驱动模型图.png)

### 基本概念

15 16 17 18 19 20 21 22 23 24 25
根据振动原理的不同,目前马达可以分为两种:

- 转子马达

  转子马达依靠旋转带动配重振动,分为普通转子和币型转子两种。转子马达的启停反应慢,并且无法实现多种振动模式,但其优点是成本低且体积小。

- 线性马达

  线性马达依靠磁力快速抖动配重来振动,分为纵向线性马达和横向线性马达两种。线性马达的启停都非常快,可以实现不同振感且具有良好的方向性。

系统通过调用马达驱动接口实现对设备的振动控制。目前,马达只有两种振动方式:
Mr-YX's avatar
Mr-YX 已提交
26 27 28 29 30 31 32

- 单次振动

  单次振动是指按照指定的时间控制振动时长。

- 周期振动

33
  周期振动是指按照预置的效果模式控制振动。例如:预置效果为“haptic.clock.timer” = [600, 600, 200, 600],表示等待600ms,振动600ms,等待200ms,振动600ms。
Mr-YX's avatar
Mr-YX 已提交
34 35 36 37 38 39 40 41 42

### 运作机制

通过介绍马达驱动模型的加载以及运行流程,对模型内部关键组件以及关联组件之间的关系进行了划分,整体加载流程如图2所示:

**图2** 马达驱动运行图

![Vibrator驱动运行图](figures/Vibrator驱动运行图.png)

43
以标准系统Hi3516DV300产品为例,介绍马达模块驱动加载及运行流程:
Mr-YX's avatar
Mr-YX 已提交
44

45 46 47 48 49 50 51 52 53 54
1. Device Manager从device_info.hcs配置文件中读取Vibrator管理配置信息。
2. HCS Parser解析Vibrator管理配置信息,并加载对应的马达抽象驱动。
3. Device Manager从linear_vibrator_config.hcs配置文件中读取Vibrator数据配置信息。
4. HCS Parser解析Vibrator数据配置信息,并加载对应的Haptic驱动。
5. Vibrator Proxy获取到Vibrator HDI接口服务实例后,通过IPC(Inter-Process Communication)调用到Vibrator Stub。
6. Vibrator Stub主要处理与IPC相关的业务逻辑,完成参数反序列化后调用Vibrator Controller。
7. Vibrator Controller中是HDI接口的真正实现,通过IPC调用Vibrator抽象驱动接口。
8. 在Haptic驱动中起线程,解析效果模块。
9. Haptic驱动调用马达抽象驱动中的Start接口。
10. 马达抽象驱动进一步调用马达差异化驱动中的Start接口,控制马达设备以给定的效果振动。
Mr-YX's avatar
Mr-YX 已提交
55 56 57 58 59 60 61 62 63

## 开发指导

### 场景介绍

当设备需要设置不同的振动效果时,可以调用Vibrator模块,例如,设备的按键可以设置不同强度和时长的振动,闹钟和来电可以设置不同强度和时长的单次或周期性振动。

### 接口说明

64
马达驱动模型支持静态HCS配置和动态参数两种振动效果配置能力。马达硬件服务调用StartOnce接口动态配置持续振动,调用Start接口启动静态配置的振动效果。马达驱动模型对外开放的API接口能力,如下表所示。
Mr-YX's avatar
Mr-YX 已提交
65 66 67 68 69

**表 1** 马达驱动模型对外API接口能力介绍

| 接口名                                  | 功能描述                                           |
| -------------------------------------- | ------------------------------------------------ |
70 71 72 73 74
| int32_t (*StartOnce)([in] uint32_t duration)                        | 控制马达以执行给定持续时间的单次振动,duration表示单次振动的持续时间。       |
| int32_t (*Start)([in] const char *effectType)                        | 控制马达以预置效果执行周期性振动,effectType表示指向预设效果类型的指针。     |
| int32_t (*Stop)([in] enum VibratorMode mode)                         | 停止马达振动,mode表示振动模式,可以是单次或周期性的。                             |
| int32_t (*EnableVibratorModulation)(uint32_t duration, int32_t intensity, int32_t frequency) | 根据传入的振动效果启动马达,duration表示马达振动的持续时间,intensity表示振动周期内的马达振幅,frequency表示振动周期内的马达频率。 |
| int32_t (*GetVibratorInfo)([out] struct VibratorInfo **vibratorInfo) | 获取系统中支持设置振幅和频率的所有马达信息,vibratorInfo表示指向马达信息的指针。 |
Mr-YX's avatar
Mr-YX 已提交
75 76 77 78 79

### 开发步骤

Vibrator驱动模型为上层马达硬件服务层提供稳定的马达控制能力接口,包括马达一次振动、马达效果配置震动、马达停止。基于HDF驱动框架开发的马达驱动模型,实现跨操作系统迁移、器件差异配置等功能。具体的开发步骤如下:

80
1. 基于HDF驱动框架,按照驱动Driver Entry程序,完成马达抽象驱动开发(主要由Bind、Init、Release、Dispatch函数接口实现),配置资源和HCS解析。
Mr-YX's avatar
Mr-YX 已提交
81

82
   - 调用HDF_INIT将驱动入口注册到HDF框架中。在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出马达驱动模型,使用HCS作为配置描述源码。HCS配置字段详细介绍参考[配置管理](driver-hdf-manage.md)。其中Driver Entry入口函数定义如下:
Mr-YX's avatar
Mr-YX 已提交
83 84 85 86

     ```c
     /* 注册马达抽象驱动入口数据结构体对象 */
     struct HdfDriverEntry g_vibratorDriverEntry = {
87 88 89 90
         .moduleVersion = 1,               // 马达模块版本号
         .moduleName = "HDF_VIBRATOR",     // 马达模块名,要与device_info.hcs文件里的马达moduleName字段值一样
         .Bind = BindVibratorDriver,       // 马达绑定函数
         .Init = InitVibratorDriver,       // 马达初始化函数
Mr-YX's avatar
Mr-YX 已提交
91 92
         .Release = ReleaseVibratorDriver, // 马达资源释放函数
     };
93
     /* 调用HDF_INIT将驱动入口注册到HDF框架中 */
Mr-YX's avatar
Mr-YX 已提交
94 95 96 97 98 99 100 101 102 103 104
     HDF_INIT(g_vibratorDriverEntry);
     ```

   - 基于HDF驱动框架,按照驱动Driver Entry程序,完成马达抽象驱动开发,主要由Bind、Init、Release、Dispatch函数接口实现。

     ```c
     /* 马达驱动对外发布的能力 */
     static int32_t DispatchVibrator(struct HdfDeviceIoClient *client,
         int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
     {
         int32_t loop;
105

Mr-YX's avatar
Mr-YX 已提交
106 107 108 109 110
         for (loop = 0; loop < sizeof(g_vibratorCmdHandle) / sizeof(g_vibratorCmdHandle[0]); ++loop) {
             if ((cmd == g_vibratorCmdHandle[loop].cmd) && (g_vibratorCmdHandle[loop].func != NULL)) {
                 return g_vibratorCmdHandle[loop].func(data, reply);
             }
         }
111

Mr-YX's avatar
Mr-YX 已提交
112 113 114 115 116 117 118 119
         return HDF_SUCCESS;
     }
     
     /* 马达驱动对外提供的服务绑定到HDF框架 */
     int32_t BindVibratorDriver(struct HdfDeviceObject *device)
     {
         struct VibratorDriverData *drvData = NULL;
         CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(device, HDF_FAILURE);
120

Mr-YX's avatar
Mr-YX 已提交
121 122
         drvData = (struct VibratorDriverData *)OsalMemCalloc(sizeof(*drvData));
         CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_MALLOC_FAIL);
123

Mr-YX's avatar
Mr-YX 已提交
124 125 126 127
         drvData->ioService.Dispatch = DispatchVibrator;
         drvData->device = device;
         device->service = &drvData->ioService;
         g_vibratorDrvData = drvData;
128

Mr-YX's avatar
Mr-YX 已提交
129 130
         return HDF_SUCCESS;
     }
131

Mr-YX's avatar
Mr-YX 已提交
132 133 134 135
     /* 马达驱动初始化入口函数*/
     int32_t InitVibratorDriver(struct HdfDeviceObject *device)
     {
         struct VibratorDriverData *drvData = NULL;
136

Mr-YX's avatar
Mr-YX 已提交
137 138 139 140
         drvData->mode = VIBRATOR_MODE_BUTT;
         drvData->state = VIBRATOR_STATE_IDLE;
         ......
         if (CreateVibratorHaptic(device) != HDF_SUCCESS) {
141
             HDF_LOGE("%s: init workQueue failed!", __func__);
Mr-YX's avatar
Mr-YX 已提交
142 143
             return HDF_FAILURE;
         }
144

Mr-YX's avatar
Mr-YX 已提交
145 146
         return HDF_SUCCESS;
     }
147

Mr-YX's avatar
Mr-YX 已提交
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
     /* 释放马达驱动初始化时分配的资源 */
     void ReleaseVibratorDriver(struct HdfDeviceObject *device)
     {
         struct VibratorDriverData *drvData = NULL;
         ......
         (void)DestroyVibratorHaptic();
         (void)OsalMutexDestroy(&drvData->mutex);
         (void)OsalMemFree(drvData);
         g_vibratorDrvData = NULL;
     }
     ```

   - 在系统启动过程中,HDF设备管理模块通过设备HCS配置信息,加载马达抽象驱动,并对外发布马达驱动接口。

     ```c
     /* 马达设备HCS配置 */
     vibrator :: host {
165 166 167 168 169 170 171 172 173 174 175 176 177
         hostName = "vibrator_host";
         device_vibrator :: device {
             device0 :: deviceNode {
                 policy = 2;                              // 驱动服务发布的策略
                 priority = 100;                          // 驱动启动优先级(0-200),值越大优先级越低,建议配置100,优先级相同则不保证device的加载顺序
                 preload = 0;                             // 驱动按需加载字段,0表示加载,2表示不加载
                 permission = 0664;                       // 驱动创建设备节点权限
                 moduleName = "HDF_VIBRATOR";             // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致
                 serviceName = "hdf_misc_vibrator";       // 驱动对外发布服务的名称,必须唯一
                 deviceMatchAttr = "hdf_vibrator_driver"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等
            }
        }
     }
Mr-YX's avatar
Mr-YX 已提交
178 179 180 181 182 183
     ```

2. 创建马达效果模型,解析马达效果HCS配置。

   - 创建马达效果模型。

184
     ```c
Mr-YX's avatar
Mr-YX 已提交
185 186 187 188 189 190 191 192 193 194 195 196
     /* 创建马达效果模型,分配资源,解析马达效果HCS配置 */
     int32_t CreateVibratorHaptic(struct HdfDeviceObject *device)
     {
         struct VibratorHapticData *hapticData = NULL;
         CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(device, HDF_FAILURE);
     
         hapticData = (struct VibratorHapticData *)OsalMemCalloc(sizeof(*hapticData));
         CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(hapticData, HDF_ERR_MALLOC_FAIL);
         g_vibratorHapticData = hapticData;
         hapticData->supportHaptic = false;
     
         if (OsalMutexInit(&hapticData->mutex) != HDF_SUCCESS) {
197
             HDF_LOGE("%s: failed to init mutex", __func__);
Mr-YX's avatar
Mr-YX 已提交
198 199 200 201 202 203 204
             goto EXIT;
         }
     
         DListHeadInit(&hapticData->effectSeqHead);
     
         /* 解析马达效果HCS配置 */
         if (ParserVibratorHapticConfig(device->property) != HDF_SUCCESS) {
205
             HDF_LOGE("%s: parser haptic config failed!", __func__);
Mr-YX's avatar
Mr-YX 已提交
206 207 208 209 210 211 212 213 214 215
             goto EXIT;
         }
     
         return HDF_SUCCESS;
     EXIT:
         OsalMemFree(hapticData);
         return HDF_FAILURE;
     }
     ```

216
   - 马达效果模型使用HCS作为配置描述源码,HCS配置文件字段详细介绍参考[配置管理](driver-hdf-manage.md)
Mr-YX's avatar
Mr-YX 已提交
217

218
     ```c
Mr-YX's avatar
Mr-YX 已提交
219 220 221 222
     /* 马达数据配置模板(vibrator_config.hcs) */
     root {
         vibratorConfig {
             boardConfig {
223
                 match_attr = "hdf_vibrator_driver"; // 需要和马达设备配置文件中的match_attr字段保持一致
Mr-YX's avatar
Mr-YX 已提交
224 225
                 vibratorAttr {
                     /* 0:转子;1:线性 */
226 227
                     deviceType = 1;                 // 设备类型
                     supportPreset = 1;              // 支持的预设类型
Mr-YX's avatar
Mr-YX 已提交
228 229 230 231
                 }
                 vibratorHapticConfig {
                     haptic_clock_timer {
                         effectName = "haptic.clock.timer";
232
                         type = 1;                   // 0:内置模式;1:时间序列
Mr-YX's avatar
Mr-YX 已提交
233 234 235 236 237 238 239 240 241 242 243 244 245
                         seq = [600, 600, 200, 600]; // 时间序列
                     }
                     haptic_default_effect {
                         effectName = "haptic.default.effect";
                         type = 0;
                         seq = [0, 3, 800, 1];
                     }
                 }
             }
         }
     }
     ```

246
3. 完成马达信息获取、振动模式设置和停止的接口开发,并实现根据振动模式创建和销毁定时器。
Mr-YX's avatar
Mr-YX 已提交
247

248
   马达硬件服务调用StartOnce接口动态配置持续振动时间,调用StartEffect接口启动静态配置的振动效果,为驱动开发者提供抽象的配置接口能力。
Mr-YX's avatar
Mr-YX 已提交
249 250

   ```c
251
   /* 按照指定持续时间触发振动马达,duration为振动持续时长。 */
Mr-YX's avatar
Mr-YX 已提交
252 253 254 255 256 257 258 259 260 261 262 263 264 265
   static int32_t StartOnce(struct HdfSBuf *data, struct HdfSBuf *reply)
   {
       uint32_t duration;
       int32_t ret;
       struct VibratorEffectCfg config;
       struct VibratorDriverData *drvData = GetVibratorDrvData();
       (void)reply;
       ...... 
       config.cfgMode = VIBRATOR_MODE_ONCE;
       config.duration = duration;
       config.effect = NULL;
       /* 根据振动效果的模式创建定时器 */
       ret = StartHaptic(&config);
       if (ret != HDF_SUCCESS) {
266
           HDF_LOGE("%s: start haptic failed!", __func__);
Mr-YX's avatar
Mr-YX 已提交
267 268 269 270 271 272
           return ret;
       }
   
       return HDF_SUCCESS;
   }
   
273
   /* 按照预置效果启动马达,effectType表示预置的振动效果。 */
Mr-YX's avatar
Mr-YX 已提交
274 275 276 277 278 279 280 281 282 283 284 285 286 287
   static int32_t StartEffect(struct HdfSBuf *data, struct HdfSBuf *reply)
   {
       int32_t ret;
       const char *effect = NULL;
       struct VibratorEffectCfg config;
       struct VibratorDriverData *drvData = GetVibratorDrvData();
       (void)reply;
       ......
       config.cfgMode = VIBRATOR_MODE_PRESET;
       config.duration = 0;
       config.effect = effect;
   
       ret = StartHaptic(&config);
       if (ret != HDF_SUCCESS) {
288
           HDF_LOGE("%s: start haptic failed!", __func__);
Mr-YX's avatar
Mr-YX 已提交
289 290 291 292 293 294 295 296 297 298 299 300 301 302
           return ret;
       }
   
       return HDF_SUCCESS;
   }
   
   /* 按照指定的振动模式停止马达振动 */
   static int32_t Stop(struct HdfSBuf *data, struct HdfSBuf *reply)
   {
       int32_t ret;
       int32_t mode;
       struct VibratorDriverData *drvData = GetVibratorDrvData();
       (void)reply;
       ......
303
       /* 停止马达效果振动,销毁马达定时器。 */
Mr-YX's avatar
Mr-YX 已提交
304 305
       ret = StopHaptic();
       if (ret != HDF_SUCCESS) {
306
           HDF_LOGE("%s: stop haptic failed!", __func__);
Mr-YX's avatar
Mr-YX 已提交
307 308 309 310 311 312 313 314 315
           return ret;
       }
   
       (void)OsalMutexLock(&drvData->mutex);
       drvData->mode = VIBRATOR_MODE_BUTT;
       (void)OsalMutexUnlock(&drvData->mutex);
   
       return HDF_SUCCESS;
   }
316 317 318 319 320 321 322 323 324 325 326
   
   /* 按照指定振幅、频率、持续时间触发振动马达。duration为振动持续时长,intensity为振动强度,frequency为振动频率。 */
   static int32_t EnableModulationParameter(struct HdfSBuf *data, struct HdfSBuf *reply)
   {
       (void)reply;
       struct VibratorEffectCfg config;
       struct VibratorDriverData *drvData;
       uint32_t duration;
       int32_t intensity;
       int32_t frequency;
       int32_t ret;
327
       .....
328 329 330
       (void)OsalMutexLock(&drvData->mutex);
       drvData->mode = VIBRATOR_MODE_ONCE;
       (void)OsalMutexUnlock(&drvData->mutex);
331
       /* 设置振幅和频率 */
332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
       ret = drvData->ops.SetParameter(intensity, frequency);
       if (ret != HDF_SUCCESS) {
           HDF_LOGE("%s: set parameter failed", __func__);
           return HDF_FAILURE;
       }
   
       config.cfgMode = VIBRATOR_MODE_ONCE;
       config.duration = duration;
       config.effect = NULL;
   
       ret = StartHaptic(&config);
       if (ret != HDF_SUCCESS) {
           HDF_LOGE("%s: start haptic failed", __func__);
           return HDF_FAILURE;
       }
   
       return HDF_SUCCESS;
   }
   
   /* 获取马达信息,包括是否支持振幅和频率的设置及振幅和频率的设置范围。 */
   static int32_t GetVibratorInfo(struct HdfSBuf *data, struct HdfSBuf *reply)
   {
       (void)data;
       struct VibratorDriverData *drvData;
   
       drvData = GetVibratorDrvData();
       CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
       CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(reply, HDF_ERR_INVALID_PARAM);
   
       if (!HdfSbufWriteBuffer(reply, &drvData->vibratorInfo, sizeof(drvData->vibratorInfo))) {
           HDF_LOGE("%s: write sbuf failed", __func__);
           return HDF_FAILURE;
       }
   
       return HDF_SUCCESS;
   }
Mr-YX's avatar
Mr-YX 已提交
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386
   ```

4. 马达驱动模型提供给开发者马达驱动差异化接口,开发者实现差异化接口。

   - 在差异化器件驱动初始化成功时,注册差异实现接口,方便实现器件差异的驱动接口。

     ```c
     /* 注册马达差异化实现接口 */
     int32_t RegisterVibrator(struct VibratorOps *ops)
     {
         struct VibratorDriverData *drvData = GetVibratorDrvData();
     
         CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(ops, HDF_FAILURE);
         CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE);
     
         (void)OsalMutexLock(&drvData->mutex);
         drvData->ops.Start = ops->Start;
         drvData->ops.StartEffect = ops->StartEffect;
         drvData->ops.Stop = ops->Stop;
387 388 389 390 391 392 393
         drvData->ops.SetParameter = ops->SetParameter;
         (void)OsalMutexUnlock(&drvData->mutex);
     
         return HDF_SUCCESS;
     }
     
     /* 注册马达信息接口 */
394
     int32_t RegisterVibratorInfo(struct VibratorInfo *vibratorInfo)
395 396 397 398 399 400 401 402 403 404 405
     {
         struct VibratorDriverData *drvData = GetVibratorDrvData();
     
         CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(vibratorInfo, HDF_FAILURE);
         CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE);
     
         (void)OsalMutexLock(&drvData->mutex);
         if (memcpy_s(&drvData->vibratorInfo, sizeof(drvData->vibratorInfo), vibratorInfo, sizeof(*vibratorInfo)) != EOK) {
             HDF_LOGE("%s: Memcpy vibrator config failed", __func__);
             return HDF_FAILURE;
         }
Mr-YX's avatar
Mr-YX 已提交
406 407 408 409 410 411
         (void)OsalMutexUnlock(&drvData->mutex);
     
         return HDF_SUCCESS;
     }
     ```

412 413
     

Mr-YX's avatar
Mr-YX 已提交
414 415 416
   - 马达驱动模型提供给开发者马达驱动差异化接口,具体实现如下:

     ```c
417 418
     /* 按照指定的振动模式停止马达的振动 */
     static int32_t StopModulationParameter()
Mr-YX's avatar
Mr-YX 已提交
419
     {
420
         uint8_t value[DRV2605L_VALUE_BUTT];
421
         struct Drv2605lDriverData *drvData = NULL;
422 423
         drvData = GetDrv2605lDrvData();
     
424
         CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE);
425 426 427 428 429 430
         CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData->drv2605lCfgData, HDF_FAILURE);
     
         value[DRV2605L_ADDR_INDEX] = (uint8_t)DRV2605_REG_MODE;
         value[DRV2605L_VALUE_INDEX] = (uint8_t)DRV2605_MODE_STANDBY;
         if (WriteDrv2605l(&drvData->drv2605lCfgData->vibratorBus.i2cCfg, value, sizeof(value)) != HDF_SUCCESS) {
             HDF_LOGE("%s: i2c addr [%0X] write failed", __func__, value[DRV2605L_ADDR_INDEX]);
431
             return HDF_FAILURE;
432 433 434 435 436
         }
     
         value[DRV2605L_ADDR_INDEX] = (uint8_t)DRV2605_REG_RTPIN;
         value[DRV2605L_VALUE_INDEX] = (uint8_t)&drvData->drv2605lCfgData->vibratorAttr.defaultIntensity;
         if (WriteDrv2605l(&drvData->drv2605lCfgData->vibratorBus.i2cCfg, value, sizeof(value)) != HDF_SUCCESS) {
437
             HDF_LOGE("%s: i2c addr [%0X] write failed", __func__, value[DRV2605L_ADDR_INDEX]);
438 439 440 441 442
         }
     
         value[DRV2605L_ADDR_INDEX] = (uint8_t)DRV2605_REG_LRARESON;
         value[DRV2605L_VALUE_INDEX] = (uint8_t)&drvData->drv2605lCfgData->vibratorAttr.defaultFrequency;
         if (WriteDrv2605l(&drvData->drv2605lCfgData->vibratorBus.i2cCfg, value, sizeof(value)) != HDF_SUCCESS) {
443
             HDF_LOGE("%s: i2c addr [%0X] write failed", __func__, value[DRV2605L_ADDR_INDEX]);
Mr-YX's avatar
Mr-YX 已提交
444 445 446 447 448
         }
     
         return HDF_SUCCESS;
     }
     
449 450
     /* 设置马达振幅和频率 */
     static void SetModulationParameter(int32_t intensity, int32_t frequency)
Mr-YX's avatar
Mr-YX 已提交
451
     {
452
         uint8_t value[DRV2605L_VALUE_BUTT];
453
         struct Drv2605lDriverData *drvData = NULL;
454 455
         drvData = GetDrv2605lDrvData();
     
Mr-YX's avatar
Mr-YX 已提交
456
         CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE);
457 458 459 460 461 462 463 464 465 466
     
         if (intensity != 0) {
             value[DRV2605L_ADDR_INDEX] = (uint8_t)DRV2605_REG_RTPIN;
             value[DRV2605L_VALUE_INDEX] = (uint8_t)INTENSITY_MAPPING_VALUE(intensity);
             if (WriteDrv2605l(&drvData->drv2605lCfgData->vibratorBus.i2cCfg, value, sizeof(value)) != HDF_SUCCESS) {
                 HDF_LOGE("%s: i2c addr [%0X] write failed", __func__, value[DRV2605L_ADDR_INDEX]);
                 return;
             }
         } else {
             HDF_LOGD("%s: the setting of intensity 0 is not supported and \
467
                 will be set as the system default intensity", __func__);
468 469 470 471 472 473 474 475 476 477 478 479
         }
     
         if (frequency != 0) {
             value[DRV2605L_ADDR_INDEX] = (uint8_t)DRV2605_REG_LRARESON;
             value[DRV2605L_VALUE_INDEX] = (uint8_t)FREQUENCY_MAPPING_VALUE(frequency);
             if (WriteDrv2605l(&drvData->drv2605lCfgData->vibratorBus.i2cCfg, value, sizeof(value)) != HDF_SUCCESS) {
                 HDF_LOGE("%s: i2c addr [%0X] write failed", __func__, value[DRV2605L_ADDR_INDEX]);
                 return;
             }
         } else {
             HDF_LOGD("%s: the setting of frequency 0 is not supported and \
                 will be set as the system default frequency", __func__);
Mr-YX's avatar
Mr-YX 已提交
480 481
         }
     }
482 483 484 485
     ```

### 调测验证

486
驱动开发完成后,在马达单元测试里面开发自测试用例,验证驱动基本功能。测试环境采用开发者自测试平台。
487

488
```c++
489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564
/* 用例执行前,初始化马达接口实例。 */
void HdfVibratorTest::SetUpTestCase()
{
    g_vibratorDev = NewVibratorInterfaceInstance();
}
/* 用例资源释放 */
void HdfVibratorTest::TearDownTestCase()
{
    if(g_vibratorDev != nullptr){
        FreeVibratorInterfaceInstance();
        g_vibratorDev = nullptr;
    }
}

/* 测试单次振动 */
HWTEST_F(HdfVibratorTest, PerformOneShotVibratorDuration_001, TestSize.Level1)
{
    ASSERT_NE(nullptr, g_vibratorDev);

    int32_t startRet = g_vibratorDev->StartOnce(g_duration);
    EXPECT_EQ(startRet, HDF_SUCCESS);

    OsalMSleep(g_sleepTime1);

    int32_t endRet = g_vibratorDev->Stop(VIBRATOR_MODE_ONCE);
    EXPECT_EQ(endRet, HDF_SUCCESS);
}
/* 测试预置效果振动 */
HWTEST_F(HdfVibratorTest, ExecuteVibratorEffect_002, TestSize.Level1)
{
    ASSERT_NE(nullptr, g_vibratorDev);

    int32_t startRet = g_vibratorDev->Start(g_builtIn);
    EXPECT_EQ(startRet, HDF_SUCCESS);

    OsalMSleep(g_sleepTime1);

    int32_t endRet = g_vibratorDev->Stop(VIBRATOR_MODE_PRESET);
    EXPECT_EQ(endRet, HDF_SUCCESS);
}
/* 获取马达信息,包括是否支持振幅和频率的设置及振幅和频率的设置范围。 */
HWTEST_F(HdfVibratorTest, GetVibratorInfo_001, TestSize.Level1)
{
    ASSERT_NE(nullptr, g_vibratorDev);

    int32_t startRet = g_vibratorDev->GetVibratorInfo(&g_vibratorInfo);
    EXPECT_EQ(startRet, HDF_SUCCESS);
    EXPECT_NE(g_vibratorInfo, nullptr);

    printf("intensity = %d, intensityMaxValue = %d, intensityMinValue = %d\n\t",
    g_vibratorInfo->isSupportIntensity, g_vibratorInfo->intensityMaxValue, g_vibratorInfo->intensityMinValue);
    printf("frequency = %d, frequencyMaxValue = %d, frequencyMinValue = %d\n\t",
    g_vibratorInfo->isSupportFrequency, g_vibratorInfo->frequencyMaxValue, g_vibratorInfo->frequencyMinValue);
}
/* 按照指定振幅、频率、持续时间触发振动马达。duration为振动持续时长,intensity为振动强度,frequency为振动频率。 */
HWTEST_F(HdfVibratorTest, EnableVibratorModulation_001, TestSize.Level1)
{
    int32_t startRet;
    ASSERT_NE(nullptr, g_vibratorDev);
    EXPECT_GT(g_duration, 0);

    if ((g_vibratorInfo->isSupportIntensity == 1) || (g_vibratorInfo->isSupportFrequency == 1)) {
        EXPECT_GE(g_intensity1, g_vibratorInfo->intensityMinValue);
        EXPECT_LE(g_intensity1, g_vibratorInfo->intensityMaxValue);
        EXPECT_GE(g_frequency1, g_vibratorInfo->frequencyMinValue);
        EXPECT_LE(g_frequency1, g_vibratorInfo->frequencyMaxValue);

        startRet = g_vibratorDev->EnableVibratorModulation(g_duration, g_intensity1, g_frequency1);
        EXPECT_EQ(startRet, HDF_SUCCESS);
        OsalMSleep(g_sleepTime1);
        startRet = g_vibratorDev->Stop(VIBRATOR_MODE_ONCE);
        EXPECT_EQ(startRet, HDF_SUCCESS);
    }
}
```