在SEE中,处理硬件sensor,高通实现的platform sensor,还有一类是通过硬件sensor等各种数据计算,抽象出来的虚拟sensor。
我们以高通提供的参考为例,看如何添加一个虚拟sensor和虚拟sensor执行流程。
1.pb协议文件定位sensor类型数据
在Non-HLOSadsp_procssc_apipbsns_oem1.proto中定义了oem1这个虚拟sensor的sns_oem1_msgid和sns_oem1_data。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22syntax = "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/s2 repeated float oem1 = 1 [(nanopb).max_count = 3]; // Accuracy of the data required 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。
1
2
3
4
5
6
7
8sns_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提供,代码如下:
1
2
3
4
5
6
7
8
9
10
11
12extern 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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18typedef 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 uid sns_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调用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34sns_rc sns_oem1_init(sns_sensor *const this) { sns_oem1_sensor_state *state = (sns_oem1_sensor_state*)this->state->state; // cb获取sensor manager struct 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 available state->config.down_value = 50.0; state->first_pass = true; // determine encoded output event size state->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");//accel sns_suid_lookup_add(this, &state->suid_lookup_data, "registry"); #ifndef OEM1_SUPPORT_DIRECT_SENSOR_REQUEST sns_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就绪。
1
2
3
4
5
6
7
8
9
10
11
12
13
14sns_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打包的。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49sns_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 message else 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_rate if(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_TYPE this->instance_api->set_client_config(rv_inst, &decoded_req); #else this->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完成,具体实现为:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17sensor_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的注册入口:
1
2
3
4
5
6
7
8
9sns_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之前。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17sns_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.高通SEE内容请搜索靠谱客的其他文章。
发表评论 取消回复