1. 程式人生 > >高通SDM845平臺Sensor學習——4.SLPI(SAM Sensor)--

高通SDM845平臺Sensor學習——4.SLPI(SAM Sensor)--

四:Sensor SLPI層SAM Sensor例項分析

上文中,我們大致瞭解了物理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)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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

  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

根據前文介紹。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;
}
  
  • 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

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;
}
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

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

  
  • 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

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

  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

當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) &&    //No.1
  (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)   //No.2
  {
    if(NULL != curr_inst)
    {
      curr_inst->cb->remove_client_request(curr_inst, curr_req);
    }
  }
  else                        //No.3
  {
    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
  • 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
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96

該函式很簡單,
No.1:處理message_id=SNS_STD_MSGID_SNS_STD_FLUSH_REQ ,此時會將該message_id傳送給sns_oem1_inst_set_client_config,並做相應的處理。
No.2:為remove分支
No.3:正常情況下走的流程。
(1)先判斷是否有與new_req匹配的sns_sensor_instance,若有直接用match的;
(2)若無,判斷是否有當前的curr_inst即舊的sns_sensor_instance存在。若有,則通過curr_inst->cb->remove_client_request函式remove掉舊的curr_req client。,並通過this->cb->create_instance()建立一個新的sns_sensor_instance。若無,則直接建立一個新的sns_sensor_instance即rv_inst。
(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。這時要remove掉curr_inst即當前的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;
}
  
  • 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

該函式,主要是獲取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;
}
  
  • 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
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115

該函式,首先根據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;
  
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
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;
}
  
  • 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
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104

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 資料。

四:Sensor SLPI層SAM Sensor例項分析