ssc HAL转载

2019-08-14  本文已影响0人  seuwt

二:Sensor Hal层代码分析

Hal code放在/vendor/qcom/proprietary/sensors-see/中

图5

sensors-hal文件夹中包含framework和sensors文件夹,为本文重点分析对象。

首先分析sensors文件夹:

根据C++继承的特性,相同的操作各个class共同拥有,不同的操作每个class可以重写,该文件夹内文件为每个sensor不同的地方,porting sensor主要是在这部分做的。sensors文件夹中包含很多sensor cpp文件比如:accelerometer.cpp为accel sensor的hal层code,step_count.cpp为计步器的hal层的code等等,主要是针对不同sensor type的操作。下面以accelerometer.cpp为例:

//accelerometer.cppSENSOR_MODULE_INIT(accelerometer_module_init);//sensor.h#define SENSOR_MODULE_INIT(module_init_func) \staticconstbool__mod_init = (module_init_func)();

每个cpp都有SENSOR_MODULE_INIT入口,__mod_init具体实现在code没有找到,不过应该类似kernel中module_init,在系统加载.so时调用。故可知,所有特定sensor的cpp在加载.so时会被调SENSOR_MODULE_INIT进行加载。

//accelerometer.cppstaticboolaccelerometer_module_init(){/* register supported sensor types with factory */sensor_factory::register_sensor(SENSOR_TYPE_ACCELEROMETER,                                    get_available_accel_calibrated);    sensor_factory::register_sensor(SENSOR_TYPE_ACCELEROMETER_UNCALIBRATED,                                    get_available_accel_uncalibrated);    sensor_factory::request_datatype(SSC_DATATYPE_ACCEL);returntrue;}//sensor_factory.hstaticvoidregister_sensor(inttype, get_available_sensors_func func){try{            callbacks().emplace(type, func);        }catch(conststd::exception& e) {            sns_loge("failed to register type %d", type);        }    }staticstd::unordered_map& callbacks()    {staticstd::unordered_map _callbacks;return_callbacks;    }//sensor_factory.hstaticvoidrequest_datatype(constchar*datatype){try{            datatypes().insert(std::string(datatype));        }catch(conststd::exception& e) {            sns_loge("failed to insert %s", datatype);        }    }

所以在,在.so被调用后,accelerometer_module_init会被执行!通过register_sensor将type和func放入callbacks的unordered_map中。并将datatype插入到datatypes的unordered_set中,以便后面使用。

下面以get_available_accel_calibrated为例继续研究:

//accelerometer.cppstaticvector> get_available_accel_calibrated(){constvector& accel_suids =        sensor_factory::instance().get_suids(SSC_DATATYPE_ACCEL);//  No.1vector> sensors;for(constauto& suid : accel_suids) {if(!(sensor_factory::instance().get_settings()// No.2& DISABLE_WAKEUP_SENSORS_FLAG)) {try{                sensors.push_back(make_unique(suid, SENSOR_WAKEUP,//No.3SENSOR_CALIBRATED));            }catch(constexception& e) {                sns_loge("failed for wakeup, %s", e.what());            }        }try{            sensors.push_back(make_unique(suid, SENSOR_NO_WAKEUP,                                                    SENSOR_CALIBRATED));        }catch(constexception& e) {            sns_loge("failed for nowakeup, %s", e.what());        }    }returnsensors;}

No.1中:accel_suids可以通过sensor_factory实例中get_suids函数来获取:

conststd::vector& sensor_factory::get_suids(conststd::string& datatype)const{autoit = _suid_map.find(datatype);if(it != _suid_map.end()) {returnit->second;    }else{staticvector empty;returnempty;    }}

从_suids_map中查找datatype来获取accel的suid。那什么时候将accel的suid插入到_suids_map中内,在framework文件夹中,后续会介绍。

No.2中:通过getsetting来查看是否有DISABLE_WAKEUP_SENSORS_FLAG flag,若有则为no wakeup,若无则为wake up sensor。

No.3中:为调用accelerometer的构造函数。

accelerometer::accelerometer(sensor_uid suid,                                sensor_wakeup_type wakeup,                                sensor_cal_type cal_type):    ssc_sensor(suid, wakeup)// No.a{if(cal_type == SENSOR_UNCALIBRATED) {// No.bset_type(SENSOR_TYPE_ACCELEROMETER_UNCALIBRATED);        set_string_type(SENSOR_STRING_TYPE_ACCELEROMETER_UNCALIBRATED);        set_sensor_typename("Accelerometer-Uncalibrated");    }else{        set_type(SENSOR_TYPE_ACCELEROMETER);        set_string_type(SENSOR_STRING_TYPE_ACCELEROMETER);        set_sensor_typename("Accelerometer");    }  ...    _cal_type = cal_type;    set_fifo_reserved_count(ACCEL_RESERVED_FIFO_COUNT);    set_resampling(true);/* convert range from Gs to m/s^2 */set_max_range(get_sensor_info().maxRange * ONE_G);/* convert resolution from mG to m/s^2 */set_resolution(get_sensor_info().resolution * ONE_G /1000.0);}

