美文网首页ssc
高通SDM845平台Sensor学习——2.Hal层

高通SDM845平台Sensor学习——2.Hal层

作者: 汉克233 | 来源:发表于2018-07-02 18:27 被阅读0次

    二: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.cpp
    SENSOR_MODULE_INIT(accelerometer_module_init);
    
    //sensor.h
    #define SENSOR_MODULE_INIT(module_init_func) \
        static const bool __mod_init = (module_init_func)();
    
    

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

    //accelerometer.cpp
    static bool accelerometer_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);
        return true;
    }
    
    //sensor_factory.h
    static void register_sensor(int type, get_available_sensors_func func)
        {
            try {
                callbacks().emplace(type, func);
            } catch (const std::exception& e) {
                sns_loge("failed to register type %d", type);
            }
        }
    static std::unordered_map<int, get_available_sensors_func>& callbacks()
        {
            static std::unordered_map<int, get_available_sensors_func> _callbacks;
            return _callbacks;
        }
    
    //sensor_factory.h
    static void request_datatype(const char *datatype)
        {
            try {
                datatypes().insert(std::string(datatype));
            } catch (const std::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.cpp
    static vector<unique_ptr<sensor>> get_available_accel_calibrated()
    {
        const vector<sensor_uid>& accel_suids =
             sensor_factory::instance().get_suids(SSC_DATATYPE_ACCEL);  //  No.1
        vector<unique_ptr<sensor>> sensors;
        for (const auto& suid : accel_suids) {
            if (!(sensor_factory::instance().get_settings()              // No.2
                                        & DISABLE_WAKEUP_SENSORS_FLAG)) {
                try {
                    sensors.push_back(make_unique<accelerometer>(suid, SENSOR_WAKEUP,  //No.3
                                                             SENSOR_CALIBRATED));
                } catch (const exception& e) {
                    sns_loge("failed for wakeup, %s", e.what());
                }
            }
            try {
                sensors.push_back(make_unique<accelerometer>(suid, SENSOR_NO_WAKEUP,
                                                         SENSOR_CALIBRATED));
            } catch (const exception& e) {
                sns_loge("failed for nowakeup, %s", e.what());
            }
        }
        return sensors;
    }
    

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

    const std::vector<sensor_uid>& sensor_factory::get_suids(const std::string& datatype) const
    {
        auto it = _suid_map.find(datatype);
        if (it != _suid_map.end()) {
            return it->second;
        } else {
            static vector<sensor_uid> empty;
            return empty;
        }
    }
    

    从_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.b
            set_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.cpp
    virtual void handle_sns_std_sensor_event(
            const sns_client_event_msg_sns_client_event& pb_event) override;
    
    void accelerometer::handle_sns_std_sensor_event(
        const sns_client_event_msg_sns_client_event& pb_event)
    {
        sns_std_sensor_event pb_sensor_event;
        pb_sensor_event.ParseFromString(pb_event.payload());
    
        sensors_event_t hal_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.cpp
    void ssc_sensor::handle_sns_std_sensor_event(
        const sns_client_event_msg_sns_client_event& pb_event)
    {
        sns_std_sensor_event pb_stream_event;
        pb_stream_event.ParseFromString(pb_event.payload());
    
        sensors_event_t hal_event = create_sensor_hal_event(pb_event.timestamp());
    
        int num_items = pb_stream_event.data_size();
        ...
        for (int i = 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.cpp
    struct sensors_module_t HAL_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函数。

    static void lazy_init_sensors_list() {
        ...
        const struct sensor_t *subhal_sensors_list;
        for (std::vector<hw_module_t*>::iterator it = sub_hw_modules->begin();
                it != sub_hw_modules->end(); it++) {
            struct sensors_module_t *module = (struct sensors_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.cpp
    static int get_sensors_list(struct sensors_module_t* module,
        struct sensor_t const** list)
    {
        sensors_hal& hal = sensors_hal::get_instance();
        return hal.get_sensors_list(list);
    }
    
    

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

    //sensors_hal.h
    static sensors_hal& get_instance()
        {
            static sensors_hal hal;
            return hal;
        }
    

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

    //sensors_hal.cpp
    sensors_hal::sensors_hal()
    {
        ...
        try {
            init_sensors();                                
        ...
        } 
        ...
    }
    
    void sensors_hal::init_sensors()
    {
        auto sensors = sensor_factory::instance().get_all_available_sensors();              //No.1
        auto cb  = [this](const auto& event, auto wakeup) { _event_queue.push(event, wakeup); }; //No.2
    
        for (unique_ptr<sensor>& s : sensors) {                                //No.3
            assert(s != nullptr);
            s->register_callback(cb);                                   
            const sensor_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实例:

    static sensor_factory& instance()
        {
            static sensor_factory factory;
            return factory;
        }
    

    调构造函数

    sensor_factory::sensor_factory()
    {
        ...
        _settings = get_sns_settings();                          // No.1
        _pending_attributes = 0;                                    // No.2
        if (!(_settings & DISABLE_SENSORS_FLAG)) {
    
            /* find available sensors on ssc */
            discover_sensors();                                       // No.3
    
            if (_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.cpp
    void sensor_factory::discover_sensors()
    {
        using namespace std::chrono;
        suid_lookup lookup(                                                         //No.a
            [this](const string& datatype, const auto& suids)
            {
                suid_lookup_callback(datatype, suids);
            });
    
        for (const string& dt : datatypes()) {
            sns_logd("requesting %s", dt.c_str());
            lookup.request_suid(dt);                                               //No.b
        }
        auto tp_wait_start = steady_clock::now();
    
        /* wait for some time for discovery of available sensors */
        auto delay = 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 (const auto& item : _suid_map) {
            sns_logd("%-20s%4u", item.first.c_str(), (unsigned int)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.cpp
    void suid_lookup::request_suid(std::string datatype)
    {
        sns_client_request_msg pb_req_msg;                   //No.a
        sns_suid_req pb_suid_req;
        string pb_suid_req_encoded;
    
        const sensor_uid LOOKUP_SUID = {                   //No.b
            12370169555311111083ull,
            12370169555311111083ull
        };
        ...
        /* populate SUID request */                                 //No.c
        pb_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.d
        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_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);
        _ssc_conn.send_request(pb_req_msg_encoded);                                 //No.e
    }
    
    //sns_client.pb.h
    typedef struct _sns_client_request_msg {
        sns_std_suid suid;
        uint32_t msg_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.cpp
    void suid_lookup::handle_ssc_event(const uint8_t *data, size_t size)
    {
        /* 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 (int i = 0; i < pb_event_msg.events_size(); i++) {               //No.b
            auto& 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.c
            pb_suid_event.ParseFromString(pb_event.payload());
            const string& datatype =  pb_suid_event.data_type();
            ...
            /* create a list of  all suids found for this datatype */
            vector<sensor_uid> suids(pb_suid_event.suid_size());        //No.d
            for (int j=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.h
    typedef enum _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<unique_ptr<sensor>> sensor_factory::get_all_available_sensors() const
    {
        vector<unique_ptr<sensor>> all_sensors;
        for (const auto& item : callbacks()) {                                            // No.a
            const auto& get_sensors = item.second;                                 // No.b
            vector<unique_ptr<sensor>> sensors = get_sensors();         
            sns_logd("type=%d, num_sensors=%u", item.first, (unsigned int)sensors.size());
            for (auto&& s : sensors) {
                all_sensors.push_back(std::move(s));                               // No.c
            }
        }
        return all_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.cpp
    int sensors_hal::get_sensors_list(const sensor_t **s_list)
    {
        int num_sensors = (int)_hal_sensors.size();
        sns_logi("num_sensors=%d", num_sensors);
        *s_list = &_hal_sensors[0];
        return num_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.cpp
    int sensors_hal::activate(int handle, int enable)
    {
        ....
    
            if (enable) {
                sensor->activate();
            } else {
                sensor->deactivate();
            }
        ....
        return 0;
    }
    

    再以accelerometer.cpp为例:
    因为accelerometer class继承ssc_sensor class,故会调用ssc_sensor中的activate。

    //ssc_sensor.cpp
    void ssc_sensor::activate()
    {
        std::lock_guard<mutex> lk(_mutex);                       //No.1
        if (!is_active()) {
            /* establish a new connection to ssc */
            _ssc_conn = make_unique<ssc_connection>(
            [this](const uint8_t *data, size_t size)
            {
                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](auto e){ ssc_conn_error_cb(e); });
            send_sensor_config_request();                                  //No.4
        }
    }
    
    void ssc_sensor::deactivate()
    {
        std::lock_guard<mutex> 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。顺便加深下上面学习的知识。

    void accel_cal::init_ssc_connectiions()
    {
    
      ssc_suid_cb = [this](const uint8_t* msg , int msgLength)
      { this->handle_ssc_suid_event(msg, msgLength);};
    
      if (NULL == (ssc_suid_obj = new ssc_connection(ssc_suid_cb))) {
        ALOGE("ssc connection for suid failed");
        return;
      }
    
      ssc_accel_cal_cb = [this](const uint8_t* msg , int msgLength)
        {this->handle_ssc_accel_cal_event(msg, msgLength);};
    
      if (NULL == (ssc_accel_cal_obj = new ssc_connection(ssc_accel_cal_cb))) {
        ALOGE("ssc connection failed");
        return;
      }
      
      ssc_accel_enable_cb = [this](const uint8_t* msg , int msgLength)
        {this->handle_ssc_enable_accel_event(msg, msgLength);};
    
      if (NULL == (ssc_accel_enable_obj = new ssc_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。

    int accel_cal::cal_init()
    {
      int result = true;
      std::string datatype_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;
      return result;
    }
    

    上面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;
    
      const sensor_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。

    void accel_cal::handle_ssc_enable_accel_event(const uint8_t *data, size_t size)
    {
      ALOGI("event callback start:\n");
      
    }
    
    
    void accel_cal::handle_ssc_accel_cal_event(const uint8_t *data, size_t size)
    {
      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 (int i=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());
             int result = 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;
        }    
          }
    }
    
    void accel_cal::handle_ssc_suid_event(const uint8_t *data, size_t size)
    {
    
      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 (int i = 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());
      const string& datatype = pb_suid_event.data_type();
        for (int j = 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();
            stringstream suidLow;
            suidLow << std::hex << accel_suid.low;
            stringstream suidHigh;
            suidHigh << std::hex << accel_suid.high;
            ALOGI("even recieved for accel suid, suid =  %s, %s",
                suidLow.str().c_str(), suidHigh.str().c_str());
    
            //printf("even recieved for accel suid, suid =  %s, %s\n",
            //    suidLow.str().c_str(), suidHigh.str().c_str());
          }
        }
      }
      pthread_cond_signal(&condition);
      pthread_mutex_unlock(&cb_mutex);
    
    }
    

    上面为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:

    void accel_cal::request_accel_cal()
    {
    
      float sample_rate = 20;
      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);
      //setting number of samples recieved to 0, and allocate the input array
      accel_sample_number = 0;
      samples_for_bias_calculation = new float*[SAMPLE_COUNT_REQUIRED_FORALGO];//SAMPLE_COUNT_REQUIRED_FORALGO = 64
      if(samples_for_bias_calculation == NULL){
        sns_loge("Memory allocation failed for samples_for_bias_calculation");
        return;
      }
    
      for (int i = 0; i < SAMPLE_COUNT_REQUIRED_FORALGO; i++) {
        samples_for_bias_calculation[i] = new float[3];
      }
    
      ssc_accel_cal_obj->send_request(pb_req_msg_encoded);
    
    }
    

    采样64组accel data。

    void accel_cal::calculate_bias(bias_output* output)
    {
    
      sns_logd("calculating bias for 64 samples");
    
      output->motionState = 0;
      float sampleSum[NUM_AXIS] = { 0 };
      float sampleSqSum[NUM_AXIS] = { 0 };
      float variance[NUM_AXIS] = { 0 };
    
      for (int j = 0; j < SAMPLE_COUNT_REQUIRED_FORALGO; j++) {
    
        for (int i = 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]));
        }
      }
    
      float varT;
    
      for (int i = 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;
        } else if (0 == variance[i]) {
          output->motionState = 0;
          return;
        } else if ( 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");
    
    }
    
    void accel_cal::handle_ssc_accel_cal_event(const uint8_t *data, size_t size)
    {
    
      sns_logd("event received for accel config");
    
      sns_client_event_msg pb_event_msg;
      pb_event_msg.ParseFromArray(data, size);
      int eventSize = pb_event_msg.events_size();
      for (int i = 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());
    
          float x = pb_sensor_event.data(0);
          float y = pb_sensor_event.data(1);
          float z = 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的操作已经完成。

    相关文章

      网友评论

        本文标题:高通SDM845平台Sensor学习——2.Hal层

        本文链接:https://www.haomeiwen.com/subject/yenluftx.html