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 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 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.hcs。 121 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.c。 140 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.hcs。 429 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.hcs。 449 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, ®[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 /* 读取加速度的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