No.a中:继承ssc_sensor,ssc_sensor的构造函数中,主要设置一些common的参数。

No.b中:设置accel中不common的参数。比如string_type、sensor_typename、是否使用resampling、最大range、分辨率等等。

Ok,accelerometer.cpp基本介绍完毕。

对了,还有个handle_sns_std_sensor_event函数是干什么的呢?

//accelerometer.cppvirtualvoidhandle_sns_std_sensor_event(constsns_client_event_msg_sns_client_event& pb_event)override;voidaccelerometer::handle_sns_std_sensor_event(constsns_client_event_msg_sns_client_event& pb_event){    sns_std_sensor_event pb_sensor_event;    pb_sensor_event.ParseFromString(pb_event.payload());sensors_event_thal_event = create_sensor_hal_event(pb_event.timestamp());if(_cal_type == SENSOR_CALIBRATED) {        hal_event.acceleration.x = pb_sensor_event.data(0);        hal_event.acceleration.y = pb_sensor_event.data(1);        hal_event.acceleration.z = pb_sensor_event.data(2);        hal_event.acceleration.status =            sensors_hal_sample_status(pb_sensor_event.status());      ...    }if(_cal_type == SENSOR_UNCALIBRATED) {        hal_event.uncalibrated_accelerometer.x_uncalib = pb_sensor_event.data(0);        hal_event.uncalibrated_accelerometer.y_uncalib = pb_sensor_event.data(1);        hal_event.uncalibrated_accelerometer.z_uncalib = pb_sensor_event.data(2);        hal_event.uncalibrated_accelerometer.x_bias =0;        hal_event.uncalibrated_accelerometer.y_bias =0;        hal_event.uncalibrated_accelerometer.z_bias =0;      ....    }    submit_sensors_hal_event(hal_event);}//framework/ssc_sensor.cppvoidssc_sensor::handle_sns_std_sensor_event(constsns_client_event_msg_sns_client_event& pb_event){    sns_std_sensor_event pb_stream_event;    pb_stream_event.ParseFromString(pb_event.payload());sensors_event_thal_event = create_sensor_hal_event(pb_event.timestamp());intnum_items = pb_stream_event.data_size();    ...for(inti =0; i < num_items; i++) {        hal_event.data[i] = pb_stream_event.data(i);    }    ...    submit_sensors_hal_event(hal_event);}

可以看到handle_sns_std_sensor_event为虚函数,在framework中有实现,在accelerometer.cpp中也有实现。Ok,若sensors文件中xxxx.cpp中没有重写handle_sns_std_sensor_event则可以使用framework common的进行实现,若有的话,则使用xxxx.cpp中的handle_sns_std_sensor_event。

接着介绍framework文件夹:

//sensors_hw_module.cppstructsensors_module_tHAL_MODULE_INFO_SYM= {.common = {        .tag = HARDWARE_MODULE_TAG,        .module_api_version = (uint16_t)SENSORS_DEVICE_API_VERSION_1_4,        .hal_api_version = HARDWARE_HAL_API_VERSION,        .id = SENSORS_HARDWARE_MODULE_ID,        .name ="QTI Sensors HAL Module",        .author ="Qualcomm Technologies, Inc.",        .methods = &sensors_module_methods,        .dso =NULL,        .reserved = {0},    },    .get_sensors_list = get_sensors_list,    .set_operation_mode = sensors_set_operation_mode,};

对Android Hal层比较熟的都知道sensors_module_t这个数据结构,hardware通过dlopen打开.so lib,并通过dlsym加载symbols,然后即可使用相应的方法,具体细节不再重复介绍。

从hardware/libhardware/modules/sensors/multihal.cpp中可以看到,首先会调用get_sensor_list函数。

staticvoidlazy_init_sensors_list(){    ...conststructsensor_t*subhal_sensors_list;for(std::vector::iterator it = sub_hw_modules->begin();            it != sub_hw_modules->end(); it++) {structsensors_module_t*module= (structsensors_module_t*) *it;global_sensors_count +=module->get_sensors_list(module, &subhal_sensors_list);        ALOGV("increased global_sensors_count to %d", global_sensors_count);    }    ...}

