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

三:Sensor SLPI层代码分析

在学习SLPI侧代码前我们先了解下SEE的registry&config。

registry 放在/persist/sensors/registry/registry中,它是通过config生成的,是给SLPI解析的文件。
config 放在/persist/sensors/registry/config中,它需要RD修改更新,用来生成register以便SLPI使用。每次config update后,即会更新registry。每次reboot后,会重新加载registry。

config都是以.json为后缀的文件,每个物理sensor会有两个json文件,一个是包含所有平台的特殊配置文件,另一个是sensor driver的特殊配置文件。

如果config文件不存在并且sensor driver支持默认参数,则sensor library会将默认参数填充到registry中。

sensor driver可以通过发送request给registry sensor来随时更新registry。

下面来详细介绍下json文件:以高通给的demo文件为例。
/persist/sensors/registry/config/sdm845_lsm6dsm_0.json

{
  "config":{
    "hw_platform": ["HDK"],
    "soc_id": ["341"]
  },
  "lsm6dso_0_platform":{
    "owner": "lsm6dso",
    ".config":{
      "owner": "lsm6dso",
      "bus_type":{ "type": "int", "ver": "0",
        "data": "1"
      },
      "bus_instance":{ "type": "int", "ver": "0",
        "data": "2"
      },
      "slave_config":{ "type": "int", "ver": "0",
        "data": "0"
      },
      "min_bus_speed_khz":{ "type": "int", "ver": "0",
        "data": "0"
      },
      "max_bus_speed_khz":{ "type": "int", "ver": "0",
        "data": "3300"
      },
      ...
}

上面config为platform-specific configuration, 格式为:target _ sensor_name _ hadware_id

图1
上图说明了platform-specific config中每个元素的含义。

图2
上图为可以用作SPI or I2C的GPIO,这些GPIO是可以复用的,
举个栗子:
bus_type:1,bus_instance:2,slave_config:1
意思为:使用SPI bus,QUP为2,即使用SSC_6、SSC_7、SSC_8、SSC_9、SSC_10、SSC_11这6组GPIO。slave_config为0,即设备连在SSC_6(QUP2 lane4)上。

若bus_type :0 ,其他不变的话。
意思为:使用I2C bus,QUP为2,即使用SSC_2、SSC_3,I2C2这组I2C。slave address为0x01。

图3
上图为sensor中断GPIO。高通强烈建议用户使用中断GPIO时与上图一一对应,所以accel的中断pin为117,mag的中断pin为119。

//sdm845_icm206xx_0.json
"dri_irq_num":{ "type": "int", "ver": "0",
        "data": "117"
      },

//sdm845_ak0991x_0.json
"dri_irq_num":{ "type": "int", "ver": "0",
        "data": "119"
      },

下面说下driver-specific configuration
/persist/sensors/registry/config/lsm6dsm_0.json

{
  "config":
  {
    "hw_platform": ["QRD", "MTP", "Dragon", "Surf", "HDK"],
    "soc_id": ["336", "341"]
  },
  "lsm6dso_0":{
    "owner": "lsm6dso",
    ".accel":{
      "owner": "lsm6dso",
      ".config":{
        "owner": "lsm6dso",
        "is_dri":{ "type": "int", "ver": "0",
          "data": "1"
        },
        "hw_id":{ "type": "int", "ver": "0",
          "data": "0"
        },
        "res_idx":{ "type": "int", "ver": "0",
          "data": "2"
        },
        "sync_stream":{ "type": "int", "ver": "0",
          "data": "0"
        }
      }
    },
    ".gyro":{
      "owner": "lsm6dso",
      ".config":{
        "owner": "lsm6dso",
        "is_dri":{ "type": "int", "ver": "0",
          "data": "1"
        },
        "hw_id":{ "type": "int", "ver": "0",
          "data": "0"
        },
        "res_idx":{ "type": "int", "ver": "0",
          "data": "4"
        },
        "sync_stream":{ "type": "int", "ver": "0",
          "data": "0"
        }
      }
    },
   ...
}

格式为: sensor_name_hadware_id

图4
上图说明了driver-specific config中每个元素的含义。

了解完registry & config,下面开始学习SLPI层Sensor。

/slpi/ssc/utils/osa/中为整个slpi的入口函数,分析build下osa.scons。可以看到user部分初始化函数为sns_user_pd_init。

 env.AddRCInitFunc(
    ['SSC_SLPI_USER','MODEM_MODEM','SSC_ADSP_USER'],
    {
      'sequence_group'             : 'RCINIT_GROUP_7',           # required
      'init_name'                  : 'sns',                      # required
      'init_function'              : 'sns_user_pd_init',         # required
      'dependencies'               : ['uTimetick','i2cbsp_init','adsppm_client','pram_mgr_clnt']
    })

该init函数为高通开放给custormer的入口函数,可以理解为main函数。

sns_rc sns_user_pd_init()
{
  if(false == sns_init_done)
  {
/* If enabled, this will delay the framework initialization by 7 seconds.
   This is to easily capture init messages when SSC boots up */
#if defined(SNS_DELAY_INIT)
    const sns_time one_second_in_ticks = 19200000ULL;
    for(int i = 7; i > 0; i--)
    {
      MSG_1(MSG_SSID_SNS, DBG_MED_PRIO, "init countdown %d ", i);
      /* sns_busy_wait is implemented as a sleep() */
      sns_busy_wait(one_second_in_ticks);
    }
#endif
    ...
    sns_fw_init();
    ...
}

这里我们不关心其他init,只研究sns_fw_init。我们开始进入SEE的framework层。
1.framework层
code放在/slpi/ssc/framework/中。

另外还要注意一下,SNS_DELAY_INIT这个宏,当定义后,会delay 7s后再进行framework 初始化。一般在debug时会加上该宏,用来抓取SSC boots up时的log。

//sns_fw_init.c
int sns_fw_init(void)
{
  ...
  rc = sns_sensor_init_fw();                      //No.1
  ...
  rc = sns_sensor_instance_init_fw();             //No.2
  ...
  rc = register_static_sensors();                 //No.3
  ...
  return 0;
}

//sns_sensor.c
sns_rc
sns_sensor_init_fw(void)
{
  ...
  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,
  };

  return SNS_RC_SUCCESS;
}

//sns_sensor_instance.c
sns_rc
sns_sensor_instance_init_fw(void)
{
  instance_cb = (sns_sensor_instance_cb)
  {
    .struct_len = sizeof(instance_cb),
    .get_service_manager = &get_service_manager,
    .get_client_request = &get_client_request,
    .remove_client_request = &remove_client_request,
    .add_client_request = &add_client_request
  };

  return SNS_RC_SUCCESS;
}

在sns_fw_init函数中我们着重分析上面三个函数,
No.1中是sns_sensor_cb的回调函数,这里需要注意下,后面分析sensor driver时会非常频繁的用到这些回调函数。
No.2中是sns_sensor_instance_cb的回到函数,同样需要注意下,后面使用也很频繁。
No.3中是所有sensor的静态注册函数。需要说明下,这个静态注册非常有意思。为了方便添加和移除sensor,高通SDM845中将注册函数写到build文件中,每次build image时,会动态的将build中注册函数写到特定的sensor注册文件中,以便register_static_sensors()使用。

举个例子,以accel的driver icm206xx为例,进入/slpi/ssc/sensors/icm206xx/中,看下build脚本sns_icm206xx.scons。

if 'USES_SSC_STATIC_LIB_BUILDER' in env:
  if 'SSC_TARGET_HEXAGON' in env['CPPDEFINES']:
    env.AddSSCSU(inspect.getfile(inspect.currentframe()),
               flavor = ["hexagon"],
               register_func_name = "sns_register_icm206xx",
               binary_lib = False,
               add_island_files = icm206xx_island_enable)

上面的含义是,若USES_SSC_STATIC_LIB_BUILDER在环境中,则往环境中添加如下数据。。。。可以看到register_func_name = “sns_register_icm206xx”,后面解析可以知道sns_register_icm206xx为accel sensor的入口函数,这里仅说明一下。

那么build环境中是否有USES_SSC_STATIC_LIB_BUILDER呢?
在SLPI build脚本ssc_static_lib_builder.py中中可以看到有加入该flag。

  env.AddUsesFlags('USES_SSC_STATIC_LIB_BUILDER')
  env.AddMethod(add_ssc_su, 'AddSSCSU')

那如何使用sensor入口函数sns_register_icm206xx呢?
还是在ssc_static_lib_builder.py中,有个函数generate_static_sensor_list()

if "sns_register_suid_sensor" == register_func_name:
          static_sensors.insert(0, (register_func_name, registration_cnt))
        else:
          static_sensors.append((register_func_name, registration_cnt))

#==============================================================================
# Generates sns_static_sensors.c
#==============================================================================
def generate_static_sensor_list(env, tags):
  global static_sensors
  if env.IsKeyEnable(tags) is True:
    logger.info("generate_static_sensor_list() called with %d sensors" % len(static_sensors))

    #dest = os.path.join(env.subst('${SSC_ROOT}'), 'framework', 'src')
    #if not os.path.isdir(dest) or not os.listdir(dest):
    #  return None

    if len(static_sensors) == 0:
      logger.error("There are no static sensors?!!!")
      return None

    static_sensors_file = os.path.join(env.subst('${SSC_ROOT}'),
                                       'framework', 'src', 'sns_static_sensors.c')
    fo = open(static_sensors_file, "w")
    fo.write("/* Autogenerated file.  Manual modification is pointless. */\n\n")
    fo.write("#include \"sns_rc.h\"\n")
    fo.write("#include \"sns_register.h\"\n")
    fo.write("#include \"sns_types.h\"\n")
    fo.write("\n")
    for reg_func,reg_cnt in static_sensors:
      fo.write("sns_rc %s(sns_register_cb const *register_api);\n" % reg_func)
    fo.write("\nconst sns_register_entry sns_register_sensor_list[] =\n{\n")
    for reg_func,reg_cnt in static_sensors:
      fo.write(" { %s, %i},\n" % (reg_func, reg_cnt))
    fo.write("};\n\n")
    fo.write("const uint32_t sns_register_sensor_list_len = ARR_SIZE(sns_register_sensor_list);\n\n")
    fo.close()

这个函数的作用是根据所有sensor的build脚本xxx.scons中入口函数,生成一个新的文件sns_static_sensors.c。
ok,编译完后git diff下,看到了生成的sns_static_sensors.c中新加了sns_register_icm206xx。

 sns_rc sns_gyro_cal_register(sns_register_cb const *register_api);
 sns_rc sns_gyro_rot_matrix_register(sns_register_cb const *register_api);
+sns_rc sns_register_icm206xx(sns_register_cb const *register_api);
 sns_rc sns_register_interrupt(sns_register_cb const *register_api);

const sns_register_entry sns_register_sensor_list[] =
 {
  { sns_gyro_rot_matrix_register, 1},
+ { sns_register_icm206xx, 1},
  { sns_register_interrupt, 1},
 }

我想大家应该都了解了吧,这样做的目的就是很快捷的添加或删除driver。

回到No.3,register_static_sensors函数中,

static sns_rc register_static_sensors(void)
{
  sns_register_cb reg_cb = (sns_register_cb)             //No.1
  {
    .struct_len = sizeof(reg_cb),
    .init_sensor = &sns_sensor_init                   
  };

  for(int i = 0; i < sns_register_sensor_list_len; i++)
  {
    for(int j = 0; j < sns_register_sensor_list[i].cnt; j++)      //No.2
    {
      ...
      sns_register_sensor_list[i].func(&reg_cb);
      sns_sensor_library_start(library);                        //No.3
      ...
    }
  }

  return SNS_RC_SUCCESS;
}

No.1中,sns_register_cb的回调函数,每个sensor driver入口函数都会调用该数据结构中.init_sensor函数。该函数的主要作用是,(1)判断是否是island mode,后面会将什么是island mode。(2)将相关数据结构加入到链表。比如library、sensors等等。
No.2中,上面生成sns_static_sensors.c文件中的sns_register_sensor_list.func,即sensor注册的入口函数;然后执行。执行后就进入的sensor driver的世界。
No.3中,sns_sensor_library_start,主要调用sensor_api->init函数和sensor_api->get_sensor_uid函数,至于sensor_api是什么,后面会讲,这里不懂先略过。

Ok,framework层初始化流程部分讲了一部分,下面开始讲sensor driver层,在sensor driver层讲解中顺带会说下相关的framework层,这样可以更深入的了解SEE框架。

2.sensor driver层
code放在/slpi/ssc/sensors/中
我们研究高通提供的demo sensor driver code:lsm6dso。

进入qcom_firware->slpi_proc->ssc->sensors->lsm6dso目录后,首先下看下build脚本。

####lsm6dso.scons######
Import('env')
import os,inspect

if ('SSC_TARGET_HEXAGON_MDSP' in env['CPPDEFINES']):
  Return()

lsm6dso_island_enable = False

if 'SNS_ISLAND_INCLUDE_LSM6DSO' in env:                                      #No.1
  lsm6dso_island_enable = True
if ('SSC_TARGET_HEXAGON' in env['CPPDEFINES']) and ('SENSORS_DD_DEV_FLAG' not in env):
  env.AddSSCSU(inspect.getfile(inspect.currentframe()),                      #No.2
               register_func_name = "sns_register_lsm6dso",
               binary_lib = False,
               add_island_files = lsm6dso_island_enable)

if 'SENSORS_DD_DEV_FLAG' in env:                                                   #No.3
  ME = inspect.getfile(inspect.currentframe())
  MY_ROOT = os.path.dirname(os.path.dirname(ME))
  REMOVE_FILES = env.FindFiles(['*.*'], MY_ROOT)
  env.CleanPack(env['SSC_BUILD_TAGS'], REMOVE_FILES)

No.1中若存在flag=SNS_ISLAND_INCLUDE_LSM6DSO,则lsm6dso_island_enable=true,即lsm6dso被设置成island mode。何为Island mode,高通解释island有着很低的功耗。

如何设置成为island mode呢?

在build脚本上,我们需要设置flag,在build/ssc.scons中加入。

env.AddUsesFlags(['SNS_ISLAND_INCLUDE_LSM6DSO'])

在sensor driver code上,我们我要
(1) 把sensor中这些API放到sns__sensor_island.c中实现

//本例为sns_lsm6dso_sensor_island.c
sns_sensor_api 内容
get_sensor_uid()
set_client_request()  only for accel driver libraries

(2)把sensor instance中这些API放到sns__sensor_instance_island.c中实现

//本例为sns_lsm6dso_sensor_instance_island.c
sns_sensor_instance_api内容
notify_event()
set_client_config()   only for accel driver libraries

(3)把所有sensor & sensor instance island中调用的函数放到sns__hal_island.c中实现:

//本例为sns_lsm6dso_hal_island.c
lsm6dso_com_write_wrapper()
lsm6dso_start_fifo_streaming()
and so on...

Normal情况哪些API放在哪些文件中呢?
(1) 把sensor中这些API放到sns__sensor.c中实现

init()
deinit()
set_client_request() for non-accel driver libraries
notify_event()

(2) 把sensor instance中这些API放到sns__sensor_instance.c中实现

init()
deinit()
set_client_config() only for non-accel driver libraries

(3)所有sensor & sensor instance 非island中调用的函数放到sns__hal.c中实现。

No.2中设置flag=SSC_TARGET_HEXAGON是动态注册,registry_func_name=”sns_register_lsm6dso”为sensor driver的入口函数。binary_lib为是否是二进制lib,高通的一些虚拟sensor比如计步器、amd、smd等等都是以lib形式提供给customer的。customer只要调用API使用即可,不需要知道如何实现。

No.3中设置flag=SENSORS_DD_DEV_FLAG是静态注册,在SDM845上使用的均为动态注册。

接着来到入口函数中:

//sns_lsm6dso.c
sns_rc sns_register_lsm6dso(sns_register_cb const *register_api)
{
  int i = 0;
  /** Register Sensors */
  for(i = 0; i< ARR_SIZE(lsm6dso_supported_sensors) ; i++) {
    register_api->init_sensor(sizeof(lsm6dso_state), lsm6dso_supported_sensors[i].sensor_api,
        lsm6dso_supported_sensors[i].instance_api);
  }
  return SNS_RC_SUCCESS;
}

//sns_lsm6dso_sensor_island.c
const lsm6dso_sensors lsm6dso_supported_sensors[ MAX_SUPPORTED_SENSORS ] = {
  {LSM6DSO_ACCEL, &lsm6dso_accel_sensor_api, &lsm6dso_sensor_instance_api},
  {LSM6DSO_GYRO, &lsm6dso_gyro_sensor_api, &lsm6dso_sensor_instance_api},
  {LSM6DSO_MOTION_DETECT , &lsm6dso_motion_detect_sensor_api, &lsm6dso_sensor_instance_api},
  {LSM6DSO_SENSOR_TEMP, &lsm6dso_sensor_temp_sensor_api, &lsm6dso_sensor_instance_api}
};

上面入口函数中注册四组api,每组api包含sns_sensor_api 和 sns_sensor_instance_api。
sns_sensor_api数据结构放在sns_lsm6dso_sensor_island.c中;该部分主要是为了sensor的初始化
sns_sensor_instance_api数据结构放在sns_lsm6dso_sensor_instance_island.c中;该部分主要是为了sensor对应的操作

以LSM6DSO_ACCEL为例:
1: sns_sensor_api定义在sns_sensor.h中,结构如下:

typedef struct sns_sensor_api
{
  uint32_t struct_len;

  /**
   * Initialize a Sensor to its hard-coded/default state.  Generate
   * requests for any other necessary data (e.g. Registry data).  A call to
   * sns_sensor_api::deinit will precede any subsequent calls to this function.
   *
   * @param[i] this Sensor reference
   *
   * @return
   * SNS_RC_INVALID_STATE - Requisite hardware not available
   * SNS_RC_POLICY - Required services not available
   * SNS_RC_SUCCESS
   */
  sns_rc (*init)(
    sns_sensor *const this);

  /**
   * Release all hardware and software resources associated with this Sensor
   *
   * @param[i] this Sensor reference
   *
   * @return
   * SNS_RC_INVALID_STATE - Error occurred: some resource could not be released
   * SNS_RC_SUCCESS
   */
  sns_rc (*deinit)(
    sns_sensor *const this);

  /**
   * Each Sensor must have a globally unique identifier; each algorithm
   * and driver will define their own. If a Sensor may be loaded twice on the
   * system, it is responsible for returning two unique values.  These must
   * not change across device reboots.
   *
   * @param[i] this Sensor reference
   *
   * @return The unique identifier for this Sensor
   */
  sns_sensor_uid const* (*get_sensor_uid)(
    sns_sensor const *const this);

  /**
   * Notification to the client that some data has been received.
   *
   * The client must use the sns_event_service to obtain this data
   * for processing.
   *
   * @return
   * SNS_RC_INVALID_STATE - A client error occurred; Framework shall destroy
   *                        client
   * SNS_RC_NOT_AVAILABLE - A transitory error occurred; Framework shall
   *                        remove all outstanding input
   * SNS_RC_INVALID_LIBRARY_STATE - A permanent error occurred; Framework shall
   *                        destroy all sensors present in the client library
   * SNS_RC_SUCCESS
   */
  sns_rc (*notify_event)(
    sns_sensor *const this);

  /**
   * Add, remove, or update a client's request to this Sensor.
   *
   * For each new request sent by a client, the Sensor (via this function)
   * will receive the new_request.  If the client has an active request
   * (which is to be replaced), it will be specified in exist_request.
   *
   * If 'remove' is false:
   * A client has sent a new request to this Sensor.  Determine if any
   * active Sensor Instance in sns_sensor_cb::get_sensor_instance()
   * will handle this request.  If yes, use add_client_request to associate
   * this new request with that existing Instance.
   *
   * If not, instantiate and initialize a new Sensor Instance with the
   * appropriate configuration, and similarly use add_client_request.
   *
   * In either case, if exist_request is provided and new_request provides
   * a superceding configuration, exist_request must be removed via
   * remove_client_request.
   *
   * If 'remove' is true:
   * Remove this client request by sns_sensor_instance_cb::remove_client_request;
   * re-arrange any remaining client requests/sensor instances.
   *
   * In all cases, if the result of the operation is a Sensor Instance with
   * zero clients, sns_sensor_cb::remove_instance must be called.
   *
   * @param[i] this Sensor reference
   * @param[i] exist_request If this request comes-in over an existing stream,
   *                       this is the existing request.
   * @param[i] new_request New request just received
   * @param[i] remove If the client no longer requires this data
   *
   * @return
   * The Sensor Instance chosen to handle this new client.  NULL if an error
   * occurred during processing; or if "remove" was true.
   * Or sns_instance_no_error (see above).
   */
  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);
} sns_sensor_api;

上面每个函数都有注释,这里不再解释。

//sns_lsm6dso_sensor_island.c , sns_sensor_api放在island文件中,上面island介绍中有解释。
sns_sensor_api lsm6dso_accel_sensor_api =
{
  .struct_len         = sizeof(sns_sensor_api),
  .init               = &lsm6dso_accel_init,
  .deinit             = &lsm6dso_accel_deinit,
  .get_sensor_uid     = &lsm6dso_get_sensor_uid,
  .set_client_request = &lsm6dso_set_client_request,
  .notify_event       = &lsm6dso_sensor_notify_event,
};

(1)lsm6dso_accel_init

//sns_lsm6dso_accel_sensor.c
sns_rc lsm6dso_accel_init(sns_sensor *const this)
{
  lsm6dso_state *state = (lsm6dso_state*)this->state->state;                   //No.1
  lsm6dso_acc_publish_attributes(this);                                                    //No.2
  lsm6dso_init_sensor_info(this, &((sns_sensor_uid)ACCEL_SUID), LSM6DSO_ACCEL); //No.3
  DBG_PRINT(state->diag_service, this, LOW, __FILENAME__, __LINE__, "accel init");
  return SNS_RC_SUCCESS;
}

No.1中:此形式应用非常广泛,同this指针中获取lsm6dso_state。
lsm6dso_state定义在sns_lsm6dso_sensor.h中,是sensor driver两个非常重要的数据结构之一,当然,另外一个是lsm6dso_instance_state。

(注:这里写成this,大家都明白什么意思了吧,虽然c语言不是面向对象语言,但底层开发处处用到面向对象的思想,this这很明显的说明sns_sensor类似于基类,不同的sensor都继承该基类,该基类数据形式都是common的,强制类型转换成每个sensor独有的数据;在C语言中只不过不叫基类而已,在这里叫做framework,在kernel中叫做core。)

No.2中:比较重要,将accel的atrributes publish到attribute service中并保存起来。

void lsm6dso_acc_publish_attributes(sns_sensor *const this)
{
  const char type[] = "accel";
  const uint32_t active_current[3] = {25, 85, 150}; //uA
  const uint32_t sleep_current = 3; //uA

  lsm6dso_publish_def_attributes(this);
  {
    sns_std_attr_value_data values[] = {SNS_ATTR, SNS_ATTR, SNS_ATTR, SNS_ATTR,     //No.a
                                        SNS_ATTR, SNS_ATTR/*, SNS_ATTR, SNS_ATTR,SNS_ATTR*/};
    values[0].has_flt = true;
    values[0].flt = LSM6DSO_ODR_13;
    values[1].has_flt = true;
    values[1].flt = LSM6DSO_ODR_26;
    values[2].has_flt = true;
    values[2].flt = LSM6DSO_ODR_52;
    values[3].has_flt = true;
    values[3].flt = LSM6DSO_ODR_104;
    values[4].has_flt = true;
    values[4].flt = LSM6DSO_ODR_208;
    values[5].has_flt = true;
    values[5].flt = LSM6DSO_ODR_416;
    //QC currently we are limiting to 416
    /*
    values[6].has_flt = true;
    values[6].flt = LSM6DSO_ODR_833;
    values[7].has_flt = true;
    values[7].flt = LSM6DSO_ODR_1660;
    values[8].has_flt = true;
    values[8].flt = LSM6DSO_ODR_3330;
    values[9].has_flt = true;
    values[9].flt = LSM6DSO_ODR_6660;
    */
    sns_publish_attribute(this, SNS_STD_SENSOR_ATTRID_RATES,
        values, ARR_SIZE(values), false);
  }
  {                                                                                                      //No.b
    sns_std_attr_value_data value = sns_std_attr_value_data_init_default;
    value.str.funcs.encode = pb_encode_string_cb;
    value.str.arg = &((pb_buffer_arg)
        { .buf = type, .buf_len = sizeof(type) });
    sns_publish_attribute(
        this, SNS_STD_SENSOR_ATTRID_TYPE, &value, 1, false);
  }
  {                                                                                                 //No.c
    sns_std_attr_value_data values[] = {SNS_ATTR, SNS_ATTR, SNS_ATTR, SNS_ATTR};
    int i;
    for(i = 0; i < ARR_SIZE(values); i++)
    {
      values[i].has_flt = true;
      values[i].flt = lsm6dso_accel_resolutions[i];
    }
    sns_publish_attribute(this, SNS_STD_SENSOR_ATTRID_RESOLUTIONS,
        values, i, false);
  }
  {                                                                                                 //No.d
    sns_std_attr_value_data values[] = {SNS_ATTR, SNS_ATTR, SNS_ATTR};
    int i;
    for(i = 0; i < ARR_SIZE(active_current); i++)
    {
      values[i].has_sint = true;
      values[i].sint = active_current[i];
    }
    sns_publish_attribute(this, SNS_STD_SENSOR_ATTRID_ACTIVE_CURRENT,
        values, i, false);
  }
  {                                                                                            //No.e
    sns_std_attr_value_data value = sns_std_attr_value_data_init_default;
    value.has_sint = true;
    value.sint = sleep_current; //uA
    sns_publish_attribute(
        this, SNS_STD_SENSOR_ATTRID_SLEEP_CURRENT, &value, 1, false);
  }
  {                                                                                          //No.f
    sns_std_attr_value_data values[] = {SNS_ATTR, SNS_ATTR, SNS_ATTR, SNS_ATTR};

    sns_std_attr_value_data range1[] = {SNS_ATTR, SNS_ATTR};
    range1[0].has_flt = true;
    range1[0].flt = LSM6DSO_ACCEL_RANGE_2G_MIN;
    range1[1].has_flt = true;
    range1[1].flt = LSM6DSO_ACCEL_RANGE_2G_MAX;
    values[0].has_subtype = true;
    values[0].subtype.values.funcs.encode = sns_pb_encode_attr_cb;
    values[0].subtype.values.arg =
      &((pb_buffer_arg){ .buf = range1, .buf_len = ARR_SIZE(range1) });

    sns_std_attr_value_data range2[] = {SNS_ATTR, SNS_ATTR};
    range2[0].has_flt = true;
    range2[0].flt = LSM6DSO_ACCEL_RANGE_4G_MIN;
    range2[1].has_flt = true;
    range2[1].flt = LSM6DSO_ACCEL_RANGE_4G_MAX;
    values[1].has_subtype = true;
    values[1].subtype.values.funcs.encode = sns_pb_encode_attr_cb;
    values[1].subtype.values.arg =
      &((pb_buffer_arg){ .buf = range2, .buf_len = ARR_SIZE(range2) });

    sns_std_attr_value_data range3[] = {SNS_ATTR, SNS_ATTR};
    range3[0].has_flt = true;
    range3[0].flt = LSM6DSO_ACCEL_RANGE_8G_MIN;
    range3[1].has_flt = true;
    range3[1].flt = LSM6DSO_ACCEL_RANGE_8G_MIN;
    values[2].has_subtype = true;
    values[2].subtype.values.funcs.encode = sns_pb_encode_attr_cb;
    values[2].subtype.values.arg =
      &((pb_buffer_arg){ .buf = range3, .buf_len = ARR_SIZE(range3) });

    sns_std_attr_value_data range4[] = {SNS_ATTR, SNS_ATTR};
    range4[0].has_flt = true;
    range4[0].flt = LSM6DSO_ACCEL_RANGE_16G_MIN;
    range4[1].has_flt = true;
    range4[1].flt = LSM6DSO_ACCEL_RANGE_16G_MAX;
    values[3].has_subtype = true;
    values[3].subtype.values.funcs.encode = sns_pb_encode_attr_cb;
    values[3].subtype.values.arg =
      &((pb_buffer_arg){ .buf = range4, .buf_len = ARR_SIZE(range4) });
    sns_publish_attribute(this, SNS_STD_SENSOR_ATTRID_RANGES,
        values, ARR_SIZE(values), true);
  }
  {                                                                                                  //No.g
    sns_std_attr_value_data values[] = {SNS_ATTR};
    char const proto1[] = "sns_accel.proto";
    values[0].str.funcs.encode = pb_encode_string_cb;
    values[0].str.arg = &((pb_buffer_arg)
        { .buf = proto1, .buf_len = sizeof(proto1) });
    sns_publish_attribute(this, SNS_STD_SENSOR_ATTRID_API,
        values, ARR_SIZE(values), false);
  }
}

看似好多东西啊,其实这些东西都是简单的参数。就是lsm6dso driver中accel的一些属性。
sns_publish_attribute参数分别代表:1,sns_sensor;2,attribute_id;3,value;4,value length;5,completed代表是否是最后一被设置的属性,若为true,后续不能修改该属性;若为false,后续可以修改该属性。

No.a中,sns_std_attr_value_data是一个保存attr value的data,初始化元素为SNS_ATTR

#define SNS_ATTR sns_std_attr_value_data_init_default

#define sns_std_attr_value_data_init_default     {false, sns_std_attr_value_init_default, {{NULL}, NULL}, false, 0, false, 0, false, 0}

typedef struct _sns_std_attr_value_data {
    bool has_subtype;
    sns_std_attr_value subtype;
    pb_callback_t str;
    bool has_flt;
    float flt;
    bool has_sint;
    int64_t sint;
    bool has_boolean;
    bool boolean;
/* @@protoc_insertion_point(struct:sns_std_attr_value_data) */
} sns_std_attr_value_data;

可以看到有6个SNS_ATTR,即后面有6个value[ 0 ~ 5 ],value的has_flt位均设为true,value的flt为LSM6DSO_ODR_13、LSM6DSO_ODR_26、LSM6DSO_ODR_52等等,

设置完后,通过sns_publish_attribute将attribute_id为SNS_STD_SENSOR_ATTRID_RATES publish到attribute service中。

后面简略的介绍下sns_publish_attribute函数后续流程。

//sns_attribute_util.c
SNS_SECTION(".text.sns") void                                                      //No.a
sns_publish_attribute(sns_sensor *const sensor,
    uint32_t attribute_id, sns_std_attr_value_data const *values,
    uint32_t values_len, bool completed)
{
  size_t attribute_len = 0;
  sns_std_attr std_attr = (sns_std_attr)                          //No.b
    { .attr_id = attribute_id, .value.values.funcs.encode = &sns_pb_encode_attr_cb,
      .value.values.arg = &((pb_buffer_arg){ .buf = values, .buf_len = values_len }) };

  if(pb_get_encoded_size(&attribute_len, sns_std_attr_fields, &std_attr))              //No.c
  {
    sns_service_manager *manager = sensor->cb->get_service_manager(sensor);
    sns_attribute_service *attribute_service =
      (sns_attribute_service*)manager->get_service(manager, SNS_ATTRIBUTE_SERVICE);

    uint8_t attribute[attribute_len];
    pb_ostream_t stream = pb_ostream_from_buffer(attribute, attribute_len);  

    if(pb_encode(&stream, sns_std_attr_fields, &std_attr))                          //No.d
      attribute_service->api->publish_attribute(attribute_service, sensor,
        attribute, attribute_len, attribute_id, completed);

    // PEND: Print a message upon errors
  }
}

No.a 中 SNS_SECTION(“.text.sns”),将函数放到.text.sns段。
No.b 中根据前面的values填充pb_buffer_arg、填充sns_std_attr数据结构。

typedef struct _sns_std_attr {
    int32_t attr_id;
    sns_std_attr_value value;
/* @@protoc_insertion_point(struct:sns_std_attr) */
} sns_std_attr;

No.c 中获取sns_service_manager,然后通过get_service来获取attribute service。
No.d 中通过attribute service中api进行push_attribute。

SNS_SECTION(".text.sns") static sns_rc
publish_attribute(sns_attribute_service *this, struct sns_sensor *sensor,
    void const *attribute, uint32_t attribute_len, sns_attribute_id attribute_id,
    bool completed)
{
  UNUSED_VAR(this);
  UNUSED_VAR(completed);
  sns_list_iter iter;
  sns_fw_sensor *fw_sensor = (sns_fw_sensor*)sensor;                      //No.a
  sns_attribute *new_attr;
  sns_mem_heap_id heap =
    (SNS_STD_SENSOR_ATTRID_TYPE == attribute_id ||
     SNS_STD_SENSOR_ATTRID_VENDOR == attribute_id)
    ? SNS_HEAP_ISLAND : SNS_HEAP_MAIN;

  SNS_ISLAND_EXIT();
  new_attr = sns_malloc(heap, sizeof(*new_attr) + attribute_len);

  if(SNS_HEAP_ISLAND == heap && NULL == new_attr)
  {
    new_attr = sns_malloc(SNS_HEAP_MAIN, sizeof(*new_attr) + attribute_len);
    fw_sensor->island_operation = SNS_ISLAND_STATE_ISLAND_DISABLED;
  }
  SNS_ASSERT(NULL != new_attr);

  sns_list_item_init(&new_attr->list_entry, new_attr);
  new_attr->id = attribute_id;
  new_attr->value_len = attribute_len;
  sns_memscpy(&new_attr->value, attribute_len, attribute, attribute_len);

  for(sns_list_iter_init(&iter, &fw_sensor->attr_info->attributes, true);
      NULL != sns_list_iter_curr(&iter);
      sns_list_iter_advance(&iter))
  {
    sns_attribute *attr =
       (sns_attribute*)sns_list_item_get_data(sns_list_iter_curr(&iter));
    if(attr->id == attribute_id)
    {
      sns_list_iter_remove(&iter);
      sns_free(attr);
      break;
    }
  }

  sns_list_iter_insert(&iter, &new_attr->list_entry, false);
  process_special_attributes(new_attr, fw_sensor);          //No.b

  return SNS_RC_SUCCESS;
}

No.a中有个重要的数据结构sns_fw_sensor,该数据结构定义在sns_fw_sensor.h,每个sensor都有自己的sns_fw_sensor。将sns_sensor地址赋给sns_fw_sensor,所以sns_fw_sensor第一个成员为sns_sensor,而且sns_fw_sensor只用在framework层,不开放给sensor开发者使用。

No.b中process_special_attributes继续:

SNS_SECTION(".text.sns") static void
process_special_attributes(sns_attribute *new_attr, sns_fw_sensor *fw_sensor)
{
  if(SNS_STD_SENSOR_ATTRID_AVAILABLE == new_attr->id)   
  {
    bool available = (bool)decode_attribute(new_attr, &pb_decode_attr_value_cb);
    if(available != sns_attr_info_get_available(fw_sensor->attr_info))
    {
      char data_type[32];
      sns_attr_info_get_data_type(fw_sensor->attr_info, data_type, sizeof(data_type));
      sns_attr_info_set_available(fw_sensor->attr_info, available);
      sns_suid_sensor_apprise(data_type);
    }
    sns_diag_register_sensor(fw_sensor);
  }
  else if(SNS_STD_SENSOR_ATTRID_TYPE == new_attr->id)
  {
    sns_attr_priority priority = { false, false };
    char const *data_type =
      (char*)decode_attribute(new_attr, &pb_decode_attr_value_cb);
    SNS_ASSERT(NULL != data_type);
    sns_attr_info_set_data_type(fw_sensor->attr_info, data_type);

    for(uint8_t i = 0; i < ARR_SIZE(event_priority_datatypes); i++)
    {
      if(0 == strcmp(data_type, event_priority_datatypes[i]))
      {
        priority.event_priority = true;
        break;
      }
    }
    for(uint8_t i = 0; i < ARR_SIZE(req_priority_datatypes); i++)
    {
      if(0 == strcmp(data_type, req_priority_datatypes[i]))
      {
        priority.req_priority = true;
        break;
      }
    }

    sns_attr_info_set_priority(fw_sensor->attr_info, priority);
  }
  else if(SNS_STD_SENSOR_ATTRID_VENDOR == new_attr->id)
  {
    char const *vendor = (char*)decode_attribute(new_attr, &pb_decode_attr_value_cb);
    sns_attr_info_set_vendor(fw_sensor->attr_info, vendor);
  }
  else if(SNS_STD_SENSOR_ATTRID_PHYSICAL_SENSOR == new_attr->id &&
          !sns_attr_info_get_is_physical_sensor(fw_sensor->attr_info))
  {
    bool physical_sensor = (bool)decode_attribute(new_attr, &pb_decode_attr_value_cb);
    sns_attr_info_set_is_physical_sensor(fw_sensor->attr_info, physical_sensor);
  }
}

上面函数主要根据attribute_id进行不同的处理,并将数据保存在fw_sensor->attr_info中。

Ok,上面关于sns_publish_attribute大概介绍完毕,有兴趣的童鞋可以仔细研究,没有兴趣的话不影响大局,可以略过不看,只需记得attribte参数放进sns_fw_sensor->attr_info中,以便后续使用!

回到lsm6dso_acc_publish_attributes中。
No.b中:同样publish attribute_id为SNS_STD_SENSOR_ATTRID_TYPE的value。
No.c中:同样publish attribute_id为SNS_STD_SENSOR_ATTRID_RESOLUTIONS的value。
No.d中:同样publish attribute_id为SNS_STD_SENSOR_ATTRID_ACTIVE_CURRENT的value。
No.e中:同样publish attribute_id为SNS_STD_SENSOR_ATTRID_SLEEP_CURRENT的value。
No.f中:同样publish attribute_id为SNS_STD_SENSOR_ATTRID_RANGES的value。范围
No.g中:同样publish attribute_id为SNS_STD_SENSOR_ATTRID_API的value。API使用的是sns_accel.proto。

回到lsm6dso_init_sensor_info中,
首先介绍几个数据结构。之前我们知道有个struct sns_sensor,sns_sensor有个成员为struct sns_sensor_cb const*cb我们没有介绍过。

//sns_sensor.h
typedef struct sns_sensor
{
  /* Functions which call back into the framework; provided by the Framework */
  struct sns_sensor_cb const *cb;

  /* API implementation provided for and by this Sensor */
  struct sns_sensor_api const *sensor_api;

  /* The associated API for an Sensor Instances created for and by this
 * Sensor. */
  struct sns_sensor_instance_api const *instance_api;

  /* State space allocated by the Framework for the sole use of the Sensor
 * developer. */
  struct sns_sensor_state *state;
} sns_sensor;
//sns_sensor.h
typedef struct sns_sensor_cb
{
  uint32_t struct_len;

  /**
 * Get a reference to the Service Manager.  With this object, a reference
 * to any other utility service can be obtained.
 *  * @param[i] this Sensor reference
 *  * @return Service Manager reference
   */
  struct sns_service_manager* (*get_service_manager)(
    sns_sensor const *this);

  /**
 * Return the next Sensor Instance associated with this Sensor.
 *  * Each Sensor has a list of associated Sensor Instances; entries are added
 * to that list within calls to 'create_instance', and removed from the
 * list when it services no client requests.
 *  * Each call to this function iterates over the list, and returns the next
 * entry.  NULL is returned at the end of the list, or if the list is empty.
 *  * @param[i] this Sensor reference
 * @param[i] first Return the first instance; reset the internal iterator
 *                 Must be called first to initialize iteration
 *  * @return Next Sensor Instance associated with this Sensor
   */
  struct sns_sensor_instance* (*get_sensor_instance)(
    sns_sensor const *this,
    bool first);

  /**
 * Allocate and initialize a new Sensor Instance to be associated with this
 * Sensor.  Will call sns_sensor_instance::init.
 *  * @note Direct pointers to the returned value should not be saved.
 *  * @param[i] this Sensor reference
 * @param[i] stateLen Allocation size for sns_sensor_instance::state
 *  * @return Newly created Sensor Instance
   */
  struct sns_sensor_instance* (*create_instance)(
    sns_sensor *this,
    uint32_t state_len);

  /**
 * Remove and deallocate a Sensor Instance.  Will call
 * sns_sensor_instance::deinit.
 *  * @param[i] instance Instance received within set_client_request
   */
  void (*remove_instance)(
    struct sns_sensor_instance *instance);

  /**
 * Return the next Sensor associated with this library.
 *  * Each Sensor is a member of a library; each library may contain several
 * Sensors.  Sensors may be removed from a library upon errors, but no
 * entries are added after Framework initialization has completed.
 *  * Each call to this function iterates over the list, and returns the next
 * entry.  NULL is returned at the end of the list, or if the list is empty.
 *  * This function is intended to be used by Sensors which share physical
 * hardware with another sensor, and hence must share state/instances.
 *  * @param[i] this Sensor reference
 * @param[i] first Return the first sensor; reset the internal iterator;
 *                 Must be called first to initialize iteration
 *  * @return Next Sensor associated with this library.
   */
  struct sns_sensor* (*get_library_sensor)(
    sns_sensor const *this,
    bool first);

  /**
 * If multiple copies of this Sensor Library have been registered with SEE,
 * this returns the index (starting at '0') of this particular copy.  See
 * parameter registration_cnt of env.AddSSCSU.
 *  * @param[i] this Sensor reference
 *  * @return Library registration index
   */
  uint32_t (*get_registration_index)(
    sns_sensor const *this);
} sns_sensor_cb;

sns_sensor_cb是通过SEE framework 提供来给sensor使用的callback。其中包含5个函数,分别是

  • .get_service_manager():用来获取service manager handle。
  • .get_sensor_instance():用来获取sensor的下一个instance。
  • .create_instance():创建新的instance。
  • .remove_instance():移除存在的instance。
  • .get_library_sensor():通过sensor library 获取另一个sensor的support。

No.3中:填充lsm6dso_state,
通过sns_sensor ->cb->get_service_manager来获取一个sns_service_manager的handle。sns_service_manager是可以管理所有service的数据结构。

然后在介绍下init_dependencies比较重要:

//sns_lsm6dso_sensor.c
static char def_dependency[][MAX_DEP_LENGTH] =  {
  "interrupt", "async_com_port", "timer", "data_acquisition_engine", "registry"
};

static void init_dependencies(sns_sensor *const this)
{
  int i = 0;
  lsm6dso_state *state = (lsm6dso_state*)this->state->state;

  DBG_PRINT(state->diag_service, this, LOW, __FILENAME__, __LINE__, "init_dependencies sensor");

  for(i=0;i<ARR_SIZE(def_dependency);i++)
  {
    send_suid_req(this, def_dependency[i], strlen(def_dependency[i]));
  }
}

accel 所依赖的platform sensor。有interrupt、async_com_port、timer、registry等等。
send_suid_req函数内容比较中要!因为后面很多地方会用到,这里我们重点介绍下:

static void send_suid_req(sns_sensor *this, char *const data_type, uint32_t data_type_len)
{
  lsm6dso_state *state = (lsm6dso_state*)this->state->state;

  if(state->fw_stream == NULL)          //No.a
  {
    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);
     stream_service->api->create_sensor_stream(stream_service, this, sns_get_suid_lookup(),
                                               &state->fw_stream);
  }

  if(state->fw_stream != NULL)               //No.b
  {
    size_t encoded_len;
    pb_buffer_arg data = (pb_buffer_arg){ .buf = data_type, .buf_len = data_type_len };
    uint8_t buffer[50];

    sns_suid_req suid_req = sns_suid_req_init_default;             
    suid_req.has_register_updates = true;
    suid_req.register_updates = true;
    suid_req.data_type.funcs.encode = &pb_encode_string_cb;
    suid_req.data_type.arg = &data;
    sns_rc rc = SNS_RC_SUCCESS;

    encoded_len = pb_encode_request(buffer, sizeof(buffer), &suid_req, sns_suid_req_fields, NULL);
    if(0 < encoded_len)
    {
      sns_request request = (sns_request){
        .request_len = encoded_len, .request = buffer, .message_id = SNS_SUID_MSGID_SNS_SUID_REQ };
      rc = state->fw_stream->api->send_request(state->fw_stream, &request);
    }
    if(0 >= encoded_len || SNS_RC_SUCCESS != rc)
    {
      DBG_PRINT(state->diag_service, this, ERROR, __FILENAME__, __LINE__,
                "encoded_len=%d rc=%u", encoded_len, rc);
    }
  }
}

No.a中:首先介绍个数据结构sns_data_stream

//sns_data_stream.h
typedef struct sns_data_stream
{
  struct sns_data_stream_api *api;
} sns_data_stream;

typedef struct sns_data_stream_api
{
  uint32_t struct_len;

  /**
   * Send a request to some other service/Sensor.  This request may
   * update or replace the existing stream, depending on the Sensor
   * specification.
   *
   * @param[io] data_stream Data stream on which to send the request
   * @param[i] Request to be sent; Framework will copy request
   *
   * @return
   * SNS_RC_INVALID_TYPE - Request ID not valid
   * SNS_RC_INVALID_STATE - Stream is no longer available; create again
   * SNS_RC_SUCCESS
   */
  sns_rc (*send_request)(
    sns_data_stream *data_stream,
    sns_request *request);

  /**
   * Initiate a flush on the connection associated with sensorUID.
   *
   * @note This is a helper function; clients may also initiate a flush
   * by generating a flush request message, and sending it via send_request.
   *
   * @param[io] data_stream Data stream on which to initiate the flush
   *
   * @return
   * SNS_RC_INVALID_STATE - Stream is no longer available; create again
   * SNS_RC_SUCCESS
   */
  sns_rc (*initiate_flush)(
    sns_data_stream *data_stream);

  /**
   * Retrieve a pointer to the oldest unprocessed input sample associated with
   * this data stream from the event queue.  This event is a single, logical
   * sample, as produced and published by the source Sensor.
   *
   * @note Multiple sequential calls to this function will return the same
   * pointer.
   *
   * @param[io] data_stream Data stream from which to get an event
   *
   * @return Next unprocessed event on the queue; NULL if no events remain
   */
  sns_sensor_event* (*peek_input)(
    sns_data_stream *data_stream);

  /**
   * Remove the current event from the input queue (the event that would
   * be returned via peek_input).  Return the next unprocessed event from the
   * event queue.
   *
   * Once this function returns, there is no means to retrieve the removed
   * Event again; the data has been freed, and its memory should not be
   * accessed.
   *
   * @param[io] data_stream Data stream from which to get an event
   *
   * @return The next unprocessed event on the queue (after the removal occurs)
   *         NULL if no further events remain
   */
  sns_sensor_event* (*get_next_input)(
    sns_data_stream *data_stream);

  /**
   * Lookup the current number of input pending on this data stream.  This
   * value may change at any time, and should not be treated as precise.
   *
   * @note Do no rely on this value to assume valid input from peek_input.
   *
   * @param[io] data_stream Data stream from which to get the input count
   *
   * @return Number of input events (aka samples) available for processing
   */
  uint32_t (*get_input_cnt)(
    sns_data_stream *data_stream);
} sns_data_stream_api;

上面注释很清楚了,不再解释。
第一次很定进入state->fw_stream==NULL,通过获取sns_service_manager获取sns_service_type为SNS_STREAM_SERVICE的stream_service。并通过stream_service来创建一个新的sensor stream。

No.b中:接着会进入state->fw_stream != NULL,这里比较重要的是:会填充一个sns_suid_req,并通过pb_encode_request函数编码成buffer,然后继续填充sns_request,最后,通过state->fw_stream->api->send_request发送改message_id为SNS_SUID_MSGID_SNS_SUID_REQ的sns_request。后面不用说也可以知道,通过SNS_SUID_MSGID_SNS_SUID_EVENT接收的event,获取suid。不信,你可以看lsm6dso_sensor_notify_event中lsm6dso_process_suid_events函数。就是对SNS_SUID_MSGID_SNS_SUID_EVENT进行处理的。后面再详细介绍。

Ok,lsm6dso_accel_init解析完毕。

(2)init对应的是deinit

sns_rc lsm6dso_accel_deinit(sns_sensor *const this)
{
  UNUSED_VAR(this);
  // Turn Sensor OFF.
  // Close COM port.
  // Turn Power Rails OFF.
  // No need to clear lsm6dso_state because it will get freed anyway.

  return SNS_RC_SUCCESS;
}

(3)lsm6dso_get_sensor_uid函数,用来获取suid。

sns_sensor_uid const* lsm6dso_get_sensor_uid(sns_sensor const *const this)
{
  lsm6dso_state *state = (lsm6dso_state*)this->state->state;
  return &state->my_suid;
}

(4)lsm6dso_set_client_request函数,用来设置来自client的request。并创建sensor instance。
set_client_request函数的解释如下:
该函数是用来Add、remove、update来自client的request。
如果remove设为false:任何从sns_sensor_cb::get_sensor_instance()获取active的sensor instance来决定是否处理该request,若是,使用add_client_request将new request和existing instance关联起来。若不是,同样使用add_client_request来实例化并初始化一个新的sensor instance。在这两种情况下,exist_request存在,并且new_request提供一个超配置,exsit_request必须通过removed_client_request来移除。

如果remove为true:通过sns_sensor_instance_cb::remove_client_request来删除这个client,并重排来自client的request和sensor_instances。

可以看到在sns_stream_service.c的handle_req中,set_client_request的remove参数为false的。在handle_stream_destroy中,set_client_request的remove参数为true。

sns_sensor_instance* lsm6dso_set_client_request(sns_sensor *const this,
                                                struct sns_request const *exist_request,
                                                struct sns_request const *new_request,
                                                bool remove)
{
  lsm6dso_state *state = (lsm6dso_state*)this->state->state;                               //No.1
  sns_sensor_instance *instance = sns_sensor_util_get_shared_instance(this);   //No.2
  sns_diag_service* diag = state->diag_service;  sns_time on_timestamp;            //No.3
  sns_time delta;
  bool reval_config = false;
  ...
  if(remove)                                                  //No.4
  {
    if(NULL == instance) {
      DBG_PRINT(diag, this, ERROR, __FILENAME__, __LINE__,
          "lsm6dso_set_client_request:: Instance not available! Returning!");
      return instance;
    }

    DBG_PRINT(diag, this, MED, __FILENAME__, __LINE__,
        "lsm6dso_set_client_request:: remove request");

    lsm6dso_instance_state *inst_state =
      (lsm6dso_instance_state*)instance->state->state;
    inst_state->config_sensors |= state->sensor;

    instance->cb->remove_client_request(instance, exist_request);
    /* Assumption: The FW will call deinit() on the instance before destroying it.
       Putting all HW resources (sensor HW, COM port, power rail)in
       low power state happens in Instance deinit().*/
    if(exist_request->message_id != SNS_PHYSICAL_SENSOR_TEST_MSGID_SNS_PHYSICAL_SENSOR_TEST_CONFIG)
    {
      lsm6dso_reval_instance_config(this, instance, state->sensor);
    }
    else
    {
      lsm6dso_instance_state *inst_state =
        (lsm6dso_instance_state*)instance->state->state;

      //if reconfigure hw has been postponed due to a remove request during self test. Do it now
      if(inst_state->self_test_info.reconfig_postpone)
      {
        DBG_PRINT(diag, this, MED, __FILENAME__, __LINE__,
                        "Reconfiguring HW for request recieved during self-test");
        lsm6dso_reval_instance_config(this, instance, state->sensor);
        inst_state->fifo_info.interrupt_cnt = 0;
        inst_state->self_test_info.reconfig_postpone = false;
      }

      //If a factory self test was run, update the registry & sensor->state
      if(inst_state->self_test_info.update_registry)
      {
        DBG_PRINT(diag, this, MED, __FILENAME__, __LINE__,
                "Updating registry and sensor state with new calibration values");

        //copy to sensor state
        if(LSM6DSO_ACCEL == inst_state->self_test_info.sensor)
        {
          sns_memscpy(state->fac_cal_bias, sizeof(state->fac_cal_bias),
                      inst_state->accel_registry_cfg.fac_cal_bias, sizeof(inst_state->accel_registry_cfg.fac_cal_bias));
        }
        else if(LSM6DSO_GYRO == inst_state->self_test_info.sensor)
        {
          sns_memscpy(state->fac_cal_bias, sizeof(state->fac_cal_bias),
                      inst_state->gyro_registry_cfg.fac_cal_bias, sizeof(inst_state->gyro_registry_cfg.fac_cal_bias));
        }

        //Update flag in sensor_state to indicate which registry is to be updated

        //write registry
        inst_state->registry_reset.request = false;
        lsm6dso_sensor_write_output_to_registry(this, instance);

        // Set the flag to false indicating that the registry is updated
        inst_state->self_test_info.update_registry = false;
      }
    }
  }
  else                                                                      //No.5
  {
    // 1. If new request then:
    //     a. Power ON rails.
    //     b. Power ON COM port - Instance must handle COM port power.
    //     c. Create new instance.
    //     d. Re-evaluate existing requests and choose appropriate instance config.
    //     e. set_client_config for this instance.
    //     f. Add new_request to list of requests handled by the Instance.
    //     g. Power OFF COM port if not needed- Instance must handle COM port power.
    //     h. Return the Instance.
    // 2. If there is an Instance already present:
    //     a. Add new_request to list of requests handled by the Instance.
    //     b. Remove exist_request from list of requests handled by the Instance.
    //     c. Re-evaluate existing requests and choose appropriate Instance config.
    //     d. set_client_config for the Instance if not the same as current config.
    //     e. publish the updated config.
    //     f. Return the Instance.
    // 3.  If "flush" request:
    //     a. Perform flush on the instance.
    //     b. Return NULL.

    DBG_PRINT(diag, this, MED, __FILENAME__, __LINE__,
        "lsm6dso_set_client_request:: add request ");
    if(NULL != instance)
    {
      lsm6dso_instance_state *inst_state =
        (lsm6dso_instance_state*)instance->state->state;
      if(inst_state->self_test_info.test_alive)
      {
        DBG_PRINT(diag, this, HIGH, __FILENAME__, __LINE__,
            "Self test is running. Ignoring new request! ");
        return NULL;  // Return without honouring any request for any sensor streaming
      }
    }
    if(NULL == instance)
    {
      if(state->sensor == LSM6DSO_GYRO)
      {
        state->rail_config.rail_vote = SNS_RAIL_ON_NPM;
      }
      else
      {
        state->rail_config.rail_vote = SNS_RAIL_ON_LPM;
      }
      state->pwr_rail_service->api->sns_vote_power_rail_update(
          state->pwr_rail_service,
          this,
          &state->rail_config,
          &on_timestamp);

      delta = sns_get_system_time() - on_timestamp;

      // Use on_timestamp to determine correct Timer value.
      if(delta < sns_convert_ns_to_ticks(LSM6DSO_OFF_TO_IDLE_MS*1000*1000))
      {
        DBG_PRINT(diag, this, MED, __FILENAME__, __LINE__,
            "lsm6dso_set_client_request:: start power rail timer");
        lsm6dso_start_power_rail_timer(this,
            sns_convert_ns_to_ticks(LSM6DSO_OFF_TO_IDLE_MS*1000*1000) - delta,
            LSM6DSO_POWER_RAIL_PENDING_SET_CLIENT_REQ);
      } else {
        // rail is already ON
        DBG_PRINT(diag, this, MED, __FILENAME__, __LINE__,
            "lsm6dso_set_client_request::  power rail already ON");
        state->power_rail_pend_state = LSM6DSO_POWER_RAIL_PENDING_NONE;
        reval_config = true;

      }
      DBG_PRINT(diag, this, MED, __FILENAME__, __LINE__,
          "lsm6dso_set_client_request::  creating instance");
      /** create_instance() calls init() for the Sensor Instance */
      instance = this->cb->create_instance(this,
          sizeof(lsm6dso_instance_state));


      /* If rail is already ON then flag instance OK to configure */
      if(reval_config)
      {
        lsm6dso_instance_state *inst_state =
          (lsm6dso_instance_state*)instance->state->state;

        inst_state->instance_is_ready_to_configure = true;
      }

    }
    else
    {
      DBG_PRINT(diag, this, HIGH, __FILENAME__, __LINE__,
          "lsm6dso_set_client_request::  instance already available");
      if(NULL != new_request)
        DBG_PRINT(diag, this, MED, __FILENAME__, __LINE__,
            "sensor %d new_req msg_id %d",state->sensor, new_request->message_id);
      if(NULL != exist_request
          &&
          NULL != new_request
          &&
          new_request->message_id == SNS_STD_MSGID_SNS_STD_FLUSH_REQ)
      {
        lsm6dso_instance_state *inst_state =
          (lsm6dso_instance_state*)instance->state->state;

        if(inst_state->fifo_info.fifo_enabled &&
          ((state->sensor == LSM6DSO_ACCEL) || (state->sensor == LSM6DSO_GYRO)))
        {
          lsm6dso_send_flush_config(this, instance);
          /** Do not update instance client request list at this point
            because FIFO flush is a transitory request for an on-going
            stream request. */
          return instance;
        }
        else
        {
          /** There aren't any FIFO sensors enabled to support flush.
           *  Send flush complete event anyway. */
          lsm6dso_send_fifo_flush_done(instance, &state->my_suid);
          return instance;
        }
      }
      else
      {
        reval_config = true;

        /** An existing client is changing request*/
        if((NULL != exist_request) && (NULL != new_request))
        {
          instance->cb->remove_client_request(instance, exist_request);
        }

        /** A new client sent new_request*/
        else if(NULL != new_request)
        {
          // No-op. new_request will be added to requests list below.
        }
      }
    }
    /** Add the new request to list of client_requests.*/
    if(NULL != instance)
    {
      lsm6dso_instance_state *inst_state =
        (lsm6dso_instance_state*)instance->state->state;
      if(NULL != new_request)
      {
        instance->cb->add_client_request(instance, new_request);

        DBG_PRINT(diag, this, HIGH, __FILENAME__, __LINE__,
            "lsm6dso_set_client_request::  adding new client request reval_config = %d inst_ready_to_config = %d", reval_config, inst_state->instance_is_ready_to_configure);
        DBG_PRINT(diag, this, HIGH, __FILENAME__, __LINE__,
            "lsm6dso_set_client_request::  adding new client request sensor %d msg_id %d", state->sensor, new_request->message_id);
        if(LSM6DSO_MOTION_DETECT == state->sensor) {
          sns_memscpy(&inst_state->md_info.md_config, sizeof(inst_state->md_info.md_config),
              &state->md_config, sizeof(state->md_config));
          DBG_PRINT(diag, this, HIGH, __FILENAME__, __LINE__,
              "lsm6dso_set_client_request:: copying md config");
        }

        if(new_request->message_id == SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG
            ||
            new_request->message_id == SNS_STD_EVENT_GATED_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG) {
          inst_state->config_sensors |= state->sensor;
          //copy range/resolution to inst state
          if(LSM6DSO_ACCEL == state->sensor)
          {
            inst_state->accel_info.sstvt = lsm6dso_accel_resolutions[state->resolution_idx]*1000;  //convert to micro-g/LSB
            inst_state->accel_info.range = lsm6dso_accel_ranges[state->resolution_idx];
            inst_state->accel_info.range_idx = state->resolution_idx;
          }
          else if(LSM6DSO_GYRO == state->sensor)
          {
            inst_state->gyro_info.sstvt = lsm6dso_gyro_resolutions[state->resolution_idx];
            inst_state->gyro_info.range = lsm6dso_gyro_ranges[state->resolution_idx];
            inst_state->gyro_info.range_idx = state->resolution_idx;
          }
        }
        if(new_request->message_id == SNS_CAL_MSGID_SNS_CAL_RESET) {
          DBG_PRINT(diag, this, HIGH, __FILENAME__, __LINE__,
              "Received event: SNS_CAL_MSGID_SNS_CAL_RESET");
          inst_state->registry_reset.request = true;
          inst_state->registry_reset.sensor_type = state->sensor;
          lsm6dso_sensor_write_output_to_registry(this, instance);

          //copy to sensor state
          if(LSM6DSO_ACCEL == state->sensor)
          {
            sns_memscpy(state->fac_cal_bias, sizeof(state->fac_cal_bias),
                        inst_state->accel_registry_cfg.fac_cal_bias, sizeof(inst_state->accel_registry_cfg.fac_cal_bias));
            sns_memscpy(&state->fac_cal_corr_mat, sizeof(state->fac_cal_corr_mat),
                        &inst_state->accel_registry_cfg.fac_cal_corr_mat, sizeof(inst_state->accel_registry_cfg.fac_cal_corr_mat));
          }
          else if(LSM6DSO_GYRO == state->sensor)
          {
            sns_memscpy(state->fac_cal_bias, sizeof(state->fac_cal_bias),
                        inst_state->gyro_registry_cfg.fac_cal_bias, sizeof(inst_state->gyro_registry_cfg.fac_cal_bias));
            sns_memscpy(&state->fac_cal_corr_mat, sizeof(state->fac_cal_corr_mat),
                        &inst_state->gyro_registry_cfg.fac_cal_corr_mat, sizeof(inst_state->gyro_registry_cfg.fac_cal_corr_mat));
          }

          lsm6dso_send_cal_event(instance, state->sensor);
        }

        if(new_request->message_id == SNS_STD_SENSOR_MSGID_SNS_STD_ON_CHANGE_CONFIG
           &&
           state->sensor == LSM6DSO_MOTION_DETECT)
        {
          if(inst_state->fifo_info.publish_sensors & LSM6DSO_ACCEL) {
            //send event as MD disabled since non-gated client is active
            //no need of this as we alreay set md_info state
            sns_motion_detect_event md_state;
            md_state.motion_detect_event_type = SNS_MOTION_DETECT_EVENT_TYPE_DISABLED;

            DBG_PRINT(diag, this, MED, __FILENAME__, __LINE__,
                "send MD_event =%d",
                md_state.motion_detect_event_type);
            pb_send_event(instance,
                sns_motion_detect_event_fields,
                &md_state,
                sns_get_system_time(),
                SNS_MOTION_DETECT_MSGID_SNS_MOTION_DETECT_EVENT,
                &inst_state->md_info.suid);
            reval_config = false;
          } else if (inst_state->md_info.enable_md_int) {
            //there is exsisting md client already present, just send event
            DBG_PRINT(diag, this, MED, __FILENAME__, __LINE__,
                "send MD_event =%d",
                inst_state->md_info.cur_md_state.motion_detect_event_type);
            pb_send_event(instance,
                sns_motion_detect_event_fields,
                &inst_state->md_info.cur_md_state,
                sns_get_system_time(),
                SNS_MOTION_DETECT_MSGID_SNS_MOTION_DETECT_EVENT,
                &inst_state->md_info.suid);
            reval_config = false;
          } else
            inst_state->md_info.md_new_req = true;
        }
      }
      if(reval_config && inst_state->instance_is_ready_to_configure)
      {
        lsm6dso_reval_instance_config(this, instance, state->sensor);
      }
    }
  }
  if(NULL != instance) {
    lsm6dso_instance_state *inst_state =
      (lsm6dso_instance_state*)instance->state->state;
    //reset config sensor bit if sensor is not present if fifo enabled
    if(!(inst_state->fifo_info.fifo_enabled & state->sensor))
      inst_state->config_sensors &= ~state->sensor;
  }

  // Sensors are required to call remove_instance when clientless
  if(NULL != instance &&
     NULL == instance->cb->get_client_request(instance,
       &(sns_sensor_uid)ACCEL_SUID, true) &&
     NULL == instance->cb->get_client_request(instance,
       &(sns_sensor_uid)MOTION_DETECT_SUID, true) &&
     NULL == instance->cb->get_client_request(instance,
       &(sns_sensor_uid)GYRO_SUID, true) &&
     NULL == instance->cb->get_client_request(instance,
       &(sns_sensor_uid)SENSOR_TEMPERATURE_SUID, true))
  {
    this->cb->remove_instance(instance);
  }
  return instance;
}

炒鸡多,一步步分析吧。开始之前,在了解下sns_sensor_instance中的sns_sensor_instance_cb的callback函数吧,上面我们介绍了sns_sensor中的sns_sensor_cb callback函数。

//sns_sensor_instance.h
typedef struct sns_sensor_instance
{
  /* Functions which call back into the framework; provided by the Framework */
  struct sns_sensor_instance_cb const *cb;

  /* State space allocated by the Framework for the sole use of the Sensor
   * Instance developer. */
  struct sns_sensor_instance_state *state;
} sns_sensor_instance;
//sns_sensor_instance.h
typedef struct sns_sensor_instance_cb
{
  uint32_t struct_len;

  /**
   * Get a reference to the Service Manager.  With this object, a reference
   * to any other utility service can be obtained.
   *
   * @param[i] this Sensor Instance reference
   *
   * @return Service Manager reference
   */
  struct sns_service_manager* (*get_service_manager)(
    sns_sensor_instance *this);

  /**
   * Return the next client request associated with this Sensor Instance and
   * SUID.
   *
   * Each Sensor Instance has a list of client requests per SUID which it is
   * servicing.  Entries are added via calls to add_client_request; removed
   * via remove_client_request.
   *
   * Each call to this function iterates over the list, and returns the next
   * entry.  NULL is returned at the end of the list, or if the list is empty.
   *
   * @note An Instance may be handling client requests for multiple
   * (related) Sensors; must use SUID parameter to filter.
   *
   * @param[i] this Sensor Instance reference
   * @param[i] suid Sensor associated with this Instance
   * @param[i] first Return the first request; reset the internal iterator
   *                 Must be called first to initialize iteration
   *
   * SNS_RC_NOT_AVAILABLE - The Framework is not aware of SUID
   * SNS_RC_SUCCESS
   */
   struct sns_request const* (*get_client_request)(
    sns_sensor_instance *this,
    sns_sensor_uid const *suid,
    bool first);

   /**
    * Remove a client request from this Sensor Instance.
    *
    * @param[i] this Sensor Instance reference
    * @param[i] request Client request to be removed
    */
   void (*remove_client_request)(
    sns_sensor_instance *this,
    struct sns_request const *request);

  /**
   * Assign this Sensor Instance to service the client request.
   *
   * @note This function may only be given sns_request objects received
   * from sns_sensor_api::set_client_request.
   *
   * @note The SUID of the recepient Sensor will be noted upon addition;
   * this SUID must be used within get_client_request.
   *
   * @param[i] this Sensor Instance reference
   * @param[i] request Client request to be added
   */
   void (*add_client_request)(
    sns_sensor_instance *this,
    struct sns_request const *request);
} sns_sensor_instance_cb;

四个函数分别如下:

  • .get_service_manager():获取service manger的handle
  • .get_client_request():获取与instance相关联的下一次client request。
  • .remove_client_request():通过instance移除一个client的request handle。
  • .add_client_request():通过instance添加一个client request handle。

然后就可以继续分析set_client_request代码了。
No.1:获取lsm6dso_state指针。
No.2:获取一个共享的instance,许多物理sensor会共享一个单独的instance,这个函数就是查找这个共享的instance,若有返回instance,若无返回NULL。
No.3:获取diag_service
No.4:remove为true,即为移除instance。首先判断instance是否为NULL,
若为NULL,OK,已经不能用了,直接返回即可。
若不为NULL,现获取从instance中获取lsm6dso_instance_state,并通过instance_state的callback函数cb来remove_client_request来从instance中移除exist_request。

紧接着,
若msg_id不是SNS_PHYSICAL_SENSOR_TEST_MSGID_SNS_PHYSICAL_SENSOR_TEST_CONFIG,需要设置instance的config并关电。在lsm6dso_reval_instance_config函数中进行处理。
若msg_id是,会将config数据写到registry sensor中,通过lsm6dso_sensor_write_output_to_registry()函数保存在“/persist/sensor/registry/registry/lsm6dso_0_platform.accel.fac_cal”和“/persist/sensor/registry/registry/lsm6dso_0_platform.gyro.fac_cal”中。

具体细节不再分析。
No.5:else为remove为false的情况。也为创建新的instance的情况。
高通代码给出了相应的注释。

  • 若instance不为NULL,从instance获取lsm6dso_instance_state
  • 若instance为NULL,
    • 填充state的rail_config,设置rail电压。并通过sns_vote_power_rail_update配置rail config。
    • 通过sns_get_system_time获取时间
    • lsm6dso_start_power_rail_timer来上电
    • 通过create_instance来创建新的instance。
  • 若instance不为NULL
    • 若exist_request & new_request不为NULL,且new_request的msg_id为SNS_STD_MSGID_SNS_STD_FLUSH_REQ,若fifo enable,则发送flush fifo config,ACCEL & GYRO使用fifo,若fifo disable 或者不是accel or gyro,发送flash 完成的event。不再enable fifo 。(这里注意下:不要在enable后更新client的request给instance,因为FIFO是一个持续的stream request。)
    • 若exist_request or new_request为NULL 或者msg_id不为上面的msg_id,相应处理。
    • 若instance 不为NULL,再跟进new_request->msg_id不同设置相应的config。这里我们看到了常见的new_request->message_id == SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG。
    • 然后都完成后,通过lsm6dso_reval_instance_config函数来通过sensor instance进行处理。

接着分析下lsm6dso_reval_instance_config(),主要有一个函数lsm6dso_set_inst_config,在该函数中,可以看到,client request发送到sensor API中.set_client_request的数据,最终通过lsm6dso_set_inst_config函数发送给sensor_instance API中.set_client_config。

void lsm6dso_reval_instance_config(sns_sensor *this,
                              sns_sensor_instance *instance,
                              lsm6dso_sensor_type sensor_type)
{
  ...
  uint8_t sensor_count = ARR_SIZE(lsm6dso_supported_sensors);
  struct {
    lsm6dso_sensor_type sensor;
    float sample_rate;
    float report_rate;
    uint64_t flush_period_ticks;
    bool ngated_client_present; //= client_present
    bool gated_client_present; //incase of accel and md
  } sensor_info[sensor_count];
  ...
  for(; i< sensor_count ; i++) {
    ...
    if((sensor_info[i].sensor == LSM6DSO_ACCEL) ||
        (sensor_info[i].sensor == LSM6DSO_GYRO)) {
      lsm6dso_get_imu_config(this, instance, sensor_info[i].sensor,
          &sensor_info[i].sample_rate,
          &sensor_info[i].report_rate,
          &sensor_info[i].flush_period_ticks,
          &sensor_info[i].ngated_client_present,
          &sensor_info[i].gated_client_present);
      message_id = SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG;
      ...
    } else if(sensor_info[i].sensor == LSM6DSO_MOTION_DETECT) {
      lsm6dso_get_motion_detect_config(this,
          instance,
          &sensor_info[i].ngated_client_present);
          ...
        message_id = SNS_STD_SENSOR_MSGID_SNS_STD_ON_CHANGE_CONFIG;
        ...
    } else if(sensor_info[i].sensor == LSM6DSO_SENSOR_TEMP) {
      lsm6dso_get_sensor_temp_config(this, instance,
          &sensor_info[i].sample_rate,
          &sensor_info[i].report_rate,
          &sensor_info[i].flush_period_ticks,
          &sensor_info[i].ngated_client_present);
      message_id = SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG;
    } .
    chosen_sample_rate = SNS_MAX(chosen_sample_rate, sensor_info[i].sample_rate);
    chosen_report_rate = SNS_MAX(chosen_report_rate, sensor_info[i].report_rate);
    chosen_flush_ticks = SNS_MAX(chosen_flush_ticks, sensor_info[i].flush_period_ticks);
  ...

  lsm6dso_set_inst_config(this,
      instance,
      sensor_type,
      chosen_report_rate,
      chosen_sample_rate,
      chosen_flush_ticks,
      registry_cfg,
      message_id);
 ...
}

lsm6dso_reval_instance_config函数中会针对不同sensor type进行不同的处理,比如accel & gyro,使用lsm6dso_get_imu_config来从request中获取payload数据填充sensor_info;motion_detect,使用lsm6dso_get_motion_detect_config来填充sensor_info等等,chosen_sample_rate & chosen_sample_rate & chosen_flush_ticks会通过request中参数和他们自己进行比较取最大者。并通过lsm6dso_set_inst_config传递给sensor instance。

static void lsm6dso_set_inst_config(sns_sensor *this,
    sns_sensor_instance *instance,
    lsm6dso_sensor_type sensor,
    float chosen_report_rate,
    float chosen_sample_rate,
    uint64_t chosen_flush_ticks,
    sns_lsm6dso_registry_cfg registry_cfg,
    uint32_t message_id)
{
  ...
  if(((sensor == LSM6DSO_ACCEL) ||
      (sensor == LSM6DSO_GYRO) ||
      (sensor == LSM6DSO_MOTION_DETECT) ||
      (sensor == LSM6DSO_SENSOR_TEMP)) &&
      (inst_state->common_info.mode & LSM6DSO_MODE_SELF_TEST) &&
      (!inst_state->self_test_info.test_alive)) {
    sns_lsm6dso_self_test_req client_config;
    client_config.test_type = inst_state->self_test_info.test_type;
    req_config.message_id = SNS_PHYSICAL_SENSOR_TEST_MSGID_SNS_PHYSICAL_SENSOR_TEST_CONFIG;
    req_config.request_len = sizeof(sns_lsm6dso_self_test_req);
    req_config.request = &client_config;
    this->instance_api->set_client_config(instance, &req_config);

  } else if((sensor == LSM6DSO_ACCEL) ||
      (sensor == LSM6DSO_GYRO) ||
      (sensor == LSM6DSO_MOTION_DETECT) ||
      (sensor == LSM6DSO_SENSOR_TEMP)) {
    sns_lsm6dso_req client_config;
    client_config.desired_report_rate = chosen_report_rate;
    client_config.desired_sample_rate = chosen_sample_rate;
    client_config.desired_flush_ticks = chosen_flush_ticks;
    client_config.registry_cfg = registry_cfg;
    req_config.message_id = message_id;
    req_config.request_len = sizeof(sns_lsm6dso_req);
    req_config.request = &client_config;
    this->instance_api->set_client_config(instance, &req_config);
  }
  else
    return;

}

在该函数,
if中当inst_state->common_info.mode & LSM6DSO_MODE_SELF_TEST && (!inst_state->self_test_info.test_alive)为true,会用msg_id=SNS_PHYSICAL_SENSOR_TEST_MSGID_SNS_PHYSICAL_SENSOR_TEST_CONFIG进行factory calibration,往上追code发现,当client request中msg_id为SNS_PHYSICAL_SENSOR_TEST_MSGID_SNS_PHYSICAL_SENSOR_TEST_CONFIG时,会把inst_state->common_info.mode设成LSM6DSO_MODE_SELF_TEST的,这里是一一对应的。另外一个inst_state->self_test_info.test_alive,即此时正在进行操作,当然正在factory calibration操作时不能再操作,所以要满足该条件。
else中为正常走的流程,msg_id=SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG也会走该路。两者最后都会调用this->instance_api->set_client_config(instance, &req_config);进入sensor instance中。

此时,sns_sensor_api除了.notify_event其他均分析完了,为了高清流程性,.notify_event会最后分析。

2: sns_sensor_instance_api定义在sns_sensor_instance.h中,结构如下:

//sns_sensor_instance.h
typedef struct sns_sensor_instance_api
{
  uint32_t struct_len;

  /**
   * Initialize a Sensor Instance to its default state.  A call to
   * sns_sensor_instance_api::deinit will precede any subsequent calls
   * to this function.
   *
   * @note Persistent configuration can be made available using the
   * sensor_state.
   *
   * @param[i] this Sensor Instance reference
   * @param[i] sensor_state State of the Sensor which created this Instance
   *
   * @return
   * SNS_RC_NOT_AVAILABLE - Sensor state does not allow for this operation
   * SNS_RC_SUCCESS
   */
  sns_rc (*init)(
    sns_sensor_instance *const this,
    sns_sensor_state const *sensor_state);

  /**
   * Release all hardware and software resources associated with this Sensor
   * Instance.
   *
   * @param[i] this Sensor Instance reference
   *
   * @return
   * SNS_RC_INVALID_STATE - Error occurred: some resource could not be released
   * SNS_RC_SUCCESS
   */
  sns_rc (*deinit)(
    sns_sensor_instance *const this);

  /**
   * Update a Sensor Instance configuration to this sensorRequest.
   *
   * The Sensor Instance is expected to start all dependent streams, timers, etc..
   *
   * @note
   * A Sensor may define any number of unique request types they support.
   * However, a client may only have a single active stream; an enable
   * request can inherently serve as a "reconfiguration" request.
   *
   * @param[i] this Sensor Instance reference
   *
   * @return
   * SNS_RC_INVALID_VALUE - Invalid client request
   * SNS_RC_SUCCESS
   */
  sns_rc (*set_client_config)(
    sns_sensor_instance *const this,
    struct sns_request const *client_request);

  /**
   * Notification to the client that some data has been received.
   *
   * The client must use the sns_manager_event to obtain this data
   * for processing.
   *
   * @return
   * SNS_RC_INVALID_STATE - A client error occurred; Framework shall destroy client
   * SNS_RC_NOT_AVAILABLE - A transitory error occurred; Framework shall remove
   *    all outstanding input
   * SNS_RC_SUCCESS
   */
  sns_rc (*notify_event)(
    sns_sensor_instance *const this);
} sns_sensor_instance_api;

上面每个函数都有注释,这里不再解释。
什么时候会进入sns_sensor_instance API .init呢?在上面介绍中在lsm6dso_set_client_request有如下一段代码,

/** create_instance() calls init() for the Sensor Instance */
      instance = this->cb->create_instance(this,
          sizeof(lsm6dso_instance_state));

当instance为NULL时,通过cb创建一个instance,SEE framework会创建一个sensor instance并调用其.init函数。简略的追下code。

//sns_sensor.c
sns_rc
sns_sensor_init_fw(void)
{
  ...
  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,
  };

  return SNS_RC_SUCCESS;
}

其中create_instance回调的是sns_sensor_instance_init。

//sns_sensor_instance.c
SNS_SECTION(".text.sns") sns_sensor_instance*
sns_sensor_instance_init(sns_sensor *sensor, uint32_t state_len)
{
    sns_fw_sensor_instance *instance = NULL;
    instance = sns_sensor_instance_alloc(fw_sensor, state_len);
    ...
    rv = sensor->instance_api->init(
          (sns_sensor_instance*)instance, sensor->state);
   ...
  return (sns_sensor_instance*)instance;
}

其他不用管,可以看到sensor->instance_api->init()。

sns_rc lsm6dso_inst_init(sns_sensor_instance *const this,
    sns_sensor_state const *sstate)
{
  state->scp_service = (sns_sync_com_port_service*)
              service_mgr->get_service(service_mgr, SNS_SYNC_COM_PORT_SERVICE);

  /**---------Setup stream connections with dependent Sensors---------*/
  stream_mgr->api->create_sensor_instance_stream(stream_mgr,
                                                 this,
                                                 sensor_state->irq_suid,
                                                 &state->interrupt_data_stream);

  stream_mgr->api->create_sensor_instance_stream(stream_mgr,
                                                 this,
                                                 sensor_state->acp_suid,
                                                 &state->async_com_port_data_stream);

在lsm6dso_inst_init中多数为初始化设置,包含获取sync_com_port service和创建async_com_port&interrupt data stream。

state->scp_service->api->sns_scp_register_com_port(&state->com_port_info.com_config,
                                              &state->com_port_info.port_handle);

通过instance注册com port。
在instance state复制所有sensor uids,初始化FIFO状态,初始Accel状态,初始Gyro状态等等,初始化中断数据,初始化com config,enable async com port:

/** Configure the Async Com Port */
  {
    sns_data_stream* data_stream = state->async_com_port_data_stream;
    uint8_t pb_encode_buffer[100];
    sns_request async_com_port_request =
    {
      .message_id  = SNS_ASYNC_COM_PORT_MSGID_SNS_ASYNC_COM_PORT_CONFIG,
      .request     = &pb_encode_buffer
    };

    async_com_port_request.request_len =
      pb_encode_request(pb_encode_buffer,
                        sizeof(pb_encode_buffer),
                        &state->ascp_config,
                        sns_async_com_port_config_fields,
                        NULL);
    data_stream->api->send_request(data_stream, &async_com_port_request);
  }

等等。。。

对应的是lsm6dso_inst_deinit

sns_rc lsm6dso_inst_deinit(sns_sensor_instance *const this)
{
  lsm6dso_instance_state *state =
                  (lsm6dso_instance_state*)this->state->state;
  inst_cleanup(this, state);

  return SNS_RC_SUCCESS;
}
static void inst_cleanup(sns_sensor_instance *const this,
                         lsm6dso_instance_state *state)
{
  ...
  if(NULL != state->com_port_info.port_handle)
  {
    state->scp_service->api->sns_scp_update_bus_power(state->com_port_info.port_handle, true);
  }
  lsm6dso_set_fifo_config(this, 0, 0, 0, 0 );
  lsm6dso_reconfig_hw(this);
  if(NULL != state->com_port_info.port_handle)
  {
    state->scp_service->api->sns_scp_update_bus_power(state->com_port_info.port_handle, false);
  }

  sns_sensor_util_remove_sensor_instance_stream(this, &state->interrupt_data_stream);
  sns_sensor_util_remove_sensor_instance_stream(this, &state->async_com_port_data_stream);
  sns_sensor_util_remove_sensor_instance_stream(this, &state->timer_sensor_temp_data_stream);
  sns_sensor_util_remove_sensor_instance_stream(this, &state->timer_md_data_stream);
  sns_sensor_util_remove_sensor_instance_stream(this, &state->timer_self_test_data_stream);
  sns_sensor_util_remove_sensor_instance_stream(this, &state->timer_heart_beat_data_stream);


  if(NULL != state->scp_service)
  {
    state->scp_service->api->sns_scp_close(state->com_port_info.port_handle);
    state->scp_service->api->sns_scp_deregister_com_port(&state->com_port_info.port_handle);
    state->scp_service = NULL;
  }
  lsm6dso_dae_if_deinit(this);
}

inst_cleanup中:

  • 判断port_handle是否存在,存在则关电。
  • 通过sns_sensor_util_remove_sensor_instance_stream,remove掉所有在instance中创建的data_stream。
  • scp_service设成NULL
  • lsm6dso_dae_if_deinit

上面代码中client request最终进入的sensor instance .set_client_config中。

猜你喜欢

转载自blog.csdn.net/liuei633/article/details/80935511