1# Vibrator 2 3## Overview 4 5### Function 6 7The vibrator driver model underpinned by the Hardware Driver Foundation (HDF) makes vibrator driver development easier and faster. This model shields the interaction between the device driver and the system, and provides unified and stable driver interface capabilities for the hardware service layer. It also provides open interfaces and interface parsing capabilities for developing vibrator drivers and deploying vibrators in different OSs.<br> The figure below shows the vibrator driver model. 8 9**Figure 1** Vibrator driver model 10 11 12 13### Basic Concepts 14 15Vibrators can be classified into the following types based on the vibration mechanism: 16 17- Rotor vibrator 18 19 The rotor vibrator uses magnetic field caused by current to drive the rotor to rotate and produce vibration. Rotor vibrators include ordinary rotor vibrators and coin rotor vibrators. The rotor vibrators cannot start or stop quickly or implement multiple vibration modes. However, they have small footprint and are cost-efficient. 20 21- Linear vibrator 22 23 The linear vibrator drives the spring mass for linear movement and produces vibration. Linear vibrators include longitudinal and transverse linear vibrators. The linear vibrators start and stop quickly, produce different vibration inductions, and have good sense of direction. 24 25The system calls vibrator driver interfaces to control the vibration of the device. Currently, there are two vibration modes: 26 27- One-shot vibration 28 29 The vibrator vibrates once for a given duration. 30 31- Periodic vibration 32 33 The vibrator vibrates at preset intervals. For example, if **haptic.clock.timer** is set to **[600, 600, 200, 600]**, the vibrator waits for 600 ms, vibrates for 600 ms, waits for 200 ms, and vibrates for 600 ms. 34 35### Working Principles 36 37The figure below shows how a vibrator driver is loaded. 38 39**Figure 2** Vibrator driver working mechanism 40 41 42 43The following describes how to load and start a vibrator driver on an RK35680 that runs the standard system. 44 451. Device Manager reads the vibrator management configuration from the **device_info.hcs** file. 462. The HDF Configuration Source (HCS) Parser parses the vibrator management configuration and loads the vibrator abstract driver. 473. Device Manager reads the vibrator data configuration from the **linear_vibrator_config.hcs** file. 484. The HCS parser parses the vibrator data configuration and loads the haptic driver. 495. The vibrator proxy obtains the vibrator HDI service instance and sends it to the vibrator stub over inter-process communication (IPC). 506. The vibrator stub processes IPC-related service logic and calls the vibrator controller after parameter deserialization. 517. The vibrator controller implements the HDI interfaces and calls the vibrator abstract driver interfaces over IPC. 528. The vibrator abstract driver starts the vibrator haptic driver. 539. The haptic driver calls **Start()** in the vibrator abstract driver. 5410. The vibrator abstract driver calls **Start()** in the vibrator chipset-specific driver to control the vibrator device to vibrate with a given effect. 55 56## Development Guidelines 57 58### When to Use 59 60You can set different vibration effects for your device, for example, you can set vibration effects with different intensities and durations for buttons on the device, and set one-shot or periodic vibration effects with different intensities and durations for clock alarms and incoming calls. 61 62### Available APIs 63 64The vibrator driver model supports static HCS and dynamic parameter configuration. The vibrator hardware service calls **StartOnce()** to trigger continuous vibration and calls **Start()** to trigger vibration with a specified effect. The following table describes the APIs provided by the vibrator driver model for the hardware service layer. 65 66**Table 1** APIs of the vibrator driver model 67 68**NOTE**<br>The following APIs are C interfaces. For details about the interface declaration, see [/drivers/peripheral/vibrator/interfaces/include](https://gitee.com/openharmony/drivers_peripheral/tree/master/vibrator/interfaces/include). 69 70| API | Description | 71| -------------------------------------- | ------------------------------------------------ | 72| int32_t (*StartOnce)(uint32_t duration) | Triggers a one-short vibration with a given duration.<br>**duration** specifies the duration of the one-short vibration. | 73| int32_t (*Start)(const char *effectType) | Triggers periodic vibrations with a preset effect. <br>**effectType** indicates the pointer to the preset effect type. | 74| int32_t (*Stop)(enum VibratorMode mode) | Stops vibration. <br>**mode** indicates the vibration mode, which can be one-short or periodic vibration. | 75| int32_t (*EnableVibratorModulation)(uint32_t duration, int32_t intensity, int32_t frequency) | Triggers a vibration with the given duration, frequency, and intensity.<br>**duration** indicates the duration of the vibration.<br>**intensity** indicates the vibration amplitude.<br>**frequency** indicates the vibrator frequency in the vibration period.| 76| int32_t (*GetVibratorInfo)(struct VibratorInfo **vibratorInfo) | Obtains information about all vibrators whose amplitude and frequency can be set in the system. <br>**vibratorInfo** indicates the pointer to the vibrator information obtained.| 77| int32_t (*EnableCompositeEffect)(struct CompositeEffect *effect); | Enables the composite effect for this vibrator.| 78| int32_t (*GetEffectInfo)(const char *effectType, struct EffectInfo *effectInfo); | Obtains the vibration effect information of a specified effect type.| 79| int32_t (*IsVibratorRunning)(bool state); | Checks whether the vibrator is running.| 80| int32_t (*PlayHapticPattern)(const HapticPaket& pkg); | Plays haptics based on the HD haptic data in the form of a .pkg.| 81| int32_t (*GetHapticCapacity)(HapticCapacity& hapticCapacity); | Obtains the haptic capabilities, including whether HD haptics is supported, whether predefined waveforms are supported, and whether delayed haptics is supported.| 82| int32_t (*GetHapticStartUpTime)(int32_t mode, int32_t& startUpTime); | Obtains the haptic startup delay. **mode** indicates the vibration mode, and **startUpTime** indicates the haptic startup delay obtained.| 83 84### How to Develop 85 86The vibrator driver model provides interfaces for the upper-layer hardware service to trigger a one-shot vibration with a given duration, trigger vibration with a given effect, and stop vibration. This model implements functionalities such as cross-OS porting and device-specific configurations. The linear vibrator driver is used as an example to describe the driver development. 87 881. Develop the vibrator abstract driver. 89 90 - Configure the vibrator host information for the vibrator abstract driver. For details, see **vendor\hihope\rk3568\hdf_config\khdf\device_info\device_info.hcs**. 91 92 The code is as follows: 93 94 ```c 95 /* Vibrator HCS configuration. */ 96 vibrator :: host { 97 hostName = "vibrator_host"; 98 device_vibrator :: device { 99 device0 :: deviceNode { 100 policy = 2; // Policy for publishing the driver services. 101 priority = 100; // Priority (0–200) for starting the vibrator driver. A larger value indicates a lower priority. The recommended value is 100. For the drivers with the same priority, the device loading sequence is uncertain. 102 preload = 0; // The value 0 means to load the driver during the system boot process. The value 2 means to dynamically load the driver after the system starts. 103 permission = 0664; // Permission for the device node created. 104 moduleName = "HDF_VIBRATOR"; // Vibrator driver name, which must be the same as moduleName in the driver entry structure. 105 serviceName = "hdf_misc_vibrator"; // Unique name of the service published by the vibrator driver. 106 deviceMatchAttr = "hdf_vibrator_driver"; // Keyword matching the private data of the driver. The value must be the same as that of match_attr in the private data configuration table of the driver. 107 } 108 } 109 } 110 ``` 111 112 - Create a vibrator haptic model and parse the haptic HCS. For details, see **drivers\hdf_core\framework\model\misc\vibrator\driver\src\vibrator_haptic.c**. 113 114 The code is as follows: 115 116 ```c 117 /* Create a vibrator haptic model. */ 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 // Obtain the 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 - Implement the vibrator abstract driver. For details, see **drivers\hdf_core\framework\model\misc\vibrator\driver\src\vibrator_driver.c**. 149 150 - Define an **HdfDriverEntry** object, in which the driver entry function is defined as follows: 151 152 ```c 153 /* Register the entry struct of the vibrator abstract driver. */ 154 struct HdfDriverEntry g_vibratorDriverEntry = { 155 .moduleVersion = 1, // Vibrator module version. 156 .moduleName = "HDF_VIBRATOR", // Vibrator module name, which must be the same as moduleName in the device_info.hcs file. 157 .Bind = BindVibratorDriver, // Bind function for the vibrator driver. 158 .Init = InitVibratorDriver, // Init function for the vibrator driver. 159 .Release = ReleaseVibratorDriver, // Release function for the vibrator driver. 160 }; 161 /* Call HDF_INIT to register the driver entry with the HDF. When loading the driver, the HDF calls Bind() and then Init() to load the driver. If Init() fails to be called, the HDF calls Release() to release resources and exit the vibrator driver model. */ 162 HDF_INIT(g_vibratorDriverEntry); 163 ``` 164 165 - Implement **Bind()** for the vibrator abstract driver as follows: 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 - Implement **Init()** for the vibrator abstract driver as follows: 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 /* Initialize work queue resources. */ 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 /* Create the vibrator haptic model. */ 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 - Implement **Release()** for the vibrator abstract driver. This interface is used to release resources when the driver is unloaded or **Init()** fails to be called. 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 - Implement internal interfaces of the vibrator abstract driver to obtain vibrator information, set and stop the vibration mode, and create and destroy timers based on the vibration mode. 249 250 - Implement **StartOnce()** for the vibrator abstract driver as follows: 251 252 ```c 253 /* Trigger vibration with a given 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 /* Start haptics based on the vibration effect mode. */ 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 - Implement **StartEffect()** for the vibrator abstract driver as follows: 299 300 ```c 301 /* Trigger a vibration with a given 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 /* Read the preset vibration effect from HdfSBuf and start the vibrator. */ 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 one-shot vibration. 326 config.cfgMode = VIBRATOR_MODE_PRESET; 327 config.duration = 0; 328 config.effect = effect; 329 /* Start haptics with the preset effect. */ 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 - Implement **Stop()** for the vibrator abstract driver as follows: 341 342 ```c 343 /* Stop vibration based on the specified vibration mode. */ 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 /* Read the specified vibration mode from HdfSBuf and then stop the vibration. */ 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 /* Stop haptics and destroy the timer. */ 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 - Implement **GetVibratorInfo** for the vibrator abstract driver as follows: 384 385 ```c 386 /* Obtain vibrator information, including whether the intensity and frequency can be set and the intensity and frequency range. */ 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 - Implement **EnableModulationParameter** for the vibrator abstract driver as follows: 406 407 ```c 408 /* Trigger vibration with the given duration, frequency, and intensity. */ 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 /* Start haptics with the preset effect. */ 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 - Register the chipset-specific vibrator driver interfaces when the vibrator driver is successfully initialized. The implementation is as follows: 469 470 ```c 471 /* Register the chipset-specific vibrator driver interfaces. */ 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 /* Register the VibratorInfo struct. */ 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. Develop chipset-specific vibrator drivers. 509 510 - Configure the vibrator host information for the chipset-specific vibrator driver. For details, see **vendor\hihope\rk3568\hdf_config\khdf\device_info\device_info.hcs**. 511 512 The code is as follows: 513 514 ```c 515 device_linear_vibrator :: device { 516 device0 :: deviceNode { 517 policy = 1; // Policy for publishing the driver services. 518 priority = 105; // Priority (0–200) for starting the vibrator driver. A larger value indicates a lower priority. The recommended value is 100. For the drivers with the same priority, the device loading sequence is uncertain. 519 preload = 0; // The value 0 means to load the driver during the system boot process. The value 2 means to dynamically load the driver after the system starts. 520 permission = 0664; // Permission for the DeviceNode created. 521 moduleName = "HDF_LINEAR_VIBRATOR"; // Driver name, which must be the same as moduleName in the driver entry struct. 522 serviceName = "hdf_misc_linear_vibrator"; // Unique name of the service released by the linear vibrator. 523 deviceMatchAttr = "hdf_linear_vibrator_driver"; // Keyword for matching the private data of the chipset-specific vibrator driver. The value must be the same as that of match_attr in the private data configuration table of the driver. 524 } 525 } 526 ``` 527 528 - Configure the private HCS configuration of the chipset-specific vibrator driver. 529 530 - For details, see **vendor\hihope\rk3568\hdf_config\khdf\vibrator\linear_vibrator_config.hcs**. 531 532 - The code is as follows: 533 534 ```c 535 root { 536 linearVibratorConfig { 537 boardConfig { 538 match_attr = "hdf_linear_vibrator_driver"; // The value must be the same as that of match_attr in the vibrator device configuration file. 539 VibratorBusConfig { 540 busType = 1; // 0 stands for I2C; 1 for GPIO. 541 busNum = 154; 542 } 543 VibratorChipConfig { 544 isSupportIntensity = 0; // Whether vibrator intensity can be set. The value 1 means the vibrator intensity can be set; the value 0 means the opposite. 545 isSupportFrequency = 0; // Whether vibrator frequency can be set. The value 1 means the vibrator frequency can be set; the value 0 means the opposite. 546 intensityMaxValue = 0; // Maximum vibrator intensity supported. 547 intensityMinValue = 0; // Minimum vibrator intensity supported. 548 frequencyMaxValue = 0; // Maximum vibrator frequency supported. 549 frequencyMinValue = 0; // Minimum vibrator frequency supported. 550 } 551 } 552 } 553 } 554 ``` 555 556 - Implement the chipset-specific vibrator driver. For details, see **drivers\peripheral\vibrator\chipset\linear\vibrator_linear_driver.c**. 557 558 - Define the **HdfDriverEntry** object of the chipset-specific vibrator driver. The driver entry function is defined as follows: 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 - Implement **Bind()** for the chipset-specific vibrator driver as follows: 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 - Implement **Init()** for the chipset-specific vibrator driver as follows: 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 /* Parse the vibrator configuration in the register. */ 619 if (GetVibratorBaseConfigData(device->property, drvData->linearCfgData) != HDF_SUCCESS) { 620 HDF_LOGE("%s: parser vibrator cfg fail", __func__); 621 return HDF_FAILURE; 622 } 623 /* Register the vibrator information for initialization. */ 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 - Implement **Release()** for the chipset-specific vibrator driver as follows: 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 - Implement the internal interfaces of the chipset-specific vibrator driver as follows: 661 662 ```c 663 /* Start the vibrator. */ 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 /* Start the vibrator based on the specified effect. */ 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 /* Stop the vibrator. */ 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### Verification 715 716After the driver is developed, develop auto-test cases in the vibrator unit test to verify the basic functionalities of the driver. Use the developer self-test platform as the test environment. 717 718- The reference test code is as follows: 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 /* Initialize the vibrator interface instance before executing test cases. */ 742 void HdfVibratorTest::SetUpTestCase() 743 { 744 g_vibratorDev = NewVibratorInterfaceInstance(); 745 } 746 /* Release test case resources. */ 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 /* Verify one-short vibration. */ 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 /* Verify vibration with the preset effect. */ 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 /* Obtain vibrator information, including whether the intensity and frequency can be set and the intensity and frequency range. */ 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 /* Trigger vibration with the given duration, frequency, and intensity. */ 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- The reference code of the .gn file is as follows: 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