对应sensor_hw_module.cpp中函数如下:

//sensors_hw_module.cppstaticintget_sensors_list(structsensors_module_t*module,    structsensor_tconst**list){    sensors_hal& hal = sensors_hal::get_instance();returnhal.get_sensors_list(list);}

获取sensors_hal的实例,然后调用get_sensors_list

//sensors_hal.hstaticsensors_hal&get_instance(){staticsensors_hal hal;returnhal;    }

sensor_hal为static的,故执行构造函数。

//sensors_hal.cppsensors_hal::sensors_hal(){    ...try{        init_sensors();                                    ...    }    ...}voidsensors_hal::init_sensors(){autosensors = sensor_factory::instance().get_all_available_sensors();//No.1autocb  = [this](constauto& event,autowakeup) { _event_queue.push(event, wakeup); };//No.2for(unique_ptr& s : sensors) {//No.3assert(s !=nullptr);        s->register_callback(cb);constsensor_t& sensor_info = s->get_sensor_info();        ...        _hal_sensors.push_back(sensor_info);        _sensors[sensor_info.handle] =std::move(s);    }  ...}

No.1中:通过sensor_factory实例中get_available_sensors()来获取sensor class。

sensor_factory实例:

staticsensor_factory&instance(){staticsensor_factory factory;returnfactory;    }

调构造函数

