高通SDM845平臺(tái)Sensor學(xué)習(xí)——2.Hal層

二:Sensor Hal層代碼分析

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

圖5

sensors-hal文件夾中包含framework和sensors文件夾概疆,為本文重點(diǎn)分析對(duì)象梅垄。

首先分析sensors文件夾:
根據(jù)C++繼承的特性,相同的操作各個(gè)class共同擁有恩沛,不同的操作每個(gè)class可以重寫,該文件夾內(nèi)文件為每個(gè)sensor不同的地方橙依,porting sensor主要是在這部分做的训堆。sensors文件夾中包含很多sensor cpp文件比如:accelerometer.cpp為accel sensor的hal層code,step_count.cpp為計(jì)步器的hal層的code等等占哟,主要是針對(duì)不同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)();

每個(gè)cpp都有SENSOR_MODULE_INIT入口酿矢,__mod_init具體實(shí)現(xiàn)在code沒有找到榨乎,不過(guò)應(yīng)該類似kernel中module_init,在系統(tǒng)加載.so時(shí)調(diào)用棠涮。故可知谬哀,所有特定sensor的cpp在加載.so時(shí)會(huì)被調(diào)SENSOR_MODULE_INIT進(jìn)行加載。

//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被調(diào)用后史煎,accelerometer_module_init會(huì)被執(zhí)行!通過(guò)register_sensor將type和func放入callbacks的unordered_map中驳糯。并將datatype插入到datatypes的unordered_set中篇梭,以便后面使用。

下面以get_available_accel_calibrated為例繼續(xù)研究:

//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可以通過(guò)sensor_factory實(shí)例中g(shù)et_suids函數(shù)來(lái)獲取:

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來(lái)獲取accel的suid酝枢。那什么時(shí)候?qū)ccel的suid插入到_suids_map中內(nèi)恬偷,在framework文件夾中,后續(xù)會(huì)介紹帘睦。

No.2中:通過(guò)getsetting來(lái)查看是否有DISABLE_WAKEUP_SENSORS_FLAG flag袍患,若有則為no wakeup,若無(wú)則為wake up sensor竣付。

No.3中:為調(diào)用accelerometer的構(gòu)造函數(shù)诡延。

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的構(gòu)造函數(shù)中古胆,主要設(shè)置一些common的參數(shù)肆良。
No.b中:設(shè)置accel中不common的參數(shù)。比如string_type逸绎、sensor_typename惹恃、是否使用resampling、最大range棺牧、分辨率等等巫糙。

Ok,accelerometer.cpp基本介紹完畢陨帆。
對(duì)了曲秉,還有個(gè)handle_sns_std_sensor_event函數(shù)是干什么的呢采蚀?

//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為虛函數(shù)疲牵,在framework中有實(shí)現(xiàn)承二,在accelerometer.cpp中也有實(shí)現(xiàn)。Ok纲爸,若sensors文件中xxxx.cpp中沒有重寫handle_sns_std_sensor_event則可以使用framework common的進(jìn)行實(shí)現(xiàn)亥鸠,若有的話,則使用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,
};

對(duì)Android Hal層比較熟的都知道sensors_module_t這個(gè)數(shù)據(jù)結(jié)構(gòu)负蚊,hardware通過(guò)dlopen打開.so lib,并通過(guò)dlsym加載symbols颓哮,然后即可使用相應(yīng)的方法家妆,具體細(xì)節(jié)不再重復(fù)介紹。

從hardware/libhardware/modules/sensors/multihal.cpp中可以看到冕茅,首先會(huì)調(diào)用get_sensor_list函數(shù)伤极。

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);
    }
    ...
}

對(duì)應(yīng)sensor_hw_module.cpp中函數(shù)如下:

//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的實(shí)例,然后調(diào)用get_sensors_list

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

sensor_hal為static的姨伤,故執(zhí)行構(gòu)造函數(shù)哨坪。

