1# Sensor
2
3
4## 概述
5
6### 功能简介
7
8Sensor驱动模型屏蔽硬件器件差异,为上层Sensor服务系统提供稳定的Sensor基础能力接口,包括Sensor列表查询、Sensor启停、Sensor订阅及取消订阅,Sensor参数配置等功能。Sensor设备驱动的开发是基于HDF驱动框架基础上,结合操作系统适配层(OSAL)和平台驱动接口(比如I2C/SPI/UART总线等平台资源)能力,屏蔽不同操作系统和平台总线资源差异,实现Sensor驱动“一次开发,多系统部署”的目标。Sensor驱动模型如图1所示。
9
10**图 1**  Sensor驱动模型图
11
12![Sensor驱动模型图](figures/Sensor驱动模型图.png)
13
14### 基本概念
15
16目前根据sensorId将Sensor分为医学类Sensor、传统类Sensor两种。
17
18- 医学类Sensor:已订阅的sensorId枚举值在128-160范围的为医学类Sensor。
19
20- 传统类Sensor:已订阅的sensorId枚举值不在128-160范围的为传统类Sensor。
21
22### 运作机制
23
24通过介绍Sensor驱动模型的加载以及运行流程,对模型内部关键组件以及关联组件之间的关系进行了划分,整体加载流程如图2所示:
25
26**图 2** Sensor驱动运行图
27
28![Sensor驱动运行图](figures/Sensor驱动运行图.png)
29
30Sensor驱动模型以标准系统RK3568产品中的加速度传感器驱动为例,介绍整个驱动加载及运行流程:
31
321. 从device_info.hcs配置文件中的Sensor Host读取到Sensor设备管理配置信息。
332. HDF配置框架从HCB数据库中解析Sensor设备管理配置信息,并关联对应设备驱动。
343. 加载并初始化Sensor设备管理驱动。
354. Sensor设备管理驱动向HDI发布Sensor基础能力接口。
365. 从device_info.hcs配置文件中的Sensor Host读取到加速度传感器驱动配置信息。
376. 加载加速度传感器抽象驱动,调用初始化接口,完成Sensor器件的驱动资源分配和数据处理队列的创建。
387. 从accel_xxx_config.hcs配置文件中读取到加速度传感器差异化驱动配置和私有化配置信息。
398. 加速度传感器芯片差异化驱动,调用通用配置解析接口,完成器件属性信息解析,器件寄存器解析。
409. 加速度传感器芯片差异化驱动完成器件的探测,并分配加速度传感器配置资源和加速度传感器差异化接口注册。
4110. 加速度传感器成功探测到器件之后,加速度传感器芯片差异化驱动通知加速度传感器抽象驱动,注册加速度传感器设备到Sensor设备管理中。
42
43## 开发指导
44
45### 场景介绍
46
47- 通过重力和陀螺仪传感器数据,能感知设备倾斜和旋转量,提高用户在游戏场景中的体验。
48- 通过接近光传感器数据,感知距离遮挡物的距离,使设备能够自动亮灭屏,达到防误触目的。例如,手机通话时,如屏幕距离人脸过近,则自动关闭屏幕,防止误触的同时降低功耗。
49- 通过气压计传感器数据,可以准确的判断设备当前所处的海拔。
50- 通过环境光传感器数据,设备能够实现背光自动调节。
51- 通过霍尔传感器数据,设备可以实现皮套功能,皮套合上,手机上开一个小窗口,可降低功耗。
52
53### 接口说明
54
55Sensor驱动模型对外开放的API接口能力如下:
56
57- 提供Sensor HDI(Hardware Device Interface)能力接口,简化服务开发。
58- 提供Sensor驱动模型能力接口:
59  - 依赖HDF驱动框架实现Sensor器件驱动的加载、器件探测、注册和去注册等能力。
60  - 提供同一类型Sensor器件驱动归一接口、寄存器配置解析操作接口、总线访问抽象接口和平台抽象接口。
61- 提供开发者实现的能力接口:依赖HDF驱动框架的HCS(HDF Configuration Source)配置管理,根据同类型Sensor差异化配置,实现Sensor器件参数序列化配置和器件部分操作接口,简化Sensor器件驱动开发。
62
63Sensor驱动模型对外开放的API接口能力的具体实现请参考:
64
65**表 1**  Sensor驱动模型对外API接口功能介绍
66
67注:以下接口列举的为C接口,接口声明见文件[/drivers/peripheral/sensor/interfaces/include](https://gitee.com/openharmony/drivers_peripheral/tree/master/sensor/interfaces/include)68
69| 接口名 | 功能描述 |
70| ----- | -------- |
71| int32_t GetAllSensors(struct SensorInformation **sensorInfo, int32_t *count) | 获取系统中注册的所有传感器信息,一组完整传感器信息包括传感器名字、设备厂商、固件版本号、硬件版本号、传感器类型编号、传感器标识、最大量程、精度、功耗。 |
72| int32_t Enable(int32_t sensorId) | 使能指定传感器设备,只有数据订阅者使能传感器后,才能获取订阅的传感器数据。 |
73| int32_t Disable(int32_t sensorId) | 去使能指定传感器设备。 |
74| int32_t SetBatch(int32_t sensorId, int64_t samplingInterval, int64_t reportInterval) | 设置指定传感器的数据采样间隔和数据上报间隔。 |
75| int32_t SetMode(int32_t sensorId, int32_t mode) | 设置指定传感器的工作模式,不同的工作模式,上报数据方式不同。 |
76| int32_t SetOption(int32_t sensorId, uint32_t option) | 设置指定传感器量程,精度等可选配置。 |
77| int32_t Register(int32_t groupId, RecordDataCallback cb) | 订阅者根据不同groupId注册传感器数据回调函数,系统会将获取到的传感器数据上报给订阅者。 |
78| int32_t Unregister(int32_t groupId, RecordDataCallback cb) | 订阅者根据groupId和回调函数注销对应订阅者的传感器数据回调函数。 |
79
80Sensor驱动模型对驱动开发者开放的功能接口,驱动开发者无需实现,直接使用,请参考:
81
82 **表2** Sensor驱动模型对驱动开发者开放的功能接口列表
83
84| 接口名 | 功能描述 |
85| ----- | -------- |
86| int32_t AddSensorDevice(const struct SensorDeviceInfo *deviceInfo) | 添加当前类型的传感器设备到传感器设备管理。 |
87| int32_t DeleteSensorDevice(const struct SensorBasicInfo *sensorBaseInfo) | 删除传感器设备管理里指定的传感器设备。 |
88| int32_t ReportSensorEvent(const struct SensorReportEvent *events) | 上报指定类型传感器的数据到用户侧。 |
89| int32_t ReadSensor(struct SensorBusCfg *busCfg, uint16_t regAddr, uint8_t *data, uint16_t dataLen) | 按照配置的总线方式,读取传感器寄存器配置数据。 |
90| int32_t WriteSensor(struct SensorBusCfg *busCfg, uint8_t *writeData, uint16_t len) | 按照配置的总线方式,将传感器配置数据写入寄存器。 |
91| int32_t SetSensorRegCfgArray(struct SensorBusCfg *busCfg, const struct SensorRegCfgGroupNode *group); | 根据传感器总线类型信息,下发寄存器分组配置。 |
92| int32_t GetSensorBaseConfigData(const struct DeviceResourceNode *node, struct SensorCfgData *config) | 根据传感器设备HCS资源配置,获取传感器信息,总线配置信息,属性配置等基本配置信息,并初始化对应的基本配置数据结构体。 |
93| int32_t ParseSensorRegConfig(struct SensorCfgData *config) | 根据传感器设备HCS资源配置,解析寄存器分组信息,并初始化配置数据结构体。 |
94| void ReleaseSensorAllRegConfig(struct SensorCfgData *config) | 释放传感器配置数据结构体里分配的资源。 |
95| int32_t GetSensorBusHandle(struct SensorBusCfg *busCfg) | 获取传感器总线句柄信息。 |
96| int32_t ReleaseSensorBusHandle(struct SensorBusCfg *busCfg) | 释放传感器句柄信息。 |
97
98Sensor驱动模型要求驱动开发者实现的接口功能,请参考:
99
100**表 3**  Sensor驱动模型要求驱动开发者实现的接口列表
101
102| 接口名 | 功能描述 |
103| ----- | -------- |
104| int32_t init(void) | 传感器设备探测成功后,需要对传感器设备初始化配置。 |
105| int32_t Enable(void) | 根据当前传感器设备的HCS配置,下发传感器设备使能操作组的寄存器配置。 |
106| int32_t Disable(void) | 根据当前传感器设备的HCS配置,下发传感器设备去使能操作组的寄存器配置。 |
107| int32_t SetBatch(int64_t samplingInterval, int64_t reportInterval) | 根据数据采样率和数据上报间隔,配置当前传感器设备的数据上报线程处理时间。 |
108| int32_t SetMode(int32_t mode) | 配置当前传感器设备数据上报方式。 |
109| int32_t SetOption(uint32_t option) | 根据可选配置、下发量程和精度等寄存器配置。 |
110| void ReadSensorData(void) | 读取传感器数据。                                             |
111
112
113接口实现参考[开发步骤](#开发步骤)章节。
114
115### 开发步骤
116基于HDF驱动框架,按照驱动Driver Entry程序,以加速度传感器驱动为例,介绍传感器驱动的开发。传感器的驱动开发包括抽象驱动开发和差异化驱动开发两部分。传感器的抽象驱动开发包括同一个传感器id中不同器件的公共接口实现;传感器的差异化驱动开发包括不同器件差异化接口的实现。
117
1181. 开发加速度传感器抽象驱动。
119
120   - 加速度传感器抽象驱动在Sensor Host中的配置信息,代码实现路径如下:vendor\hihope\rk3568\hdf_config\khdf\device_info\device_info.hcs121
122     具体代码实现如下:
123
124     ```c
125     /* 加速度计传感器设备HCS配置 */
126     device_sensor_accel :: device {
127         device0 :: deviceNode {
128             policy = 1;                                  // 驱动服务发布的策略
129             priority = 110;                              // 驱动启动优先级(0-200),值越大优先级越低,建议配置为100,优先级相同则不保证device的加载顺序
130             preload = 0;                                 // 驱动按需加载字段,0表示加载,2表示不加载
131             permission = 0664;                           // 驱动创建设备节点权限
132             moduleName = "HDF_SENSOR_ACCEL";             // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致
133             serviceName = "sensor_accel";                // 驱动对外发布服务的名称,必须唯一
134             deviceMatchAttr = "hdf_sensor_accel_driver"; // 驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等
135         }
136     }
137     ```
138
139   - 加速度传感器抽象驱动代码实现路径为:drivers\hdf_core\framework\model\sensor\driver\accel\sensor_accel_driver.c140
141     - 加速度传感器抽象驱动对应的HdfDriverEntry对象,其中,Driver Entry入口函数定义如下:
142
143       ```c
144       struct HdfDriverEntry g_sensorAccelDevEntry = {
145           .moduleVersion = 1,                // 加速度计传感器模块版本号
146           .moduleName = "HDF_SENSOR_ACCEL",  // 加速度计传感器模块名,要与device_info.hcs文件里的加速度计moduleName字段值一样
147           .Bind = BindAccelDriver,           // 加速度计传感器绑定函数
148           .Init = InitAccelDriver,           // 加速度计传感器初始化函数
149           .Release = ReleaseAccelDriver,     // 加速度计传感器资源释放函数
150       };
151
152       /* 调用HDF_INIT将驱动入口注册到HDF框架中。在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动。当Init调用异常时,HDF框架会调用Release释放驱动资源并退出 */
153       HDF_INIT(g_sensorAccelDevEntry);
154       ```
155
156     - 加速度传感器抽象驱动Bind接口实现如下:
157
158       ```c
159       int32_t AccelBindDriver(struct HdfDeviceObject *device)
160       {
161           CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
162
163           struct AccelDrvData *drvData = (struct AccelDrvData *)OsalMemCalloc(sizeof(*drvData));
164           if (drvData == NULL) {
165               HDF_LOGE("%s: Malloc accel drv data fail!", __func__);
166               return HDF_ERR_MALLOC_FAIL;
167           }
168
169           drvData->ioService.Dispatch = DispatchAccel;
170           drvData->device = device;
171           device->service = &drvData->ioService;
172           g_accelDrvData = drvData;
173           return HDF_SUCCESS;
174       }
175       ```
176
177     - 加速度传感器抽象驱动Init接口实现如下:
178
179       ```c
180       int32_t AccelInitDriver(struct HdfDeviceObject *device)
181       {
182           CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
183           struct AccelDrvData *drvData = (struct AccelDrvData *)device->service;
184           CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
185       	 /* 工作队列资源初始化 */
186           if (InitAccelData(drvData) != HDF_SUCCESS) {
187               HDF_LOGE("%s: Init accel config failed", __func__);
188               return HDF_FAILURE;
189           }
190       	/* 分配加速度配置信息资源 */
191           drvData->accelCfg = (struct SensorCfgData            *)OsalMemCalloc(sizeof(*drvData->accelCfg));
192           if (drvData->accelCfg == NULL) {
193               HDF_LOGE("%s: Malloc accel config data failed", __func__);
194               return HDF_FAILURE;
195           }
196       	/* 注册寄存器分组信息 */
197           drvData->accelCfg->regCfgGroup = &g_regCfgGroup[0];
198           drvData->cb = NULL;
199
200           HDF_LOGI("%s: Init accel driver success", __func__);
201           return HDF_SUCCESS;
202       }
203       ```
204
205     - 加速度抽象传感器驱动Release接口在驱动卸载或者Init执行失败时,会调用此接口释放资源,具体实现如下:
206
207       ```c
208       void AccelReleaseDriver(struct HdfDeviceObject *device)
209       {
210           CHECK_NULL_PTR_RETURN(device);
211
212           struct AccelDrvData *drvData = (struct AccelDrvData *)device->service;
213           CHECK_NULL_PTR_RETURN(drvData);
214       	/* 器件在位,释放已分配资源 */
215           if (drvData->detectFlag && drvData->accelCfg != NULL) {
216               AccelReleaseCfgData(drvData->accelCfg);
217           }
218
219           OsalMemFree(drvData->accelCfg);
220           drvData->accelCfg = NULL;
221       	/* 器件在位,销毁工作队列资源 */
222           HdfWorkDestroy(&drvData->accelWork);
223           HdfWorkQueueDestroy(&drvData->accelWorkQueue);
224           OsalMemFree(drvData);
225       }
226       ```
227
228     - 加速度传感器抽象驱动内部接口代码实现如下:
229
230       - 提供给差异化驱动的初始化接口,完成加速度传感器器件的基本配置信息解析(加速度传感器信息,加速度传感器总线配置,加速度传感器器件探测寄存器配置),器件探测,器件寄存器解析,具体实现如下:
231
232         ```c
233         static int32_t InitAccelAfterDetected(struct SensorCfgData *config)
234         {
235             struct SensorDeviceInfo deviceInfo;
236             CHECK_NULL_PTR_RETURN_VALUE(config, HDF_ERR_INVALID_PARAM);
237         	/* 初始化加速度计接口函数 */
238             if (InitAccelOps(config, &deviceInfo) != HDF_SUCCESS) {
239                 HDF_LOGE("%s: Init accel ops failed", __func__);
240                 return HDF_FAILURE;
241             }
242         	/* 注册加速度计器件到传感器设备管理模块 */
243             if (AddSensorDevice(&deviceInfo) != HDF_SUCCESS) {
244                 HDF_LOGE("%s: Add accel device failed", __func__);
245                 return HDF_FAILURE;
246             }
247         	/* 器件寄存器解析 */
248             if (ParseSensorDirection(config) != HDF_SUCCESS) {
249                 HDF_LOGE("%s: Parse accel direction failed", __func__);
250                 (void)DeleteSensorDevice(&config->sensorInfo);
251                 return HDF_FAILURE;
252             }
253
254             if (ParseSensorRegConfig(config) != HDF_SUCCESS) {
255                 HDF_LOGE("%s: Parse sensor register failed", __func__);
256                 (void)DeleteSensorDevice(&config->sensorInfo);
257                 ReleaseSensorAllRegConfig(config);
258                 ReleaseSensorDirectionConfig(config);
259                 return HDF_FAILURE;
260             }
261             return HDF_SUCCESS;
262         }
263
264         struct SensorCfgData *AccelCreateCfgData(const struct DeviceResourceNode *node)
265         {
266             struct AccelDrvData *drvData = AccelGetDrvData();
267         	/* 如果器件不在位,返回进行下个器件探测 */
268             if (drvData == NULL || node == NULL) {
269                 HDF_LOGE("%s: Accel node pointer NULL", __func__);
270                 return NULL;
271             }
272
273             if (drvData->detectFlag) {
274                 HDF_LOGE("%s: Accel sensor have detected", __func__);
275                 return NULL;
276             }
277
278             if (drvData->accelCfg == NULL) {
279                 HDF_LOGE("%s: Accel accelCfg pointer NULL", __func__);
280                 return NULL;
281             }
282         	/* 设备基本配置信息解析 */
283             if (GetSensorBaseConfigData(node, drvData->accelCfg) != HDF_SUCCESS) {
284                 HDF_LOGE("%s: Get sensor base config failed", __func__);
285                 goto BASE_CONFIG_EXIT;
286             }
287         	/* 如果器件不在位(存在器件ID的情况),返回进行下个器件探测 */
288             if (DetectSensorDevice(drvData->accelCfg) != HDF_SUCCESS) {
289                 HDF_LOGI("%s: Accel sensor detect device no exist", __func__);
290                 drvData->detectFlag = false;
291                 goto BASE_CONFIG_EXIT;
292             }
293         	/* 器件寄存器解析 */
294             drvData->detectFlag = true;
295             if (InitAccelAfterDetected(drvData->accelCfg) != HDF_SUCCESS) {
296                 HDF_LOGE("%s: Accel sensor detect device no exist", __func__);
297                 goto INIT_EXIT;
298             }
299             return drvData->accelCfg;
300
301         INIT_EXIT:
302             (void)ReleaseSensorBusHandle(&drvData->accelCfg->busCfg);
303         BASE_CONFIG_EXIT:
304             drvData->accelCfg->root = NULL;
305             (void)memset_s(&drvData->accelCfg->sensorInfo, sizeof(struct SensorBasicInfo), 0, sizeof(struct SensorBasicInfo));
306             (void)memset_s(&drvData->accelCfg->busCfg, sizeof(struct SensorBusCfg), 0, sizeof(struct SensorBusCfg));
307             (void)memset_s(&drvData->accelCfg->sensorAttr, sizeof(struct SensorAttr), 0, sizeof(struct SensorAttr));
308             return drvData->accelCfg;
309         }
310         ```
311
312       - Enable接口的代码实现如下:
313
314         ```c
315         static int32_t SetAccelEnable(void)
316         {
317             int32_t ret;
318             struct AccelDrvData *drvData = AccelGetDrvData();
319
320             CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
321             CHECK_NULL_PTR_RETURN_VALUE(drvData->accelCfg, HDF_ERR_INVALID_PARAM);
322
323             if (drvData->enable) {
324                 HDF_LOGE("%s: Accel sensor is enabled", __func__);
325                 return HDF_SUCCESS;
326             }
327         	/* 设置寄存器 */
328             ret = SetSensorRegCfgArray(&drvData->accelCfg->busCfg, drvData->accelCfg->regCfgGroup[SENSOR_ENABLE_GROUP]);
329             if (ret != HDF_SUCCESS) {
330                 HDF_LOGE("%s: Accel sensor enable config failed", __func__);
331                 return ret;
332             }
333         	/* 创建定时器 */
334             ret = OsalTimerCreate(&drvData->accelTimer, SENSOR_TIMER_MIN_TIME, AccelTimerEntry, (uintptr_t)drvData);
335             if (ret != HDF_SUCCESS) {
336                 HDF_LOGE("%s: Accel create timer failed[%d]", __func__, ret);
337                 return ret;
338             }
339         	/* 开启定时器进行数据上报 */
340             ret = OsalTimerStartLoop(&drvData->accelTimer);
341             if (ret != HDF_SUCCESS) {
342                 HDF_LOGE("%s: Accel start timer failed[%d]", __func__, ret);
343                 return ret;
344             }
345             drvData->enable = true;
346
347             return HDF_SUCCESS;
348         }
349         ```
350
351       - Disable接口的代码实现如下:
352
353         ```c
354         static int32_t SetAccelDisable(void)
355         {
356             int32_t ret;
357             struct AccelDrvData *drvData = AccelGetDrvData();
358
359             CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
360             CHECK_NULL_PTR_RETURN_VALUE(drvData->accelCfg, HDF_ERR_INVALID_PARAM);
361
362             if (!drvData->enable) {
363                 HDF_LOGE("%s: Accel sensor had disable", __func__);
364                 return HDF_SUCCESS;
365             }
366         	/* 设置寄存器 */
367             ret = SetSensorRegCfgArray(&drvData->accelCfg->busCfg, drvData->accelCfg->regCfgGroup[SENSOR_DISABLE_GROUP]);
368             if (ret != HDF_SUCCESS) {
369                 HDF_LOGE("%s: Accel sensor disable config failed", __func__);
370                 return ret;
371             }
372         	/* 删除定时器 */
373             ret = OsalTimerDelete(&drvData->accelTimer);
374             if (ret != HDF_SUCCESS) {
375                 HDF_LOGE("%s: Accel delete timer failed", __func__);
376                 return ret;
377             }
378             drvData->enable = false;
379
380             return HDF_SUCCESS;
381         }
382         ```
383
384       - SetBatch接口的代码实现如下:
385
386         ```c
387         static int32_t SetAccelBatch(int64_t samplingInterval, int64_t interval)
388         {
389             (void)interval;
390
391             struct AccelDrvData *drvData = NULL;
392
393             drvData = AccelGetDrvData();
394             CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
395         	/* 给定时器设置采样率 */
396             drvData->interval = samplingInterval;
397
398             return HDF_SUCCESS;
399         }
400         ```
401
402       - SetMode接口的代码实现如下:
403
404         ```c
405         static int32_t SetAccelMode(int32_t mode)
406         {
407             if (mode <= SENSOR_WORK_MODE_DEFAULT || mode >= SENSOR_WORK_MODE_MAX) {
408                 HDF_LOGE("%s: The current mode is not supported", __func__);
409                 return HDF_FAILURE;
410             }
411
412             return HDF_SUCCESS;
413         }
414         ```
415
416       - SetOption接口的代码实现如下:
417
418         ```c
419         static int32_t SetAccelOption(uint32_t option)
420         {
421             (void)option;
422             return HDF_SUCCESS;
423         }
424         ```
425
4262. 开发加速度传感器差异化驱动。
427
428   - 加速度传感器差异化驱动在Sensor Host中的配置信息,代码实现路径如下:vendor\hihope\rk3568\hdf_config\khdf\device_info\device_info.hcs429
430     具体代码实现如下:
431
432     ```c
433     device_sensor_mxc6655xa :: device {
434         device0 :: deviceNode {
435             policy = 1;		// policy字段是驱动服务发布的策略
436             priority = 120; // 驱动启动优先级(0-200),值越大优先级越低,建议配置为100,优先级相同则不保证device的加载顺序
437             preload = 0;    // 驱动按需加载字段,0表示加载,2表示不加载
438             permission = 0664; // 驱动创建设备节点权限
439             moduleName = "HDF_SENSOR_ACCEL_MXC6655XA"; // 驱动名称,该字段的值必须和驱动入口结构的moduleName值一致
440             serviceName = "hdf_accel_mxc6655xa"; // 加速度mxc6655xa对外发布服务的名称,必须唯一
441             deviceMatchAttr = "hdf_sensor_accel_mxc6655xa_driver"; // 加速度差异化驱动私有数据匹配的关键字,必须和驱动私有数据配置表中的match_attr值相等
442         }
443     }
444     ```
445
446   - 加速度传感器差异化驱动私有HCS配置:
447
448     - 代码实现路径:vendor\hihope\rk3568\hdf_config\khdf\sensor\accel\mxc6655xa_config.hcs449
450     - 具体代码实现如下:
451
452       ```c
453       #include "../sensor_common.hcs"
454       root {
455           accel_mxc6655xa_chip_config : sensorConfig {
456               match_attr = "hdf_sensor_accel_mxc6655xa_driver";
457               sensorInfo :: sensorDeviceInfo {
458                   sensorName = "accelerometer";
459                   vendorName = "memsi_mxc6655xa"; // max string length is 16 bytes
460                   sensorTypeId = 1; // enum SensorTypeTag
461                   sensorId = 1; // user define sensor id
462                   power = 230;
463                   minDelay = 5000000; // nanosecond
464                   maxDelay = 200000000; // nanosecond
465               }
466               sensorBusConfig :: sensorBusInfo {
467                   busType = 0; // 0:i2c 1:spi
468                   busNum = 5;
469                   busAddr = 0x15;
470                   regWidth = 1; // 1byte
471               }
472               sensorIdAttr :: sensorIdInfo {
473                   chipName = "mxc6655xa";
474                   chipIdRegister = 0x0f;
475                   chipIdValue = 0x05; // 根据器件ID寄存器,读取的值,或查看相关芯片datasheet手册确认该值
476               }
477               sensorDirection {
478                   direction = 1; // chip direction range of value:0-7
479                   /* <sign> 1:negative  0:positive
480                      <map> 0:AXIS_X  1:AXIS_Y  2:AXIS_Z
481                   */
482                   /* sign[AXIS_X], sign[AXIS_Y], sign[AXIS_Z], map[AXIS_X], map[AXIS_Y], map[AXIS_Z] */
483                   convert = [
484                       0, 0, 0, 0, 1, 2,
485                       1, 0, 0, 1, 0, 2,
486                       0, 0, 1, 0, 1, 2,
487                       0, 1, 0, 1, 0, 2,
488                       1, 0, 1, 0, 1, 2,
489                       0, 0, 1, 1, 0, 2,
490                       0, 1, 1, 0, 1, 2,
491                       1, 1, 1, 1, 0, 2
492                   ];
493               }
494               sensorRegConfig {
495                   /*  regAddr: register address
496                       value: config register value
497                       len: size of value
498                       mask: mask of value
499                       delay: config register delay time (ms)
500                       opsType: enum SensorOpsType 0-none 1-read 2-write 3-read_check 4-update_bit
501                       calType: enum SensorBitCalType 0-none 1-set 2-revert 3-xor 4-left shift 5-right shift
502                       shiftNum: shift bits
503                       debug: 0-no debug 1-debug
504                       save: 0-no save 1-save
505                   */
506                   /* regAddr, value, mask, len, delay, opsType, calType, shiftNum, debug, save */
507                   initSeqConfig = [
508                       0x7e,    0xb6, 0xff,   1,     5,       2,       0,        0,     0,    0,
509                       0x7e,    0x10, 0xff,   1,     5,       2,       0,        0,     0,    0
510                   ];
511                   enableSeqConfig = [
512                       0x7e,    0x11, 0xff,   1,     5,       2,       0,        0,     0,    0,
513                       0x41,    0x03, 0xff,   1,     0,       2,       0,        0,     0,    0,
514                       0x40,    0x08, 0xff,   1,     0,       2,       0,        0,     0,    0
515                   ];
516                   disableSeqConfig = [
517                       0x7e,    0x10, 0xff,   1,     5,       2,       0,        0,     0,    0
518                   ];
519               }
520           }
521       }
522       ```
523
524   - 加速度差异化驱动的代码实现路径:drivers\peripheral\sensor\chipset\accel\accel_mxc6655xa.c
525
526     - 加速度传感器差异化驱动对应的HdfDriverEntry对象,其中,Driver Entry入口函数定义如下:
527
528       ```c
529       /* 注册加速度mxc6655xa传感器入口数据结构体对象 */
530       struct HdfDriverEntry g_accelMxc6655xaDevEntry = {
531           .moduleVersion = 1, // 加速度mxc6655xa传感器模块版本号
532           .moduleName = "HDF_SENSOR_ACCEL_MXC6655XA", // 加速度mxc6655xa传感器模块名,要与device_info.hcs文件里加速度mxc6655xa传感器moduleName字段值一致
533           .Bind = Mxc6655xaBindDriver, // 加速度mxc6655xa传感器的绑定函数
534           .Init = Mxc6655xaInitDriver, // 加速度mxc6655xa传感器的初始化函数
535           .Release = Mxc6655xaReleaseDriver, // 加速度mxc6655xa传感器资源释放函数
536       };
537       /* 调用HDF_INIT将驱动入口注册到HDF框架中,在加载驱动时HDF框架会先调用Bind函数,再调用Init函数加载该驱动,当Init调用异常时,HDF框架会调用Release释放驱动资源并退出 */
538       HDF_INIT(g_accelMxc6655xaDevEntry);
539       ```
540
541     - 加速度传感器差异化驱动Bind接口实现如下:
542
543       ```c
544       int32_t Mxc6655xaBindDriver(struct HdfDeviceObject *device)
545       {
546           CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
547
548           struct Mxc6655xaDrvData *drvData = (struct Mxc6655xaDrvData *)OsalMemCalloc(sizeof(*drvData));
549           if (drvData == NULL) {
550               HDF_LOGE("%s: Malloc MXC6655XA drv data fail", __func__);
551               return HDF_ERR_MALLOC_FAIL;
552           }
553
554           drvData->ioService.Dispatch = DispatchMXC6655xa;
555           drvData->device = device;
556           device->service = &drvData->ioService;
557           g_mxc6655xaDrvData = drvData;
558
559           return HDF_SUCCESS;
560       }
561       ```
562
563     - 加速度传感器差异化驱动Init接口实现如下:
564
565       ```c
566       int32_t Mxc6655xaInitDriver(struct HdfDeviceObject *device)
567       {
568           int32_t ret;
569           struct AccelOpsCall ops;
570
571           CHECK_NULL_PTR_RETURN_VALUE(device, HDF_ERR_INVALID_PARAM);
572           struct Mxc6655xaDrvData *drvData = (struct Mxc6655xaDrvData *)device->service;
573           CHECK_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_INVALID_PARAM);
574
575           drvData->sensorCfg = AccelCreateCfgData(device->property);
576           if (drvData->sensorCfg == NULL || drvData->sensorCfg->root == NULL) {
577               HDF_LOGD("%s: Creating accelcfg failed because detection failed", __func__);
578               return HDF_ERR_NOT_SUPPORT;
579           }
580
581           ops.Init = NULL;
582           ops.ReadData = ReadMxc6655xaData;
583           ret = AccelRegisterChipOps(&ops);
584           if (ret != HDF_SUCCESS) {
585               HDF_LOGE("%s: Register MXC6655XA accel failed", __func__);
586               return HDF_FAILURE;
587           }
588
589           ret = InitMxc6655xa(drvData->sensorCfg);
590           if (ret != HDF_SUCCESS) {
591               HDF_LOGE("%s: Init MXC6655XA accel failed", __func__);
592               return HDF_FAILURE;
593           }
594
595           return HDF_SUCCESS;
596       }
597       ```
598
599     - 加速度传感器差异化驱动Release接口实现如下:
600
601       ```c
602       void Mxc6655xaReleaseDriver(struct HdfDeviceObject *device)
603       {
604           CHECK_NULL_PTR_RETURN(device);
605
606           struct Mxc6655xaDrvData *drvData = (struct Mxc6655xaDrvData *)device->service;
607           CHECK_NULL_PTR_RETURN(drvData);
608
609           if (drvData->sensorCfg != NULL) {
610               AccelReleaseCfgData(drvData->sensorCfg);
611               drvData->sensorCfg = NULL;
612           }
613           OsalMemFree(drvData);
614       }
615       ```
616
617     - 加速度传感器差异化驱动内部接口实现。
618
619       需要开发者实现的ReadMxc6655xaData接口函数,在 Mxc6655xaInitDriver函数里面注册此函数,具体实现如下:
620
621       ```c
622       static int32_t ReadMxc6655xaRawData(struct SensorCfgData *data, struct AccelData *rawData, uint64_t *timestamp)
623       {
624           uint8_t status = 0;
625           uint8_t reg[ACCEL_AXIS_BUTT];
626           OsalTimespec time;
627           int32_t x;
628           int32_t y;
629           int32_t z;
630
631           (void)memset_s(&time, sizeof(time), 0, sizeof(time));
632           (void)memset_s(reg, sizeof(reg), 0, sizeof(reg));
633
634           CHECK_NULL_PTR_RETURN_VALUE(data, HDF_ERR_INVALID_PARAM);
635
636           if (OsalGetTime(&time) != HDF_SUCCESS) {
637               HDF_LOGE("%s: Get time failed", __func__);
638               return HDF_FAILURE;
639           }
640           *timestamp = time.sec * SENSOR_SECOND_CONVERT_NANOSECOND + time.usec * SENSOR_CONVERT_UNIT; /* unit nanosecond */
641
642           int32_t ret = ReadSensor(&data->busCfg, MXC6655XA_STATUS_ADDR, &status, sizeof(uint8_t));
643           if (ret != HDF_SUCCESS) {
644               HDF_LOGE("%s: data status [%u] ret [%d]", __func__, status, ret);
645               return HDF_FAILURE;
646           }
647
648           ret = ReadSensor(&data->busCfg, MXC6655XA_ACCEL_X_LSB_ADDR, &reg[ACCEL_X_AXIS_LSB], sizeof(uint8_t));
649           CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
650
651           ret = ReadSensor(&data->busCfg, MXC6655XA_ACCEL_X_MSB_ADDR, &reg[ACCEL_X_AXIS_MSB], sizeof(uint8_t));
652           CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
653
654           ret = ReadSensor(&data->busCfg, MXC6655XA_ACCEL_Y_LSB_ADDR, &reg[ACCEL_Y_AXIS_LSB], sizeof(uint8_t));
655           CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
656
657           ret = ReadSensor(&data->busCfg, MXC6655XA_ACCEL_Y_MSB_ADDR, &reg[ACCEL_Y_AXIS_MSB], sizeof(uint8_t));
658           CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
659
660           ret = ReadSensor(&data->busCfg, MXC6655XA_ACCEL_Z_LSB_ADDR, &reg[ACCEL_Z_AXIS_LSB], sizeof(uint8_t));
661           CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
662
663           ret = ReadSensor(&data->busCfg, MXC6655XA_ACCEL_Z_MSB_ADDR, &reg[ACCEL_Z_AXIS_MSB], sizeof(uint8_t));
664           CHECK_PARSER_RESULT_RETURN_VALUE(ret, "read data");
665
666           x = SensorConvertData(reg[ACCEL_X_AXIS_MSB], reg[ACCEL_X_AXIS_LSB]);
667           y = SensorConvertData(reg[ACCEL_Y_AXIS_MSB], reg[ACCEL_Y_AXIS_LSB]);
668           z = SensorConvertData(reg[ACCEL_Z_AXIS_MSB], reg[ACCEL_Z_AXIS_LSB]);
669           rawData->x = x;
670           rawData->y = y;
671           rawData->z = z;
672
673           return HDF_SUCCESS;
674       }
675       /* 读取加速度的event数据,在 Mxc6655xaInitDriver函数里面注册此函数,将数据传给加速度抽象驱动 */
676       int32_t ReadMxc6655xaData(struct SensorCfgData *cfg, struct SensorReportEvent *event)
677       {
678           int32_t ret;
679           struct AccelData rawData = { 0, 0, 0 };
680           static int32_t tmp[ACCEL_AXIS_NUM];
681
682           CHECK_NULL_PTR_RETURN_VALUE(cfg, HDF_ERR_INVALID_PARAM);
683           CHECK_NULL_PTR_RETURN_VALUE(event, HDF_ERR_INVALID_PARAM);
684
685           ret = ReadMxc6655xaRawData(cfg, &rawData, &event->timestamp);
686           if (ret != HDF_SUCCESS) {
687               HDF_LOGE("%s: MXC6655XA read raw data failed", __func__);
688               return HDF_FAILURE;
689           }
690
691           event->sensorId = SENSOR_TAG_ACCELEROMETER;
692           event->option = 0;
693           event->mode = SENSOR_WORK_MODE_REALTIME;
694
695           rawData.x = rawData.x * MXC6655XA_ACC_SENSITIVITY_2G;
696           rawData.y = rawData.y * MXC6655XA_ACC_SENSITIVITY_2G;
697           rawData.z = rawData.z * MXC6655XA_ACC_SENSITIVITY_2G;
698
699           tmp[ACCEL_X_AXIS] = (rawData.x * SENSOR_CONVERT_UNIT) / SENSOR_CONVERT_UNIT;
700           tmp[ACCEL_Y_AXIS] = (rawData.y * SENSOR_CONVERT_UNIT) / SENSOR_CONVERT_UNIT;
701           tmp[ACCEL_Z_AXIS] = (rawData.z * SENSOR_CONVERT_UNIT) / SENSOR_CONVERT_UNIT;
702
703           ret = SensorRawDataToRemapData(cfg->direction, tmp, sizeof(tmp) / sizeof(tmp[0]));
704           if (ret != HDF_SUCCESS) {
705               HDF_LOGE("%s: MXC6655XA convert raw data failed", __func__);
706               return HDF_FAILURE;
707           }
708
709           event->dataLen = sizeof(tmp);
710           event->data = (uint8_t *)&tmp;
711
712           return ret;
713       }
714       ```
715
716### 调测验证
717
718驱动开发完成后,在传感器单元测试里面开发自测试用例,验证驱动基本功能。测试环境采用开发者自测试平台。
719
720- 参考测试代码如下:
721
722  ```c
723  #include <cmath>
724  #include <cstdio>
725  #include <unistd.h>
726  #include <gtest/gtest.h>
727  #include <securec.h>
728  #include "hdf_base.h"
729  #include "osal_mem.h"
730  #include "osal_time.h"
731  #include "sensor_if.h"
732  #include "sensor_type.h"
733
734  using namespace testing::ext;
735  const struct SensorInterface *g_sensorDev = nullptr;
736  /* 创建回调函数 */
737  static int32_t SensorDataCallback(const struct SensorEvents *event)
738  {
739      if (event == NULL) {
740          return HDF_FAILURE;
741      }
742
743      float *data = (float*)event->data;
744      printf("time [%lld] sensor id [%d] x-[%f] y-[%f] z-[%f]\n\r", event->timestamp,
745          event->sensorId, (*data), *(data + 1), *(data + 2));
746
747      return HDF_SUCCESS;
748  }
749
750  class HdfSensorTest : public testing::Test {
751  public:
752      static void SetUpTestCase();
753      static void TearDownTestCase();
754      void SetUp();
755      void TearDown();
756  };
757
758  /* 用例执行前,初始化传感器接口实例 */
759  void HdfSensorTest::SetUpTestCase()
760  {
761      g_sensorDev = NewSensorInterfaceInstance();
762      if (g_sensorDev == nullptr) {
763          printf("test sensor get module instance failed\n\r");
764      }
765  }
766  /* 用例资源释放 */
767  void HdfSensorTest::TearDownTestCase()
768  {
769      if (g_sensorDev != nullptr) {
770          FreeSensorInterfaceInstance();
771          g_sensorDev = nullptr;
772      }
773  }
774
775  void HdfSensorTest::SetUp()
776  {
777  }
778
779  void HdfSensorTest::TearDown()
780  {
781  }
782
783  HWTEST_F(HdfSensorTest,TestAccelDriver_001, TestSize.Level0)
784  {
785      int ret;
786      struct SensorInformation *sensorInfo = NULL;
787      int32_t count = 0;
788      int32_t sensorInterval = 200000000; /* 数据采样率设置200毫秒,单位纳秒 */
789      int32_t reportInterval = 400000000;
790
791      /* 2.订阅者注册传感器数据回调处理函数 */
792      ret = g_sensorDev->Register(TRADITIONAL_SENSOR_TYPE, SensorDataCallback);
793      if (ret != 0) {
794          return;
795      }
796      printf("Register success\n");
797
798      /* 3.获取设备支持的Sensor列表 */
799      ret = g_sensorDev->GetAllSensors(&sensorInfo, &count);
800      if (ret != 0) {
801          return;
802      }
803
804      printf("GetAllSensors count: %d\n", count);
805
806      for (int i = 0; i < count; i++)
807      {
808          printf("sensor [%d]: sensorName: %s, vendorName: %s, sensorTypeId: %d, sensorId: %d\n", i,
809                 sensorInfo[i].sensorName, sensorInfo[i].vendorName, sensorInfo[i].sensorTypeId, sensorInfo[i].sensorId);
810      }
811
812      for (int i = 0; i < count; i++)
813      {
814          /* 4.设置传感器采样率 */
815          ret = g_sensorDev->SetBatch(sensorInfo[i].sensorId, sensorInterval, reportInterval);
816          if (ret != 0) {
817              printf("SetBatch failed\n ,ret: %d",ret);
818              continue;
819          }
820          printf("SetBatch success\n");
821
822          /* 5.使能传感器 */
823          ret = g_sensorDev->Enable(sensorInfo[i].sensorId);
824          if (ret != 0) {
825              continue;
826          }
827       printf("Enable success\n");
828
829       usleep(1000 * 1000);
830
831          /* 6.去使能传感器 */
832          ret = g_sensorDev->Disable(sensorInfo[i].sensorId);
833          if (ret != 0) {
834              continue;
835          }
836          printf("Disable success\n");
837      }
838
839      /* 7.取消传感器数据订阅函数 */
840      ret = g_sensorDev->Unregister(TRADITIONAL_SENSOR_TYPE, SensorDataCallback);
841      if (ret != 0) {
842          return;
843      }
844      printf("Unregister success\n");
845  }
846  ```
847
848- 编译文件gn参考代码如下:
849
850  ```
851  import("//build/ohos.gni")
852  import("//build/test.gni")
853  import("//drivers/hdf_core/adapter/uhdf2/uhdf.gni")
854
855  module_output_path = "drivers_peripheral_sensor/sensor"
856  ohos_unittest("sensor_test") {
857    module_out_path = module_output_path
858    sources = [ "sensor_test.cpp" ]
859    include_dirs = [
860      "//drivers/peripheral/sensor/interfaces/include",
861    ]
862    deps = [ "//drivers/peripheral/sensor/hal:hdi_sensor" ]
863
864    external_deps = [
865      "c_utils:utils",
866      "hdf_core:libhdf_utils",
867      "hiviewdfx_hilog_native:libhilog",
868    ]
869
870    cflags = [
871      "-Wall",
872      "-Wextra",
873      "-Werror",
874      "-Wno-format",
875      "-Wno-format-extra-args",
876    ]
877
878    install_enable = true
879    install_images = [ "vendor" ]
880    module_install_dir = "bin"
881    part_name = "unionman_products"
882  }
883  ```
884
885