1e41f4b71Sopenharmony_ci# Vibrator 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## Overview 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ci### Function 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ciThe 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. 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ci**Figure 1** Vibrator driver model 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ci 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ci### Basic Concepts 14e41f4b71Sopenharmony_ci 15e41f4b71Sopenharmony_ciVibrators can be classified into the following types based on the vibration mechanism: 16e41f4b71Sopenharmony_ci 17e41f4b71Sopenharmony_ci- Rotor vibrator 18e41f4b71Sopenharmony_ci 19e41f4b71Sopenharmony_ci 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. 20e41f4b71Sopenharmony_ci 21e41f4b71Sopenharmony_ci- Linear vibrator 22e41f4b71Sopenharmony_ci 23e41f4b71Sopenharmony_ci 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. 24e41f4b71Sopenharmony_ci 25e41f4b71Sopenharmony_ciThe system calls vibrator driver interfaces to control the vibration of the device. Currently, there are two vibration modes: 26e41f4b71Sopenharmony_ci 27e41f4b71Sopenharmony_ci- One-shot vibration 28e41f4b71Sopenharmony_ci 29e41f4b71Sopenharmony_ci The vibrator vibrates once for a given duration. 30e41f4b71Sopenharmony_ci 31e41f4b71Sopenharmony_ci- Periodic vibration 32e41f4b71Sopenharmony_ci 33e41f4b71Sopenharmony_ci 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. 34e41f4b71Sopenharmony_ci 35e41f4b71Sopenharmony_ci### Working Principles 36e41f4b71Sopenharmony_ci 37e41f4b71Sopenharmony_ciThe figure below shows how a vibrator driver is loaded. 38e41f4b71Sopenharmony_ci 39e41f4b71Sopenharmony_ci**Figure 2** Vibrator driver working mechanism 40e41f4b71Sopenharmony_ci 41e41f4b71Sopenharmony_ci 42e41f4b71Sopenharmony_ci 43e41f4b71Sopenharmony_ciThe following describes how to load and start a vibrator driver on an RK35680 that runs the standard system. 44e41f4b71Sopenharmony_ci 45e41f4b71Sopenharmony_ci1. Device Manager reads the vibrator management configuration from the **device_info.hcs** file. 46e41f4b71Sopenharmony_ci2. The HDF Configuration Source (HCS) Parser parses the vibrator management configuration and loads the vibrator abstract driver. 47e41f4b71Sopenharmony_ci3. Device Manager reads the vibrator data configuration from the **linear_vibrator_config.hcs** file. 48e41f4b71Sopenharmony_ci4. The HCS parser parses the vibrator data configuration and loads the haptic driver. 49e41f4b71Sopenharmony_ci5. The vibrator proxy obtains the vibrator HDI service instance and sends it to the vibrator stub over inter-process communication (IPC). 50e41f4b71Sopenharmony_ci6. The vibrator stub processes IPC-related service logic and calls the vibrator controller after parameter deserialization. 51e41f4b71Sopenharmony_ci7. The vibrator controller implements the HDI interfaces and calls the vibrator abstract driver interfaces over IPC. 52e41f4b71Sopenharmony_ci8. The vibrator abstract driver starts the vibrator haptic driver. 53e41f4b71Sopenharmony_ci9. The haptic driver calls **Start()** in the vibrator abstract driver. 54e41f4b71Sopenharmony_ci10. The vibrator abstract driver calls **Start()** in the vibrator chipset-specific driver to control the vibrator device to vibrate with a given effect. 55e41f4b71Sopenharmony_ci 56e41f4b71Sopenharmony_ci## Development Guidelines 57e41f4b71Sopenharmony_ci 58e41f4b71Sopenharmony_ci### When to Use 59e41f4b71Sopenharmony_ci 60e41f4b71Sopenharmony_ciYou 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. 61e41f4b71Sopenharmony_ci 62e41f4b71Sopenharmony_ci### Available APIs 63e41f4b71Sopenharmony_ci 64e41f4b71Sopenharmony_ciThe 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. 65e41f4b71Sopenharmony_ci 66e41f4b71Sopenharmony_ci**Table 1** APIs of the vibrator driver model 67e41f4b71Sopenharmony_ci 68e41f4b71Sopenharmony_ci**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). 69e41f4b71Sopenharmony_ci 70e41f4b71Sopenharmony_ci| API | Description | 71e41f4b71Sopenharmony_ci| -------------------------------------- | ------------------------------------------------ | 72e41f4b71Sopenharmony_ci| 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. | 73e41f4b71Sopenharmony_ci| int32_t (*Start)(const char *effectType) | Triggers periodic vibrations with a preset effect. <br>**effectType** indicates the pointer to the preset effect type. | 74e41f4b71Sopenharmony_ci| int32_t (*Stop)(enum VibratorMode mode) | Stops vibration. <br>**mode** indicates the vibration mode, which can be one-short or periodic vibration. | 75e41f4b71Sopenharmony_ci| 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.| 76e41f4b71Sopenharmony_ci| 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.| 77e41f4b71Sopenharmony_ci| int32_t (*EnableCompositeEffect)(struct CompositeEffect *effect); | Enables the composite effect for this vibrator.| 78e41f4b71Sopenharmony_ci| int32_t (*GetEffectInfo)(const char *effectType, struct EffectInfo *effectInfo); | Obtains the vibration effect information of a specified effect type.| 79e41f4b71Sopenharmony_ci| int32_t (*IsVibratorRunning)(bool state); | Checks whether the vibrator is running.| 80e41f4b71Sopenharmony_ci| int32_t (*PlayHapticPattern)(const HapticPaket& pkg); | Plays haptics based on the HD haptic data in the form of a .pkg.| 81e41f4b71Sopenharmony_ci| 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.| 82e41f4b71Sopenharmony_ci| 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.| 83e41f4b71Sopenharmony_ci 84e41f4b71Sopenharmony_ci### How to Develop 85e41f4b71Sopenharmony_ci 86e41f4b71Sopenharmony_ciThe 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. 87e41f4b71Sopenharmony_ci 88e41f4b71Sopenharmony_ci1. Develop the vibrator abstract driver. 89e41f4b71Sopenharmony_ci 90e41f4b71Sopenharmony_ci - Configure the vibrator host information for the vibrator abstract driver. For details, see **vendor\hihope\rk3568\hdf_config\khdf\device_info\device_info.hcs**. 91e41f4b71Sopenharmony_ci 92e41f4b71Sopenharmony_ci The code is as follows: 93e41f4b71Sopenharmony_ci 94e41f4b71Sopenharmony_ci ```c 95e41f4b71Sopenharmony_ci /* Vibrator HCS configuration. */ 96e41f4b71Sopenharmony_ci vibrator :: host { 97e41f4b71Sopenharmony_ci hostName = "vibrator_host"; 98e41f4b71Sopenharmony_ci device_vibrator :: device { 99e41f4b71Sopenharmony_ci device0 :: deviceNode { 100e41f4b71Sopenharmony_ci policy = 2; // Policy for publishing the driver services. 101e41f4b71Sopenharmony_ci 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. 102e41f4b71Sopenharmony_ci 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. 103e41f4b71Sopenharmony_ci permission = 0664; // Permission for the device node created. 104e41f4b71Sopenharmony_ci moduleName = "HDF_VIBRATOR"; // Vibrator driver name, which must be the same as moduleName in the driver entry structure. 105e41f4b71Sopenharmony_ci serviceName = "hdf_misc_vibrator"; // Unique name of the service published by the vibrator driver. 106e41f4b71Sopenharmony_ci 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. 107e41f4b71Sopenharmony_ci } 108e41f4b71Sopenharmony_ci } 109e41f4b71Sopenharmony_ci } 110e41f4b71Sopenharmony_ci ``` 111e41f4b71Sopenharmony_ci 112e41f4b71Sopenharmony_ci - 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**. 113e41f4b71Sopenharmony_ci 114e41f4b71Sopenharmony_ci The code is as follows: 115e41f4b71Sopenharmony_ci 116e41f4b71Sopenharmony_ci ```c 117e41f4b71Sopenharmony_ci /* Create a vibrator haptic model. */ 118e41f4b71Sopenharmony_ci int32_t CreateVibratorHaptic(struct HdfDeviceObject *device) 119e41f4b71Sopenharmony_ci { 120e41f4b71Sopenharmony_ci struct VibratorHapticData *hapticData = NULL; 121e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(device, HDF_FAILURE); 122e41f4b71Sopenharmony_ci 123e41f4b71Sopenharmony_ci hapticData = (struct VibratorHapticData *)OsalMemCalloc(sizeof(*hapticData)); 124e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(hapticData, HDF_ERR_MALLOC_FAIL); 125e41f4b71Sopenharmony_ci g_vibratorHapticData = hapticData; 126e41f4b71Sopenharmony_ci hapticData->supportHaptic = false; 127e41f4b71Sopenharmony_ci 128e41f4b71Sopenharmony_ci if (OsalMutexInit(&hapticData->mutex) != HDF_SUCCESS) { 129e41f4b71Sopenharmony_ci HDF_LOGE("%s: fail to init mutex", __func__); 130e41f4b71Sopenharmony_ci goto EXIT; 131e41f4b71Sopenharmony_ci } 132e41f4b71Sopenharmony_ci 133e41f4b71Sopenharmony_ci DListHeadInit(&hapticData->effectSeqHead); 134e41f4b71Sopenharmony_ci 135e41f4b71Sopenharmony_ci // Obtain the haptic HCS. 136e41f4b71Sopenharmony_ci if (ParserVibratorHapticConfig(device->property) != HDF_SUCCESS) { 137e41f4b71Sopenharmony_ci HDF_LOGE("%s: parser haptic config fail!", __func__); 138e41f4b71Sopenharmony_ci goto EXIT; 139e41f4b71Sopenharmony_ci } 140e41f4b71Sopenharmony_ci 141e41f4b71Sopenharmony_ci return HDF_SUCCESS; 142e41f4b71Sopenharmony_ci EXIT: 143e41f4b71Sopenharmony_ci OsalMemFree(hapticData); 144e41f4b71Sopenharmony_ci return HDF_FAILURE; 145e41f4b71Sopenharmony_ci } 146e41f4b71Sopenharmony_ci ``` 147e41f4b71Sopenharmony_ci 148e41f4b71Sopenharmony_ci - Implement the vibrator abstract driver. For details, see **drivers\hdf_core\framework\model\misc\vibrator\driver\src\vibrator_driver.c**. 149e41f4b71Sopenharmony_ci 150e41f4b71Sopenharmony_ci - Define an **HdfDriverEntry** object, in which the driver entry function is defined as follows: 151e41f4b71Sopenharmony_ci 152e41f4b71Sopenharmony_ci ```c 153e41f4b71Sopenharmony_ci /* Register the entry struct of the vibrator abstract driver. */ 154e41f4b71Sopenharmony_ci struct HdfDriverEntry g_vibratorDriverEntry = { 155e41f4b71Sopenharmony_ci .moduleVersion = 1, // Vibrator module version. 156e41f4b71Sopenharmony_ci .moduleName = "HDF_VIBRATOR", // Vibrator module name, which must be the same as moduleName in the device_info.hcs file. 157e41f4b71Sopenharmony_ci .Bind = BindVibratorDriver, // Bind function for the vibrator driver. 158e41f4b71Sopenharmony_ci .Init = InitVibratorDriver, // Init function for the vibrator driver. 159e41f4b71Sopenharmony_ci .Release = ReleaseVibratorDriver, // Release function for the vibrator driver. 160e41f4b71Sopenharmony_ci }; 161e41f4b71Sopenharmony_ci /* 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. */ 162e41f4b71Sopenharmony_ci HDF_INIT(g_vibratorDriverEntry); 163e41f4b71Sopenharmony_ci ``` 164e41f4b71Sopenharmony_ci 165e41f4b71Sopenharmony_ci - Implement **Bind()** for the vibrator abstract driver as follows: 166e41f4b71Sopenharmony_ci 167e41f4b71Sopenharmony_ci ```c 168e41f4b71Sopenharmony_ci int32_t BindVibratorDriver(struct HdfDeviceObject *device) 169e41f4b71Sopenharmony_ci { 170e41f4b71Sopenharmony_ci struct VibratorDriverData *drvData = NULL; 171e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(device, HDF_FAILURE); 172e41f4b71Sopenharmony_ci 173e41f4b71Sopenharmony_ci drvData = (struct VibratorDriverData *)OsalMemCalloc(sizeof(*drvData)); 174e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_MALLOC_FAIL); 175e41f4b71Sopenharmony_ci 176e41f4b71Sopenharmony_ci drvData->ioService.Dispatch = DispatchVibrator; 177e41f4b71Sopenharmony_ci drvData->device = device; 178e41f4b71Sopenharmony_ci device->service = &drvData->ioService; 179e41f4b71Sopenharmony_ci g_vibratorDrvData = drvData; 180e41f4b71Sopenharmony_ci 181e41f4b71Sopenharmony_ci return HDF_SUCCESS; 182e41f4b71Sopenharmony_ci } 183e41f4b71Sopenharmony_ci ``` 184e41f4b71Sopenharmony_ci 185e41f4b71Sopenharmony_ci - Implement **Init()** for the vibrator abstract driver as follows: 186e41f4b71Sopenharmony_ci 187e41f4b71Sopenharmony_ci ```c 188e41f4b71Sopenharmony_ci int32_t InitVibratorDriver(struct HdfDeviceObject *device) 189e41f4b71Sopenharmony_ci { 190e41f4b71Sopenharmony_ci struct VibratorDriverData *drvData = NULL; 191e41f4b71Sopenharmony_ci 192e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(device, HDF_FAILURE); 193e41f4b71Sopenharmony_ci drvData = (struct VibratorDriverData *)device->service; 194e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE); 195e41f4b71Sopenharmony_ci 196e41f4b71Sopenharmony_ci drvData->mode = VIBRATOR_MODE_BUTT; 197e41f4b71Sopenharmony_ci drvData->state = VIBRATOR_STATE_IDLE; 198e41f4b71Sopenharmony_ci 199e41f4b71Sopenharmony_ci if (OsalMutexInit(&drvData->mutex) != HDF_SUCCESS) { 200e41f4b71Sopenharmony_ci HDF_LOGE("%s: init mutex failed!", __func__); 201e41f4b71Sopenharmony_ci return HDF_FAILURE; 202e41f4b71Sopenharmony_ci } 203e41f4b71Sopenharmony_ci /* Initialize work queue resources. */ 204e41f4b71Sopenharmony_ci if (HdfWorkQueueInit(&drvData->workQueue, VIBRATOR_WORK_QUEUE_NAME) != HDF_SUCCESS) { 205e41f4b71Sopenharmony_ci HDF_LOGE("%s: init workQueue failed!", __func__); 206e41f4b71Sopenharmony_ci return HDF_FAILURE; 207e41f4b71Sopenharmony_ci } 208e41f4b71Sopenharmony_ci 209e41f4b71Sopenharmony_ci if (HdfWorkInit(&drvData->work, VibratorWorkEntry, (void*)drvData) != HDF_SUCCESS) { 210e41f4b71Sopenharmony_ci HDF_LOGE("%s: init workQueue failed!", __func__); 211e41f4b71Sopenharmony_ci return HDF_FAILURE; 212e41f4b71Sopenharmony_ci } 213e41f4b71Sopenharmony_ci /* Create the vibrator haptic model. */ 214e41f4b71Sopenharmony_ci if (CreateVibratorHaptic(device) != HDF_SUCCESS) { 215e41f4b71Sopenharmony_ci HDF_LOGE("%s: create vibrator haptic failed!", __func__); 216e41f4b71Sopenharmony_ci return HDF_FAILURE; 217e41f4b71Sopenharmony_ci } 218e41f4b71Sopenharmony_ci 219e41f4b71Sopenharmony_ci return HDF_SUCCESS; 220e41f4b71Sopenharmony_ci } 221e41f4b71Sopenharmony_ci ``` 222e41f4b71Sopenharmony_ci 223e41f4b71Sopenharmony_ci - 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. 224e41f4b71Sopenharmony_ci 225e41f4b71Sopenharmony_ci ```c 226e41f4b71Sopenharmony_ci void ReleaseVibratorDriver(struct HdfDeviceObject *device) 227e41f4b71Sopenharmony_ci { 228e41f4b71Sopenharmony_ci struct VibratorDriverData *drvData = NULL; 229e41f4b71Sopenharmony_ci 230e41f4b71Sopenharmony_ci if (device == NULL) { 231e41f4b71Sopenharmony_ci HDF_LOGE("%s: device is null!", __func__); 232e41f4b71Sopenharmony_ci return; 233e41f4b71Sopenharmony_ci } 234e41f4b71Sopenharmony_ci 235e41f4b71Sopenharmony_ci drvData = (struct VibratorDriverData *)device->service; 236e41f4b71Sopenharmony_ci if (drvData == NULL) { 237e41f4b71Sopenharmony_ci HDF_LOGE("%s: drvData is null!", __func__); 238e41f4b71Sopenharmony_ci return; 239e41f4b71Sopenharmony_ci } 240e41f4b71Sopenharmony_ci 241e41f4b71Sopenharmony_ci (void)DestroyVibratorHaptic(); 242e41f4b71Sopenharmony_ci (void)OsalMutexDestroy(&drvData->mutex); 243e41f4b71Sopenharmony_ci OsalMemFree(drvData); 244e41f4b71Sopenharmony_ci g_vibratorDrvData = NULL; 245e41f4b71Sopenharmony_ci } 246e41f4b71Sopenharmony_ci ``` 247e41f4b71Sopenharmony_ci 248e41f4b71Sopenharmony_ci - 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. 249e41f4b71Sopenharmony_ci 250e41f4b71Sopenharmony_ci - Implement **StartOnce()** for the vibrator abstract driver as follows: 251e41f4b71Sopenharmony_ci 252e41f4b71Sopenharmony_ci ```c 253e41f4b71Sopenharmony_ci /* Trigger vibration with a given duration. */ 254e41f4b71Sopenharmony_ci static int32_t StartOnce(struct HdfSBuf *data, struct HdfSBuf *reply) 255e41f4b71Sopenharmony_ci { 256e41f4b71Sopenharmony_ci uint32_t duration; 257e41f4b71Sopenharmony_ci int32_t ret; 258e41f4b71Sopenharmony_ci struct VibratorEffectCfg config; 259e41f4b71Sopenharmony_ci struct VibratorDriverData *drvData = GetVibratorDrvData(); 260e41f4b71Sopenharmony_ci (void)reply; 261e41f4b71Sopenharmony_ci 262e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(data, HDF_FAILURE); 263e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE); 264e41f4b71Sopenharmony_ci 265e41f4b71Sopenharmony_ci if (!HdfSbufReadUint32(data, &duration)) { 266e41f4b71Sopenharmony_ci HDF_LOGE("%s: sbuf read duration failed!", __func__); 267e41f4b71Sopenharmony_ci return HDF_FAILURE; 268e41f4b71Sopenharmony_ci } 269e41f4b71Sopenharmony_ci 270e41f4b71Sopenharmony_ci if (duration == 0) { 271e41f4b71Sopenharmony_ci HDF_LOGE("%s: vibrator duration invalid para!", __func__); 272e41f4b71Sopenharmony_ci return HDF_ERR_INVALID_PARAM; 273e41f4b71Sopenharmony_ci } 274e41f4b71Sopenharmony_ci 275e41f4b71Sopenharmony_ci if (drvData->mode != VIBRATOR_MODE_BUTT) { 276e41f4b71Sopenharmony_ci HDF_LOGI("%s: vibrater haptic is busy now, please stop first!", __func__); 277e41f4b71Sopenharmony_ci return HDF_ERR_DEVICE_BUSY; 278e41f4b71Sopenharmony_ci } 279e41f4b71Sopenharmony_ci 280e41f4b71Sopenharmony_ci (void)OsalMutexLock(&drvData->mutex); 281e41f4b71Sopenharmony_ci drvData->mode = VIBRATOR_MODE_ONCE; 282e41f4b71Sopenharmony_ci (void)OsalMutexUnlock(&drvData->mutex); 283e41f4b71Sopenharmony_ci 284e41f4b71Sopenharmony_ci config.cfgMode = VIBRATOR_MODE_ONCE; 285e41f4b71Sopenharmony_ci config.duration = duration; 286e41f4b71Sopenharmony_ci config.effect = NULL; 287e41f4b71Sopenharmony_ci /* Start haptics based on the vibration effect mode. */ 288e41f4b71Sopenharmony_ci ret = StartHaptic(&config); 289e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 290e41f4b71Sopenharmony_ci HDF_LOGE("%s: start haptic failed!", __func__); 291e41f4b71Sopenharmony_ci return ret; 292e41f4b71Sopenharmony_ci } 293e41f4b71Sopenharmony_ci 294e41f4b71Sopenharmony_ci return HDF_SUCCESS; 295e41f4b71Sopenharmony_ci } 296e41f4b71Sopenharmony_ci ``` 297e41f4b71Sopenharmony_ci 298e41f4b71Sopenharmony_ci - Implement **StartEffect()** for the vibrator abstract driver as follows: 299e41f4b71Sopenharmony_ci 300e41f4b71Sopenharmony_ci ```c 301e41f4b71Sopenharmony_ci /* Trigger a vibration with a given effect. */ 302e41f4b71Sopenharmony_ci static int32_t StartEffect(struct HdfSBuf *data, struct HdfSBuf *reply) 303e41f4b71Sopenharmony_ci { 304e41f4b71Sopenharmony_ci int32_t ret; 305e41f4b71Sopenharmony_ci const char *effect = NULL; 306e41f4b71Sopenharmony_ci struct VibratorEffectCfg config; 307e41f4b71Sopenharmony_ci struct VibratorDriverData *drvData = GetVibratorDrvData(); 308e41f4b71Sopenharmony_ci (void)reply; 309e41f4b71Sopenharmony_ci 310e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(data, HDF_FAILURE); 311e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE); 312e41f4b71Sopenharmony_ci /* Read the preset vibration effect from HdfSBuf and start the vibrator. */ 313e41f4b71Sopenharmony_ci effect = HdfSbufReadString(data); 314e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(effect, HDF_FAILURE); 315e41f4b71Sopenharmony_ci 316e41f4b71Sopenharmony_ci if (drvData->mode != VIBRATOR_MODE_BUTT) { 317e41f4b71Sopenharmony_ci HDF_LOGI("%s: vibrater haptic is busy now, please stop first!", __func__); 318e41f4b71Sopenharmony_ci return HDF_ERR_DEVICE_BUSY; 319e41f4b71Sopenharmony_ci } 320e41f4b71Sopenharmony_ci 321e41f4b71Sopenharmony_ci (void)OsalMutexLock(&drvData->mutex); 322e41f4b71Sopenharmony_ci drvData->mode = VIBRATOR_MODE_PRESET; 323e41f4b71Sopenharmony_ci (void)OsalMutexUnlock(&drvData->mutex); 324e41f4b71Sopenharmony_ci 325e41f4b71Sopenharmony_ci // Start one-shot vibration. 326e41f4b71Sopenharmony_ci config.cfgMode = VIBRATOR_MODE_PRESET; 327e41f4b71Sopenharmony_ci config.duration = 0; 328e41f4b71Sopenharmony_ci config.effect = effect; 329e41f4b71Sopenharmony_ci /* Start haptics with the preset effect. */ 330e41f4b71Sopenharmony_ci ret = StartHaptic(&config); 331e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 332e41f4b71Sopenharmony_ci HDF_LOGE("%s: start haptic failed!", __func__); 333e41f4b71Sopenharmony_ci return ret; 334e41f4b71Sopenharmony_ci } 335e41f4b71Sopenharmony_ci 336e41f4b71Sopenharmony_ci return HDF_SUCCESS; 337e41f4b71Sopenharmony_ci } 338e41f4b71Sopenharmony_ci ``` 339e41f4b71Sopenharmony_ci 340e41f4b71Sopenharmony_ci - Implement **Stop()** for the vibrator abstract driver as follows: 341e41f4b71Sopenharmony_ci 342e41f4b71Sopenharmony_ci ```c 343e41f4b71Sopenharmony_ci /* Stop vibration based on the specified vibration mode. */ 344e41f4b71Sopenharmony_ci static int32_t Stop(struct HdfSBuf *data, struct HdfSBuf *reply) 345e41f4b71Sopenharmony_ci { 346e41f4b71Sopenharmony_ci int32_t ret; 347e41f4b71Sopenharmony_ci int32_t mode; 348e41f4b71Sopenharmony_ci struct VibratorDriverData *drvData = GetVibratorDrvData(); 349e41f4b71Sopenharmony_ci (void)reply; 350e41f4b71Sopenharmony_ci 351e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(data, HDF_FAILURE); 352e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE); 353e41f4b71Sopenharmony_ci /* Read the specified vibration mode from HdfSBuf and then stop the vibration. */ 354e41f4b71Sopenharmony_ci if (!HdfSbufReadInt32(data, &mode)) { 355e41f4b71Sopenharmony_ci HDF_LOGE("%s: sbuf read mode failed!", __func__); 356e41f4b71Sopenharmony_ci return HDF_FAILURE; 357e41f4b71Sopenharmony_ci } 358e41f4b71Sopenharmony_ci 359e41f4b71Sopenharmony_ci if ((mode != VIBRATOR_MODE_ONCE) && (mode != VIBRATOR_MODE_PRESET)) { 360e41f4b71Sopenharmony_ci HDF_LOGE("%s: vibrator stop mode failed!", __func__); 361e41f4b71Sopenharmony_ci return HDF_FAILURE; 362e41f4b71Sopenharmony_ci } 363e41f4b71Sopenharmony_ci 364e41f4b71Sopenharmony_ci if (drvData->mode == VIBRATOR_MODE_BUTT) { 365e41f4b71Sopenharmony_ci HDF_LOGD("%s: vibrater haptic had stopped!", __func__); 366e41f4b71Sopenharmony_ci return HDF_SUCCESS; 367e41f4b71Sopenharmony_ci } 368e41f4b71Sopenharmony_ci /* Stop haptics and destroy the timer. */ 369e41f4b71Sopenharmony_ci ret = StopHaptic(); 370e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 371e41f4b71Sopenharmony_ci HDF_LOGE("%s: stop haptic failed!", __func__); 372e41f4b71Sopenharmony_ci return ret; 373e41f4b71Sopenharmony_ci } 374e41f4b71Sopenharmony_ci 375e41f4b71Sopenharmony_ci (void)OsalMutexLock(&drvData->mutex); 376e41f4b71Sopenharmony_ci drvData->mode = VIBRATOR_MODE_BUTT; 377e41f4b71Sopenharmony_ci (void)OsalMutexUnlock(&drvData->mutex); 378e41f4b71Sopenharmony_ci 379e41f4b71Sopenharmony_ci return HDF_SUCCESS; 380e41f4b71Sopenharmony_ci } 381e41f4b71Sopenharmony_ci ``` 382e41f4b71Sopenharmony_ci 383e41f4b71Sopenharmony_ci - Implement **GetVibratorInfo** for the vibrator abstract driver as follows: 384e41f4b71Sopenharmony_ci 385e41f4b71Sopenharmony_ci ```c 386e41f4b71Sopenharmony_ci /* Obtain vibrator information, including whether the intensity and frequency can be set and the intensity and frequency range. */ 387e41f4b71Sopenharmony_ci static int32_t GetVibratorInfo(struct HdfSBuf *data, struct HdfSBuf *reply) 388e41f4b71Sopenharmony_ci { 389e41f4b71Sopenharmony_ci (void)data; 390e41f4b71Sopenharmony_ci struct VibratorDriverData *drvData; 391e41f4b71Sopenharmony_ci 392e41f4b71Sopenharmony_ci drvData = GetVibratorDrvData(); 393e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM); 394e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(reply, HDF_ERR_INVALID_PARAM); 395e41f4b71Sopenharmony_ci 396e41f4b71Sopenharmony_ci if (!HdfSbufWriteBuffer(reply, &drvData->vibratorInfo, sizeof(drvData->vibratorInfo))) { 397e41f4b71Sopenharmony_ci HDF_LOGE("%s: write sbuf failed!", __func__); 398e41f4b71Sopenharmony_ci return HDF_FAILURE; 399e41f4b71Sopenharmony_ci } 400e41f4b71Sopenharmony_ci 401e41f4b71Sopenharmony_ci return HDF_SUCCESS; 402e41f4b71Sopenharmony_ci } 403e41f4b71Sopenharmony_ci ``` 404e41f4b71Sopenharmony_ci 405e41f4b71Sopenharmony_ci - Implement **EnableModulationParameter** for the vibrator abstract driver as follows: 406e41f4b71Sopenharmony_ci 407e41f4b71Sopenharmony_ci ```c 408e41f4b71Sopenharmony_ci /* Trigger vibration with the given duration, frequency, and intensity. */ 409e41f4b71Sopenharmony_ci static int32_t EnableModulationParameter(struct HdfSBuf *data, struct HdfSBuf *reply) 410e41f4b71Sopenharmony_ci { 411e41f4b71Sopenharmony_ci (void)reply; 412e41f4b71Sopenharmony_ci struct VibratorEffectCfg config; 413e41f4b71Sopenharmony_ci struct VibratorDriverData *drvData; 414e41f4b71Sopenharmony_ci uint32_t duration; 415e41f4b71Sopenharmony_ci uint16_t intensity; 416e41f4b71Sopenharmony_ci int16_t frequency; 417e41f4b71Sopenharmony_ci int32_t ret; 418e41f4b71Sopenharmony_ci 419e41f4b71Sopenharmony_ci drvData = GetVibratorDrvData(); 420e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM); 421e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData->ops.SetParameter, HDF_ERR_INVALID_PARAM); 422e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM); 423e41f4b71Sopenharmony_ci 424e41f4b71Sopenharmony_ci if (drvData->mode != VIBRATOR_MODE_BUTT) { 425e41f4b71Sopenharmony_ci HDF_LOGE("%s: vibrater is busy now, please stop first!", __func__); 426e41f4b71Sopenharmony_ci return HDF_ERR_DEVICE_BUSY; 427e41f4b71Sopenharmony_ci } 428e41f4b71Sopenharmony_ci 429e41f4b71Sopenharmony_ci if (!HdfSbufReadUint32(data, &duration)) { 430e41f4b71Sopenharmony_ci HDF_LOGE("%s: sbuf read vibration period failed!", __func__); 431e41f4b71Sopenharmony_ci return HDF_FAILURE; 432e41f4b71Sopenharmony_ci } 433e41f4b71Sopenharmony_ci 434e41f4b71Sopenharmony_ci if (!HdfSbufReadUint16(data, &intensity)) { 435e41f4b71Sopenharmony_ci HDF_LOGE("%s: sbuf read intensity failed!", __func__); 436e41f4b71Sopenharmony_ci return HDF_FAILURE; 437e41f4b71Sopenharmony_ci } 438e41f4b71Sopenharmony_ci 439e41f4b71Sopenharmony_ci if (!HdfSbufReadInt16(data, &frequency)) { 440e41f4b71Sopenharmony_ci HDF_LOGE("%s: sbuf read frequency failed!", __func__); 441e41f4b71Sopenharmony_ci return HDF_FAILURE; 442e41f4b71Sopenharmony_ci } 443e41f4b71Sopenharmony_ci 444e41f4b71Sopenharmony_ci (void)OsalMutexLock(&drvData->mutex); 445e41f4b71Sopenharmony_ci drvData->mode = VIBRATOR_MODE_ONCE; 446e41f4b71Sopenharmony_ci (void)OsalMutexUnlock(&drvData->mutex); 447e41f4b71Sopenharmony_ci 448e41f4b71Sopenharmony_ci ret = drvData->ops.SetParameter(intensity, frequency); 449e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 450e41f4b71Sopenharmony_ci HDF_LOGE("%s: set parameter failed!", __func__); 451e41f4b71Sopenharmony_ci return HDF_FAILURE; 452e41f4b71Sopenharmony_ci } 453e41f4b71Sopenharmony_ci 454e41f4b71Sopenharmony_ci config.cfgMode = VIBRATOR_MODE_ONCE; 455e41f4b71Sopenharmony_ci config.duration = duration; 456e41f4b71Sopenharmony_ci config.effect = NULL; 457e41f4b71Sopenharmony_ci /* Start haptics with the preset effect. */ 458e41f4b71Sopenharmony_ci ret = StartHaptic(&config); 459e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 460e41f4b71Sopenharmony_ci HDF_LOGE("%s: start haptic failed!", __func__); 461e41f4b71Sopenharmony_ci return HDF_FAILURE; 462e41f4b71Sopenharmony_ci } 463e41f4b71Sopenharmony_ci 464e41f4b71Sopenharmony_ci return HDF_SUCCESS; 465e41f4b71Sopenharmony_ci } 466e41f4b71Sopenharmony_ci ``` 467e41f4b71Sopenharmony_ci 468e41f4b71Sopenharmony_ci - Register the chipset-specific vibrator driver interfaces when the vibrator driver is successfully initialized. The implementation is as follows: 469e41f4b71Sopenharmony_ci 470e41f4b71Sopenharmony_ci ```c 471e41f4b71Sopenharmony_ci /* Register the chipset-specific vibrator driver interfaces. */ 472e41f4b71Sopenharmony_ci int32_t RegisterVibrator(struct VibratorOps *ops) 473e41f4b71Sopenharmony_ci { 474e41f4b71Sopenharmony_ci struct VibratorDriverData *drvData = GetVibratorDrvData(); 475e41f4b71Sopenharmony_ci 476e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(ops, HDF_FAILURE); 477e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE); 478e41f4b71Sopenharmony_ci 479e41f4b71Sopenharmony_ci (void)OsalMutexLock(&drvData->mutex); 480e41f4b71Sopenharmony_ci drvData->ops.Start = ops->Start; 481e41f4b71Sopenharmony_ci drvData->ops.StartEffect = ops->StartEffect; 482e41f4b71Sopenharmony_ci drvData->ops.Stop = ops->Stop; 483e41f4b71Sopenharmony_ci drvData->ops.SetParameter = ops->SetParameter; 484e41f4b71Sopenharmony_ci (void)OsalMutexUnlock(&drvData->mutex); 485e41f4b71Sopenharmony_ci 486e41f4b71Sopenharmony_ci return HDF_SUCCESS; 487e41f4b71Sopenharmony_ci } 488e41f4b71Sopenharmony_ci 489e41f4b71Sopenharmony_ci /* Register the VibratorInfo struct. */ 490e41f4b71Sopenharmony_ci int32_t RegisterVibratorInfo(struct VibratorInfo *vibratorInfo) 491e41f4b71Sopenharmony_ci { 492e41f4b71Sopenharmony_ci struct VibratorDriverData *drvData = GetVibratorDrvData(); 493e41f4b71Sopenharmony_ci 494e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(vibratorInfo, HDF_FAILURE); 495e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE); 496e41f4b71Sopenharmony_ci 497e41f4b71Sopenharmony_ci (void)OsalMutexLock(&drvData->mutex); 498e41f4b71Sopenharmony_ci if (memcpy_s(&drvData->vibratorInfo, sizeof(drvData->vibratorInfo), vibratorInfo, sizeof(*vibratorInfo)) != EOK) { 499e41f4b71Sopenharmony_ci HDF_LOGE("%s: Memcpy vibrator config failed", __func__); 500e41f4b71Sopenharmony_ci return HDF_FAILURE; 501e41f4b71Sopenharmony_ci } 502e41f4b71Sopenharmony_ci (void)OsalMutexUnlock(&drvData->mutex); 503e41f4b71Sopenharmony_ci 504e41f4b71Sopenharmony_ci return HDF_SUCCESS; 505e41f4b71Sopenharmony_ci } 506e41f4b71Sopenharmony_ci ``` 507e41f4b71Sopenharmony_ci 508e41f4b71Sopenharmony_ci1. Develop chipset-specific vibrator drivers. 509e41f4b71Sopenharmony_ci 510e41f4b71Sopenharmony_ci - 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**. 511e41f4b71Sopenharmony_ci 512e41f4b71Sopenharmony_ci The code is as follows: 513e41f4b71Sopenharmony_ci 514e41f4b71Sopenharmony_ci ```c 515e41f4b71Sopenharmony_ci device_linear_vibrator :: device { 516e41f4b71Sopenharmony_ci device0 :: deviceNode { 517e41f4b71Sopenharmony_ci policy = 1; // Policy for publishing the driver services. 518e41f4b71Sopenharmony_ci 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. 519e41f4b71Sopenharmony_ci 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. 520e41f4b71Sopenharmony_ci permission = 0664; // Permission for the DeviceNode created. 521e41f4b71Sopenharmony_ci moduleName = "HDF_LINEAR_VIBRATOR"; // Driver name, which must be the same as moduleName in the driver entry struct. 522e41f4b71Sopenharmony_ci serviceName = "hdf_misc_linear_vibrator"; // Unique name of the service released by the linear vibrator. 523e41f4b71Sopenharmony_ci 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. 524e41f4b71Sopenharmony_ci } 525e41f4b71Sopenharmony_ci } 526e41f4b71Sopenharmony_ci ``` 527e41f4b71Sopenharmony_ci 528e41f4b71Sopenharmony_ci - Configure the private HCS configuration of the chipset-specific vibrator driver. 529e41f4b71Sopenharmony_ci 530e41f4b71Sopenharmony_ci - For details, see **vendor\hihope\rk3568\hdf_config\khdf\vibrator\linear_vibrator_config.hcs**. 531e41f4b71Sopenharmony_ci 532e41f4b71Sopenharmony_ci - The code is as follows: 533e41f4b71Sopenharmony_ci 534e41f4b71Sopenharmony_ci ```c 535e41f4b71Sopenharmony_ci root { 536e41f4b71Sopenharmony_ci linearVibratorConfig { 537e41f4b71Sopenharmony_ci boardConfig { 538e41f4b71Sopenharmony_ci match_attr = "hdf_linear_vibrator_driver"; // The value must be the same as that of match_attr in the vibrator device configuration file. 539e41f4b71Sopenharmony_ci VibratorBusConfig { 540e41f4b71Sopenharmony_ci busType = 1; // 0 stands for I2C; 1 for GPIO. 541e41f4b71Sopenharmony_ci busNum = 154; 542e41f4b71Sopenharmony_ci } 543e41f4b71Sopenharmony_ci VibratorChipConfig { 544e41f4b71Sopenharmony_ci isSupportIntensity = 0; // Whether vibrator intensity can be set. The value 1 means the vibrator intensity can be set; the value 0 means the opposite. 545e41f4b71Sopenharmony_ci isSupportFrequency = 0; // Whether vibrator frequency can be set. The value 1 means the vibrator frequency can be set; the value 0 means the opposite. 546e41f4b71Sopenharmony_ci intensityMaxValue = 0; // Maximum vibrator intensity supported. 547e41f4b71Sopenharmony_ci intensityMinValue = 0; // Minimum vibrator intensity supported. 548e41f4b71Sopenharmony_ci frequencyMaxValue = 0; // Maximum vibrator frequency supported. 549e41f4b71Sopenharmony_ci frequencyMinValue = 0; // Minimum vibrator frequency supported. 550e41f4b71Sopenharmony_ci } 551e41f4b71Sopenharmony_ci } 552e41f4b71Sopenharmony_ci } 553e41f4b71Sopenharmony_ci } 554e41f4b71Sopenharmony_ci ``` 555e41f4b71Sopenharmony_ci 556e41f4b71Sopenharmony_ci - Implement the chipset-specific vibrator driver. For details, see **drivers\peripheral\vibrator\chipset\linear\vibrator_linear_driver.c**. 557e41f4b71Sopenharmony_ci 558e41f4b71Sopenharmony_ci - Define the **HdfDriverEntry** object of the chipset-specific vibrator driver. The driver entry function is defined as follows: 559e41f4b71Sopenharmony_ci 560e41f4b71Sopenharmony_ci ```c 561e41f4b71Sopenharmony_ci struct HdfDriverEntry g_linearVibratorDriverEntry = { 562e41f4b71Sopenharmony_ci .moduleVersion = 1, 563e41f4b71Sopenharmony_ci .moduleName = "HDF_LINEAR_VIBRATOR", 564e41f4b71Sopenharmony_ci .Bind = BindLinearVibratorDriver, 565e41f4b71Sopenharmony_ci .Init = InitLinearVibratorDriver, 566e41f4b71Sopenharmony_ci .Release = ReleaseLinearVibratorDriver, 567e41f4b71Sopenharmony_ci }; 568e41f4b71Sopenharmony_ci 569e41f4b71Sopenharmony_ci HDF_INIT(g_linearVibratorDriverEntry); 570e41f4b71Sopenharmony_ci ``` 571e41f4b71Sopenharmony_ci 572e41f4b71Sopenharmony_ci - Implement **Bind()** for the chipset-specific vibrator driver as follows: 573e41f4b71Sopenharmony_ci 574e41f4b71Sopenharmony_ci ```c 575e41f4b71Sopenharmony_ci int32_t BindLinearVibratorDriver(struct HdfDeviceObject *device) 576e41f4b71Sopenharmony_ci { 577e41f4b71Sopenharmony_ci struct VibratorLinearDriverData *drvData = NULL; 578e41f4b71Sopenharmony_ci 579e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(device, HDF_FAILURE); 580e41f4b71Sopenharmony_ci 581e41f4b71Sopenharmony_ci drvData = (struct VibratorLinearDriverData *)OsalMemCalloc(sizeof(*drvData)); 582e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_MALLOC_FAIL); 583e41f4b71Sopenharmony_ci 584e41f4b71Sopenharmony_ci drvData->ioService.Dispatch = DispatchLinearVibrator; 585e41f4b71Sopenharmony_ci drvData->device = device; 586e41f4b71Sopenharmony_ci device->service = &drvData->ioService; 587e41f4b71Sopenharmony_ci g_linearVibratorData = drvData; 588e41f4b71Sopenharmony_ci 589e41f4b71Sopenharmony_ci return HDF_SUCCESS; 590e41f4b71Sopenharmony_ci } 591e41f4b71Sopenharmony_ci ``` 592e41f4b71Sopenharmony_ci 593e41f4b71Sopenharmony_ci - Implement **Init()** for the chipset-specific vibrator driver as follows: 594e41f4b71Sopenharmony_ci 595e41f4b71Sopenharmony_ci ```c 596e41f4b71Sopenharmony_ci int32_t InitLinearVibratorDriver(struct HdfDeviceObject *device) 597e41f4b71Sopenharmony_ci { 598e41f4b71Sopenharmony_ci static struct VibratorOps ops; 599e41f4b71Sopenharmony_ci struct VibratorLinearDriverData *drvData = NULL; 600e41f4b71Sopenharmony_ci 601e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(device, HDF_FAILURE); 602e41f4b71Sopenharmony_ci 603e41f4b71Sopenharmony_ci drvData = (struct VibratorLinearDriverData *)device->service; 604e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE); 605e41f4b71Sopenharmony_ci 606e41f4b71Sopenharmony_ci ops.Start = StartLinearVibrator; 607e41f4b71Sopenharmony_ci ops.StartEffect = StartEffectLinearVibrator; 608e41f4b71Sopenharmony_ci ops.Stop = StopLinearVibrator; 609e41f4b71Sopenharmony_ci ops.SetParameter = NULL; 610e41f4b71Sopenharmony_ci 611e41f4b71Sopenharmony_ci if (RegisterVibratorOps(&ops) != HDF_SUCCESS) { 612e41f4b71Sopenharmony_ci HDF_LOGE("%s: register vibrator ops fail", __func__); 613e41f4b71Sopenharmony_ci return HDF_FAILURE; 614e41f4b71Sopenharmony_ci } 615e41f4b71Sopenharmony_ci 616e41f4b71Sopenharmony_ci drvData->linearCfgData = (struct VibratorCfgData *)OsalMemCalloc(sizeof(*drvData->linearCfgData)); 617e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData->linearCfgData, HDF_ERR_MALLOC_FAIL); 618e41f4b71Sopenharmony_ci /* Parse the vibrator configuration in the register. */ 619e41f4b71Sopenharmony_ci if (GetVibratorBaseConfigData(device->property, drvData->linearCfgData) != HDF_SUCCESS) { 620e41f4b71Sopenharmony_ci HDF_LOGE("%s: parser vibrator cfg fail", __func__); 621e41f4b71Sopenharmony_ci return HDF_FAILURE; 622e41f4b71Sopenharmony_ci } 623e41f4b71Sopenharmony_ci /* Register the vibrator information for initialization. */ 624e41f4b71Sopenharmony_ci if (RegisterVibratorInfo(&drvData->linearCfgData->vibratorInfo) != HDF_SUCCESS) { 625e41f4b71Sopenharmony_ci HDF_LOGE("%s: register vibrator info fail", __func__); 626e41f4b71Sopenharmony_ci return HDF_FAILURE; 627e41f4b71Sopenharmony_ci } 628e41f4b71Sopenharmony_ci 629e41f4b71Sopenharmony_ci if (GpioSetDir(drvData->linearCfgData->vibratorBus.GpioNum, GPIO_DIR_OUT) != HDF_SUCCESS) { 630e41f4b71Sopenharmony_ci HDF_LOGE("%s: set vibrator gpio fail", __func__); 631e41f4b71Sopenharmony_ci return HDF_FAILURE; 632e41f4b71Sopenharmony_ci } 633e41f4b71Sopenharmony_ci return HDF_SUCCESS; 634e41f4b71Sopenharmony_ci } 635e41f4b71Sopenharmony_ci ``` 636e41f4b71Sopenharmony_ci 637e41f4b71Sopenharmony_ci - Implement **Release()** for the chipset-specific vibrator driver as follows: 638e41f4b71Sopenharmony_ci 639e41f4b71Sopenharmony_ci ```c 640e41f4b71Sopenharmony_ci void ReleaseLinearVibratorDriver(struct HdfDeviceObject *device) 641e41f4b71Sopenharmony_ci { 642e41f4b71Sopenharmony_ci struct VibratorLinearDriverData *drvData = NULL; 643e41f4b71Sopenharmony_ci 644e41f4b71Sopenharmony_ci if (device == NULL) { 645e41f4b71Sopenharmony_ci HDF_LOGE("%s: Device is null", __func__); 646e41f4b71Sopenharmony_ci return; 647e41f4b71Sopenharmony_ci } 648e41f4b71Sopenharmony_ci drvData = (struct VibratorLinearDriverData *)device->service; 649e41f4b71Sopenharmony_ci if (drvData == NULL) { 650e41f4b71Sopenharmony_ci HDF_LOGE("%s: DrvData pointer is null", __func__); 651e41f4b71Sopenharmony_ci return; 652e41f4b71Sopenharmony_ci } 653e41f4b71Sopenharmony_ci 654e41f4b71Sopenharmony_ci OsalMemFree(drvData->linearCfgData); 655e41f4b71Sopenharmony_ci OsalMemFree(drvData); 656e41f4b71Sopenharmony_ci g_linearVibratorData = NULL; 657e41f4b71Sopenharmony_ci } 658e41f4b71Sopenharmony_ci ``` 659e41f4b71Sopenharmony_ci 660e41f4b71Sopenharmony_ci - Implement the internal interfaces of the chipset-specific vibrator driver as follows: 661e41f4b71Sopenharmony_ci 662e41f4b71Sopenharmony_ci ```c 663e41f4b71Sopenharmony_ci /* Start the vibrator. */ 664e41f4b71Sopenharmony_ci static int32_t StartLinearVibrator(void) 665e41f4b71Sopenharmony_ci { 666e41f4b71Sopenharmony_ci int32_t ret; 667e41f4b71Sopenharmony_ci struct VibratorLinearDriverData *drvData = GetLinearVibratorData(); 668e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE); 669e41f4b71Sopenharmony_ci 670e41f4b71Sopenharmony_ci if (drvData->linearCfgData->vibratorBus.busType != VIBRATOR_BUS_GPIO) { 671e41f4b71Sopenharmony_ci HDF_LOGE("%s: vibrator bus type not gpio", __func__); 672e41f4b71Sopenharmony_ci return HDF_FAILURE; 673e41f4b71Sopenharmony_ci } 674e41f4b71Sopenharmony_ci 675e41f4b71Sopenharmony_ci ret = GpioWrite(drvData->linearCfgData->vibratorBus.GpioNum, GPIO_VAL_HIGH); 676e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 677e41f4b71Sopenharmony_ci HDF_LOGE("%s: pull gpio%d to %d level failed", __func__, 678e41f4b71Sopenharmony_ci drvData->linearCfgData->vibratorBus.GpioNum, GPIO_VAL_HIGH); 679e41f4b71Sopenharmony_ci return ret; 680e41f4b71Sopenharmony_ci } 681e41f4b71Sopenharmony_ci return HDF_SUCCESS; 682e41f4b71Sopenharmony_ci } 683e41f4b71Sopenharmony_ci /* Start the vibrator based on the specified effect. */ 684e41f4b71Sopenharmony_ci static int32_t StartEffectLinearVibrator(uint32_t effectType) 685e41f4b71Sopenharmony_ci { 686e41f4b71Sopenharmony_ci (void)effectType; 687e41f4b71Sopenharmony_ci HDF_LOGE("%s: vibrator set built-in effect no support!", __func__); 688e41f4b71Sopenharmony_ci return HDF_SUCCESS; 689e41f4b71Sopenharmony_ci } 690e41f4b71Sopenharmony_ci /* Stop the vibrator. */ 691e41f4b71Sopenharmony_ci static int32_t StopLinearVibrator(void) 692e41f4b71Sopenharmony_ci { 693e41f4b71Sopenharmony_ci int32_t ret; 694e41f4b71Sopenharmony_ci struct VibratorLinearDriverData *drvData = GetLinearVibratorData(); 695e41f4b71Sopenharmony_ci CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE); 696e41f4b71Sopenharmony_ci 697e41f4b71Sopenharmony_ci if (drvData->linearCfgData->vibratorBus.busType != VIBRATOR_BUS_GPIO) { 698e41f4b71Sopenharmony_ci HDF_LOGE("%s: vibrator bus type not gpio", __func__); 699e41f4b71Sopenharmony_ci return HDF_FAILURE; 700e41f4b71Sopenharmony_ci } 701e41f4b71Sopenharmony_ci 702e41f4b71Sopenharmony_ci ret = GpioWrite(drvData->linearCfgData->vibratorBus.GpioNum, GPIO_VAL_LOW); 703e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 704e41f4b71Sopenharmony_ci HDF_LOGE("%s: pull gpio%d to %d level failed", __func__, 705e41f4b71Sopenharmony_ci drvData->linearCfgData->vibratorBus.GpioNum, GPIO_VAL_LOW); 706e41f4b71Sopenharmony_ci return ret; 707e41f4b71Sopenharmony_ci } 708e41f4b71Sopenharmony_ci return HDF_SUCCESS; 709e41f4b71Sopenharmony_ci } 710e41f4b71Sopenharmony_ci ``` 711e41f4b71Sopenharmony_ci 712e41f4b71Sopenharmony_ci 713e41f4b71Sopenharmony_ci 714e41f4b71Sopenharmony_ci### Verification 715e41f4b71Sopenharmony_ci 716e41f4b71Sopenharmony_ciAfter 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. 717e41f4b71Sopenharmony_ci 718e41f4b71Sopenharmony_ci- The reference test code is as follows: 719e41f4b71Sopenharmony_ci 720e41f4b71Sopenharmony_ci ```c 721e41f4b71Sopenharmony_ci #include <cmath> 722e41f4b71Sopenharmony_ci #include <cstdio> 723e41f4b71Sopenharmony_ci #include <gtest/gtest.h> 724e41f4b71Sopenharmony_ci #include <securec.h> 725e41f4b71Sopenharmony_ci #include "hdf_base.h" 726e41f4b71Sopenharmony_ci #include "osal_time.h" 727e41f4b71Sopenharmony_ci #include "vibrator_if.h" 728e41f4b71Sopenharmony_ci #include "vibrator_type.h" 729e41f4b71Sopenharmony_ci 730e41f4b71Sopenharmony_ci using namespace testing::ext; 731e41f4b71Sopenharmony_ci const struct VibratorInterface *g_vibratorDev = nullptr; 732e41f4b71Sopenharmony_ci static struct VibratorInfo *g_vibratorInfo = nullptr; 733e41f4b71Sopenharmony_ci 734e41f4b71Sopenharmony_ci class HdfVibratorTest : public testing::Test { 735e41f4b71Sopenharmony_ci public: 736e41f4b71Sopenharmony_ci static void SetUpTestCase(); 737e41f4b71Sopenharmony_ci static void TearDownTestCase(); 738e41f4b71Sopenharmony_ci void SetUp(); 739e41f4b71Sopenharmony_ci void TearDown(); 740e41f4b71Sopenharmony_ci }; 741e41f4b71Sopenharmony_ci /* Initialize the vibrator interface instance before executing test cases. */ 742e41f4b71Sopenharmony_ci void HdfVibratorTest::SetUpTestCase() 743e41f4b71Sopenharmony_ci { 744e41f4b71Sopenharmony_ci g_vibratorDev = NewVibratorInterfaceInstance(); 745e41f4b71Sopenharmony_ci } 746e41f4b71Sopenharmony_ci /* Release test case resources. */ 747e41f4b71Sopenharmony_ci void HdfVibratorTest::TearDownTestCase() 748e41f4b71Sopenharmony_ci { 749e41f4b71Sopenharmony_ci if(g_vibratorDev != nullptr){ 750e41f4b71Sopenharmony_ci FreeVibratorInterfaceInstance(); 751e41f4b71Sopenharmony_ci g_vibratorDev = nullptr; 752e41f4b71Sopenharmony_ci } 753e41f4b71Sopenharmony_ci } 754e41f4b71Sopenharmony_ci 755e41f4b71Sopenharmony_ci void HdfVibratorTest::SetUp() 756e41f4b71Sopenharmony_ci { 757e41f4b71Sopenharmony_ci } 758e41f4b71Sopenharmony_ci 759e41f4b71Sopenharmony_ci void HdfVibratorTest::TearDown() 760e41f4b71Sopenharmony_ci { 761e41f4b71Sopenharmony_ci } 762e41f4b71Sopenharmony_ci 763e41f4b71Sopenharmony_ci /* Verify one-short vibration. */ 764e41f4b71Sopenharmony_ci HWTEST_F(HdfVibratorTest, PerformOneShotVibratorDuration_001, TestSize.Level1) 765e41f4b71Sopenharmony_ci { 766e41f4b71Sopenharmony_ci uint32_t duration = 1000; 767e41f4b71Sopenharmony_ci uint32_t sleepTime = 2000; 768e41f4b71Sopenharmony_ci 769e41f4b71Sopenharmony_ci ASSERT_NE(nullptr, g_vibratorDev); 770e41f4b71Sopenharmony_ci 771e41f4b71Sopenharmony_ci int32_t startRet = g_vibratorDev->StartOnce(duration); 772e41f4b71Sopenharmony_ci EXPECT_EQ(startRet, HDF_SUCCESS); 773e41f4b71Sopenharmony_ci 774e41f4b71Sopenharmony_ci OsalMSleep(sleepTime); 775e41f4b71Sopenharmony_ci 776e41f4b71Sopenharmony_ci int32_t endRet = g_vibratorDev->Stop(VIBRATOR_MODE_ONCE); 777e41f4b71Sopenharmony_ci EXPECT_EQ(endRet, HDF_SUCCESS); 778e41f4b71Sopenharmony_ci } 779e41f4b71Sopenharmony_ci /* Verify vibration with the preset effect. */ 780e41f4b71Sopenharmony_ci HWTEST_F(HdfVibratorTest, ExecuteVibratorEffect_001, TestSize.Level1) 781e41f4b71Sopenharmony_ci { 782e41f4b71Sopenharmony_ci uint32_t sleepTime = 5000; 783e41f4b71Sopenharmony_ci const char *timeSequence = "haptic.clock.timer"; 784e41f4b71Sopenharmony_ci 785e41f4b71Sopenharmony_ci ASSERT_NE(nullptr, g_vibratorDev); 786e41f4b71Sopenharmony_ci 787e41f4b71Sopenharmony_ci int32_t startRet = g_vibratorDev->Start(timeSequence); 788e41f4b71Sopenharmony_ci EXPECT_EQ(startRet, HDF_SUCCESS); 789e41f4b71Sopenharmony_ci 790e41f4b71Sopenharmony_ci OsalMSleep(sleepTime); 791e41f4b71Sopenharmony_ci 792e41f4b71Sopenharmony_ci int32_t endRet = g_vibratorDev->Stop(VIBRATOR_MODE_PRESET); 793e41f4b71Sopenharmony_ci EXPECT_EQ(endRet, HDF_SUCCESS); 794e41f4b71Sopenharmony_ci } 795e41f4b71Sopenharmony_ci /* Obtain vibrator information, including whether the intensity and frequency can be set and the intensity and frequency range. */ 796e41f4b71Sopenharmony_ci HWTEST_F(HdfVibratorTest, GetVibratorInfo_001, TestSize.Level1) 797e41f4b71Sopenharmony_ci { 798e41f4b71Sopenharmony_ci ASSERT_NE(nullptr, g_vibratorDev); 799e41f4b71Sopenharmony_ci 800e41f4b71Sopenharmony_ci int32_t startRet = g_vibratorDev->GetVibratorInfo(&g_vibratorInfo); 801e41f4b71Sopenharmony_ci EXPECT_EQ(startRet, HDF_SUCCESS); 802e41f4b71Sopenharmony_ci EXPECT_NE(g_vibratorInfo, nullptr); 803e41f4b71Sopenharmony_ci 804e41f4b71Sopenharmony_ci printf("intensity = %d, intensityMaxValue = %d, intensityMinValue = %d\n\t", 805e41f4b71Sopenharmony_ci g_vibratorInfo->isSupportIntensity, g_vibratorInfo->intensityMaxValue, g_vibratorInfo->intensityMinValue); 806e41f4b71Sopenharmony_ci printf("frequency = %d, frequencyMaxValue = %d, frequencyMinValue = %d\n\t", 807e41f4b71Sopenharmony_ci g_vibratorInfo->isSupportFrequency, g_vibratorInfo->frequencyMaxValue, g_vibratorInfo->frequencyMinValue); 808e41f4b71Sopenharmony_ci } 809e41f4b71Sopenharmony_ci /* Trigger vibration with the given duration, frequency, and intensity. */ 810e41f4b71Sopenharmony_ci HWTEST_F(HdfVibratorTest, EnableVibratorModulation_001, TestSize.Level1) 811e41f4b71Sopenharmony_ci { 812e41f4b71Sopenharmony_ci int32_t startRet; 813e41f4b71Sopenharmony_ci int32_t intensity = 30; 814e41f4b71Sopenharmony_ci int32_t frequency = 200; 815e41f4b71Sopenharmony_ci uint32_t duration = 1000; 816e41f4b71Sopenharmony_ci uint32_t sleepTime = 2000; 817e41f4b71Sopenharmony_ci 818e41f4b71Sopenharmony_ci ASSERT_NE(nullptr, g_vibratorDev); 819e41f4b71Sopenharmony_ci 820e41f4b71Sopenharmony_ci if ((g_vibratorInfo->isSupportIntensity == 1) || (g_vibratorInfo->isSupportFrequency == 1)) { 821e41f4b71Sopenharmony_ci EXPECT_GE(intensity, g_vibratorInfo->intensityMinValue); 822e41f4b71Sopenharmony_ci EXPECT_LE(intensity, g_vibratorInfo->intensityMaxValue); 823e41f4b71Sopenharmony_ci EXPECT_GE(frequency, g_vibratorInfo->frequencyMinValue); 824e41f4b71Sopenharmony_ci EXPECT_LE(frequency, g_vibratorInfo->frequencyMaxValue); 825e41f4b71Sopenharmony_ci 826e41f4b71Sopenharmony_ci startRet = g_vibratorDev->EnableVibratorModulation(duration, intensity, duration); 827e41f4b71Sopenharmony_ci EXPECT_EQ(startRet, HDF_SUCCESS); 828e41f4b71Sopenharmony_ci OsalMSleep(sleepTime); 829e41f4b71Sopenharmony_ci startRet = g_vibratorDev->Stop(VIBRATOR_MODE_ONCE); 830e41f4b71Sopenharmony_ci EXPECT_EQ(startRet, HDF_SUCCESS); 831e41f4b71Sopenharmony_ci } 832e41f4b71Sopenharmony_ci } 833e41f4b71Sopenharmony_ci ``` 834e41f4b71Sopenharmony_ci 835e41f4b71Sopenharmony_ci- The reference code of the .gn file is as follows: 836e41f4b71Sopenharmony_ci 837e41f4b71Sopenharmony_ci ```c++ 838e41f4b71Sopenharmony_ci import("//build/ohos.gni") 839e41f4b71Sopenharmony_ci import("//build/test.gni") 840e41f4b71Sopenharmony_ci import("//drivers/hdf_core/adapter/uhdf2/uhdf.gni") 841e41f4b71Sopenharmony_ci 842e41f4b71Sopenharmony_ci module_output_path = "drivers_peripheral_vibrator/vibrator" 843e41f4b71Sopenharmony_ci ohos_unittest("vibrator_test") { 844e41f4b71Sopenharmony_ci module_out_path = module_output_path 845e41f4b71Sopenharmony_ci sources = [ "vibrator_test.cpp" ] 846e41f4b71Sopenharmony_ci include_dirs = [ 847e41f4b71Sopenharmony_ci "//drivers/peripheral/vibrator/interfaces/include", 848e41f4b71Sopenharmony_ci ] 849e41f4b71Sopenharmony_ci deps = [ "//drivers/peripheral/vibrator/hal:hdi_vibrator" ] 850e41f4b71Sopenharmony_ci 851e41f4b71Sopenharmony_ci external_deps = [ 852e41f4b71Sopenharmony_ci "c_utils:utils", 853e41f4b71Sopenharmony_ci "hdf_core:libhdf_utils", 854e41f4b71Sopenharmony_ci "hiviewdfx_hilog_native:libhilog", 855e41f4b71Sopenharmony_ci ] 856e41f4b71Sopenharmony_ci 857e41f4b71Sopenharmony_ci cflags = [ 858e41f4b71Sopenharmony_ci "-Wall", 859e41f4b71Sopenharmony_ci "-Wextra", 860e41f4b71Sopenharmony_ci "-Werror", 861e41f4b71Sopenharmony_ci "-Wno-format", 862e41f4b71Sopenharmony_ci "-Wno-format-extra-args", 863e41f4b71Sopenharmony_ci ] 864e41f4b71Sopenharmony_ci 865e41f4b71Sopenharmony_ci install_enable = true 866e41f4b71Sopenharmony_ci install_images = [ "vendor" ] 867e41f4b71Sopenharmony_ci module_install_dir = "bin" 868e41f4b71Sopenharmony_ci part_name = "unionman_products" 869e41f4b71Sopenharmony_ci } 870e41f4b71Sopenharmony_ci ``` 871