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

匿名 (未验证) 提交于 2019-12-02 22:56:40

上文中,我们大致了解了物理sensor driver整个流程,但在项目中,一般写这种sensor driver的情况很少。这种sensor driver基本上都是各个vendor厂商提供的,我们也只需要看懂即可。

但是SAM sensor我们完全是可以自己写的,根据一些物理sensor的数据,来实现一些算法。
比如,实现拿起唤醒功能,这个功能在oem手机中非常常见。
基本功能就是:当用户拿起手机时,手机屏幕亮起,此时可以通过脸部识别,来解锁手机等等。

这时好多人可能会说,这不是很简单吗?在framework层就可以做,注册一个加速度传感器,并根据data做一定算法处理。根本不需要再SLPI侧再实现一个SAM sensor。这种思维就是典型的应用层程序员的思想,系统层程序员如果有这种思想,那就很危险了。

为什么不能再framework层上做算法处理呢?
framework层进行算法处理,当系统睡下去怎么办?若是注册Non-Wakeup的sensor的话,在系统suspend时,不会有任何数据上报,如何唤醒系统呢?若是注册Wakeup的sensor的话,系统会被wakelock住,根本睡不下去,这时系统功耗非常高。

可见在framework层做的想法是在系统层面不可能实施的。
那么在SLPI侧实现pick up sensor的思路是什么呢?
pick up sensor在LPSS侧是work的,APSS侧是可以suspend的,当pick up Sensor获取accel sensor的数据满足算法时,会publish event给APSS中client,此时会唤醒系统。唤醒系统后,framework层会根据该sensor type,做相应的操作,比如亮屏、震动等等。。。

Ok,下面我们以该pickup sensor为例,解析下SLPI 侧 SAM Sensor driver。
高通给我们参考的oem sensor实例,下面我们在oem sensor实例上实现pickup sensor。

1:build脚本
根据上文中介绍。各个sensor都是通过xxxx.scons静态添加sensor的。
oem sensor的source code在/slpi/ssc/sensors/oem1中。

if 'USES_SSC_STATIC_LIB_BUILDER' in env:   env.AddSSCSU(inspect.getfile(inspect.currentframe()),                register_func_name = "sns_oem1_register",                clean_pack_list = oem1_clean_pack_list,                binary_lib = oem1_binary_lib,                add_island_files = oem1_island_enable,                diag_ssid = ssid)

build脚本会通过register_func_name = “sns_oem1_register”,调到sns_oem1_register函数。

2:Initialization

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_sensor_api sns_oem1_api = {     .struct_len = sizeof(sns_sensor_api),     .init = &sns_oem1_init,     .deinit = &sns_oem1_deinit,     .get_sensor_uid = &sns_oem1_get_sensor_uid,     .set_client_request = &sns_oem1_set_client_request,     .notify_event = &sns_oem1_notify_event, }; 

根据前文介绍。sns_register_sensor()注册函数后,会执行sns_sensor_api的init函数。

.init

sns_rc sns_oem1_init(sns_sensor *const this) {   sns_oem1_sensor_state *state = (sns_oem1_sensor_state*)this->state->state;   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);    SNS_SUID_LOOKUP_INIT(state->suid_lookup_data, NULL);   sns_suid_lookup_add(this, &state->suid_lookup_data, "accel");//No.1   sns_suid_lookup_add(this, &state->suid_lookup_data, "amd");  //No.2 #ifndef SUPPORT_DIRECT_SENSOR_REQUEST   sns_suid_lookup_add(this, &state->suid_lookup_data, "resampler");//No.3 #endif    publish_attributes(this); //No.4   SNS_PRINTF(MED, this, "OEM1 init success and attributes published");   return SNS_RC_SUCCESS; }

No.1:sns_suid_look_add添加所需要的sensor。
No.2:添加amd sensor。
No.3:添加resampler sensor。
No.4:并pushlish atrribute。比如sensor name、type、vendor等,Client层会根据该attribute,设置sensor的一些属性,比如on_change、streaming等等

.get_sensor_uid