//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中:通過(guò)sensor_factory實(shí)例中g(shù)et_available_sensors()來(lái)獲取sensor class。

sensor_factory實(shí)例:

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

調(diào)構(gòu)造函數(shù)

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中:通過(guò)"/persist/sensors/registry/registry/sensors_settings"文件來(lái)設(shè)置setting乍楚。
No.2中:_pending_attributes為pending sensor的數(shù)目当编。
No.3中:discover_sensors用來(lái)發(fā)現(xiàn)所有的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())徒溪,其中g(shù)et_ssc_event_cb為回調(diào)函數(shù)忿偷。event在該函數(shù)中處理。
suid_lookup_callback(datatype, suids);函數(shù)比較重要臊泌,把suid加入到_suid_map中鲤桥,回頭看sensors文件夾中的 sensor_factory::get_suids函數(shù),即從_suid_map中查找datatype為accel的suid缺虐。前后聯(lián)系在一起了芜壁。那么suids和datatype哪兒來(lái)的呢?透露一下高氮,發(fā)送request后等待callback函數(shù)接收到event并獲取到datatype和suids慧妄。然后會(huì)執(zhí)行該函數(shù)。

No.b中:通過(guò)loopup類中的request_suid發(fā)送request給SLPI中的sensor剪芍。dt為accel塞淹、gryo、mag等等罪裹。

下面分析下request_suid函數(shù):

//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套耕。這里需要說(shuō)明一下谁帕,在sdm845 see中,包含物理sensor冯袍、虛擬sensor和platform sensor匈挖。前面兩個(gè)sensor我們都了解,platform sensor是什么呢康愤?原來(lái) 高通在see上定義專門為platform服務(wù)的sensor儡循,這些sensor是內(nèi)嵌的,可以被任何sensor或者sensor instance使用征冷,來(lái)提供相應(yīng)的功能择膝。這里suid sensor為platform sensor,它的作用是為所有其他sensor提供suid检激。suid sensor會(huì)根據(jù)不同的datatype提供相應(yīng)的suid肴捉。當(dāng)然suid sensor也有個(gè)suid。這個(gè)suid也是固定不變的呵扛,就是No.b中的數(shù)字每庆。

拓展:除了suid sensor外還有很多platform sensor,比如:register sensor , 可以解析并獲取其他sensor的register今穿;Interrupt sensor缤灵,為其他sensor提供中斷;等等蓝晒。

No.c中:填充pb_suid_req腮出,設(shè)置datatype,register_updates芝薇;并將pb_suid_req序列化成字符串格式胚嘲,成為pb_suid_req_encoded,以便ps_req_msg使用洛二。

No.d中:填充pb_req_msg馋劈,設(shè)置msg_id,這里msg_id比較重要晾嘶,到SLPI側(cè)sensor driver中妓雾,會(huì)根據(jù)該msg_id做相應(yīng)的操作,這是后話垒迂。
設(shè)置成員request中的payload為pb_suid_req_encoded械姻。設(shè)置成員suid中的suid_high、suid_low為L(zhǎng)OOKUP_SUID的高机断、低位楷拳。
設(shè)置成員susp_config中內(nèi)容绣夺。。欢揖。
最后將pb_req_msg序列化字符串pb_req_msg_encoded陶耍。

No.e中:通過(guò)_ssc_conn.request將該字符串發(fā)送出去。
發(fā)送的流程我們?cè)诖瞬辉傺芯拷牵际歉咄ǚ庋b好的API物臂,我們直接使用即可旺拉,有興趣的童鞋可以繼續(xù)追code产上。

發(fā)送完request后,我們需要靜等callback蛾狗。根據(jù)前面描述可知晋涣,callback為suid_lookup::handle_ssc_event()函數(shù),在該函數(shù)中沉桌,
No.a中sns_client_event_msg為對(duì)應(yīng)event的封裝谢鹊,通過(guò)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對(duì)應(yīng)佃扼。

