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 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 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, ®[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, ®[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, ®[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, ®[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, ®[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, ®[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