static sns_sensor_uid const* sns_oem1_get_sensor_uid(sns_sensor const *this) {   UNUSED_VAR(this);   static const sns_sensor_uid oem1_suid = OEM1_SUID;   return &oem1_suid; }

oem1_suid是指定的,返回的是oem_suid。

.notify

sns_rc sns_oem1_notify_event(sns_sensor *const this) {   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);  #ifdef SUPPORT_REGISTRY   if(NULL != state->registry_stream)   {     handle_oem1_registry_event(this);   } #endif    if(sns_suid_lookup_complete(&state->suid_lookup_data))   { #ifdef SUPPORT_REGISTRY     if(state->first_pass == true){       state->first_pass = false;       sns_oem1_registry_req(this);     } #endif     publish_available(this);     sns_suid_lookup_deinit(this, &state->suid_lookup_data);   }   return SNS_RC_SUCCESS; } 

该notify,主要处理init中的event。
通过sns_suid_lookup_handle(),handle一个suid或者attribute event。
通过sns_suid_lookup_complete(),来返回所有sensor data 的suid是否找到。

Initialization分析完毕,Initialization重要东西不多,主要是添加所需要的dependency sensor,比如accel、amd、resampler等等,并获取oem1_suid。然后通过notify_event来查看sensor type的suid是否找到。

3: Activation

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 }; 

当client发送request时,先进入sns_sensor_api中的.set_client_config。