No.c中:同No.a一樣,將pb_event.payload() 解碼成sns_suid_event蔼夜。
No.d中:創(chuàng)建一個(gè)suid的vector兼耀,將獲得suid string放進(jìn)去。然后調(diào)用_cb將suids保存起來(lái)求冷,即調(diào)用suid_lookup_callback函數(shù)將datatype和suids放入到_suid_map的unordered_map中瘤运。

Ok,discover_sensors基本介紹完畢匠题,sensor_factory構(gòu)造函數(shù)中還會(huì)在retrieve_attributes()發(fā)送request來(lái)獲取attribute拯坟。并放在_attributes的unordered_map中。操作基本相同韭山,只是request發(fā)送的msg_id不同而已郁季,在此不再詳細(xì)介紹。

接著钱磅,繼續(xù)回到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文件夾中可知塞琼,通過(guò)register_sensor將type和func放入到叫callbacks的unordered_map中。

No.b中禁舷,get_sensors獲取callbacks中第二個(gè)元素get_available_sensors_func彪杉。然后通過(guò)get_sensors()函數(shù)即get_available_sensors_func()來(lái)獲取sensor class毅往。對(duì)應(yīng)sensors文件中accelerometer.cpp中g(shù)et_available_accel_calibrated()和get_available_accel_uncalibrated()。

No.c中派近,將獲取到的vector<unique_ptr<sensor>>放到all_sensors這個(gè)容器中攀唯。以便后續(xù)使用!

回到init_sensors函數(shù):
No.2中:將event和wakeup push到_event_queue中渴丸,即變成sensors_event_t _event_queue侯嘀。
No.3中:register_callback 后,通過(guò)get_sensor_info()獲取sensor_info谱轨。然后戒幔,把sensor_info push到_hal_sensors的vector中,將sensor class放到unordered_map _sensors的sensor_info.handle成員中土童。

init_sensors解析完畢诗茎。注:數(shù)據(jù)結(jié)構(gòu)放在sensors.h中(/hardware/libhardware/include/hardware/sensors.h)

然后繼續(xù)分析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;
}

通過(guò)判斷_hal_sensors的大小獲取到所有sensor的數(shù)目。并將_hal_sensors的首地址賦給s_list献汗。

至此敢订,系統(tǒng)獲取了全部sensor的suid和attributes,并將其放在指定的容器中保存起來(lái)罢吃,完成sensor的初始化工作楚午。下面就等user來(lái)使用了。

Enable/Disable Sensor

framewark層getDefaultSensor并registerListener后尿招,經(jīng)過(guò)一系列函數(shù)后矾柜,最終會(huì)調(diào)到sensors_hal中activate函數(shù)來(lái)enable/disable。

//sensors_hal.cpp
int sensors_hal::activate(int handle, int enable)
{
    ....

        if (enable) {
            sensor->activate();
        } else {
            sensor->deactivate();
        }
    ....
    return 0;
}

再以accelerometer.cpp為例:
因?yàn)閍ccelerometer class繼承ssc_sensor class泊业,故會(huì)調(diào)用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中:申請(qǐng)互斥鎖lk。
No.2中:接收event的callback函數(shù)吁伺。
No.3中:針對(duì)wakeup sensor處理的函數(shù)饮睬。
No.4中發(fā)送config request,enabe accle sensor篮奄。
等發(fā)送到enable request后捆愁,等待接收event合冀。然后通過(guò)submit_sensors_hal_event(hal_event)將數(shù)據(jù)上報(bào)荠列。

No.5中:deactivate為disable sensor,首先判斷sensor狀態(tài)是否是active簿废,若是則reset夸赫,若不是菩帝,不做任何處理。

Factory Calibration
加速度傳感器在進(jìn)工廠時(shí)需要進(jìn)行calibration。下面提供accelerometer calibration的code呼奢。順便加深下上面學(xué)習(xí)的知識(shí)宜雀。

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");
}

