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