在SEE中,处理硬件sensor,高通实现的platform sensor,还有一类是通过硬件sensor等各种数据计算,抽象出来的虚拟sensor。

我们以高通提供的参考为例,看如何添加一个虚拟sensor和虚拟sensor执行流程。

1.pb协议文件定位sensor类型数据

在Non-HLOS\adsp_proc\ssc_api\pb\sns_oem1.proto中定义了oem1这个虚拟sensor的sns_oem1_msgid和sns_oem1_data。

syntax = "proto2";
import "nanopb.proto";
import "sns_std_sensor.proto";enum sns_oem1_msgid
{option (nanopb_enumopt).long_names = false;SNS_OEM1_MSGID_SNS_OEM1_DATA = 1024;
}// Data Message
// Output data event generated by the oem1 sensor.
message sns_oem1_data
{// oem1 Vector along axis x,y,z in m/s2repeated float oem1 = 1 [(nanopb).max_count = 3];// Accuracy of the datarequired sns_std_sensor_sample_status accuracy = 2;
}

这个文件在pb工具编译后,将生成对应的.c和.h文件。pb是一种数据打包协议,SEE中传递数据和事件信息,全都通过pb进行打包,打包将会包含这笔数据的msgid,表示是什么数据。对应oem1这个sensor, 如果是数据类型是sns_oem1_msgid,则还会包含sns_oem1_data类型数据。

2.sensor

虚拟sensor的在sns_oem1.c中的sns_oem1_register方法。这个方法将被调用,用来将sensor和sensor_instance对应的api注册到framework。

sns_rc sns_oem1_register(sns_register_cb const *register_api)
{register_api->init_sensor(sizeof(sns_oem1_sensor_state),&sns_oem1_api,&sns_oem1_sensor_instance_api);return SNS_RC_SUCCESS;
}

sns_oem1_register被放到framework的一个数组中,用来逐个注册sensor。register_api方法有framework提供,代码如下:

extern sns_sensor_cb sensor_cb;sensor_cb = (sns_sensor_cb){.struct_len = sizeof(sensor_cb),.get_service_manager = &get_service_manager,.get_sensor_instance = &get_sensor_instance,.create_instance = &sns_sensor_instance_init,.remove_instance = &sns_sensor_instance_deinit,.get_library_sensor = &get_library_sensor,.get_registration_index = &get_registration_index,};

这个结构的具体意义已经在结构注释中说明。

另外这里有sensor_api和sensor_inst_api。虚拟sensor中sensor用户虚招要使用的其他sensor, 发布sensor attr表示这个sensor存在,以及创建和管理sensor instance。sensor instance是实际存在和发布数据的实体。

我们在看sns_sensor_instance_api和sns_sensor_api这两个结构。我们首先看sensor_api.

typedef struct sns_sensor_api
{uint32_t struct_len;sns_rc (*init)(sns_sensor *const this);//初始化sns_rc (*deinit)(sns_sensor *const this);//反初始化释放资源sns_sensor_uid const* (*get_sensor_uid)(sns_sensor const *const this); //获取sensor uidsns_rc (*notify_event)(sns_sensor *const this); //通知sensor有数据struct sns_sensor_instance* (*set_client_request)(sns_sensor *const this,struct sns_request const *exist_request,struct sns_request const *new_request,bool remove); //接收client的request
}

sensor_api的init在开机时被framework调用。

sns_rc
sns_oem1_init(sns_sensor *const this)
{sns_oem1_sensor_state *state = (sns_oem1_sensor_state*)this->state->state;// cb获取sensor managerstruct sns_service_manager *smgr = this->cb->get_service_manager(this);float data[3];state->diag_service = (sns_diag_service*)smgr->get_service(smgr, SNS_DIAG_SERVICE);// set default output value corresponding to OEM1_FACING_DOWN to 50. will // rewrite if registry sensor is availablestate->config.down_value = 50.0;state->first_pass = true;// determine encoded output event sizestate->config.encoded_data_event_len =pb_get_encoded_size_sensor_stream_event(data, 3);// 通过sensor的datatype查找sensor对应的suid.在frmework中会将每个sensor的datatype和suid绑定,这些sensor是本虚拟sensor数据来源SNS_SUID_LOOKUP_INIT(state->suid_lookup_data, NULL);sns_suid_lookup_add(this, &state->suid_lookup_data, "gyro");//accelsns_suid_lookup_add(this, &state->suid_lookup_data, "registry");
#ifndef OEM1_SUPPORT_DIRECT_SENSOR_REQUESTsns_suid_lookup_add(this, &state->suid_lookup_data, "resampler");
#endif//发布snesor信息,包括sensor的datatype, sample rate等publish_attributes(this);SNS_PRINTF(MED, this, "OEM1 init success and attributes published");return SNS_RC_SUCCESS;
}

