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

本文介绍了在高通SDM845平台上,如何在Sensor SLPI层实现SAM Sensor,特别是针对拿起唤醒功能的实现。分析了为何不能在framework层做算法处理,解释了SLPI侧实现该功能的优势,详细阐述了从初始化、激活到数据处理的步骤,并以pickup sensor为例进行了深入讲解。
摘要由CSDN通过智能技术生成
四: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)

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->
  • 15
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值