Sensor HAL Library
android的通用HAL接口,高通实现了自己的部分,相关文件为sensors_hal.cpp
sensor1 remoting layer(libsensor1)
这是一个通信库,通过该库函数提供的API可以允许客户端向SensorDaemon服务端请求消息或者接收来自服务端的消息。
SensorDaemon
用户空间的一个后台守护进程,用于监听sensor客户端的请求以及通过共享内存与DSPS通信。
这三部分的代码结构如下:
那么DSPS是什么呢? 今天我们主要了解下DSPS架构和重要组成部分,
有些知识点会涉及QMI的相关技术QCCI以及QCSI,之前的博客我们也讲解了相关的接口定义,请点击复习
如标题所述,DSPS即Dedicated Sensors Processor Subsystem,专用传感器处理器子系统。
下面这张图完整的展示了整个Sensor模块DSPS相关的架构图,包括我们的DSPS部分。
我们重点从图中标注的6部分来看,各个部分主要功能是什么。
首先第一部分即Device Driver Framework板块。
这部分即高通的设备驱动框架,而sensor相关的代码则在adsp_proc/Sensors/ddf/下,而驱动代码则在dd路径下,
DDF的主要功能如下:
在DDF中有一个非常重要的接口我们已经在之前的相关文章中见过,即sns_ddf_driver_if_s:
typedef struct
{
/**
* 初始化驱动并且开启sensor设备
* 主要工作: 1. 分配一个驱动实例句柄 2. 打开相关设备的通信端口
* 3. 配置驱动和设备,将设备设到默认的电源状态
*/
sns_ddf_status_e (*init)(
sns_ddf_handle_t* dd_handle_ptr,
sns_ddf_handle_t smgr_handle,
sns_ddf_nv_params_s* nv_params,
sns_ddf_device_access_s device_info[],
uint32_t num_devices,
sns_ddf_memhandler_s* memhandler,
sns_ddf_sensor_e** sensors,
uint32_t* num_sensors);
/**
* 向每一个特定的sensor请求单个数据样本
* 数据有如下两种方式返回:
* (1) 当读到数据的序号相匹配后立即返回
* (2) 在sensor需要读取几个步骤的情形下,
* 以SNS_DDF_PENDING状态通过sns_ddf_smgr_data_notify携带数据异步返回
*/
sns_ddf_status_e (*get_data)(
sns_ddf_handle_t dd_handle,
sns_ddf_sensor_e sensors[],
uint32_t num_sensors,
sns_ddf_memhandler_s* memhandler,
sns_ddf_sensor_data_s** data);
/**
* 设置sensor指定的属性值
*/
sns_ddf_status_e (*set_attrib)(
sns_ddf_handle_t dd_handle,
sns_ddf_sensor_e sensor,
sns_ddf_attribute_e attrib,
void* value);
/**
* 获取sensor指定的属性值
*/
sns_ddf_status_e (*get_attrib)(
sns_ddf_handle_t dd_handle,
sns_ddf_sensor_e sensor,
sns_ddf_attribute_e attrib,
sns_ddf_memhandler_s* memhandler,
void** value,
uint32_t* num_elems);
/**
* timer回调,初始化timer时要指定回调方法
*/
void (*handle_timer)(sns_ddf_handle_t dd_handle, void* arg);
/**
* 处理驱动中断
*/
void (*handle_irq)(
sns_ddf_handle_t dd_handle,
uint32_t gpio_num,
sns_ddf_time_t timestamp);
/**
* 重置驱动及设备回到init状态
*/
sns_ddf_status_e (*reset)(sns_ddf_handle_t dd_handle);
/**
* 运行一个指定的工厂测试,流式数据不能调用该方法
*/
sns_ddf_status_e (*run_test)(
sns_ddf_handle_t dd_handle,
sns_ddf_sensor_e sensor,
sns_ddf_test_e test,
uint32_t* err);
/**
* 启动设备调度采样,通过DRI使能通知功能
* 数据就绪后,handle_irq被调用
*/
sns_ddf_status_e (*enable_sched_data)(
sns_ddf_handle_t handle,
sns_ddf_sensor_e sensor,
bool enable);
/**
* 根据给定的配置探测设备
*/
sns_ddf_status_e(*probe)(
sns_ddf_device_access_s* device_info,
sns_ddf_memhandler_s* memhandler,
uint32_t* num_sensors,
sns_ddf_sensor_e** sensors );
/**
* 从指定的sensor中检索一组传感器数据,异步API
* 使用sns_ddf_data_notify_data上报数据
*/
sns_ddf_status_e (*trigger_fifo_data)(
sns_ddf_handle_t dd_handle,
sns_ddf_sensor_e sensor,
uint16_t num_samples,
bool trigger_now);
/**
* 发送一个DAF消息到驱动,异步/同步API
*/
sns_ddf_status_e (*process_daf_req)(
sns_ddf_handle_t dd_handle,
uint32_t req_id,
const void* req_msg,
uint32_t req_size,
sns_ddf_memhandler_s* memhandler,
void** resp_msg,
uint32_t* resp_size,
const uint8_t* trans_id_ptr,
void* conn_handle);
/**
* 为提供的connect handle取消所有驱动当前的DAF异步事务
*/
void (*cancel_daf_trans)(
sns_ddf_handle_t dd_handle,
void* conn_handle);
} sns_ddf_driver_if_s;
所有的传感器驱动程序都要实现上面的接口,并将其对应的结构体在sns_dd.h中进行声明,如:
extern sns_ddf_driver_if_s sns_dd_mpu6515_if;
extern sns_ddf_driver_if_s sns_accel_driver_fn_list;
extern sns_ddf_driver_if_s sns_accel_adxl350_driver_fn_list;
extern sns_ddf_driver_if_s sns_gyro_driver_fn_list;
extern sns_ddf_driver_if_s sns_mag_driver_fn_list;
………………
第二部分则是Sensor的管理器服务SMGR,其主要功能如下
首先它在自己的DSPS线程中运行
可移植到其他目标并可扩展到其他传感器类型
传感器原始值使用SI单位,二进制缩放Q16,(例外:磁感应器MAG使用高斯(不是SI单位))
跟踪多个自主客户端请求的所有传感器需求
维护所有传感器设备驱动程序
列出所有可用的传感器
列出每个传感器的属性
支持客户端自定义的report可操作选择
每个客户端可以指定不同的报告速率(在传感器支持的最小值和最大值以内)。
每个报告可以组合任何可用传感器的组合。
利用硬件滤波实现报告率和数据处理
第三部分则是sensor algorithm manager,sensor算法管理器,其主要功能如下:
提供客户端和算法之间的抽象
只要算法符合简单的SAM接口集,就提供可移植性和重用性
被许可者可以通过做极小的修改将自己的算法插入-使用到SAM架构中
是一个控制模块,管理由算法提供的服务
管理算法和提供算法服务的外部客户端之间的所有交互
管理所有算法间的交互,例如 算法X 请求 算法Y 的数据
可以服务运行在不同的处理器上的客户机
AP
DSPS
CP(modem)
管理算法实例的实例化和销毁
通过下列方式进行最小内存分配:
允许多个客户端共享相同的算法实例
允许多个算法实例共享相同的传感器数据批处理
第四部分则是Sensor Message Router,光从名字就能知道他是负责消息传递用的。
事实上也是这样的,SMR是一个集中在应用程序处理器(ap)、调制解调器处理器(cp/modem)上的消息传递实用程序,
其主要的功能如下:
支持一个互操作协议,通过该协议将编码的QMI消息打包并发送到接收处理器上的对等实体。
支持处理器内部的软件协议,其中处理器内部的软件模块在没有QMI编码的情况下进行通信。
在处理器和模块分区中提供模块位置透明性
模块可以在与其他模块透明的处理器之间迁移,例如保持相同的接口
通过部署两个优先级级别来支持消息优先级排序(现在禁用,但是当需要消息优先级时可以启用)
提供流量控制——SMR保证将消息传递到目的队列,或通知源模块失败。
第五部分就是我们已经提到的QMI了。之所以选择QMI作为AP与BP侧的通信协议,高通给出的理由如下:
客户端管理器主要用于向客户端提供请求接口,其内部有一个Receive thread,
当有消息从SMR发过来,receive thread查找回调函数,并将该消息通过对应的cb分发至对应的客户端。
在上面的DSPS架构图中,我们还看到一个模块,叫Sensor Calibration Manager,这个模块主要用于sensor数据校验等,比如出厂设置时的校验等,后面分析数据校验的时候再重点关注这部分。
好了,介绍完DSPS的架构及相关的重要模块,后续的文章我们将重点分析SensoDaemon是怎样通过QCCI, QCSI通信API与DSPS端通信的,欢迎关注。