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![Vibrator driver model](figures/vibrator_driver_model.png)
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![](figures/vibrator_working.png)
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