高通SDM845平臺Sensor學習——2.Hal層--
二:Sensor Hal層程式碼分析
Hal code放在/vendor/qcom/proprietary/sensors-see/中
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)();
- 1
- 2
- 3
- 4
- 5
- 6
- 7
每個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);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
所以在,在.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;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
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;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
從_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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
可以看到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,
};
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
對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);
}
...
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
對應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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
獲取sensors_hal的例項,然後呼叫get_sensors_list
//sensors_hal.h
static sensors_hal& get_instance()
{
static sensors_hal hal;
return hal;
}
- 1
- 2
- 3
- 4
- 5
- 6
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);
}
...
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
No.1中:通過sensor_factory例項中get_available_sensors()來獲取sensor class。
sensor_factory例項:
static sensor_factory& instance()
{
static sensor_factory factory;
return factory;
}
- 1
- 2
- 3
- 4
- 5
調建構函式
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
}
...
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
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());
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
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;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
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;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
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;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
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
//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;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
通過判斷_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;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
再以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
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
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");
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
上面函式是在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;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
上面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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
上面為三個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);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
上面為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
相關推薦
高通SDM845平臺Sensor學習——2.Hal層--
二:Sensor Hal層程式碼分析
Hal code放在/vendor/qcom/proprietary/sensors-see/中
sensors-hal資料夾中包含framework和sensors資料夾,為本文重點分析物件
高通SDM845平臺Sensor學習——4.SLPI(SAM Sensor)--
四:Sensor SLPI層SAM Sensor例項分析
上文中,我們大致瞭解了物理sensor driver整個流程,但在專案中,一般寫這種sensor driver的情況很少。這種sensor driver基本上都是各個vendor廠商
關於高通8053平臺i2c和spi配置的學習總結
這次完成的任務是要使能高通8053平臺的i2c和spi,主要做的工作就是在裝置樹檔案中新增節點資訊。主要的工作在於對裝置樹檔案的修改,主要修改了msm8953-pinctrl.dtsi和msm8953.dtsi兩個檔案。
msm8953-pinctrl.dtsi是配置M
高通820(msm8996)camera hal原始碼分析
之前閱讀過高通的camera的v4l2的driver,和video codec的driver,還沒有分享出原始碼架構圖。現在首先先分享出camera hal的原始碼架構圖吧,高通的hal可以使用hal1和hal3.
一,在hardware/qcom/camera下是高通的c
高通Android平臺 OTA差分包的生成方法
1、首先高通平臺的編譯流程與android原生態的編譯流程一樣,需要經歷以下幾步:
a. source build/envsetup.sh;
b. lunch 選擇專案
c. make -j24
編譯完之後
4.make otapackage
高通8xxx平臺雙MIC設定
dts檔案修改:
qcom,audio-routing =
"RX_BIAS", "MCLK",
"LDO_H", "MCLK",
"SPK_OUT", "MCLK",
"SPK_OUT", "EXT_VDD_SPKR",
"Lineo
高通android平臺功耗優化方法
1、底電流除錯(Rock Bottom Current Optimization)
底電流在手機飛航模式下除錯。每個平臺的底電流資料可能不一樣,具體可以參考release出來的Current Consumption Data文件或者release note。一般情況下的底電流參考資料上限是:
512M
高通MDM平臺開發入門
原始碼下載
高通MDM平臺程式碼分為兩個部分:高通私有程式碼 以及 開源公有程式碼
針對某一個平臺,高通會提供一條基線,包括了私有程式碼的版本以及公有程式碼每個庫的revision
公有程式碼下載:在基線中有codeaurora相關的repo下載路徑,找到對應的ma
高通Android平臺硬體除錯之Camera篇
Camera工作流程圖Camera的成像原理可以簡單概括如下:景物(SCENE)通過鏡頭(LENS)生成的光學影象投射到影象感測器(Sensor)表面上,然後轉為電訊號,經過A/D(模數轉換)轉換後變為數字影象訊號,再送到數字訊號處理晶片(DSP)中加工處理,再通過IO介面傳輸到CPU中處理,通過DISPLA
高通1100平臺解鎖ATCOP相關改動
1. SBNAALZ.cmd
USES_NO_ATCOP=NO
2. custsbnaalz.h
去掉#define FEATURE_DATA_STRIP_ATCOP
#define FEATURE_ASYNC_DATA_NOOP
高通平臺framework,hal,kernel開啟log【轉】
本文轉載自:https://blog.csdn.net/u010164190/article/details/78625636
1 1.Add framework log
2 #define LOG_NDEBUG 0
3 2.Add hal log
4 #define LOG_NDEBU
[高通平臺小米4]的電源管理配置學習
1.溫控調頻
/system/etc/thermal-engine-8974.conf
sampling 5000
[CPU0_MONITOR]
algo_type monitor
sensor cp
高通平臺手機開發之Sensor
4.6. Sensor
高通文件
1) 80-N7635-1_E_Snapdragon_Sensors_Core_New_Sensor_Driver_Integration_LA.pdf
2) 80-NA157-92_C_MSM8974_Snap
泛泰A820L (高通MSM8660 cpu) 3.4內核的CM10.1(Android 4.2.2) 測試版第二版
卸載 反饋 span lin clas wan 系統分區 漢化 sof
歡迎關註泛泰非盈利專業第三方開發團隊 VegaDevTeam (本team 由 syhost suky zhaochengw(z大) xuefy(大星星) tenfar(R大師) loogeo
高通HAL層之bmp18x.cpp
report handle and n) blog fine targe oat img 繼續上一個鏈接內容所講:http://www.cnblogs.com/linhaostudy/p/8430583.html
下面bmp18x sensor為例進行分析。
BMP18
基於Android7.1 8953 高通平臺下零死角玩轉裝置樹DTS
【基於Android7.1 8953 高通平臺下零死角玩轉裝置樹DTS】
更新內容:
【創科之龍_安卓開發】第01課_為什麼引用linux裝置樹和對比優勢
【創科之龍_安卓開發】第02課_如何在Linux-3.x核心
高通平臺啟動log概述(PBL log、sbl1 log、kernel log)【轉】
本文轉自:https://blog.csdn.net/RadianceBlau/article/details/78416776?utm_source=blogxgwz9
高通平臺啟動log概述(PBL log、sbl1 log、kernel log)在嵌入式linux的除錯過程中log有著至關重要的地位,
高通平臺讀寫nv總結【轉】
本文轉載自:https://blog.csdn.net/suofeng12345/article/details/52713993
一,引言 1. 什麼是NV &nbs
高通平臺 ramdump-parser 簡介
ramdump 是什麼?簡單來說就是把系統memory中的某一個時間點的的資料資訊通過一定手段取出來儲存起來的記憶體崩潰檔案,屬於ELF檔案格式。
當系統發生致命錯誤無法恢復的時候,主動觸發抓取ramdump把異常現場保留下來供離線分析定位問題是一種非常重要的高階除錯手段。
高
通過高通平臺簡單總結的許可權問題
android 5.x開始,引入了非常嚴格的selinux許可權管理機制,我們經常會遇到因為selinux許可權問題造成的各種avc denied困擾。有時候我們在添加了一些驅動或應用的時候,發現不能用,但是程式本身查不出問題來,那就要抓log看一下了,很多時候就是因為沒有新增許可權,下