.set_client_config

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_PRINTF(MED, this, "sns_oem1_set_client_request");   if((NULL != curr_inst) && (NULL != new_req) &&   (SNS_STD_MSGID_SNS_STD_FLUSH_REQ == new_req->message_id))   {    SNS_PRINTF(HIGH, this, "Received Flush Request");    this->instance_api->set_client_config(curr_inst, new_req);    rv_inst = curr_inst;   }   else if(remove)   {     if(NULL != curr_inst)     {       curr_inst->cb->remove_client_request(curr_inst, curr_req);     }   }   else   {     pb_istream_t stream;     sns_std_sensor_config config = {0};     sns_std_request request = sns_std_request_init_default;      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);      if(pb_decode(&stream, sns_std_request_fields, &request))     {       sns_request decoded_req = {.message_id = new_req->message_id,           .request_len = sizeof(config), .request = &config };       sns_sensor_instance *match_inst = sns_sensor_util_find_instance_match(           this, &decoded_req, &find_instance_match);       if(NULL == curr_inst)       {         // If this is a request from a new client         if(NULL == match_inst)         {           rv_inst = this->cb->create_instance(this,               (sizeof(sns_oem1_inst_state)));         }         else         {           rv_inst = match_inst;         }       }       else       {         if(NULL != curr_req)         {           curr_inst->cb->remove_client_request(curr_inst, curr_req);         }         if(NULL != match_inst)         {           rv_inst = match_inst;         }         else         {           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);         this->instance_api->set_client_config(rv_inst, &decoded_req);       }     }     else     {       SNS_PRINTF(ERROR, this, "failed to decode request");     }   }    if(NULL != curr_inst && NULL == curr_inst->cb->get_client_request(       curr_inst, this->sensor_api->get_sensor_uid(this), true))   {     this->cb->remove_instance(curr_inst);   }    return rv_inst; }

该函数很简单,
(1)先判断是否有与new_request匹配的sns_sensor_instance,若有直接用match的;
(2)若无,判断是否有当前的sns_sensor_instance即旧的sns_sensor_instance。若有,则通过curr_inst->cb->remove_client_request函数remove掉旧的sns_sensor_instance,并通过this->cb->create_instance()创建一个新的sns_sensor_instance。若无,则直接创建一个新的sns_sensor_instance。
(3)创建好的sns_sensor_instance叫rv_inst,然后通过rv_inst->cb->add_client_request添加新的client request。
(4)并通过this->instance_api->set_client_config处理该新建的sns_sensor_instance ,即rv_inst。
(5)出错处理,若curr_inst不为空,并且curr_inst还可以获取到client_reqeust。说明旧的sns_sensor_instance移除失败。

Ok,create_instance()执行后便进入sns_sensor_instance_api.init()。
set_client_config()执行后便进入sns_sensor_instance_api.set_client_config()。

.init

sns_rc sns_oem1_inst_init(sns_sensor_instance *this,     sns_sensor_state const *state) {   sns_rc rc = SNS_RC_SUCCESS;   sns_oem1_inst_state *inst_state =       (sns_oem1_inst_state*)this->state->state;   sns_oem1_sensor_state *sensor_state =       (sns_oem1_sensor_state*)state->state;   sns_service_manager *service_mgr = this->cb->get_service_manager(this); #ifdef SUPPORT_DIRECT_SENSOR_REQUEST   sns_stream_service *stream_service = (sns_stream_service*)         service_mgr->get_service(service_mgr, SNS_STREAM_SERVICE); #endif  #ifdef SUPPORT_DIRECT_SENSOR_REQUEST   sns_suid_lookup_get(&sensor_state->suid_lookup_data, "accel", &inst_state->accel_suid); #else   sns_suid_lookup_get(&sensor_state->suid_lookup_data, "resampler", &inst_state->resampler_suid);   sns_suid_lookup_get(&sensor_state->suid_lookup_data, "accel", &inst_state->accel_suid); #endif    inst_state->diag_service = (sns_diag_service*)           service_mgr->get_service(service_mgr, SNS_DIAG_SERVICE);    inst_state->down_value = sensor_state->config.down_value;  #ifdef SUPPORT_DIRECT_SENSOR_REQUEST   // start regular stream for accel   stream_service->api->create_sensor_instance_stream(       stream_service,       this,       inst_state->accel_suid,       &inst_state->accel_stream); #endif    inst_state->inst_config.previous_state = OEM1_UNKNOWN;   inst_state->inst_config.current_state = OEM1_UNKNOWN;    // read platform specific configuration   sns_memscpy(&inst_state->config,       sizeof(inst_state->config),       &sensor_state->config,       sizeof(sensor_state->config) );   return rc; }

该函数,主要是获取resampler、accel等的suid。将suid放到inst_state->xxxx_suid中。

.set_client_config

sns_rc sns_oem1_inst_set_client_config(sns_sensor_instance *const this,     sns_request const *client_request) {   sns_rc rc = SNS_RC_SUCCESS;   sns_oem1_inst_state *state = (sns_oem1_inst_state*)this->state->state;    SNS_INST_PRINTF(LOW, this, "sns_oem1_inst_set_client_config");    if(SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG == client_request->message_id)   {      // initialize state here     sns_std_sensor_config *client_req =         (sns_std_sensor_config *)(client_request->request);     sns_memscpy(&state->client_config,         sizeof(state->client_config),         client_request->request,         client_request->request_len);      state->config.sample_rate = client_req->sample_rate;   #ifndef SUPPORT_DIRECT_SENSOR_REQUEST     // start streaming from resampler     SNS_INST_PRINTF(LOW, this, "Enable resampler at rate %f", client_req->sample_rate);     sns_service_manager *manager =         this->cb->get_service_manager(this);     sns_stream_service *stream_service =         (sns_stream_service*)manager->get_service(manager, SNS_STREAM_SERVICE);      sns_resampler_config resampler_config = sns_resampler_config_init_default;     size_t encoded_len;     uint8_t buffer[100];     client_req->sample_rate = 25.0f;     sns_memscpy(&resampler_config.sensor_uid, //No.1         sizeof(resampler_config.sensor_uid),         &state->accel_suid,         sizeof(state->accel_suid));     resampler_config.resampled_rate = client_req->sample_rate;     resampler_config.rate_type = SNS_RESAMPLER_RATE_MINIMUM;     resampler_config.filter = false;      // create connection with resampler sensor     stream_service->api->create_sensor_instance_stream(  //No.2         stream_service,         this,         state->resampler_suid,         &state->resampler_stream);      if(NULL != state->resampler_stream)     {       encoded_len = pb_encode_request(buffer, sizeof(buffer),           &resampler_config, sns_resampler_config_fields, NULL);       if(0 < encoded_len)       {         sns_request request = (sns_request){           .message_id = SNS_RESAMPLER_MSGID_SNS_RESAMPLER_CONFIG,               .request_len = encoded_len, .request = buffer };         rc = state->resampler_stream->api->send_request(state->resampler_stream, &request);         SNS_INST_PRINTF(MED, this, "oem1 sent accel request to resampler at rate %f", client_req->sample_rate);       }       else       {         SNS_INST_PRINTF(ERROR, this, "oem1 failed to encode resampler config");       }     }     else     {       SNS_INST_PRINTF(ERROR, this, "oem1 resampler stream creation failed");     } #else // not using the resampler, request accel directly     size_t encoded_len;     uint8_t buffer[20];      // enable accel here     sns_memset(buffer, 0, sizeof(buffer));     client_req->sample_rate = 25.0f;      sns_std_sensor_config accel_config = {.sample_rate = client_req->sample_rate};     SNS_INST_PRINTF(LOW, this, "Enable accel at rate %f", client_req->sample_rate);      encoded_len = pb_encode_request(buffer,         sizeof(buffer),         &accel_config,         sns_std_sensor_config_fields,         NULL);     if(0 < encoded_len && NULL != state->accel_stream )     {       sns_request request = (sns_request){         .message_id = SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG,             .request_len = encoded_len, .request = buffer };       state->accel_stream->api->send_request(state->accel_stream, &request);     }     else     {       SNS_INST_PRINTF(ERROR, this, "Error in creating accel stream OR encoding failed");       rc = SNS_RC_NOT_SUPPORTED;     }      SNS_INST_PRINTF(LOW, this, "Processed oem1 config request: enabled accel with"         "sample rate %f, result: %u", state->client_config.sample_rate, rc); #endif   }   else if(client_request->message_id ==  SNS_STD_MSGID_SNS_STD_FLUSH_REQ)   {     sns_sensor_util_send_flush_event(NULL, this);   }   else   {     SNS_INST_PRINTF(ERROR, this, "Unsupported request message id %u",         client_request->message_id);     rc = SNS_RC_NOT_SUPPORTED;   }   return rc; }

该函数,首先根据client传入的msg_id做处理。
当message_id = SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG时,这时,我们就需要发送accel的request,来获取accel的data了。

这里面有个宏SUPPORT_DIRECT_SENSOR_REQUEST,这里我们不support这个宏,走的是resampler。若support这个宏,则直接发送request给accel。

这里用resampler后,会先发送request给resampler sensor,resampler sensor再获取accel的数据。
No.1中,填充sns_resampler_config。并将state->accel_suid赋给resampler_config.sensor_uid。
No.2中,create_sensor_instance_stream会创建data stream,以后resampler request和event都会走该data stream。
然后通过pb_encode_request,将sns_resampler_config 编码成buffer。
最后填充sns_request request,可以看到request message_id = SNS_RESAMPLER_MSGID_SNS_RESAMPLER_CONFIG ,.request = buffer。然后通过send_request发送出去。

sns_oem1_inst_set_client_config发送完毕后,接下来就是接收event了。

.notify_event

static sns_rc sns_oem1_inst_notify_event(sns_sensor_instance *const this) {   sns_rc rc = SNS_RC_SUCCESS;   sns_oem1_process_resampler_event(this);   return rc;
static sns_rc sns_oem1_process_resampler_event(sns_sensor_instance *const this) {   sns_rc rc = SNS_RC_SUCCESS;   sns_oem1_inst_state *state = (sns_oem1_inst_state*)this->state->state;    sns_sensor_event *resampler_event_in = NULL;   SNS_INST_PRINTF(LOW, this, "sns_oem1_inst_process_resampler_event");    resampler_event_in = state->resampler_stream->api->peek_input(state->resampler_stream);    while( NULL != resampler_event_in )   {     if(SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_EVENT == resampler_event_in->message_id) //No.1     {       float data[3] = { 0 };       float oem1_payload[OEM1_NUM_ELEMS];        uint8_t arr_index = 0;       pb_float_arr_arg arg = {           .arr = data,           .arr_len = ARR_SIZE(data),           .arr_index = &arr_index       };        pb_istream_t stream = pb_istream_from_buffer((pb_byte_t*)resampler_event_in->event,resampler_event_in->event_len);       sns_std_sensor_event resampler_data = sns_std_sensor_event_init_default;        resampler_data.data = (struct pb_callback_s) {         .funcs.decode = &pb_decode_float_arr_cb, .arg = &arg       };        if(!pb_decode(&stream, sns_std_sensor_event_fields, &resampler_data)) //No.2       {         SNS_INST_PRINTF(ERROR, this, "Error in decoding resampler event");       }       else       {         if (SNS_STD_SENSOR_SAMPLE_STATUS_UNRELIABLE == resampler_data.status)         {           SNS_INST_PRINTF(LOW, this, " OEM1 received unreliable accel data"               " from resampler ignoring..");           resampler_event_in = state->resampler_stream->api->get_next_input(state->resampler_stream);           continue;         }         //This is dummy logic for OEM1 demonstration purposes         //OEMs can replace with their algo logic         oem1_facing_state current_state = OEM1_UNKNOWN;          SNS_INST_PRINTF(LOW, this,             "resampler accel data: x %d/1000, y %d/1000, z %d/1000",            (int) (1000*data[0]),(int)( 1000*data[1]),(int)(1000*data[2]));          //sns_oem1_procces(this, &input);         state->inst_config.previous_state = state->inst_config.current_state;          if(0 < data[2])                           //No.3         {           current_state = OEM1_FACING_UP;           oem1_payload[0]=100;           oem1_payload[1]=data[1];           oem1_payload[2]=data[2];         }         else         {           current_state = OEM1_FACING_DOWN;           oem1_payload[0]= state->down_value;           oem1_payload[1]=data[1];           oem1_payload[2]=data[2];         }          state->inst_config.current_state = current_state;         SNS_INST_PRINTF(LOW, this, "OEM1 output:  x %d/1000, y %d/1000, z %d/1000",             (int) (1000*oem1_payload[0]),(int)( 1000*oem1_payload[1]),(int)(1000*oem1_payload[2]));  #ifdef SUPPORT_EVENT_TYPE         if(state->inst_config.current_state != state->inst_config.previous_state)         { #endif           SNS_INST_PRINTF(MED, this,               "OEM1 last %d current %d",               state->inst_config.current_state,               state->inst_config.previous_state);           rc = pb_send_sensor_stream_event(this,      //No.4               NULL,               resampler_event_in->timestamp,               SNS_OEM1_MSGID_SNS_OEM1_DATA,               SNS_STD_SENSOR_SAMPLE_STATUS_ACCURACY_HIGH,               oem1_payload,               OEM1_NUM_ELEMS,               state->config.encoded_data_event_len);           if(SNS_RC_SUCCESS != rc)           {             SNS_INST_PRINTF(ERROR, this, "sns_oem1_inst_notify_event - Error in sending event");           } #ifdef SUPPORT_EVENT_TYPE         } #endif       }     }     // check next sample     resampler_event_in = state->resampler_stream->api->get_next_input(state->resampler_stream);   }   return rc; }

No.1:接收到accel的message_id。
No.2:将stream解码成resampler_data的格式。resampler_data.data.arr即为accel的sensor data。
No.3:该处是根据accel数据做算法处理。比如panel朝向,panel加速度等等。
No.4:pb_send_sensor_stream_event来publish event,若算法满足,可以通过该函数publish event,client便接收到event来唤醒系统,最终实现wake up。

Ok,SAM sensor分析完毕,该文与上一篇文章流程基本相似,唯一不同点就是SAM Sensor会Dependency other sensor,并在sns_sensor_instance_api.set_client_config中发送Dependency sensor的request,然后在sns_sensor_instance_api.notify_event中处理获取到的dependency sensor 数据。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!