三:Sensor SLPI層代碼分析
在學(xué)習(xí)SLPI側(cè)代碼前我們先了解下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支持默認(rèn)參數(shù)冯丙,則sensor library會將默認(rèn)參數(shù)填充到registry中肉瓦。
sensor driver可以通過發(fā)送request給registry sensor來隨時更新registry。
下面來詳細(xì)介紹下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泞莉,格式為:<sensor_name>
圖1
上圖說明了platform-specific config中每個元素的含義。
圖2
上圖為可以用作SPI or I2C的GPIO船殉,這些GPIO是可以復(fù)用的鲫趁,
舉個栗子:
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理郑,即設(shè)備連在SSC_6(QUP2 lane4)上。
若bus_type :0 咨油,其他不變的話您炉。
意思為:使用I2C bus,QUP為2役电,即使用SSC_2赚爵、SSC_3,I2C2這組I2C法瑟。slave address為0x01冀膝。
圖3
上圖為sensor中斷GPIO。高通強烈建議用戶使用中斷GPIO時與上圖一一對應(yīng)霎挟,所以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赐纱,下面開始學(xué)習(xí)SLPI層Sensor脊奋。
我們研究高通提供的demo sensor driver code:lsm6dso,順帶會說下SLPI側(cè)sensor framework的code。
進(jìn)入qcom_firware->slpi_proc->ssc->sensors->lsm6dso目錄后疙描,首先下看下build腳本诚隙。
####lsm6dso.scons######Import('env')importos,inspectif('SSC_TARGET_HEXAGON_MDSP'inenv['CPPDEFINES']):? Return()lsm6dso_island_enable =Falseif'SNS_ISLAND_INCLUDE_LSM6DSO'inenv:#No.1lsm6dso_island_enable =Trueif('SSC_TARGET_HEXAGON'inenv['CPPDEFINES'])and('SENSORS_DD_DEV_FLAG'notinenv):? env.AddSSCSU(inspect.getfile(inspect.currentframe()),#No.2register_func_name ="sns_register_lsm6dso",? ? ? ? ? ? ? binary_lib =False,? ? ? ? ? ? ? add_island_files = lsm6dso_island_enable)if'SENSORS_DD_DEV_FLAG'inenv:#No.3ME = 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被設(shè)置成island mode久又。何為Island mode,高通解釋island有著很低的功耗效五。
如何設(shè)置成為island mode呢籽孙?
在build腳本上,我們需要設(shè)置flag火俄,在build/ssc.scons中加入犯建。
env.AddUsesFlags(['SNS_ISLAND_INCLUDE_LSM6DSO'])
在sensor driver code上,我們我要
(1) 把sensor中這些API放到sns__sensor_island.c中實現(xiàn)
//本例為sns_lsm6dso_sensor_island.csns_sensor_api 內(nèi)容get_sensor_uid()set_client_request()? onlyforaccel driver libraries
(2)把sensor instance中這些API放到sns_<drv_name>_sensor_instance_island.c中實現(xiàn)
//本例為sns_lsm6dso_sensor_instance_island.csns_sensor_instance_api內(nèi)容notify_event()set_client_config()? onlyforaccel driver libraries
(3)把所有sensor & sensor instance island中調(diào)用的函數(shù)放到sns_<drv_name>_hal_island.c中實現(xiàn):
//本例為sns_lsm6dso_hal_island.clsm6dso_com_write_wrapper()lsm6dso_start_fifo_streaming()andso on...
Normal情況哪些API放在哪些文件中呢瓜客?
(1) 把sensor中這些API放到sns__sensor.c中實現(xiàn)
init()deinit()set_client_request()fornon-accel driver librariesnotify_event()
(2) 把sensor instance中這些API放到sns_<drv_name>_sensor_instance.c中實現(xiàn)
init()deinit()set_client_config() onlyfornon-accel driver libraries
(3)所有sensor & sensor instance 非island中調(diào)用的函數(shù)放到sns_<drv_name>_hal.c中實現(xiàn)适瓦。
No.2中設(shè)置flag=SSC_TARGET_HEXAGON是動態(tài)注冊,registry_func_name="sns_register_lsm6dso"為sensor driver的入口函數(shù)谱仪。binary_lib為是否是二進(jìn)制lib玻熙,高通的一些虛擬sensor比如計步器、amd疯攒、smd等等都是以lib形式提供給customer的嗦随。customer只要調(diào)用API使用即可,不需要知道如何實現(xiàn)敬尺。
No.3中設(shè)置flag=SENSORS_DD_DEV_FLAG是靜態(tài)注冊枚尼,在SDM845上使用的均為動態(tài)注冊。
接著來到入口函數(shù)中:
//sns_lsm6dso.csns_rcsns_register_lsm6dso(sns_register_cbconst*register_api){inti =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);? }returnSNS_RC_SUCCESS;}//sns_lsm6dso_sensor_island.cconstlsm6dso_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}};
上面入口函數(shù)中注冊四組api砂吞,每組api包含sns_sensor_api 和 sns_sensor_instance_api署恍。
sns_sensor_api數(shù)據(jù)結(jié)構(gòu)放在sns_lsm6dso_sensor_island.c中;
sns_sensor_instance_api數(shù)據(jù)結(jié)構(gòu)放在sns_lsm6dso_sensor_instance_island.c中蜻直。
以LSM6DSO_ACCEL為例:
1: sns_sensor_api定義在sns_sensor.h中盯质,結(jié)構(gòu)如下:
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 *constthis);/**? * 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 *constthis);/**? * 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? *? *@returnThe unique identifier for this Sensor? */sns_sensor_uidconst* (*get_sensor_uid)(? ? sns_sensorconst*constthis);/**? * 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 *constthis);/**? * 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 *constthis,? ? struct sns_requestconst*exist_request,? ? struct sns_requestconst*new_request,? ? bool remove);} sns_sensor_api;
上面每個函數(shù)都有注釋,這里不再解釋概而。
//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.csns_rclsm6dso_accel_init(sns_sensor *constthis){? lsm6dso_state *state = (lsm6dso_state*)this->state->state;//No.1lsm6dso_acc_publish_attributes(this);//No.2lsm6dso_init_sensor_info(this, &((sns_sensor_uid)ACCEL_SUID), LSM6DSO_ACCEL);//No.3DBG_PRINT(state->diag_service,this, LOW, __FILENAME__, __LINE__,"accel init");returnSNS_RC_SUCCESS;}
No.1中:此形式應(yīng)用非常廣泛赎瑰,同this指針中獲取lsm6dso_state王悍。
lsm6dso_state定義在sns_lsm6dso_sensor.h中,是sensor driver兩個非常重要的數(shù)據(jù)結(jié)構(gòu)之一乡范,當(dāng)然配名,另外一個是lsm6dso_instance_state啤咽。
(注:這里寫成this,大家都明白什么意思了吧渠脉,雖然c語言不是面向?qū)ο笳Z言宇整,但底層開發(fā)處處用到面向?qū)ο蟮乃枷耄瑃his這很明顯的說明sns_sensor類似于基類芋膘,不同的sensor都繼承該基類鳞青,該基類數(shù)據(jù)形式都是common的,強制類型轉(zhuǎn)換成每個sensor獨有的數(shù)據(jù)为朋;在C語言中只不過不叫基類而已臂拓,在這里叫做framework,在kernel中叫做core习寸。)
No.2中:比較重要胶惰,將accel的atrributes publish到attribute service中并保存起來。
voidlsm6dso_acc_publish_attributes(sns_sensor *constthis){constchartype[] ="accel";constuint32_tactive_current[3] = {25,85,150};//uAconstuint32_tsleep_current =3;//uAlsm6dso_publish_def_attributes(this);? {? ? sns_std_attr_value_data values[] = {SNS_ATTR, SNS_ATTR, SNS_ATTR, SNS_ATTR,//No.aSNS_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.bsns_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.csns_std_attr_value_data values[] = {SNS_ATTR, SNS_ATTR, SNS_ATTR, SNS_ATTR};inti;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.dsns_std_attr_value_data values[] = {SNS_ATTR, SNS_ATTR, SNS_ATTR};inti;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.esns_std_attr_value_data value = sns_std_attr_value_data_init_default;? ? value.has_sint =true;? ? value.sint = sleep_current;//uAsns_publish_attribute(this, SNS_STD_SENSOR_ATTRID_SLEEP_CURRENT, &value,1,false);? }? {//No.fsns_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.gsns_std_attr_value_data values[] = {SNS_ATTR};charconstproto1[] ="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);? }}
看似好多東西啊霞溪,其實這些東西都是簡單的參數(shù)孵滞。就是lsm6dso driver中accel的一些屬性。
sns_publish_attribute參數(shù)分別代表:1鸯匹,sns_sensor坊饶;2,attribute_id殴蓬;3匿级,value;4染厅,value length痘绎;5,completed代表是否是最后一被設(shè)置的屬性糟秘,若為true简逮,后續(xù)不能修改該屬性;若為false,后續(xù)可以修改該屬性秩伞。
No.a中待讳,sns_std_attr_value_data是一個保存attr value的data,初始化元素為SNS_ATTR
#defineSNS_ATTR sns_std_attr_value_data_init_default#definesns_std_attr_value_data_init_default? ? {false, sns_std_attr_value_init_default, {{NULL}, NULL}, false, 0, false, 0, false, 0}typedefstruct_sns_std_attr_value_data{boolhas_subtype;? ? sns_std_attr_value subtype;pb_callback_tstr;boolhas_flt;floatflt;boolhas_sint;int64_tsint;boolhas_boolean;boolboolean;/* @@protoc_insertion_point(struct:sns_std_attr_value_data) */} sns_std_attr_value_data;
可以看到有6個SNS_ATTR寻狂,即后面有6個value[ 0 ~ 5 ],value的has_flt位均設(shè)為true,value的flt為LSM6DSO_ODR_13冰寻、LSM6DSO_ODR_26、LSM6DSO_ODR_52等等皿渗,
設(shè)置完后斩芭,通過sns_publish_attribute將attribute_id為SNS_STD_SENSOR_ATTRID_RATES publish到attribute service中轻腺。
后面簡略的介紹下sns_publish_attribute函數(shù)后續(xù)流程。
//sns_attribute_util.cSNS_SECTION(".text.sns")void//No.asns_publish_attribute(sns_sensor *constsensor,uint32_tattribute_id, sns_std_attr_value_dataconst*values,uint32_tvalues_len,boolcompleted){size_tattribute_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_tattribute[attribute_len];pb_ostream_tstream = pb_ostream_from_buffer(attribute, attribute_len);if(pb_encode(&stream, sns_std_attr_fields, &std_attr))//No.dattribute_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")划乖,將函數(shù)放到.text.sns段贬养。
No.b 中根據(jù)前面的values填充pb_buffer_arg、填充sns_std_attr數(shù)據(jù)結(jié)構(gòu)琴庵。
typedefstruct_sns_std_attr{int32_tattr_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進(jìn)行push_attribute迷殿。
SNS_SECTION(".text.sns")staticsns_rcpublish_attribute(sns_attribute_service *this,structsns_sensor *sensor,voidconst*attribute, uint32_t attribute_len, sns_attribute_id attribute_id,boolcompleted){? UNUSED_VAR(this);? UNUSED_VAR(completed);? sns_list_iter iter;? sns_fw_sensor *fw_sensor = (sns_fw_sensor*)sensor;//No.asns_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.breturnSNS_RC_SUCCESS;}
No.a中有個重要的數(shù)據(jù)結(jié)構(gòu)sns_fw_sensor儿礼,該數(shù)據(jù)結(jié)構(gòu)定義在sns_fw_sensor.h,每個sensor都有自己的sns_fw_sensor庆寺。將sns_sensor地址賦給sns_fw_sensor蚊夫,所以sns_fw_sensor第一個成員為sns_sensor,而且sns_fw_sensor只用在framework層懦尝,不開放給sensor開發(fā)者使用这橙。
No.b中process_special_attributes繼續(xù):
SNS_SECTION(".text.sns")staticvoidprocess_special_attributes(sns_attribute *new_attr, sns_fw_sensor *fw_sensor){if(SNS_STD_SENSOR_ATTRID_AVAILABLE == new_attr->id)? ? {boolavailable = (bool)decode_attribute(new_attr, &pb_decode_attr_value_cb);if(available != sns_attr_info_get_available(fw_sensor->attr_info))? ? {chardata_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);? }elseif(SNS_STD_SENSOR_ATTRID_TYPE == new_attr->id)? {? ? sns_attr_priority priority = {false,false};charconst*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_ti =0; i < ARR_SIZE(event_priority_datatypes); i++)? ? {if(0==strcmp(data_type, event_priority_datatypes[i]))? ? ? {? ? ? ? priority.event_priority =true;break;? ? ? }? ? }for(uint8_ti =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);? }elseif(SNS_STD_SENSOR_ATTRID_VENDOR == new_attr->id)? {charconst*vendor = (char*)decode_attribute(new_attr, &pb_decode_attr_value_cb);? ? sns_attr_info_set_vendor(fw_sensor->attr_info, vendor);? }elseif(SNS_STD_SENSOR_ATTRID_PHYSICAL_SENSOR == new_attr->id &&? ? ? ? ? !sns_attr_info_get_is_physical_sensor(fw_sensor->attr_info))? {boolphysical_sensor = (bool)decode_attribute(new_attr, &pb_decode_attr_value_cb);? ? sns_attr_info_set_is_physical_sensor(fw_sensor->attr_info, physical_sensor);? }}
上面函數(shù)主要根據(jù)attribute_id進(jìn)行不同的處理,并將數(shù)據(jù)保存在fw_sensor->attr_info中导披。
Ok屈扎,上面關(guān)于sns_publish_attribute大概介紹完畢撩匕,有興趣的童鞋可以仔細(xì)研究,沒有興趣的話不影響大局止毕,可以略過不看模蜡,只需記得attribte參數(shù)放進(jìn)sns_fw_sensor->attr_info中扁凛,以便后續(xù)使用忍疾!
回到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中士复,
首先介紹幾個數(shù)據(jù)結(jié)構(gòu)。之前我們知道有個struct sns_sensor翩活,sns_sensor有個成員為struct sns_sensor_cb const*cb我們沒有介紹過阱洪。
//sns_sensor.htypedefstructsns_sensor{/* Functions which call back into the framework; provided by the Framework */structsns_sensor_cbconst*cb;/* API implementation provided for and by this Sensor */structsns_sensor_apiconst*sensor_api;/* The associated API for an Sensor Instances created for and by this
? * Sensor. */structsns_sensor_instance_apiconst*instance_api;/* State space allocated by the Framework for the sole use of the Sensor
? * developer. */structsns_sensor_state*state;} sns_sensor;
//sns_sensor.htypedef 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? *? *@returnService Manager reference? */struct sns_service_manager* (*get_service_manager)(? ? sns_sensorconst*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? *? *@returnNext Sensor Instance associated with this Sensor? */struct sns_sensor_instance* (*get_sensor_instance)(? ? sns_sensorconst*this,? ? bool first);/**? * Allocate and initialize a new Sensor Instance to be associated with this? * Sensor.? Will call sns_sensor_instance::init.? *? *@noteDirect pointers to the returned value should not be saved.? *? *@param[i] this Sensor reference? *@param[i] stateLen Allocation size for sns_sensor_instance::state? *? *@returnNewly 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? *? *@returnNext Sensor associated with this library.? */struct sns_sensor* (*get_library_sensor)(? ? sns_sensorconst*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? *? *@returnLibrary registration index? */uint32_t (*get_registration_index)(? ? sns_sensorconst*this);} sns_sensor_cb;
sns_sensor_cb是通過SEE framework 提供來給sensor使用的callback便贵。其中包含5個函數(shù),分別是
*.get_service_manager():用來獲取service manager handle冗荸。
*.get_sensor_instance():用來獲取sensor的下一個instance承璃。
*.create_instance():創(chuàng)建新的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的數(shù)據(jù)結(jié)構(gòu)玻佩。
然后在介紹下init_dependencies比較重要:
//sns_lsm6dso_sensor.cstaticchardef_dependency[][MAX_DEP_LENGTH] =? {"interrupt","async_com_port","timer","data_acquisition_engine","registry"};staticvoidinit_dependencies(sns_sensor *constthis){inti =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
accel 所依賴的platform sensor。有interrupt席楚、async_com_port咬崔、timer、registry等等烦秩。
send_suid_req函數(shù)內(nèi)容比較中要垮斯!因為后面很多地方會用到,這里我們重點介紹下:
staticvoid send_suid_req(sns_sensor *this, char *constdata_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中:首先介紹個數(shù)據(jù)結(jié)構(gòu)sns_data_stream
//sns_data_stream.htypedef 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.? *? *@noteThis 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.? *? *@noteMultiple sequential calls to this function will return the same? * pointer.? *? *@param[io] data_stream Data stream from which to get an event? *? *@returnNext 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? *? *@returnThe 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.? *? *@noteDo 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? *? *@returnNumber of input events (aka samples) available for processing? */uint32_t (*get_input_cnt)(? ? sns_data_stream *data_stream);} sns_data_stream_api;
上面注釋很清楚了,不再解釋抛寝。
第一次很定進(jìn)入state->fw_stream==NULL,通過獲取sns_service_manager獲取sns_service_type為SNS_STREAM_SERVICE的stream_service盗舰。并通過stream_service來創(chuàng)建一個新的sensor stream。
No.b中:接著會進(jìn)入state->fw_stream != NULL川陆,這里比較重要的是:會填充一個sns_suid_req,并通過pb_encode_request函數(shù)編碼成buffer较沪,然后繼續(xù)填充sns_request,最后土至,通過state->fw_stream->api->send_request發(fā)送改message_id為SNS_SUID_MSGID_SNS_SUID_REQ的sns_request。后面不用說也可以知道,通過SNS_SUID_MSGID_SNS_SUID_EVENT接收的event垂蜗,獲取suid解幽。不信烘苹,你可以看lsm6dso_sensor_notify_event中l(wèi)sm6dso_process_suid_events函數(shù)。就是對SNS_SUID_MSGID_SNS_SUID_EVENT進(jìn)行處理的镣衡。后面再詳細(xì)介紹。
Ok望浩,lsm6dso_accel_init解析完畢。
(2)init對應(yīng)的是deinit
sns_rclsm6dso_accel_deinit(sns_sensor *constthis){? 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.returnSNS_RC_SUCCESS;}
(3)lsm6dso_get_sensor_uid函數(shù)磨德,用來獲取suid吆视。
sns_sensor_uidconst*lsm6dso_get_sensor_uid(sns_sensorconst*constthis){? lsm6dso_state *state = (lsm6dso_state*)this->state->state;return&state->my_suid;}
(4)lsm6dso_set_client_request函數(shù),用來設(shè)置來自client的request啦吧。并創(chuàng)建sensor instance。
set_client_request函數(shù)的解釋如下:
該函數(shù)是用來Add琳水、remove、update來自client的request炫刷。
如果remove設(shè)為false:任何從sns_sensor_cb::get_sensor_instance()獲取active的sensor instance來決定是否處理該request郁妈,若是,使用add_client_request將new request和existing instance關(guān)聯(lián)起來噩咪。若不是,同樣使用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參數(shù)為false的。在handle_stream_destroy中争舞,set_client_request的remove參數(shù)為true疗韵。
sns_sensor_instance* lsm6dso_set_client_request(sns_sensor *constthis,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct sns_requestconst*exist_request,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? struct sns_requestconst*new_request,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? bool remove){? lsm6dso_state *state = (lsm6dso_state*)this->state->state;//No.1sns_sensor_instance *instance = sns_sensor_util_get_shared_instance(this);//No.2sns_diag_service* diag = state->diag_service;? sns_time on_timestamp;//No.3sns_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!");returninstance;? ? }? ? 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 nowif(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->stateif(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 stateif(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));? ? ? ? }elseif(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 registryinst_state->registry_reset.request =false;? ? ? ? lsm6dso_sensor_write_output_to_registry(this, instance);// Set the flag to false indicating that the registry is updatedinst_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! ");returnNULL;// 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 ONDBG_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. */returninstance;? ? ? ? }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);returninstance;? ? ? ? }? ? ? }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*/elseif(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 stateif(LSM6DSO_ACCEL == state->sensor)? ? ? ? ? {? ? ? ? ? ? inst_state->accel_info.sstvt = lsm6dso_accel_resolutions[state->resolution_idx]*1000;//convert to micro-g/LSBinst_state->accel_info.range = lsm6dso_accel_ranges[state->resolution_idx];? ? ? ? ? ? inst_state->accel_info.range_idx = state->resolution_idx;? ? ? ? ? }elseif(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 stateif(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));? ? ? ? ? }elseif(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 statesns_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;? ? ? ? ? }elseif(inst_state->md_info.enable_md_int) {//there is exsisting md client already present, just send eventDBG_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;? ? ? ? ? }elseinst_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 enabledif(!(inst_state->fifo_info.fifo_enabled & state->sensor))? ? ? inst_state->config_sensors &= ~state->sensor;? }// Sensors are required to call remove_instance when clientlessif(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);? }returninstance;}
炒雞多,一步步分析吧者疤。開始之前,在了解下sns_sensor_instance中的sns_sensor_instance_cb的callback函數(shù)吧革砸,上面我們介紹了sns_sensor中的sns_sensor_cb callback函數(shù)糯累。
//sns_sensor_instance.htypedefstructsns_sensor_instance{/* Functions which call back into the framework; provided by the Framework */structsns_sensor_instance_cbconst*cb;/* State space allocated by the Framework for the sole use of the Sensor
? * Instance developer. */structsns_sensor_instance_state*state;} sns_sensor_instance;
//sns_sensor_instance.htypedef 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? *? *@returnService 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.? *? *@noteAn 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_requestconst* (*get_client_request)(? ? sns_sensor_instance *this,? ? sns_sensor_uidconst*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_requestconst*request);/**? * Assign this Sensor Instance to service the client request.? *? *@noteThis function may only be given sns_request objects received? * from sns_sensor_api::set_client_request.? *? *@noteThe 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_requestconst*request);} sns_sensor_instance_cb;
四個函數(shù)分別如下:
*.get_service_manager():獲取service manger的handle
*.get_client_request():獲取與instance相關(guān)聯(lián)的下一次client request。
*.remove_client_request():通過instance移除一個client的request handle效拭。
*.add_client_request():通過instance添加一個client request handle胖秒。
然后就可以繼續(xù)分析set_client_request代碼了。
No.1:獲取lsm6dso_state指針阎肝。
No.2:獲取一個共享的instance,許多物理sensor會共享一個單獨的instance风题,這個函數(shù)就是查找這個共享的instance嫉父,若有返回instance熔号,若無返回NULL稽鞭。
No.3:獲取diag_service
No.4:remove為true,即為移除instance篮条。首先判斷instance是否為NULL,
若為NULL涉茧,OK疹娶,已經(jīng)不能用了,直接返回即可雨饺。
若不為NULL,現(xiàn)獲取從instance中獲取lsm6dso_instance_state额港,并通過instance_state的callback函數(shù)cb來remove_client_request來從instance中移除exist_request。
緊接著肚医,
若msg_id不是SNS_PHYSICAL_SENSOR_TEST_MSGID_SNS_PHYSICAL_SENSOR_TEST_CONFIG向瓷,需要設(shè)置instance的config并關(guān)電。在lsm6dso_reval_instance_config函數(shù)中進(jìn)行處理猖任。
若msg_id是,會將config數(shù)據(jù)寫到registry sensor中超升,通過lsm6dso_sensor_write_output_to_registry()函數(shù)保存在“/persist/sensor/registry/registry/lsm6dso_0_platform.accel.fac_cal”和“/persist/sensor/registry/registry/lsm6dso_0_platform.gyro.fac_cal”中。
具體細(xì)節(jié)不再分析室琢。
No.5:else為remove為false的情況。也為創(chuàng)建新的instance的情況盈滴。
高通代碼給出了相應(yīng)的注釋轿钠。
若instance不為NULL病苗,從instance獲取lsm6dso_instance_state
若instance為NULL,
填充state的rail_config硫朦,設(shè)置rail電壓。并通過sns_vote_power_rail_update配置rail config咬展。
通過sns_get_system_time獲取時間
lsm6dso_start_power_rail_timer來上電
通過create_instance來創(chuàng)建新的instance。
若instance不為NULL
若exist_request & new_request不為NULL涮总,且new_request的msg_id為SNS_STD_MSGID_SNS_STD_FLUSH_REQ祷舀,若fifo enable,則發(fā)送flush fifo config裳扯,ACCEL & GYRO使用fifo,若fifo disable 或者不是accel or gyro铺纽,發(fā)送flash 完成的event哟忍。不再enable fifo 。(這里注意下:不要在enable后更新client的request給instance锅很,因為FIFO是一個持續(xù)的stream request。)
若exist_request or? new_request為NULL 或者msg_id不為上面的msg_id叛复,相應(yīng)處理。
若instance 不為NULL褐奥,再跟進(jìn)new_request->msg_id不同設(shè)置相應(yīng)的config翘簇。這里我們看到了常見的new_request->message_id == SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG。
然后都完成后版保,通過lsm6dso_reval_instance_config函數(shù)來通過sensor instance進(jìn)行處理夫否。
接著分析下lsm6dso_reval_instance_config()叫胁,主要有一個函數(shù)lsm6dso_set_inst_config,在該函數(shù)中微谓,可以看到谤民,client request發(fā)送到sensor API中.set_client_request的數(shù)據(jù),最終通過lsm6dso_set_inst_config函數(shù)發(fā)送給sensor_instance API中.set_client_config张足。
voidlsm6dso_reval_instance_config(sns_sensor *this,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? sns_sensor_instance *instance,? ? ? ? ? ? ? ? ? ? ? ? ? ? ? lsm6dso_sensor_type sensor_type){? ...uint8_tsensor_count = ARR_SIZE(lsm6dso_supported_sensors);struct{lsm6dso_sensor_type sensor;floatsample_rate;floatreport_rate;uint64_tflush_period_ticks;boolngated_client_present;//= client_presentboolgated_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;? ? ? ...? ? }elseif(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;? ? ? ? ...? ? }elseif(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函數(shù)中會針對不同sensor type進(jìn)行不同的處理为牍,比如accel & gyro碉咆,使用lsm6dso_get_imu_config來從request中獲取payload數(shù)據(jù)填充sensor_info;motion_detect疫铜,使用lsm6dso_get_motion_detect_config來填充sensor_info等等双谆,chosen_sample_rate & chosen_sample_rate & chosen_flush_ticks會通過request中參數(shù)和他們自己進(jìn)行比較取最大者。并通過lsm6dso_set_inst_config傳遞給sensor instance顽馋。
staticvoidlsm6dso_set_inst_config(sns_sensor *this,? ? sns_sensor_instance *instance,? ? lsm6dso_sensor_type sensor,floatchosen_report_rate,floatchosen_sample_rate,uint64_tchosen_flush_ticks,? ? sns_lsm6dso_registry_cfg registry_cfg,uint32_tmessage_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);? }elseif((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);? }elsereturn;}
在該函數(shù)寸谜,
if中當(dāng)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進(jìn)行factory calibration他爸,往上追code發(fā)現(xiàn),當(dāng)client request中msg_id為SNS_PHYSICAL_SENSOR_TEST_MSGID_SNS_PHYSICAL_SENSOR_TEST_CONFIG時诊笤,會把inst_state->common_info.mode設(shè)成LSM6DSO_MODE_SELF_TEST的岭埠,這里是一一對應(yīng)的蔚鸥。另外一個inst_state->self_test_info.test_alive止喷,即此時正在進(jìn)行操作,當(dāng)然正在factory calibration操作時不能再操作混聊,所以要滿足該條件。
else中為正常走的流程预愤,msg_id=SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG也會走該路咳胃。兩者最后都會調(diào)用this->instance_api->set_client_config(instance, &req_config);進(jìn)入sensor instance中。
此時销睁,sns_sensor_api除了.notify_event其他均分析完了,為了高清流程性冻记,.notify_event會最后分析来惧。
2: sns_sensor_instance_api定義在sns_sensor_instance.h中,結(jié)構(gòu)如下:
//sns_sensor_instance.htypedef 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.? *? *@notePersistent 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 *constthis,? ? sns_sensor_stateconst*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 *constthis);/**? * 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 *constthis,? ? struct sns_requestconst*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 *constthis);} sns_sensor_instance_api;
上面每個函數(shù)都有注釋隅居,這里不再解釋趁曼。
什么時候會進(jìn)入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));
當(dāng)instance為NULL時,通過cb創(chuàng)建一個instance赞季,SEE framework會創(chuàng)建一個sensor instance并調(diào)用其.init函數(shù)奢驯。簡略的追下code。
//sns_sensor.csns_rcsns_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,? };returnSNS_RC_SUCCESS;}
其中create_instance回調(diào)的是sns_sensor_instance_init瘪阁。
//sns_sensor_instance.cSNS_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 *constthis,? ? sns_sensor_stateconst*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中多數(shù)為初始化設(shè)置廉涕,包含獲取sync_com_port service和創(chuàng)建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復(fù)制所有sensor uids,初始化FIFO狀態(tài)婆瓜,初始Accel狀態(tài)湃累,初始Gyro狀態(tài)等等,初始化中斷數(shù)據(jù),初始化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);? }
等等。覆获。。
對應(yīng)的是lsm6dso_inst_deinit
sns_rclsm6dso_inst_deinit(sns_sensor_instance *constthis){? lsm6dso_instance_state *state =? ? ? ? ? ? ? ? ? (lsm6dso_instance_state*)this->state->state;? inst_cleanup(this, state);returnSNS_RC_SUCCESS;}
staticvoid inst_cleanup(sns_sensor_instance *constthis,? ? ? ? ? ? ? ? ? ? ? ? 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是否存在痊班,存在則關(guān)電摹量。
通過sns_sensor_util_remove_sensor_instance_stream,remove掉所有在instance中創(chuàng)建的data_stream凝果。
scp_service設(shè)成NULL
lsm6dso_dae_if_deinit
上面代碼中client request最終進(jìn)入的sensor instance? .set_client_config中。
作者:漢克233
鏈接:http://www.reibang.com/p/6eaad04bdc00
來源:簡書
簡書著作權(quán)歸作者所有器净,任何形式的轉(zhuǎn)載都請聯(lián)系作者獲得授權(quán)并注明出處当凡。