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