1# Sensor
2
3
4## Overview
5
6### Function
7
8The sensor driver model shields the hardware difference and provides interfaces for the upper-layer sensor service to implement basic sensor capabilities, including querying the sensor list, enabling or disabling a sensor, subscribing to or unsubscribing from sensor data changes, and setting sensor attributes. Developed based on the Hardware Driver Foundation (HDF), the sensor driver model leverages the capabilities of the OS adaptation layer (OSAL) and platform driver interfaces (such as I2C, SPI, and UART buses) to shield the difference between OSs and platform bus resources, achieving "one-time development and multi-system deployment" of the sensor driver. The figure below shows the architecture of the sensor driver model.
9
10**Figure 1** Sensor driver model
11
12![Sensor driver model](figures/sensor_driver_model.png)
13
14### Basic Concepts
15
16Currently, sensors are classified into the following types by sensor ID:
17
18- Medical sensors: The sensor IDs range from 128 to 160.
19
20- Traditional sensors: The sensor IDs are out of the range of 128 to 160.
21
22### Working Principles
23
24The following figure shows how a sensor driver works.
25
26**Figure 2** How a sensor driver works
27
28![How sensor driver works](figures/sensor_working.png)
29
30The following uses the acceleration sensor driver on the RK3568 development board of the standard system as an example to describe the driver loading and running process.
31
321. The sensor host reads the sensor device management configuration from **Sensor Host** in the **device_info.hcs** file.
332. The sensor host parses the sensor management configuration from the HCB database and associates the configuration with the sensor driver.
343. The sensor host loads and initializes the sensor manager driver.
354. The sensor manager driver publishes the sensor APIs for the hardware driver interface (HDI).
365. The sensor host reads the acceleration sensor driver configuration information from **Sensor Host** in the **device_info.hcs** configuration file.
376. The sensor host loads the acceleration sensor abstract driver and calls the initialization interface to allocate the sensor driver resources and create the data processing queue.
387. The sensor host reads the chipset driver configuration and private configuration of the acceleration sensor from the **accel_xxx_config.hcs** file.
398. The acceleration sensor chipset driver calls the common configuration parsing interface to parse the sensor attributes and registers.
409. The chipset driver detects sensors, allocates configuration resources to the acceleration sensor, and registers the acceleration sensor chipset interfaces.
4110. Upon successful sensor detection, the chipset driver instructs the abstract driver to register the acceleration sensor to the sensor manager driver.
42
43## Development Guidelines
44
45### When to Use
46
47- Data provided by the gravity and gyroscope sensors denotes the tilt and rotation of the device, which helps improve user experience in games.
48- Data provided by the proximity sensor denotes the distance between the device and a visible object, which enables the device to automatically turn on or off its screen accordingly to prevent accidental touch on the screen. For example, when the proximity sensor detects the user face approaches the earpiece during a call, it triggers backlight of the screen to be turned off. This prevents the screen from being accidentally touched and further reduces power consumption.
49- Data provided by the barometric pressure sensor helps your application accurately determine the altitude of the device.
50- Data provided by the ambient light sensor helps your device automatically adjust its backlight.
51- Data provided by the Hall effect sensor implements the smart cover mode of your device. When the smart cover is closed, a small window is opened on the phone to reduce power consumption.
52
53### Available APIs
54
55The sensor driver model offers the following APIs:
56
57- Sensor HDI APIs, for easier sensor service development
58- APIs for implementing sensor driver model capabilities
59  - APIs for loading, registering, and deregistering sensor drivers, and detecting sensors based on the HDF.
60  - Unified driver API, register configuration parsing API, bus access abstract API, and platform abstract API for the same type of sensors
61- APIs to be implemented by developers: Based on the HDF Configuration Source (HCS) and differentiated configuration for sensors of the same type, developers need to implement serialized configuration of sensor device parameters and some sensor device operation interfaces to simplify sensor driver development.
62
63The sensor driver model provides APIs for the hardware service to make sensor service development easier. See the table below.
64
65**Table 1** APIs of the sensor driver model
66
67**NOTE**<br>The following APIs are C interfaces. For details about the interface declaration, see [/drivers/peripheral/sensor/interfaces/include](https://gitee.com/openharmony/drivers_peripheral/tree/master/sensor/interfaces/include).
68
69| API| Description|
70| ----- | -------- |
71| int32_t GetAllSensors(struct SensorInformation **sensorInfo, int32_t *count) | Obtains information about all registered sensors in the system. The sensor information includes the sensor name, sensor vendor, firmware version, hardware version, sensor type ID, sensor ID, maximum range, accuracy, and power consumption.|
72| int32_t Enable(int32_t sensorId) | Enables a sensor. The subscriber can obtain sensor data only after the sensor is enabled.|
73| int32_t Disable(int32_t sensorId) | Disables a sensor.|
74| int32_t SetBatch(int32_t sensorId, int64_t samplingInterval, int64_t reportInterval) | Sets the sampling interval and data reporting interval for a sensor.|
75| int32_t SetMode(int32_t sensorId, int32_t mode) | Sets the data reporting mode for a sensor.|
76| int32_t SetOption(int32_t sensorId, uint32_t option) | Sets options for a sensor, including its range and accuracy.|
77| int32_t Register(int32_t groupId, RecordDataCallback cb) | Registers a sensor data callback based on the group ID.|
78| int32_t Unregister(int32_t groupId, RecordDataCallback cb) | Deregisters a sensor data callback based on the group ID.|
79
80The sensor driver model provides driver development APIs that do not require further implementation. See the table below.
81
82 **Table 2** Sensor driver development APIs
83
84| API| Description|
85| ----- | -------- |
86| int32_t AddSensorDevice(const struct SensorDeviceInfo *deviceInfo) | Adds a sensor of the current type to the sensor management module.|
87| int32_t DeleteSensorDevice(const struct SensorBasicInfo *sensorBaseInfo) | Deletes a sensor from the sensor management module.|
88| int32_t ReportSensorEvent(const struct SensorReportEvent *events) | Reports data of a specified sensor type.|
89| int32_t ReadSensor(struct SensorBusCfg *busCfg, uint16_t regAddr, uint8_t *data, uint16_t dataLen) | Reads sensor configuration data from the sensor register based on the bus configuration.|
90| int32_t WriteSensor(struct SensorBusCfg *busCfg, uint8_t *writeData, uint16_t len) | Writes sensor configuration data to the sensor register based on the bus configuration.|
91| int32_t SetSensorRegCfgArray(struct SensorBusCfg *busCfg, const struct SensorRegCfgGroupNode *group); | Sets the sensor register group configuration based on the sensor bus type.|
92| int32_t GetSensorBaseConfigData(const struct DeviceResourceNode *node, struct SensorCfgData *config) | Obtains basic configuration information such as sensor, bus, and attribute configurations based on the device information HCS configuration, and initializes the basic configuration data structure.|
93| int32_t ParseSensorRegConfig(struct SensorCfgData *config) | Parses the register group information based on the device information HCS configuration and initializes the configuration data structure.|
94| void ReleaseSensorAllRegConfig(struct SensorCfgData *config) | Releases the resources allocated to the sensor configuration data structure.|
95| int32_t GetSensorBusHandle(struct SensorBusCfg *busCfg) | Obtains the sensor bus handle information.|
96| int32_t ReleaseSensorBusHandle(struct SensorBusCfg *busCfg) | Releases the sensor bus handle information.|
97
98The sensor driver model also provides certain driver development APIs that need to be implemented by driver developers. See the table below.
99
100**Table 3** APIs to be implemented by driver developers
101
102| API| Description|
103| ----- | -------- |
104| int32_t init(void) | Initializes the sensor device configuration after a sensor is detected.|
105| int32_t Enable(void) | Enables the current sensor by delivering the register configuration in the enabling operation group based on the device information HCS configuration.|
106| int32_t Disable(void) | Disables the current sensor by delivering the register configuration in the disabling operation group based on the device information HCS configuration.|
107| int32_t SetBatch(int64_t samplingInterval, int64_t reportInterval) | Sets the processing time of the data reporting thread for the current sensor based on the sampling interval and data reporting interval.|
108| int32_t SetMode(int32_t mode) | Sets the data reporting mode of the current sensor device.|
109| int32_t SetOption(uint32_t option) | Sets the register configuration such as the range and accuracy based on sensor options.|
110| void ReadSensorData(void) | Reads sensor data.                                            |
111
112
113For details about the interface implementation, see [How to Develop](#how-to-develop).
114
115### How to Develop
116The following describes how to develop an acceleration sensor driver based on the HDF and the driver entry. Sensor driver development includes abstracted driver development and differentiated driver development. The abstracted driver development implements the common interfaces for different devices with the same sensor ID. The differentiated driver development implements device-specific interfaces.
117
1181. Develop the abstracted driver of the acceleration sensor.
119
120   - Configure the host information for the abstracted driver of the acceleration sensor in **vendor\hihope\rk3568\hdf_config\khdf\device_info\device_info.hcs**.
121
122     The code is as follows:
123
124     ```c
125     /* Device information HCS configuration of the acceleration sensor. */
126     device_sensor_accel :: device {
127         device0 :: deviceNode {
128             policy = 1;                                  // Policy for the driver to publish services.
129             priority = 100;                              // Priority (0–200) for starting the driver. A larger value indicates a lower priority. The recommended value is 100. If the priorities are the same, the device loading sequence is not ensured.
130             preload = 0;                                 // The value 0 means to load the driver by default during the startup of the system. The value 2 means the opposite.
131             permission = 0664;                           // Permission for the device node created.
132             moduleName = "HDF_SENSOR_ACCEL";             // Driver name. It must be the same as moduleName in the driver entry structure.
133             serviceName = "sensor_accel";                // Name of the service published by the driver. The name must be unique.
134             deviceMatchAttr = "hdf_sensor_accel_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.
135         }
136     }
137     ```
138
139   - Implement the abstracted driver of the acceleration sensor in **drivers\hdf_core\framework\model\sensor\driver\accel\sensor_accel_driver.c**.
140
141     - Define the **HdfDriverEntry** object of the abstracted driver. The driver entry function is defined as follows:
142
143       ```c
144       struct HdfDriverEntry g_sensorAccelDevEntry = {
145           .moduleVersion = 1,                // Version of the accelerometer sensor module.
146           .moduleName = "HDF_SENSOR_ACCEL",  // Name of the acceleration sensor module. The value must be the same as that of moduleName in the device_info.hcs file.
147           .Bind = BindAccelDriver,           // Function for binding an acceleration sensor.
148           .Init = InitAccelDriver,           // Function for initializing an acceleration sensor.
149           .Release = ReleaseAccelDriver      // Function for releasing acceleration sensor resources.
150       };
151
152       /* 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. */
153       HDF_INIT(g_sensorAccelDevEntry);
154       ```
155
156     - Implement **Bind()** for the abstracted driver of the acceleration sensor.
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     - Implement **Init()** for the abstracted driver of the acceleration sensor.
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       	 /* Initialize work queue resources. */
186           if (InitAccelData(drvData) != HDF_SUCCESS) {
187               HDF_LOGE("%s: Init accel config failed", __func__);
188               return HDF_FAILURE;
189           }
190       	/* Allocate acceleration configuration resources. */
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       	/* Register the register group information. */
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     - Implement **Release()** for the abstracted driver of the acceleration sensor. When the driver is unloaded or **Init()** fails, **Release()** can be used to release resources.
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       	/* Release the resources if the sensor is in position. */
215           if (drvData->detectFlag && drvData->accelCfg != NULL) {
216               AccelReleaseCfgData(drvData->accelCfg);
217           }
218
219           OsalMemFree(drvData->accelCfg);
220           drvData->accelCfg = NULL;
221       	/* Destroy the work queue resource if the sensor is in position. */
222           HdfWorkDestroy(&drvData->accelWork);
223           HdfWorkQueueDestroy(&drvData->accelWorkQueue);
224           OsalMemFree(drvData);
225       }
226       ```
227
228     - Implement the internal interfaces for the abstracted driver of the acceleration sensor.
229
230       - Implement the initialization interface provided for the differentiated driver. This interface parses the basic configuration information (acceleration sensor information, acceleration sensor bus configuration, and acceleration sensor detection register configuration) of the acceleration sensor, detects devices, and parses the device register. The initialization interface is implementation is as follows:
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         	/* Initialize the acceleration sensor. */
238             if (InitAccelOps(config, &deviceInfo) != HDF_SUCCESS) {
239                 HDF_LOGE("%s: Init accel ops failed", __func__);
240                 return HDF_FAILURE;
241             }
242         	/* Register the accelerometer device with the sensor device management module. */
243             if (AddSensorDevice(&deviceInfo) != HDF_SUCCESS) {
244                 HDF_LOGE("%s: Add accel device failed", __func__);
245                 return HDF_FAILURE;
246             }
247         	/* Parse the sensor register. */
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         	/* If the device is not in position, return to detect the next device. */
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         	/* Parse the basic sensor configuration. */
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         	/* If the device is not in position (the device ID exists), return to detect the next device. */
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         	/* Parse the sensor register. */
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       - Implement **Enable()** as follows.
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         	/* Set the register. */
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         	/* Create a timer. */
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         	/* Start the timer to report data. */
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       - Implement **Disable()** as follows.
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         	/* Set the register. */
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         	/* Delete the timer. */
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       - Implement **SetBatch()** as follows.
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         	/* Set the sampling rate for the timer. */
396             drvData->interval = samplingInterval;
397
398             return HDF_SUCCESS;
399         }
400         ```
401
402       - Implement **SetMode()** as follows.
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       - Implement **SetOption()** as follows.
417
418         ```c
419         static int32_t SetAccelOption(uint32_t option)
420         {
421             (void)option;
422             return HDF_SUCCESS;
423         }
424         ```
425
4262. Develop the differentiated drivers for acceleration sensors.
427
428   - Configure the host information for the differentiated driver of the acceleration sensor in **vendor\hihope\rk3568\hdf_config\khdf\device_info\device_info.hcs**.
429
430     The code is as follows:
431
432     ```c
433     device_sensor_mxc6655xa :: device {
434         device0 :: deviceNode {
435             policy = 1; 		    // Policy for publishing drive services.
436             priority = 120;          // Driver startup priority (0–200). A larger value indicates a lower priority. The default value 100 is recommended. The sequence for loading devices with the same priority is random.
437             preload = 0;             // Whether to load the driver on demand. The value 0 means to load the driver on demand, and 2 means the opposite.
438             permission = 0664;       // Permission for the driver to create a device node.
439             moduleName = "HDF_SENSOR_ACCEL_MXC6655XA";  // Driver name, which must be the same as moduleName in the driver entry structure.
440             serviceName = "hdf_accel_mxc6655xa";        // Name of the service published by acceleration mxc6655xa. It must be unique.
441             deviceMatchAttr = "hdf_sensor_accel_mxc6655xa_driver"; // Keyword for matching the private data of the driver. The value must be the same as the match_attr value in the private data configuration table of the driver.
442         }
443     }
444     ```
445
446   - Configure the private HCS for the differentiated driver of the acceleration sensor.
447
448     - Code path: **vendor\hihope\rk3568\hdf_config\khdf\sensor\accel\mxc6655xa_config.hcs**.
449
450     - The code is as follows:
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-defined 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;                   // 1 byte
471               }
472               sensorIdAttr :: sensorIdInfo {
473                   chipName = "mxc6655xa";
474                   chipIdRegister = 0x0f;
475                   chipIdValue = 0x05;             // Read the value based on the device ID register or check the value in the related chip 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   - Implement the code for the differentiated driver in **drivers\peripheral\sensor\chipset\accel\accel_mxc6655xa.c**.
525
526     - Define the **HdfDriverEntry** object corresponding to the acceleration sensor chipset driver. The driver entry function is defined as follows:
527
528       ```c
529       /* Register the entry struct object of the mxc6655xa acceleration sensor. */
530       struct HdfDriverEntry g_accelMxc6655xaDevEntry = {
531           .moduleVersion = 1,                         // Module version of the mxc6655xa acceleration sensor.
532           .moduleName = "HDF_SENSOR_ACCEL_MXC6655XA", // Module name of the mxc6655xa acceleration sensor. The value must be the same as the value of moduleName of the acceleration sensor in the device_info.hcs file.
533           .Bind = Mxc6655xaBindDriver,                // Bind function of the mxc6655xa acceleration sensor.
534           .Init = Mxc6655xaInitDriver,                // Init function of the mxc6655xa acceleration sensor.
535           .Release = Mxc6655xaReleaseDriver,          // Release function of the mxc6655xa acceleration sensor.
536       };
537       /* 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. */
538       HDF_INIT(g_accelMxc6655xaDevEntry);
539       ```
540
541     - Implement **Bind()** for the differentiated driver as follows.
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     - Implement **Init()** for the differentiated driver as follows.
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     - Implement **Release()** for the differentiated driver as follows.
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     - Implement the internal interfaces of the differentiated driver of the acceleration sensor.
618
619       You need to implement **ReadMxc6655xaData** and register it in **Mxc6655xaInitDriver**. The implementation is as follows:
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       /* Read the event data of the accelerator. Register this function in Mxc6655xaInitDriver() to pass in the data to the abstracted driver of the acceleration sensor. */
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### Verification
717
718After the driver is developed, develop test cases in the sensor unit test to verify the basic functions of the driver. Use the developer self-test platform as the test environment.
719
720- The reference test code is as follows:
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  /* Create a callback. */
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  /* Initialize the sensor interface instance before executing the test cases. */
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  /* Release case resources. */
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; /* Set the data sampling rate to 200000000, in the unit of nanoseconds (200 ms). */
789      int32_t reportInterval = 400000000;
790
791       /* 2. Register a sensor data callback. */
792      ret = g_sensorDev->Register(TRADITIONAL_SENSOR_TYPE, SensorDataCallback);
793      if (ret != 0) {
794          return;
795      }
796      printf("Register success\n");
797
798      /* 3. Obtain the list of sensors supported by the device. */
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. Set the sensor sampling rate. */
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. Enable the sensor. */
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. Disable the sensor. */
832          ret = g_sensorDev->Disable(sensorInfo[i].sensorId);
833          if (ret != 0) {
834              continue;
835          }
836          printf("Disable success\n");
837      }
838
839      /* 7. Unregister the sensor data callback. */
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- The reference code of the .gn file is as follows:
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