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