在sns_suid_lookup_add查找suid完成,会通过sensor framework调用sensor_api->notify_event。sns_suid_lookup_add()方法将创建和suid_sensor的流并做请求,请求后的回复通过framework调用notify_event。如果找到则宣布sensor就绪。

sns_rc
sns_oem1_notify_event(sns_sensor *const this)//接收sns_suid_lookup_add返回
{sns_oem1_sensor_state *state = (sns_oem1_sensor_state*)this->state->state;SNS_PRINTF(LOW, this, "sns_oem1_notify_event");sns_suid_lookup_handle(this, &state->suid_lookup_data);if(sns_suid_lookup_complete(&state->suid_lookup_data)) {publish_available(this);sns_suid_lookup_deinit(this, &state->suid_lookup_data);}return SNS_RC_SUCCESS;
}

publish_available发布改sensor可用。到这里sensor就准备好了。

sensor发布出去后,AP测就可以查询到并且使用。当AP测应用程序激活sensor,sensor_api->set_client_request将被调用,而且AP测发送过来的数据,也是通过pb打包的。

sns_sensor_instance*
sns_oem1_set_client_request(sns_sensor *const this,sns_request const *curr_req,sns_request const *new_req,bool remove)
{sns_sensor_instance *curr_inst =sns_sensor_util_find_instance(this,curr_req,this->sensor_api->get_sensor_uid(this));sns_sensor_instance *rv_inst = NULL;sns_sensor_instance *match_inst = NULL;// 接收到到config messageelse if((new_req->message_id == SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG) ||  (new_req->message_id == SNS_STD_SENSOR_MSGID_SNS_STD_ON_CHANGE_CONFIG)){pb_simple_cb_arg arg ={ .decoded_struct = &config, .fields = sns_std_sensor_config_fields };request.payload = (struct pb_callback_s){ .funcs.decode = &pb_decode_simple_cb, .arg = &arg };//获取到请求的流stream = pb_istream_from_buffer(new_req->request, new_req->request_len);//从流中解析出请求数据,标准sensor请求数据只有sample_rateif(pb_decode(&stream, sns_std_request_fields, &request)){decoded_req.message_id = new_req->message_id;decoded_req.request_len = sizeof(config);decoded_req.request = &config;match_inst = sns_sensor_util_find_instance_match(this, &decoded_req, &find_instance_match);}//然后创建sensor instance,将请求的设置在instance中设置rv_inst = this->cb->create_instance(this,(sizeof(sns_oem1_inst_state)));if(NULL != rv_inst){rv_inst->cb->add_client_request(rv_inst, new_req);
#ifndef OEM1_SUPPORT_EVENT_TYPEthis->instance_api->set_client_config(rv_inst, &decoded_req);
#elsethis->instance_api->set_client_config(rv_inst, new_req);
#endif}}}

上面代码接收来自client的config请求,并根据请求创建或者复用一个sensor instance,设置需要的配置。到这里就进入到sensor instance。

3.sensor instance

sensor管理者sensor instance,sensor instance实际管理者sensor数据。create_instance由framework完成,具体实现为:

  sensor_cb = (sns_sensor_cb){.struct_len = sizeof(sensor_cb),.get_service_manager = &get_service_manager,.get_sensor_instance = &get_sensor_instance,.create_instance = &sns_sensor_instance_init,.remove_instance = &sns_sensor_instance_deinit,.get_library_sensor = &get_library_sensor,.get_registration_index = &get_registration_index,};sns_rc
sns_sensor_init(uint32_t state_len, struct sns_sensor_api const *sensor_api,struct sns_sensor_instance_api const *instance_api) {sensor->sensor.cb = &sensor_cb;}

现在看sensor instance的注册入口:

sns_sensor_instance_api sns_oem1_sensor_instance_api =
{.struct_len = sizeof(sns_sensor_instance_api),.init = &sns_oem1_inst_init,.deinit = &sns_oem1_inst_deinit,.set_client_config = &sns_oem1_inst_set_client_config,.notify_event = &sns_oem1_inst_notify_event
};

sns_sensor_instance_init()创建instance将会调用到sns_sensor_instance_api->init,完成instance的init过程。

在init中我们查找在sensor中寻找的sensor uid,并且对需要的非resampler sensor创建流。resampler sensor的流放到请求resampler之前。

sns_rc
sns_oem1_inst_init(sns_sensor_instance *this,sns_sensor_state const *state){sns_service_manager *service_mgr = this->cb->get_service_manager(this);sns_stream_service *stream_service = (sns_stream_service*)service_mgr->get_service(service_mgr, SNS_STREAM_SERVICE);sns_suid_lookup_get(&sensor_state->suid_lookup_data, "gyro", &inst_state->accel_suid);stream_service->api->create_sensor_instance_stream(stream_service,this,inst_state->accel_suid,&inst_state->accel_stream);}

1.高通SEE 虚拟sensor分析相关推荐

  1. 高通SDM845平台Sensor学习——3.SLPI(Physical Sensor)

    ####三:Sensor SLPI层代码分析 #### 在学习SLPI侧代码前我们先了解下SEE的registry&config. registry 放在/persist/sensors/re ...

  2. 高通SDM845平台Sensor学习——2.Hal层

    二:Sensor Hal层代码分析 Hal code放在/vendor/qcom/proprietary/sensors-see/中 sensors-hal文件夹中包含framework和sensor ...

  3. 高通SDM845平台Sensor学习——2.Hal层--

    二:Sensor Hal层代码分析 Hal code放在/vendor/qcom/proprietary/sensors-see/中 sensors-hal文件夹中包含framework和sensor ...

  4. 高通SDM845平台Sensor学习——4.SLPI(SAM Sensor)

    四:Sensor SLPI层SAM Sensor实例分析 上文中,我们大致了解了物理sensor driver整个流程,但在项目中,一般写这种sensor driver的情况很少.这种sensor d ...

  5. 高通SDM845平台Sensor学习——1.框架

    一:简介 高通从SDM845平台开始,Sensor使用新的架构SEE(Sensors Execution Environment),和之前架构不同,新的架构有着太多的优点. 首先,先对比下新架构和旧架 ...

  6. 高通Android display架构分析

    目录(?)[-] Kernel Space Display架构介绍 函数和数据结构介绍 函数和数据结构介绍 函数和数据结构介绍 数据流分析 初始化过程分析 User Space display接口 K ...

  7. 高通SDM845平台Sensor学习——4.SLPI(SAM Sensor)--

    四:Sensor SLPI层SAM Sensor实例分析 上文中,我们大致了解了物理sensor driver整个流程,但在项目中,一般写这种sensor driver的情况很少.这种sensor d ...

  8. 高通SDM855平台Sensor学习——1.框架

    一:简介 高通从SDM845平台开始,Sensor使用新的架构SEE(Sensors Execution Environment),和之前架构不同,新的架构有着太多的优点. 首先,先对比下新架构和旧架 ...

  9. 高通8155/8295 boot分析

    目录 前言 通用boot流程 8155/8295 boot流程概述 前言 本文将基于高通8155/8295 Q+A hypervisor平台分析整个boot的启动流程.高通其他SOC芯片的启动流程大致 ...

最新文章

  1. nand flash 扇区的管理以及初始化
  2. IntelliJ IDEA 导入 IntelliJ IDEA 创建好的JavaWeb项目!
  3. artTemplate的使用总结
  4. proxy in nodejs code
  5. leetcode初级算法1.删除排序数组中的重复项
  6. wangeditor html编辑,Vue整合wangEditor富文本编辑器
  7. HDU5212 CODE【莫比乌斯函数】
  8. ArcGIS For Flex学习之Mapping---Map Extent and Mouse Coordinates
  9. fftw3 嵌入式linux安装,Ubuntu18.04下快速的安装UHD与GnuRadio并连接USRP设备
  10. php中admin文件什么意思,开始使用 · tpAdmin 文档 · 看云
  11. 打印服务器 支持 佳能 2900+打印机,Deepin20(1002版本)安装佳能Canon LBP2900+打印机
  12. 这5种数据挖掘技术,大数据玩的贼溜!
  13. HTML YouTube 视频
  14. python淘宝cookies抢购_Python爬虫利用cookie抓取淘宝商品比价
  15. 铁路警方启用AI眼镜,当场抓逃犯!外媒惊叹不已!
  16. Python实现回归树
  17. P1535 游荡的奶牛
  18. 洛谷 P5664 Emiya 家今天的饭【dp】
  19. 理工男学计算机,案例分享 | 一名“理工男”的春天
  20. 那些年啊,那些事——一个程序员的奋斗史 ——113

热门文章

  1. 基于原生js和css3实现barrage弹幕效果
  2. 支付宝做社交缺什么?
  3. 2022人工智能顶会时间序列论文汇总
  4. JQuery事件的基本使用
  5. 物理系统仿真有哪些作用和功能?速看
  6. 荣耀V9可以升级鸿蒙吗,荣耀手机能升级鸿蒙系统吗,支持鸿蒙系统的荣耀手机有哪些...
  7. 拼多多新店正确起步方法!
  8. 苹果天气不显示_手机锁屏显示天气预报可不只安卓有,iPhone也能显示!太实用了吧...
  9. C++ 操作重载与类型转换 《C++Primer》第14章 读书笔记
  10. 包邮送33本11.11京东TOP5的精选书,先到先得!