sensor_factory::sensor_factory(){    ...    _settings = get_sns_settings();// No.1_pending_attributes =0;// No.2if(!(_settings & DISABLE_SENSORS_FLAG)) {/* find available sensors on ssc */discover_sensors();// No.3if(_suid_map.size() >0) {            retrieve_attributes();// No.4}      ...    }}

No.1中:通过"/persist/sensors/registry/registry/sensors_settings"文件来设置setting。

No.2中:_pending_attributes为pending sensor的数目。

No.3中:discover_sensors用来发现所有的sensor。

//sensor_factory.cppvoidsensor_factory::discover_sensors(){usingnamespacestd::chrono;suid_lookuplookup(//No.a[this](conststring& datatype,constauto& suids){            suid_lookup_callback(datatype, suids);        });for(conststring& dt : datatypes()) {        sns_logd("requesting %s", dt.c_str());        lookup.request_suid(dt);//No.b}autotp_wait_start = steady_clock::now();/* wait for some time for discovery of available sensors */autodelay = get_discovery_timeout_ms();    this_thread::sleep_for(std::chrono::milliseconds(delay));/* additional wait for discovery of critical sensors */wait_for_mandatory_sensors(lookup);    sns_logd("available sensors on ssc");for(constauto& item : _suid_map) {        sns_logd("%-20s%4u", item.first.c_str(), (unsignedint)item.second.size());    }}

No.a中:suid_lookup继承_ssc_conn(get_ssc_event_cb()),其中get_ssc_event_cb为回调函数。event在该函数中处理。

suid_lookup_callback(datatype, suids);函数比较重要,把suid加入到_suid_map中,回头看sensors文件夹中的 sensor_factory::get_suids函数,即从_suid_map中查找datatype为accel的suid。前后联系在一起了。那么suids和datatype哪儿来的呢?透露一下,发送request后等待callback函数接收到event并获取到datatype和suids。然后会执行该函数。

No.b中:通过loopup类中的request_suid发送request给SLPI中的sensor。dt为accel、gryo、mag等等。

下面分析下request_suid函数:

//ssc_utils.cppvoidsuid_lookup::request_suid(std::stringdatatype){    sns_client_request_msg pb_req_msg;//No.asns_suid_req pb_suid_req;stringpb_suid_req_encoded;constsensor_uid LOOKUP_SUID = {//No.b12370169555311111083ull,12370169555311111083ull    };    .../* populate SUID request *///No.cpb_suid_req.set_data_type(datatype);    pb_suid_req.set_register_updates(true);    pb_suid_req.SerializeToString(&pb_suid_req_encoded);/* populate the client request message */pb_req_msg.set_msg_id(SNS_SUID_MSGID_SNS_SUID_REQ);//No.dpb_req_msg.mutable_request()->set_payload(pb_suid_req_encoded);    pb_req_msg.mutable_suid()->set_suid_high(LOOKUP_SUID.high);    pb_req_msg.mutable_suid()->set_suid_low(LOOKUP_SUID.low);    pb_req_msg.mutable_susp_config()->set_delivery_type(SNS_CLIENT_DELIVERY_WAKEUP);    pb_req_msg.mutable_susp_config()->set_client_proc_type(SNS_STD_CLIENT_PROCESSOR_APSS);stringpb_req_msg_encoded;    pb_req_msg.SerializeToString(&pb_req_msg_encoded);    _ssc_conn.send_request(pb_req_msg_encoded);//No.e}//sns_client.pb.htypedefstruct_sns_client_request_msg{sns_std_suid suid;uint32_tmsg_id;    sns_client_request_msg_suspend_config susp_config;    sns_std_request request;/* @@protoc_insertion_point(struct:sns_client_request_msg) */} sns_client_request_msg;

No.a中:sns_client_request_msg 为最外层的requset封装。sns_suid_req 包在sns_client_request_msg->requset->payload中,pb_suid_req_encoded  为encode后的字符串。

No.b中:suid sensor的suid。这里需要说明一下,在sdm845 see中,包含物理sensor、虚拟sensor和platform sensor。前面两个sensor我们都了解,platform sensor是什么呢?原来 高通在see上定义专门为platform服务的sensor,这些sensor是内嵌的,可以被任何sensor或者sensor instance使用,来提供相应的功能。这里suid sensor为platform sensor,它的作用是为所有其他sensor提供suid。suid sensor会根据不同的datatype提供相应的suid。当然suid sensor也有个suid。这个suid也是固定不变的,就是No.b中的数字。

拓展:除了suid sensor外还有很多platform sensor,比如:register sensor , 可以解析并获取其他sensor的register;Interrupt  sensor,为其他sensor提供中断;等等。

No.c中:填充pb_suid_req,设置datatype,register_updates;并将pb_suid_req序列化成字符串格式,成为pb_suid_req_encoded,以便ps_req_msg使用。

No.d中:填充pb_req_msg,设置msg_id,这里msg_id比较重要,到SLPI侧sensor driver中,会根据该msg_id做相应的操作,这是后话。

设置成员request中的payload为pb_suid_req_encoded。设置成员suid中的suid_high、suid_low为LOOKUP_SUID的高、低位。

设置成员susp_config中内容。。。

最后将pb_req_msg序列化字符串pb_req_msg_encoded。

No.e中:通过_ssc_conn.request将该字符串发送出去。

发送的流程我们在此不再研究,都是高通封装好的API,我们直接使用即可,有兴趣的童鞋可以继续追code。

发送完request后,我们需要静等callback。根据前面描述可知,callback为suid_lookup::handle_ssc_event()函数,在该函数中,

No.a中sns_client_event_msg为对应event的封装,通过PaseFromArray解码data & size生成。

//ssc_utils.cppvoidsuid_lookup::handle_ssc_event(constuint8_t*data,size_tsize){/* parse the pb encoded event */sns_client_event_msg pb_event_msg;//No.a                        pb_event_msg.ParseFromArray(data, size);/* iterate over all events in the message */for(inti =0; i < pb_event_msg.events_size(); i++) {//No.bauto& pb_event = pb_event_msg.events(i);if(pb_event.msg_id() != SNS_SUID_MSGID_SNS_SUID_EVENT) {            sns_loge("invalid event msg_id=%d", pb_event.msg_id());continue;        }        sns_suid_event pb_suid_event;//No.cpb_suid_event.ParseFromString(pb_event.payload());conststring& datatype =  pb_suid_event.data_type();        .../* create a list of  all suids found for this datatype */vector suids(pb_suid_event.suid_size());//No.dfor(intj=0; j < pb_suid_event.suid_size(); j++) {            suids[j] = sensor_uid(pb_suid_event.suid(j).suid_low(),                                  pb_suid_event.suid(j).suid_high());        }/* send callback for this datatype */_cb(datatype, suids);    }}//sns_suid.pb.htypedefenum_sns_suid_msgid {    SNS_SUID_MSGID_SNS_SUID_REQ =512,    SNS_SUID_MSGID_SNS_SUID_EVENT =768} sns_suid_msgid;

No.b中:要判断msg_id是否是SNS_SUID_MSGID_SNS_SUID_EVENT,可以看到与SNS_SUID_MSGID_SNS_SUID_REQ对应。

No.c中:同No.a一样,将pb_event.payload() 解码成sns_suid_event。

No.d中:创建一个suid的vector,将获得suid string放进去。然后调用_cb将suids保存起来,即调用suid_lookup_callback函数将datatype和suids放入到_suid_map的unordered_map中。

Ok,discover_sensors基本介绍完毕,sensor_factory构造函数中还会在retrieve_attributes()发送request来获取attribute。并放在_attributes的unordered_map中。操作基本相同,只是request发送的msg_id不同而已,在此不再详细介绍。

接着,继续回到init_sensors()的No.1中。

vector> sensor_factory::get_all_available_sensors()const{vector> all_sensors;for(constauto& item : callbacks()) {// No.aconstauto& get_sensors = item.second;// No.bvector> sensors = get_sensors();                sns_logd("type=%d, num_sensors=%u", item.first, (unsignedint)sensors.size());for(auto&& s : sensors) {            all_sensors.push_back(std::move(s));// No.c}    }returnall_sensors;}

No.a中,又看到了callbacks,上面sensors文件夹中可知,通过register_sensor将type和func放入到叫callbacks的unordered_map中。

No.b中,get_sensors获取callbacks中第二个元素get_available_sensors_func。然后通过get_sensors()函数即get_available_sensors_func()来获取sensor class。对应sensors文件中accelerometer.cpp中get_available_accel_calibrated()和get_available_accel_uncalibrated()。

No.c中,将获取到的vector<unique_ptr<sensor>>放到all_sensors这个容器中。以便后续使用!

回到init_sensors函数:

No.2中:将event和wakeup push到_event_queue中,即变成sensors_event_t _event_queue。

No.3中:register_callback 后,通过get_sensor_info()获取sensor_info。然后,把sensor_info push到_hal_sensors的vector中,将sensor class放到unordered_map  _sensors的sensor_info.handle成员中。

init_sensors解析完毕。注:数据结构放在sensors.h中(/hardware/libhardware/include/hardware/sensors.h)

然后继续分析get_sensors_list:

//sensors_hal.cppintsensors_hal::get_sensors_list(constsensor_t**s_list){intnum_sensors = (int)_hal_sensors.size();    sns_logi("num_sensors=%d", num_sensors);    *s_list = &_hal_sensors[0];returnnum_sensors;}

通过判断_hal_sensors的大小获取到所有sensor的数目。并将_hal_sensors的首地址赋给s_list。

至此,系统获取了全部sensor的suid和attributes,并将其放在指定的容器中保存起来,完成sensor的初始化工作。下面就等user来使用了。

Enable/Disable Sensor

framewark层getDefaultSensor并registerListener后,经过一系列函数后,最终会调到sensors_hal中activate函数来enable/disable。

//sensors_hal.cppintsensors_hal::activate(inthandle,intenable){    ....if(enable) {            sensor->activate();        }else{            sensor->deactivate();        }    ....return0;}

再以accelerometer.cpp为例:

因为accelerometer class继承ssc_sensor class,故会调用ssc_sensor中的activate。

//ssc_sensor.cppvoidssc_sensor::activate(){std::lock_guard lk(_mutex);//No.1if(!is_active()) {/* establish a new connection to ssc */_ssc_conn = make_unique(        [this](constuint8_t*data,size_tsize)        {            ssc_conn_event_cb(data, size);//No.2});if( _wakeup_type == SENSOR_WAKEUP)            _ssc_conn->set_unsuspendable_channel();//No.3_ssc_conn->register_error_cb([this](autoe){ ssc_conn_error_cb(e); });        send_sensor_config_request();//No.4}}voidssc_sensor::deactivate(){std::lock_guard lk(_mutex);if(is_active()) {        _ssc_conn.reset();//No.5}}

No.1中:申请互斥锁lk。

No.2中:接收event的callback函数。

No.3中:针对wakeup sensor处理的函数。

No.4中发送config request,enabe accle sensor。

等发送到enable request后,等待接收event。然后通过submit_sensors_hal_event(hal_event)将数据上报。

No.5中:deactivate为disable sensor,首先判断sensor状态是否是active,若是则reset,若不是,不做任何处理。

Factory Calibration

加速度传感器在进工厂时需要进行calibration。下面提供accelerometer calibration的code。顺便加深下上面学习的知识。

voidaccel_cal::init_ssc_connectiions(){  ssc_suid_cb = [this](constuint8_t* msg ,intmsgLength)  {this->handle_ssc_suid_event(msg, msgLength);};if(NULL== (ssc_suid_obj =newssc_connection(ssc_suid_cb))) {    ALOGE("ssc connection for suid failed");return;  }  ssc_accel_cal_cb = [this](constuint8_t* msg ,intmsgLength)    {this->handle_ssc_accel_cal_event(msg, msgLength);};if(NULL== (ssc_accel_cal_obj =newssc_connection(ssc_accel_cal_cb))) {    ALOGE("ssc connection failed");return;  }    ssc_accel_enable_cb = [this](constuint8_t* msg ,intmsgLength)    {this->handle_ssc_enable_accel_event(msg, msgLength);};if(NULL== (ssc_accel_enable_obj =newssc_connection(ssc_accel_enable_cb))) {    ALOGE("ssc connection failed");return;  }  ALOGI("ssc connections successful");}

上面函数是在new的时候调用,建立 3个callback函数,分别用来接收suid的event、accel calibration的event、accel enable的event。

intaccel_cal::cal_init(){intresult =true;std::stringdatatype_accel = ACCEL;  pthread_mutex_lock(&cb_mutex);  request_suid(datatype_accel);  pthread_cond_wait(&condition, &cb_mutex);  enable_accel();  usleep(10000);  request_accel_cal();  timeout =0;while((accel_sensor_indication !=1) && timeout <2000){    usleep(1000);    timeout++;  }  result = accel_sensor_indication;returnresult;}

上面request_suid发送request来获取accel的suid。

上面enable_accel发送request来enabe accel

上面request_accel_cal发送request来让SLPI侧的sensor进行calibration。

超时处理,当2s内没有接收到callback,退出。

void accel_cal::request_suid(std::string datatype){  sns_client_request_msg pb_req_msg;  sns_suid_req pb_suid_req;  string pb_suid_req_encoded;constsensor_uid LOOKUP_SUID = {12370169555311111083ull,12370169555311111083ull };/* populate SUID request */pb_suid_req.set_data_type(datatype);  pb_suid_req.set_register_updates(false);  pb_suid_req.SerializeToString(&pb_suid_req_encoded);/* populate the client request message */pb_req_msg.set_msg_id(SNS_SUID_MSGID_SNS_SUID_REQ);  pb_req_msg.mutable_request()->set_payload(pb_suid_req_encoded);  pb_req_msg.mutable_suid()->set_suid_high(LOOKUP_SUID.high);  pb_req_msg.mutable_suid()->set_suid_low(LOOKUP_SUID.low);  pb_req_msg.mutable_susp_config()->set_delivery_type(      SNS_CLIENT_DELIVERY_NO_WAKEUP);  pb_req_msg.mutable_susp_config()->set_client_proc_type(      SNS_STD_CLIENT_PROCESSOR_APSS);  string pb_req_msg_encoded;  pb_req_msg.SerializeToString(&pb_req_msg_encoded);//DEBUG_LOG(log_instance," sending request to QMI connection for accel suid ");ssc_suid_obj->send_request(pb_req_msg_encoded);}void accel_cal::enable_accel(){  float sample_rate =80;  sns_client_request_msg pb_req_msg;  sns_std_sensor_config pb_stream_cfg;  string pb_stream_cfg_encoded;  pb_stream_cfg.set_sample_rate(sample_rate);  pb_stream_cfg.SerializeToString(&pb_stream_cfg_encoded);  pb_req_msg.set_msg_id(SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG);  pb_req_msg.mutable_request()->set_payload(pb_stream_cfg_encoded);  pb_req_msg.mutable_suid()->set_suid_high(accel_suid.high);  pb_req_msg.mutable_suid()->set_suid_low(accel_suid.low);  pb_req_msg.mutable_susp_config()->set_delivery_type(      SNS_CLIENT_DELIVERY_WAKEUP);  pb_req_msg.mutable_susp_config()->set_client_proc_type(      SNS_STD_CLIENT_PROCESSOR_APSS);  string pb_req_msg_encoded;  pb_req_msg.SerializeToString(&pb_req_msg_encoded);    pb_req_msg.SerializeToString(&pb_req_msg_encoded);    ssc_accel_cal_obj->send_request(pb_req_msg_encoded);    }void accel_cal::request_accel_cal(){    string pb_req_msg_encoded;    string config_encoded;    sns_client_request_msg pb_req_msg;    sns_physical_sensor_test_config config;    config.set_test_type((sns_physical_sensor_test_type)accel_test_type);    config.SerializeToString(&config_encoded);    pb_req_msg.set_msg_id(SNS_PHYSICAL_SENSOR_TEST_MSGID_SNS_PHYSICAL_SENSOR_TEST_CONFIG);    pb_req_msg.mutable_request()->set_payload(config_encoded);    pb_req_msg.mutable_suid()->set_suid_high(accel_suid.high);    pb_req_msg.mutable_suid()->set_suid_low(accel_suid.low);    pb_req_msg.mutable_susp_config()->set_delivery_type(SNS_CLIENT_DELIVERY_WAKEUP);    pb_req_msg.mutable_susp_config()->        set_client_proc_type(SNS_STD_CLIENT_PROCESSOR_APSS);    pb_req_msg.SerializeToString(&pb_req_msg_encoded);    ssc_accel_cal_obj->send_request(pb_req_msg_encoded);    }

上面为三个request请求函数处理。

request_suid的msg_id为SNS_SUID_MSGID_SNS_SUID_REQ;

enable_accel的msg_id为SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG;

request_accel_cal的msg_id为SNS_PHYSICAL_SENSOR_TEST_MSGID_SNS_PHYSICAL_SENSOR_TEST_CONFIG,test_type为SELF_TEST_TYPE_FACTORY。

voidaccel_cal::handle_ssc_enable_accel_event(constuint8_t*data,size_tsize){  ALOGI("event callback start:\n");  }voidaccel_cal::handle_ssc_accel_cal_event(constuint8_t*data,size_tsize){  ALOGI("event callback start:\n");  sns_client_event_msg pb_event_msg;  FILE *file =NULL;  sns_physical_sensor_test_event test_event;  pb_event_msg.ParseFromArray(data, size);for(inti=0; i < pb_event_msg.events_size(); i++) {auto&& pb_event = pb_event_msg.events(i);      ALOGI("event[%d] msg_id=%d", i, pb_event.msg_id());if(pb_event.msg_id() ==        SNS_PHYSICAL_SENSOR_TEST_MSGID_SNS_PHYSICAL_SENSOR_TEST_EVENT)            test_event.ParseFromString(pb_event.payload());intresult = test_event.test_passed();if(result==1&&  test_event.test_data().size() >3){          file = fopen(GsensorCalibration_factory_file,"w+");if(NULL== file)          {            ALOGI("accel fopen error \n");            accel_sensor_indication =3;          }else{fprintf(file,"%s\n",test_event.test_data().c_str());              accel_sensor_indication =1;          }          fclose(file);        }else{        accel_sensor_indication =2;    }          }}voidaccel_cal::handle_ssc_suid_event(constuint8_t*data,size_tsize){  ALOGI(" event received for accel suid");/* parse the pb encoded event */sns_client_event_msg pb_event_msg;  pb_event_msg.ParseFromArray(data, size);for(inti =0; i < pb_event_msg.events_size(); i++) {    ALOGI("suid event iteration %d", i);auto& pb_event = pb_event_msg.events(i);if(pb_event.msg_id() != SNS_SUID_MSGID_SNS_SUID_EVENT) {return;  }  sns_suid_event pb_suid_event;  pb_suid_event.ParseFromString(pb_event.payload());conststring& datatype = pb_suid_event.data_type();for(intj =0; j < pb_suid_event.suid_size(); j++) {      ALOGI("suid number %d", j);if(datatype == ACCEL) {        accel_suid.low = pb_suid_event.suid(j).suid_low();        accel_suid.high = pb_suid_event.suid(j).suid_high();stringstreamsuidLow;        suidLow <

上面为callback函数:

handle_ssc_suid_event 中msg_id为SNS_SUID_MSGID_SNS_SUID_EVENT,并将suid保存到sensor_uid accel_suid数据结构中。

handle_ssc_enable_accel_event中没有做任务处理,因为我们不需要gsensor数据,只需要enable它。

handle_ssc_accel_cal_event中为gsensor calibration,msg_id为:SNS_PHYSICAL_SENSOR_TEST_MSGID_SNS_PHYSICAL_SENSOR_TEST_EVENT,该command下下去后,会在SLPI侧accel driver中进行factory calibration,然后把calibration的数据通过event传回client。

然后将calibration的数据保存在/factory/GsensorCalibration.ini中,以便调用。

除了上面的方式外,还可以在enable accel后,获取accel 数据自行进行calibration。

比如下面一段code:

voidaccel_cal::request_accel_cal(){floatsample_rate =20;  sns_client_request_msg pb_req_msg;  sns_std_sensor_config pb_stream_cfg;stringpb_stream_cfg_encoded;  pb_stream_cfg.set_sample_rate(sample_rate);  pb_stream_cfg.SerializeToString(&pb_stream_cfg_encoded);  pb_req_msg.set_msg_id(SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_CONFIG);  pb_req_msg.mutable_request()->set_payload(pb_stream_cfg_encoded);  pb_req_msg.mutable_suid()->set_suid_high(accel_suid.high);  pb_req_msg.mutable_suid()->set_suid_low(accel_suid.low);  pb_req_msg.mutable_susp_config()->set_delivery_type(      SNS_CLIENT_DELIVERY_WAKEUP);  pb_req_msg.mutable_susp_config()->set_client_proc_type(      SNS_STD_CLIENT_PROCESSOR_APSS);stringpb_req_msg_encoded;  pb_req_msg.SerializeToString(&pb_req_msg_encoded);//setting number of samples recieved to 0, and allocate the input arrayaccel_sample_number =0;  samples_for_bias_calculation =newfloat*[SAMPLE_COUNT_REQUIRED_FORALGO];//SAMPLE_COUNT_REQUIRED_FORALGO = 64if(samples_for_bias_calculation ==NULL){    sns_loge("Memory allocation failed for samples_for_bias_calculation");return;  }for(inti =0; i < SAMPLE_COUNT_REQUIRED_FORALGO; i++) {    samples_for_bias_calculation[i] =newfloat[3];  }  ssc_accel_cal_obj->send_request(pb_req_msg_encoded);}

采样64组accel data。

voidaccel_cal::calculate_bias(bias_output* output){  sns_logd("calculating bias for 64 samples");  output->motionState =0;floatsampleSum[NUM_AXIS] = {0};floatsampleSqSum[NUM_AXIS] = {0};floatvariance[NUM_AXIS] = {0};for(intj =0; j < SAMPLE_COUNT_REQUIRED_FORALGO; j++) {for(inti =0; i < NUM_AXIS; i++) {      sampleSum[i] += samples_for_bias_calculation[j][i];      sampleSqSum[i] += ((float) (samples_for_bias_calculation[j][i])          * (float) (samples_for_bias_calculation[j][i]));    }  }floatvarT;for(inti =0; i < NUM_AXIS; i++) {    varT = (float) (sampleSum[i]) * (float) (sampleSum[i]);    variance[i] = (sampleSqSum[i] - (varT / (float) SAMPLE_COUNT_REQUIRED_FORALGO)) / (float) SAMPLE_COUNT_REQUIRED_FORALGO;if(variance[i] > variance_threshold) {      output->motionState =0;return;    }elseif(0== variance[i]) {      output->motionState =0;return;    }elseif( FX_ABS(sampleSum[i] / SAMPLE_COUNT_REQUIRED_FORALGO) > bias_thresholds[i]) {      output->motionState =0;return;    }  }  output->motionState =1;  output->x = sampleSum[0] / SAMPLE_COUNT_REQUIRED_FORALGO;  output->y = sampleSum[1] / SAMPLE_COUNT_REQUIRED_FORALGO;  output->z = sampleSum[2] / SAMPLE_COUNT_REQUIRED_FORALGO;  sns_logd("bias successfully calculated for 64 samples");}voidaccel_cal::handle_ssc_accel_cal_event(constuint8_t*data,size_tsize){  sns_logd("event received for accel config");  sns_client_event_msg pb_event_msg;  pb_event_msg.ParseFromArray(data, size);inteventSize = pb_event_msg.events_size();for(inti =0; i < eventSize; i++) {auto&& pb_event = pb_event_msg.events(i);if(pb_event.msg_id() == SNS_STD_SENSOR_MSGID_SNS_STD_SENSOR_EVENT) {      sns_std_sensor_event pb_sensor_event;      pb_sensor_event.ParseFromString(pb_event.payload());floatx = pb_sensor_event.data(0);floaty = pb_sensor_event.data(1);floatz = pb_sensor_event.data(2);      sns_logd("accel data received from event ::: x=%f, y=%f, z=%f", x,y, z);      sample_cal.x = x;      sample_cal.y = y;      sample_cal.z = z;      sample_calculated_offset.x =0;      sample_calculated_offset.y =0;      sample_calculated_offset.z =0;      ...      samples_for_bias_calculation[accel_sample_number][0] = x;      samples_for_bias_calculation[accel_sample_number][1] = y;      samples_for_bias_calculation[accel_sample_number][2] = z;if(accel_sample_number == SAMPLE_COUNT_REQUIRED_FORALGO -1) {        bias_output output;        calculate_bias(&output);//对64组accel data进行calibration。if(output.motionState ==0) {          sns_logd("Motion detected.");        }else{          sns_logd("Device at rest");          sns_logd("calculated cal values: %f, %f, %f", output.x,output.y, output.z);          curr_cal.x = output.x;          curr_cal.y = output.y;          curr_cal.z = output.z;        }      }      accel_sample_number = (accel_sample_number +1) %64;    }  }}

上面通过event获取accel sample ,当收集64笔时进行calibration。并将calibration的数据输出。

通过上面的操作也可以完成gsensor的calibration。不过算法要自己设计。

Ok,accel的calibration的操作已经完成。

作者:汉克233

链接:https://www.jianshu.com/p/9a77a3655f1f

来源:简书

简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

上一篇下一篇

猜你喜欢

热点阅读