上面函數(shù)是在new的時(shí)候調(diào)用,建立 3個(gè)callback函數(shù)握础,分別用來(lái)接收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發(fā)送request來(lái)獲取accel的suid简烘。
上面enable_accel發(fā)送request來(lái)enabe accel
上面request_accel_cal發(fā)送request來(lái)讓SLPI側(cè)的sensor進(jìn)行calibration。
超時(shí)處理定枷,當(dāng)2s內(nèi)沒有接收到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);    
}

上面為三個(gè)request請(qǐng)求函數(shù)處理依鸥。
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函數(shù):
handle_ssc_suid_event 中msg_id為SNS_SUID_MSGID_SNS_SUID_EVENT絮供,并將suid保存到sensor_uid accel_suid數(shù)據(jù)結(jié)構(gòu)中衣吠。

handle_ssc_enable_accel_event中沒有做任務(wù)處理,因?yàn)槲覀儾恍枰猤sensor數(shù)據(jù)壤靶,只需要enable它缚俏。
handle_ssc_accel_cal_event中為gsensor calibration,msg_id為:SNS_PHYSICAL_SENSOR_TEST_MSGID_SNS_PHYSICAL_SENSOR_TEST_EVENT贮乳,該command下下去后忧换,會(huì)在SLPI側(cè)accel driver中進(jìn)行factory calibration,然后把calibration的數(shù)據(jù)通過(guò)event傳回client向拆。

然后將calibration的數(shù)據(jù)保存在/factory/GsensorCalibration.ini中亚茬,以便調(diào)用。

除了上面的方式外浓恳,還可以在enable accel后刹缝,獲取accel 數(shù)據(jù)自行進(jìn)行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);     //對(duì)64組accel data進(jìn)行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;
    }
  }
}

上面通過(guò)event獲取accel sample ,當(dāng)收集64筆時(shí)進(jìn)行calibration晴圾。并將calibration的數(shù)據(jù)輸出颂砸。
通過(guò)上面的操作也可以完成gsensor的calibration。不過(guò)算法要自己設(shè)計(jì)。

Ok人乓,accel的calibration的操作已經(jīng)完成梗醇。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市撒蟀,隨后出現(xiàn)的幾起案子叙谨,更是在濱河造成了極大的恐慌,老刑警劉巖保屯,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件手负,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡姑尺,警方通過(guò)查閱死者的電腦和手機(jī)竟终,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)切蟋,“玉大人统捶,你說(shuō)我怎么就攤上這事”猓” “怎么了喘鸟?”我有些...
    開封第一講書人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)驻右。 經(jīng)常有香客問(wèn)我什黑,道長(zhǎng),這世上最難降的妖魔是什么堪夭? 我笑而不...
    開封第一講書人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任愕把,我火速辦了婚禮,結(jié)果婚禮上森爽,老公的妹妹穿的比我還像新娘恨豁。我一直安慰自己,他們只是感情好爬迟,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開白布橘蜜。 她就那樣靜靜地躺著,像睡著了一般雕旨。 火紅的嫁衣襯著肌膚如雪扮匠。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評(píng)論 1 285
  • 那天凡涩,我揣著相機(jī)與錄音棒搜,去河邊找鬼。 笑死活箕,一個(gè)胖子當(dāng)著我的面吹牛力麸,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼克蚂,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼闺鲸!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起埃叭,我...
    開封第一講書人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤摸恍,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后赤屋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體立镶,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年类早,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了媚媒。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡涩僻,死狀恐怖缭召,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情逆日,我是刑警寧澤嵌巷,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站屏富,受9級(jí)特大地震影響晴竞,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜狠半,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望颤难。 院中可真熱鬧神年,春花似錦、人聲如沸行嗤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)栅屏。三九已至飘千,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間栈雳,已是汗流浹背护奈。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留哥纫,地道東北人霉旗。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親厌秒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子读拆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容