1# Vibrator 2 3## 概述 4 5### 功能简介 6 7为了快速开发马达驱动,基于HDF(Hardware Driver Foundation)驱动框架开发了马达(Vibrator)驱动模型。马达驱动模型,屏蔽设备驱动与系统交互的实现,为硬件服务层提供统一稳定的驱动接口能力,为驱动开发者提供开放的接口和解析接口的能力,用于不同操作系统马达设备部件的部署指导和马达设备部件驱动的开发。马达驱动模型如图1所示: 8 9**图 1** 马达驱动模型图 10 11 12 13### 基本概念 14 15根据振动原理的不同,目前马达可以分为两种: 16 17- 转子马达 18 19 转子马达依靠旋转带动配重振动,分为普通转子和币型转子两种。转子马达的启停反应慢,并且无法实现多种振动模式,但其优点是成本低且体积小。 20 21- 线性马达 22 23 线性马达依靠磁力快速抖动配重来振动,分为纵向线性马达和横向线性马达两种。线性马达的启停都非常快,可以实现不同振感且具有良好的方向性。 24 25系统通过调用马达驱动接口实现对设备的振动控制。目前,马达只有两种振动方式: 26 27- 单次振动 28 29 单次振动是指按照指定的时间控制振动时长。 30 31- 周期振动 32 33 周期振动是指按照预置的效果模式控制振动。例如:预置效果为“haptic.clock.timer” = [600, 600, 200, 600],表示等待600ms,振动600ms,等待200ms,振动600ms。 34 35### 运作机制 36 37通过介绍马达驱动模型的加载以及运行流程,对模型内部关键组件以及关联组件之间的关系进行了划分,整体加载流程如图2所示: 38 39**图2** 马达驱动运行图 40 41 42 43以标准系统RK3568产品为例,介绍马达模块驱动加载及运行流程: 44 451. Device Manager从device_info.hcs配置文件中读取Vibrator管理配置信息。 462. HCS Parser解析Vibrator管理配置信息,并加载对应的马达抽象驱动。 473. Device Manager从linear_vibrator_config.hcs配置文件中读取Vibrator数据配置信息。 484. HCS Parser解析Vibrator数据配置信息,并加载对应的Haptic驱动。 495. Vibrator Proxy获取到Vibrator HDI接口服务实例后,通过IPC(Inter-Process Communication)调用到Vibrator Stub。 506. Vibrator Stub主要处理与IPC相关的业务逻辑,完成参数反序列化后调用Vibrator Controller。 517. Vibrator Controller中是HDI接口的真正实现,通过IPC调用Vibrator抽象驱动接口。 528. 在Haptic驱动中起线程,解析效果模块。 539. Haptic驱动调用马达抽象驱动中的Start接口。 5410. 马达抽象驱动进一步调用马达差异化驱动中的Start接口,控制马达设备以给定的效果振动。 55 56## 开发指导 57 58### 场景介绍 59 60当设备需要设置不同的振动效果时,可以调用Vibrator模块,例如,设备的按键可以设置不同强度和时长的振动,闹钟和来电可以设置不同强度和时长的单次或周期性振动。 61 62### 接口说明 63 64马达驱动模型支持静态HCS配置和动态参数两种振动效果配置能力。马达硬件服务调用StartOnce接口动态配置持续振动,调用Start接口启动静态配置的振动效果。马达驱动模型对外开放的API接口能力,如下表所示。 65 66**表 1** 马达驱动模型对外API接口能力介绍 67 68注:以下接口列举的为C接口,接口声明见文件[/drivers/peripheral/vibrator/interfaces/include](https://gitee.com/openharmony/drivers_peripheral/tree/master/vibrator/interfaces/include)。 69 70| 接口名 | 功能描述 | 71| -------------------------------------- | ------------------------------------------------ | 72| int32_t (*StartOnce)(uint32_t duration) | 控制马达以执行给定持续时间的单次振动,duration表示单次振动的持续时间。 | 73| int32_t (*Start)(const char *effectType) | 控制马达以预置效果执行周期性振动,effectType表示指向预设效果类型的指针。 | 74| int32_t (*Stop)(enum VibratorMode mode) | 停止马达振动,mode表示振动模式,可以是单次或周期性的。 | 75| int32_t (*EnableVibratorModulation)(uint32_t duration, int32_t intensity, int32_t frequency) | 根据传入的振动效果启动马达,duration表示马达振动的持续时间,intensity表示振动周期内的马达振幅,frequency表示振动周期内的马达频率。 | 76| int32_t (*GetVibratorInfo)(struct VibratorInfo **vibratorInfo) | 获取系统中支持设置振幅和频率的所有马达信息,vibratorInfo表示指向马达信息的指针。 | 77| int32_t (*EnableCompositeEffect)(struct CompositeEffect *effect); | 控制马达以自定义复合效果进行周期性振动。 | 78| int32_t (*GetEffectInfo)(const char *effectType, struct EffectInfo *effectInfo); | 获取指定效果类型的振动效果信息。 | 79| int32_t (*IsVibratorRunning)(bool state); | 获取到的马达当前是否正在振动。 | 80 81### 开发步骤 82 83Vibrator驱动模型为上层马达硬件服务层提供稳定的马达控制能力接口,包括马达一次振动、马达效果配置震动、马达停止。基于HDF驱动框架开发的马达驱动模型,实现跨操作系统迁移、器件差异配置等功能。以线性马达驱动为例介绍马达驱动开发。 84 851. 开发马达抽象驱动。 86 87 - 马达抽象驱动在Vibrator Host中的配置信息,代码实现路径如下:vendor\hihope\rk3568\hdf_config\khdf\device_info\device_info.hcs。 88 89 具体代码实现如下: 90 91 ```c 92 /* 马达设备HCS配置 */ 93 vibrator :: host { 94 hostName = "vibrator_host"; 95 device_vibrator :: device { 96 device0 :: deviceNode { 97 policy = 2; // 驱动服务发布的策略 98 priority = 100; // 驱动启动优先级(0-200),值越大优先级越低,建议配置100,优先级相同则不保证device的加载顺序 99 preload = 0; // 驱动按需加载字段,0表示加载,2表示不加载 100 permission = 0664; // 驱动创建设备节点权限 101 moduleName = "HDF_VIBRATOR"; // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 102 serviceName = "hdf_misc_vibrator"; // 驱动对外发布服务的名称,必须唯一 103 deviceMatchAttr = "hdf_vibrator_driver"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等 104 } 105 } 106 } 107 ``` 108 109 - 创建马达效果模型,解析马达效果HCS配置,代码实现路径:drivers\hdf_core\framework\model\misc\vibrator\driver\src\vibrator_haptic.c。 110 111 具体代码实现如下: 112 113 ```c 114 /* 创建马达效果模型 */ 115 int32_t CreateVibratorHaptic(struct HdfDeviceObject *device) 116 { 117 struct VibratorHapticData *hapticData = NULL; 118 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(device, HDF_FAILURE); 119 120 hapticData = (struct VibratorHapticData *)OsalMemCalloc(sizeof(*hapticData)); 121 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(hapticData, HDF_ERR_MALLOC_FAIL); 122 g_vibratorHapticData = hapticData; 123 hapticData->supportHaptic = false; 124 125 if (OsalMutexInit(&hapticData->mutex) != HDF_SUCCESS) { 126 HDF_LOGE("%s: fail to init mutex", __func__); 127 goto EXIT; 128 } 129 130 DListHeadInit(&hapticData->effectSeqHead); 131 132 // get haptic hcs 133 if (ParserVibratorHapticConfig(device->property) != HDF_SUCCESS) { 134 HDF_LOGE("%s: parser haptic config fail!", __func__); 135 goto EXIT; 136 } 137 138 return HDF_SUCCESS; 139 EXIT: 140 OsalMemFree(hapticData); 141 return HDF_FAILURE; 142 } 143 ``` 144 145 - 马达抽象驱动代码实现路径:drivers\hdf_core\framework\model\misc\vibrator\driver\src\vibrator_driver.c。 146 147 - 马达抽象驱动对应的HdfDriverEntry对象,其中,Driver Entry入口函数定义如下: 148 149 ```c 150 /* 注册马达抽象驱动入口数据结构体对象 */ 151 struct HdfDriverEntry g_vibratorDriverEntry = { 152 .moduleVersion = 1, // 马达模块版本号 153 .moduleName = "HDF_VIBRATOR", // 马达模块名,要与device_info.hcs文件里的马达moduleName字段值一样 154 .Bind = BindVibratorDriver, // 马达绑定函数 155 .Init = InitVibratorDriver, // 马达初始化函数 156 .Release = ReleaseVibratorDriver, // 马达资源释放函数 157 }; 158 /* 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出马达驱动模型 */ 159 HDF_INIT(g_vibratorDriverEntry); 160 ``` 161 162 - 马达抽象驱动Bind接口实现如下: 163 164 ```c 165 int32_t BindVibratorDriver(struct HdfDeviceObject *device) 166 { 167 struct VibratorDriverData *drvData = NULL; 168 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(device, HDF_FAILURE); 169 170 drvData = (struct VibratorDriverData *)OsalMemCalloc(sizeof(*drvData)); 171 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_MALLOC_FAIL); 172 173 drvData->ioService.Dispatch = DispatchVibrator; 174 drvData->device = device; 175 device->service = &drvData->ioService; 176 g_vibratorDrvData = drvData; 177 178 return HDF_SUCCESS; 179 } 180 ``` 181 182 - 马达抽象驱动Init接口实现如下: 183 184 ```c 185 int32_t InitVibratorDriver(struct HdfDeviceObject *device) 186 { 187 struct VibratorDriverData *drvData = NULL; 188 189 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(device, HDF_FAILURE); 190 drvData = (struct VibratorDriverData *)device->service; 191 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE); 192 193 drvData->mode = VIBRATOR_MODE_BUTT; 194 drvData->state = VIBRATOR_STATE_IDLE; 195 196 if (OsalMutexInit(&drvData->mutex) != HDF_SUCCESS) { 197 HDF_LOGE("%s: init mutex failed!", __func__); 198 return HDF_FAILURE; 199 } 200 /* 工作队列资源初始化 */ 201 if (HdfWorkQueueInit(&drvData->workQueue, VIBRATOR_WORK_QUEUE_NAME) != HDF_SUCCESS) { 202 HDF_LOGE("%s: init workQueue failed!", __func__); 203 return HDF_FAILURE; 204 } 205 206 if (HdfWorkInit(&drvData->work, VibratorWorkEntry, (void*)drvData) != HDF_SUCCESS) { 207 HDF_LOGE("%s: init workQueue failed!", __func__); 208 return HDF_FAILURE; 209 } 210 /* 创建马达效果模型初始化 */ 211 if (CreateVibratorHaptic(device) != HDF_SUCCESS) { 212 HDF_LOGE("%s: create vibrator haptic failed!", __func__); 213 return HDF_FAILURE; 214 } 215 216 return HDF_SUCCESS; 217 } 218 ``` 219 220 - 马达抽象驱动Release接口在驱动卸载或者Init执行失败时,会调用此接口释放资源,具体实现如下: 221 222 ```c 223 void ReleaseVibratorDriver(struct HdfDeviceObject *device) 224 { 225 struct VibratorDriverData *drvData = NULL; 226 227 if (device == NULL) { 228 HDF_LOGE("%s: device is null!", __func__); 229 return; 230 } 231 232 drvData = (struct VibratorDriverData *)device->service; 233 if (drvData == NULL) { 234 HDF_LOGE("%s: drvData is null!", __func__); 235 return; 236 } 237 238 (void)DestroyVibratorHaptic(); 239 (void)OsalMutexDestroy(&drvData->mutex); 240 OsalMemFree(drvData); 241 g_vibratorDrvData = NULL; 242 } 243 ``` 244 245 - 马达抽象驱动内部接口实现了马达信息获取、振动模式设置和停止等功能,并实现根据振动模式创建和销毁定时器。 246 247 - 马达抽象驱动StartOnce接口实现如下: 248 249 ```c 250 /* 按照指定持续时间触发振动马达,duration为振动持续时长 */ 251 static int32_t StartOnce(struct HdfSBuf *data, struct HdfSBuf *reply) 252 { 253 uint32_t duration; 254 int32_t ret; 255 struct VibratorEffectCfg config; 256 struct VibratorDriverData *drvData = GetVibratorDrvData(); 257 (void)reply; 258 259 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(data, HDF_FAILURE); 260 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE); 261 262 if (!HdfSbufReadUint32(data, &duration)) { 263 HDF_LOGE("%s: sbuf read duration failed!", __func__); 264 return HDF_FAILURE; 265 } 266 267 if (duration == 0) { 268 HDF_LOGE("%s: vibrator duration invalid para!", __func__); 269 return HDF_ERR_INVALID_PARAM; 270 } 271 272 if (drvData->mode != VIBRATOR_MODE_BUTT) { 273 HDF_LOGI("%s: vibrater haptic is busy now, please stop first!", __func__); 274 return HDF_ERR_DEVICE_BUSY; 275 } 276 277 (void)OsalMutexLock(&drvData->mutex); 278 drvData->mode = VIBRATOR_MODE_ONCE; 279 (void)OsalMutexUnlock(&drvData->mutex); 280 281 config.cfgMode = VIBRATOR_MODE_ONCE; 282 config.duration = duration; 283 config.effect = NULL; 284 /* 根据振动效果的模式开启马达效果模型 */ 285 ret = StartHaptic(&config); 286 if (ret != HDF_SUCCESS) { 287 HDF_LOGE("%s: start haptic failed!", __func__); 288 return ret; 289 } 290 291 return HDF_SUCCESS; 292 } 293 ``` 294 295 - 马达抽象驱动StartEffect接口实现如下: 296 297 ```c 298 /* 按照预置效果启动马达,effect表示预置的振动效果 */ 299 static int32_t StartEffect(struct HdfSBuf *data, struct HdfSBuf *reply) 300 { 301 int32_t ret; 302 const char *effect = NULL; 303 struct VibratorEffectCfg config; 304 struct VibratorDriverData *drvData = GetVibratorDrvData(); 305 (void)reply; 306 307 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(data, HDF_FAILURE); 308 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE); 309 /* 从HdfSBuf中读取出预置的振动效果,进而操作马达振动 */ 310 effect = HdfSbufReadString(data); 311 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(effect, HDF_FAILURE); 312 313 if (drvData->mode != VIBRATOR_MODE_BUTT) { 314 HDF_LOGI("%s: vibrater haptic is busy now, please stop first!", __func__); 315 return HDF_ERR_DEVICE_BUSY; 316 } 317 318 (void)OsalMutexLock(&drvData->mutex); 319 drvData->mode = VIBRATOR_MODE_PRESET; 320 (void)OsalMutexUnlock(&drvData->mutex); 321 322 // start once time vibrate 323 config.cfgMode = VIBRATOR_MODE_PRESET; 324 config.duration = 0; 325 config.effect = effect; 326 /* 预置效果启动马达 */ 327 ret = StartHaptic(&config); 328 if (ret != HDF_SUCCESS) { 329 HDF_LOGE("%s: start haptic failed!", __func__); 330 return ret; 331 } 332 333 return HDF_SUCCESS; 334 } 335 ``` 336 337 - 马达抽象驱动Stop接口实现如下: 338 339 ```c 340 /* 按照指定的振动模式停止马达振动 */ 341 static int32_t Stop(struct HdfSBuf *data, struct HdfSBuf *reply) 342 { 343 int32_t ret; 344 int32_t mode; 345 struct VibratorDriverData *drvData = GetVibratorDrvData(); 346 (void)reply; 347 348 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(data, HDF_FAILURE); 349 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE); 350 /* 从HdfSBuf中读取指定的振动模式,进而操作马达停止振动 */ 351 if (!HdfSbufReadInt32(data, &mode)) { 352 HDF_LOGE("%s: sbuf read mode failed!", __func__); 353 return HDF_FAILURE; 354 } 355 356 if ((mode != VIBRATOR_MODE_ONCE) && (mode != VIBRATOR_MODE_PRESET)) { 357 HDF_LOGE("%s: vibrator stop mode failed!", __func__); 358 return HDF_FAILURE; 359 } 360 361 if (drvData->mode == VIBRATOR_MODE_BUTT) { 362 HDF_LOGD("%s: vibrater haptic had stopped!", __func__); 363 return HDF_SUCCESS; 364 } 365 /* 停止马达效果振动,销毁马达定时器 */ 366 ret = StopHaptic(); 367 if (ret != HDF_SUCCESS) { 368 HDF_LOGE("%s: stop haptic failed!", __func__); 369 return ret; 370 } 371 372 (void)OsalMutexLock(&drvData->mutex); 373 drvData->mode = VIBRATOR_MODE_BUTT; 374 (void)OsalMutexUnlock(&drvData->mutex); 375 376 return HDF_SUCCESS; 377 } 378 ``` 379 380 - 马达抽象驱动GetVibratorInfo接口实现如下: 381 382 ```c 383 /* 获取马达信息,包括是否支持振幅和频率的设置及振幅和频率的设置范围 */ 384 static int32_t GetVibratorInfo(struct HdfSBuf *data, struct HdfSBuf *reply) 385 { 386 (void)data; 387 struct VibratorDriverData *drvData; 388 389 drvData = GetVibratorDrvData(); 390 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM); 391 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(reply, HDF_ERR_INVALID_PARAM); 392 393 if (!HdfSbufWriteBuffer(reply, &drvData->vibratorInfo, sizeof(drvData->vibratorInfo))) { 394 HDF_LOGE("%s: write sbuf failed!", __func__); 395 return HDF_FAILURE; 396 } 397 398 return HDF_SUCCESS; 399 } 400 ``` 401 402 - 马达抽象驱动EnableModulationParameter接口实现如下: 403 404 ```c 405 /* 按照指定振幅、频率、持续时间触发振动马达。duration为振动持续时长,intensity为振动强度,frequency为振动频率 */ 406 static int32_t EnableModulationParameter(struct HdfSBuf *data, struct HdfSBuf *reply) 407 { 408 (void)reply; 409 struct VibratorEffectCfg config; 410 struct VibratorDriverData *drvData; 411 uint32_t duration; 412 uint16_t intensity; 413 int16_t frequency; 414 int32_t ret; 415 416 drvData = GetVibratorDrvData(); 417 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM); 418 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData->ops.SetParameter, HDF_ERR_INVALID_PARAM); 419 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM); 420 421 if (drvData->mode != VIBRATOR_MODE_BUTT) { 422 HDF_LOGE("%s: vibrater is busy now, please stop first!", __func__); 423 return HDF_ERR_DEVICE_BUSY; 424 } 425 426 if (!HdfSbufReadUint32(data, &duration)) { 427 HDF_LOGE("%s: sbuf read vibration period failed!", __func__); 428 return HDF_FAILURE; 429 } 430 431 if (!HdfSbufReadUint16(data, &intensity)) { 432 HDF_LOGE("%s: sbuf read intensity failed!", __func__); 433 return HDF_FAILURE; 434 } 435 436 if (!HdfSbufReadInt16(data, &frequency)) { 437 HDF_LOGE("%s: sbuf read frequency failed!", __func__); 438 return HDF_FAILURE; 439 } 440 441 (void)OsalMutexLock(&drvData->mutex); 442 drvData->mode = VIBRATOR_MODE_ONCE; 443 (void)OsalMutexUnlock(&drvData->mutex); 444 445 ret = drvData->ops.SetParameter(intensity, frequency); 446 if (ret != HDF_SUCCESS) { 447 HDF_LOGE("%s: set parameter failed!", __func__); 448 return HDF_FAILURE; 449 } 450 451 config.cfgMode = VIBRATOR_MODE_ONCE; 452 config.duration = duration; 453 config.effect = NULL; 454 /* 预置效果启动马达 */ 455 ret = StartHaptic(&config); 456 if (ret != HDF_SUCCESS) { 457 HDF_LOGE("%s: start haptic failed!", __func__); 458 return HDF_FAILURE; 459 } 460 461 return HDF_SUCCESS; 462 } 463 ``` 464 465 - 在马达差异化器件驱动初始化成功时,注册差异化接口,方便实现马达器件差异化驱动接口,具体实现如下: 466 467 ```c 468 /* 注册马达差异化实现接口 */ 469 int32_t RegisterVibrator(struct VibratorOps *ops) 470 { 471 struct VibratorDriverData *drvData = GetVibratorDrvData(); 472 473 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(ops, HDF_FAILURE); 474 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE); 475 476 (void)OsalMutexLock(&drvData->mutex); 477 drvData->ops.Start = ops->Start; 478 drvData->ops.StartEffect = ops->StartEffect; 479 drvData->ops.Stop = ops->Stop; 480 drvData->ops.SetParameter = ops->SetParameter; 481 (void)OsalMutexUnlock(&drvData->mutex); 482 483 return HDF_SUCCESS; 484 } 485 486 /* 注册马达信息接口 */ 487 int32_t RegisterVibratorInfo(struct VibratorInfo *vibratorInfo) 488 { 489 struct VibratorDriverData *drvData = GetVibratorDrvData(); 490 491 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(vibratorInfo, HDF_FAILURE); 492 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE); 493 494 (void)OsalMutexLock(&drvData->mutex); 495 if (memcpy_s(&drvData->vibratorInfo, sizeof(drvData->vibratorInfo), vibratorInfo, sizeof(*vibratorInfo)) != EOK) { 496 HDF_LOGE("%s: Memcpy vibrator config failed", __func__); 497 return HDF_FAILURE; 498 } 499 (void)OsalMutexUnlock(&drvData->mutex); 500 501 return HDF_SUCCESS; 502 } 503 ``` 504 5051. 开发马达差异化驱动。 506 507 - 马达差异化驱动在Vibrator Host中的配置信息,代码实现路径如下:vendor\hihope\rk3568\hdf_config\khdf\device_info\device_info.hcs。 508 509 具体代码实现如下: 510 511 ```c 512 device_linear_vibrator :: device { 513 device0 :: deviceNode { 514 policy = 1; // 驱动服务发布的策略 515 priority = 105; // 驱动启动优先级(0-200),值越大优先级越低,建议配置100,优先级相同则不保证device的加载顺序 516 preload = 0; // 驱动按需加载字段,0表示加载,2表示不加载 517 permission = 0664; // 驱动创建设备节点权限 518 moduleName = "HDF_LINEAR_VIBRATOR"; // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致 519 serviceName = "hdf_misc_linear_vibrator"; // 线性马达对外发布服务的名称,必须唯一 520 deviceMatchAttr = "hdf_linear_vibrator_driver"; // 马达差异化驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等 521 } 522 } 523 ``` 524 525 - 马达差异化驱动私有HCS配置: 526 527 - 代码实现路径:vendor\hihope\rk3568\hdf_config\khdf\vibrator\linear_vibrator_config.hcs。 528 529 - 具体代码实现如下: 530 531 ```c 532 root { 533 linearVibratorConfig { 534 boardConfig { 535 match_attr = "hdf_linear_vibrator_driver"; // 需要和马达设备配置文件中的match_attr字段保持一致 536 VibratorBusConfig { 537 busType = 1; // 0:i2c 1:gpio 538 busNum = 154; 539 } 540 VibratorChipConfig { 541 isSupportIntensity = 0; // 设置马达振幅能力。1表示支持,0表示不支持。 542 isSupportFrequency = 0; // 设置马达振动频率能力。1表示支持,0表示不支持。 543 intensityMaxValue = 0; // 马达振动支持的最大振幅 544 intensityMinValue = 0; // 马达振动支持的最小振幅 545 frequencyMaxValue = 0; // 马达振动支持的最大频率 546 frequencyMinValue = 0; // 马达振动支持的最小频率 547 } 548 } 549 } 550 } 551 ``` 552 553 - 马达差异化驱动代码实现路径为:drivers\peripheral\vibrator\chipset\linear\vibrator_linear_driver.c。 554 555 - 马达差异化驱动对应的HdfDriverEntry对象,其中,Driver Entry入口函数定义如下: 556 557 ```c 558 struct HdfDriverEntry g_linearVibratorDriverEntry = { 559 .moduleVersion = 1, 560 .moduleName = "HDF_LINEAR_VIBRATOR", 561 .Bind = BindLinearVibratorDriver, 562 .Init = InitLinearVibratorDriver, 563 .Release = ReleaseLinearVibratorDriver, 564 }; 565 566 HDF_INIT(g_linearVibratorDriverEntry); 567 ``` 568 569 - 马达差异化驱动Bind接口实现如下: 570 571 ```c 572 int32_t BindLinearVibratorDriver(struct HdfDeviceObject *device) 573 { 574 struct VibratorLinearDriverData *drvData = NULL; 575 576 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(device, HDF_FAILURE); 577 578 drvData = (struct VibratorLinearDriverData *)OsalMemCalloc(sizeof(*drvData)); 579 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_MALLOC_FAIL); 580 581 drvData->ioService.Dispatch = DispatchLinearVibrator; 582 drvData->device = device; 583 device->service = &drvData->ioService; 584 g_linearVibratorData = drvData; 585 586 return HDF_SUCCESS; 587 } 588 ``` 589 590 - 马达差异化驱动Init接口实现如下: 591 592 ```c 593 int32_t InitLinearVibratorDriver(struct HdfDeviceObject *device) 594 { 595 static struct VibratorOps ops; 596 struct VibratorLinearDriverData *drvData = NULL; 597 598 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(device, HDF_FAILURE); 599 600 drvData = (struct VibratorLinearDriverData *)device->service; 601 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE); 602 603 ops.Start = StartLinearVibrator; 604 ops.StartEffect = StartEffectLinearVibrator; 605 ops.Stop = StopLinearVibrator; 606 ops.SetParameter = NULL; 607 608 if (RegisterVibratorOps(&ops) != HDF_SUCCESS) { 609 HDF_LOGE("%s: register vibrator ops fail", __func__); 610 return HDF_FAILURE; 611 } 612 613 drvData->linearCfgData = (struct VibratorCfgData *)OsalMemCalloc(sizeof(*drvData->linearCfgData)); 614 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData->linearCfgData, HDF_ERR_MALLOC_FAIL); 615 /* 解析马达寄存器初始化 */ 616 if (GetVibratorBaseConfigData(device->property, drvData->linearCfgData) != HDF_SUCCESS) { 617 HDF_LOGE("%s: parser vibrator cfg fail", __func__); 618 return HDF_FAILURE; 619 } 620 /* 注册马达Info信息初始化 */ 621 if (RegisterVibratorInfo(&drvData->linearCfgData->vibratorInfo) != HDF_SUCCESS) { 622 HDF_LOGE("%s: register vibrator info fail", __func__); 623 return HDF_FAILURE; 624 } 625 626 if (GpioSetDir(drvData->linearCfgData->vibratorBus.GpioNum, GPIO_DIR_OUT) != HDF_SUCCESS) { 627 HDF_LOGE("%s: set vibrator gpio fail", __func__); 628 return HDF_FAILURE; 629 } 630 return HDF_SUCCESS; 631 } 632 ``` 633 634 - 马达差异化驱动Release接口实现如下: 635 636 ```c 637 void ReleaseLinearVibratorDriver(struct HdfDeviceObject *device) 638 { 639 struct VibratorLinearDriverData *drvData = NULL; 640 641 if (device == NULL) { 642 HDF_LOGE("%s: Device is null", __func__); 643 return; 644 } 645 drvData = (struct VibratorLinearDriverData *)device->service; 646 if (drvData == NULL) { 647 HDF_LOGE("%s: DrvData pointer is null", __func__); 648 return; 649 } 650 651 OsalMemFree(drvData->linearCfgData); 652 OsalMemFree(drvData); 653 g_linearVibratorData = NULL; 654 } 655 ``` 656 657 - 马达差异化驱动内部接口实现如下: 658 659 ```c 660 /* 触发振动马达 */ 661 static int32_t StartLinearVibrator(void) 662 { 663 int32_t ret; 664 struct VibratorLinearDriverData *drvData = GetLinearVibratorData(); 665 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE); 666 667 if (drvData->linearCfgData->vibratorBus.busType != VIBRATOR_BUS_GPIO) { 668 HDF_LOGE("%s: vibrator bus type not gpio", __func__); 669 return HDF_FAILURE; 670 } 671 672 ret = GpioWrite(drvData->linearCfgData->vibratorBus.GpioNum, GPIO_VAL_HIGH); 673 if (ret != HDF_SUCCESS) { 674 HDF_LOGE("%s: pull gpio%d to %d level failed", __func__, 675 drvData->linearCfgData->vibratorBus.GpioNum, GPIO_VAL_HIGH); 676 return ret; 677 } 678 return HDF_SUCCESS; 679 } 680 /* 按照指定效果触发振动马达 */ 681 static int32_t StartEffectLinearVibrator(uint32_t effectType) 682 { 683 (void)effectType; 684 HDF_LOGE("%s: vibrator set built-in effect no support!", __func__); 685 return HDF_SUCCESS; 686 } 687 /* 停止振动马达 */ 688 static int32_t StopLinearVibrator(void) 689 { 690 int32_t ret; 691 struct VibratorLinearDriverData *drvData = GetLinearVibratorData(); 692 CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE); 693 694 if (drvData->linearCfgData->vibratorBus.busType != VIBRATOR_BUS_GPIO) { 695 HDF_LOGE("%s: vibrator bus type not gpio", __func__); 696 return HDF_FAILURE; 697 } 698 699 ret = GpioWrite(drvData->linearCfgData->vibratorBus.GpioNum, GPIO_VAL_LOW); 700 if (ret != HDF_SUCCESS) { 701 HDF_LOGE("%s: pull gpio%d to %d level failed", __func__, 702 drvData->linearCfgData->vibratorBus.GpioNum, GPIO_VAL_LOW); 703 return ret; 704 } 705 return HDF_SUCCESS; 706 } 707 ``` 708 709 710 711### 调测验证 712 713驱动开发完成后,在马达单元测试里面开发自测试用例,验证驱动基本功能。测试环境采用开发者自测试平台。 714 715- 参考测试代码如下: 716 717 ```c 718 #include <cmath> 719 #include <cstdio> 720 #include <gtest/gtest.h> 721 #include <securec.h> 722 #include "hdf_base.h" 723 #include "osal_time.h" 724 #include "vibrator_if.h" 725 #include "vibrator_type.h" 726 727 using namespace testing::ext; 728 const struct VibratorInterface *g_vibratorDev = nullptr; 729 static struct VibratorInfo *g_vibratorInfo = nullptr; 730 731 class HdfVibratorTest : public testing::Test { 732 public: 733 static void SetUpTestCase(); 734 static void TearDownTestCase(); 735 void SetUp(); 736 void TearDown(); 737 }; 738 /* 用例执行前,初始化马达接口实例。 */ 739 void HdfVibratorTest::SetUpTestCase() 740 { 741 g_vibratorDev = NewVibratorInterfaceInstance(); 742 } 743 /* 用例资源释放 */ 744 void HdfVibratorTest::TearDownTestCase() 745 { 746 if(g_vibratorDev != nullptr){ 747 FreeVibratorInterfaceInstance(); 748 g_vibratorDev = nullptr; 749 } 750 } 751 752 void HdfVibratorTest::SetUp() 753 { 754 } 755 756 void HdfVibratorTest::TearDown() 757 { 758 } 759 760 /* 测试单次振动 */ 761 HWTEST_F(HdfVibratorTest, PerformOneShotVibratorDuration_001, TestSize.Level1) 762 { 763 uint32_t duration = 1000; 764 uint32_t sleepTime = 2000; 765 766 ASSERT_NE(nullptr, g_vibratorDev); 767 768 int32_t startRet = g_vibratorDev->StartOnce(duration); 769 EXPECT_EQ(startRet, HDF_SUCCESS); 770 771 OsalMSleep(sleepTime); 772 773 int32_t endRet = g_vibratorDev->Stop(VIBRATOR_MODE_ONCE); 774 EXPECT_EQ(endRet, HDF_SUCCESS); 775 } 776 /* 测试预置效果振动 */ 777 HWTEST_F(HdfVibratorTest, ExecuteVibratorEffect_001, TestSize.Level1) 778 { 779 uint32_t sleepTime = 5000; 780 const char *timeSequence = "haptic.clock.timer"; 781 782 ASSERT_NE(nullptr, g_vibratorDev); 783 784 int32_t startRet = g_vibratorDev->Start(timeSequence); 785 EXPECT_EQ(startRet, HDF_SUCCESS); 786 787 OsalMSleep(sleepTime); 788 789 int32_t endRet = g_vibratorDev->Stop(VIBRATOR_MODE_PRESET); 790 EXPECT_EQ(endRet, HDF_SUCCESS); 791 } 792 /* 获取马达信息,包括是否支持振幅和频率的设置及振幅和频率的设置范围。 */ 793 HWTEST_F(HdfVibratorTest, GetVibratorInfo_001, TestSize.Level1) 794 { 795 ASSERT_NE(nullptr, g_vibratorDev); 796 797 int32_t startRet = g_vibratorDev->GetVibratorInfo(&g_vibratorInfo); 798 EXPECT_EQ(startRet, HDF_SUCCESS); 799 EXPECT_NE(g_vibratorInfo, nullptr); 800 801 printf("intensity = %d, intensityMaxValue = %d, intensityMinValue = %d\n\t", 802 g_vibratorInfo->isSupportIntensity, g_vibratorInfo->intensityMaxValue, g_vibratorInfo->intensityMinValue); 803 printf("frequency = %d, frequencyMaxValue = %d, frequencyMinValue = %d\n\t", 804 g_vibratorInfo->isSupportFrequency, g_vibratorInfo->frequencyMaxValue, g_vibratorInfo->frequencyMinValue); 805 } 806 /* 按照指定振幅、频率、持续时间触发振动马达。duration为振动持续时长,intensity为振动强度,frequency为振动频率。 */ 807 HWTEST_F(HdfVibratorTest, EnableVibratorModulation_001, TestSize.Level1) 808 { 809 int32_t startRet; 810 int32_t intensity = 30; 811 int32_t frequency = 200; 812 uint32_t duration = 1000; 813 uint32_t sleepTime = 2000; 814 815 ASSERT_NE(nullptr, g_vibratorDev); 816 817 if ((g_vibratorInfo->isSupportIntensity == 1) || (g_vibratorInfo->isSupportFrequency == 1)) { 818 EXPECT_GE(intensity, g_vibratorInfo->intensityMinValue); 819 EXPECT_LE(intensity, g_vibratorInfo->intensityMaxValue); 820 EXPECT_GE(frequency, g_vibratorInfo->frequencyMinValue); 821 EXPECT_LE(frequency, g_vibratorInfo->frequencyMaxValue); 822 823 startRet = g_vibratorDev->EnableVibratorModulation(duration, intensity, duration); 824 EXPECT_EQ(startRet, HDF_SUCCESS); 825 OsalMSleep(sleepTime); 826 startRet = g_vibratorDev->Stop(VIBRATOR_MODE_ONCE); 827 EXPECT_EQ(startRet, HDF_SUCCESS); 828 } 829 } 830 ``` 831 832- 编译文件gn参考代码如下: 833 834 ```c++ 835 import("//build/ohos.gni") 836 import("//build/test.gni") 837 import("//drivers/hdf_core/adapter/uhdf2/uhdf.gni") 838 839 module_output_path = "drivers_peripheral_vibrator/vibrator" 840 ohos_unittest("vibrator_test") { 841 module_out_path = module_output_path 842 sources = [ "vibrator_test.cpp" ] 843 include_dirs = [ 844 "//drivers/peripheral/vibrator/interfaces/include", 845 ] 846 deps = [ "//drivers/peripheral/vibrator/hal:hdi_vibrator" ] 847 848 external_deps = [ 849 "c_utils:utils", 850 "hdf_core:libhdf_utils", 851 "hiviewdfx_hilog_native:libhilog", 852 ] 853 854 cflags = [ 855 "-Wall", 856 "-Wextra", 857 "-Werror", 858 "-Wno-format", 859 "-Wno-format-extra-args", 860 ] 861 862 install_enable = true 863 install_images = [ "vendor" ] 864 module_install_dir = "bin" 865 part_name = "unionman_products" 866 } 867 ``` 868 869