Androidセンサー分析
Androidセンサー分析
ターゲット:deviceの状態を検出する不正状態で光機を閉じる 不法移動クローズジェスチャー ステップは、次の3つのステップに分けられます. 1.sensor移植(accelerometer and gyro) 2.frameworkにsensorListener を登録する 3.sensor calibration
sensor移植
本文はLinux 3に基づく.18,CPUはMT 8163である.最初のステップは駆動部の移植であり、Arm Linuxカーネルは3.x DTSを導入する.DTSファイルを修正する必要がある.dts修正部分は元の構成案を参照し、主に2つの部分に分けられ、一部はrootノードの下に直接掛けられ、一部はi 2 c 2コントローラの下に掛けられる.すなわち、1つのGsensor(or GYRO)は、i 2 cバスとplatformバスに同時にi 2 cデバイスとしてマウントされる.原因についてはゆっくり分析します.
ここではacceのみを解析し,gyroの原理は同じである.ソースコード位置kernel-3.18/drivers/misc/mediatek/accelerometer/mpu 6050 g-new/mpu 6050.c.先来init関数
内容は少なく、2つの関数しかありません.先にget_accel_dts_funcはrootノードの下に直接掛けられたdts node属性を読み出してhwに保存する.さらにacc_を通過driver_addはdriverを登録し、次にこの関数を重点的に分析します.この関数はkernel-3.18/drivers/misc/mediatek/accelerometer/accel.cで実現する.
中のplatformに注目driver_register、ここではdtsに直接rootの下に掛けられているnodeと一致しますが、i 2 c driverは?焦らないで探し続けましょう.この関数ではgsensor_に注目しますinit_List[i]=obj,我々はgsensorが1つしかないので,ここでのiは0に等しい.objが何なのか見に行きます.mpu 6050 gseでinitはmpu 6050ですinit_infoのアドレスはmpu 6050に戻ります.c
この構造体のメンバー変数、init、uninitを見てください.これは初期化関数に違いありませんが、どこで実行されますか?前に見た住所がaccelに伝わった.c中、じゃあ、あちらへ行ってみます.accelの初期化関数
acc_probe関数はいろいろなことをしてaccに注目しましたreal_driver_Initその他はinput時間報告など、自分で検討することができます
見つけた!ここではgsensor_を実行しましたinit_list[i]->init()
こちらにi 2 c driverが登録されており、platformもi 2 c driverも登録済みで、その後のデータ取得は比較的簡単(i 2 c通信にほかならない)で、貼りません.これでsensorのdriverがオンになり、inputイベント(acc_input_init)が報告され、自分で見ることに興味があり、標準的なinputデバイスフレームワークがセットされ、frameworkに入ります.
frameworkにsensorListenerを登録する
frameworkでは比較的簡単で、android sensor APIを直接呼び出せばよい.
こんなに简単にacceのデータを取得することができて、しかしデータを得てどのように使うのがあなた自身を见ます
sensor calibration
一般的に私たちのsensorは工場を出る前に多くの操作をする必要があります.その中にsensorキャリブレーションがあります.ここでmtkプラットフォームにadbを通じてエンジニアリングモードに入ってsensorキャリブレーションを行うコマンドがあります.
MTKsensorキャリブレーションコードsensorをもう1つ貼ってください.cali
ターゲット:deviceの状態を検出する
sensor移植
本文はLinux 3に基づく.18,CPUはMT 8163である.最初のステップは駆動部の移植であり、Arm Linuxカーネルは3.x DTSを導入する.DTSファイルを修正する必要がある.dts修正部分は元の構成案を参照し、主に2つの部分に分けられ、一部はrootノードの下に直接掛けられ、一部はi 2 c 2コントローラの下に掛けられる.すなわち、1つのGsensor(or GYRO)は、i 2 cバスとplatformバスに同時にi 2 cデバイスとしてマウントされる.原因についてはゆっくり分析します.
/ {
...
cust_gyro@0 {
compatible = "mediatek,mpu6050gy";
i2c_num = <2>;
i2c_addr = <0x68 0 0 0>;
direction = <7>;
power_id = <0xffff>;
power_vol = <0>;
firlen = <0>;
is_batch_supported = <0>;
};
cust_accel@0 {
compatible = "mediatek,mpu6050g";
i2c_num = <2>;
i2c_addr = <0x68 0 0 0>;
direction = <7>;
power_id = <0xffff>;
power_vol = <0>;
firlen = <0>;
is_batch_supported = <0>;
};
...
&i2c2 {
gsensor@68 {
compatible = "mediatek,gsensor";
reg = <0x68>;
};
gyro@69 {
compatible = "mediatek,gyro";
reg = <0x69>;
};
}
ここではacceのみを解析し,gyroの原理は同じである.ソースコード位置kernel-3.18/drivers/misc/mediatek/accelerometer/mpu 6050 g-new/mpu 6050.c.先来init関数
static int __init mpu6050gse_init(void)
{
const char *name = "mediatek,mpu6050g";
hw = get_accel_dts_func(name, hw);
if (!hw)
GSE_ERR("get dts info fail
");
acc_driver_add(&mpu6050_init_info);
return 0;
}
内容は少なく、2つの関数しかありません.先にget_accel_dts_funcはrootノードの下に直接掛けられたdts node属性を読み出してhwに保存する.さらにacc_を通過driver_addはdriverを登録し、次にこの関数を重点的に分析します.この関数はkernel-3.18/drivers/misc/mediatek/accelerometer/accel.cで実現する.
int acc_driver_add(struct acc_init_info *obj)
{
int err = 0;
int i = 0;
if (!obj) {
ACC_ERR("ACC driver add fail, acc_init_info is NULL
");
return -1;
}
for (i = 0; i < MAX_CHOOSE_G_NUM; i++) {
if ((i == 0) && (NULL == gsensor_init_list[0])) {
ACC_LOG("register gensor driver for the first time
");
if (platform_driver_register(&gsensor_driver))
ACC_ERR("failed to register gensor driver already exist
");
}
if (NULL == gsensor_init_list[i]) {
obj->platform_diver_addr = &gsensor_driver;
gsensor_init_list[i] = obj;
break;
}
}
if (i >= MAX_CHOOSE_G_NUM) {
ACC_ERR("ACC driver add err
");
err = -1;
}
return err;
}
中のplatformに注目driver_register、ここではdtsに直接rootの下に掛けられているnodeと一致しますが、i 2 c driverは?焦らないで探し続けましょう.この関数ではgsensor_に注目しますinit_List[i]=obj,我々はgsensorが1つしかないので,ここでのiは0に等しい.objが何なのか見に行きます.mpu 6050 gseでinitはmpu 6050ですinit_infoのアドレスはmpu 6050に戻ります.c
static struct acc_init_info mpu6050_init_info = {
.name = "mpu6050g",
.init = mpu6050_local_init,
.uninit = mpu6050_remove,
};
この構造体のメンバー変数、init、uninitを見てください.これは初期化関数に違いありませんが、どこで実行されますか?前に見た住所がaccelに伝わった.c中、じゃあ、あちらへ行ってみます.accelの初期化関数
static int __init acc_init(void)
{
ACC_LOG("acc_init
");
if (acc_probe()) {
ACC_ERR("failed to register acc driver
");
return -ENODEV;
}
return 0;
}
static int acc_probe(void)
{
int err;
acc_context_obj = acc_context_alloc_object();
if (!acc_context_obj) {
err = -ENOMEM;
ACC_ERR("unable to allocate devobj!
");
goto exit_alloc_data_failed;
}
/* init real acceleration driver */
err = acc_real_driver_init();
if (err) {
ACC_ERR("acc real driver init fail
");
goto real_driver_init_fail;
}
/* init acc common factory mode misc device */
err = acc_factory_device_init();
if (err)
ACC_ERR("acc factory device already registed
");
/* init input dev */
err = acc_input_init(acc_context_obj);
if (err) {
ACC_ERR("unable to register acc input device!
");
goto exit_alloc_input_dev_failed;
}
ACC_LOG("----accel_probe OK !!
");
return 0;
...
}
acc_probe関数はいろいろなことをしてaccに注目しましたreal_driver_Initその他はinput時間報告など、自分で検討することができます
static int acc_real_driver_init(void)
{
int i = 0;
int err = 0;
ACC_LOG(" acc_real_driver_init +
");
for (i = 0; i < MAX_CHOOSE_G_NUM; i++) {
ACC_LOG(" i=%d
", i);
if (0 != gsensor_init_list[i]) {
ACC_LOG(" acc try to init driver %s
", gsensor_init_list[i]->name);
err = gsensor_init_list[i]->init();
if (0 == err) {
ACC_LOG(" acc real driver %s probe ok
",
gsensor_init_list[i]->name);
break;
}
}
}
if (i == MAX_CHOOSE_G_NUM) {
ACC_LOG(" acc_real_driver_init fail
");
err = -1;
}
return err;
}
見つけた!ここではgsensor_を実行しましたinit_list[i]->init()
static int mpu6050_local_init(void)
{
MPU6050_power(hw, 1);
if (i2c_add_driver(&mpu6050g_i2c_driver)) {
GSE_ERR("add driver error
");
return -1;
}
if (-1 == mpu6050_init_flag)
return -1;
return 0;
}
こちらにi 2 c driverが登録されており、platformもi 2 c driverも登録済みで、その後のデータ取得は比較的簡単(i 2 c通信にほかならない)で、貼りません.これでsensorのdriverがオンになり、inputイベント(acc_input_init)が報告され、自分で見ることに興味があり、標準的なinputデバイスフレームワークがセットされ、frameworkに入ります.
frameworkにsensorListenerを登録する
frameworkでは比較的簡単で、android sensor APIを直接呼び出せばよい.
private Sensor mGravitySensor;
private final SensorEventListener mListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
float acceleroX = event.values[0];
float acceleroY = event.values[1];
float acceleroZ = event.values[2];
//do what you want
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
//init
mGravitySensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
//register
if (sensorManager.registerListener(mListener, mGravitySensor,SensorManager.SENSOR_DELAY_NORMAL)){
Slog.e(TAG, "mGravitySensor!!!");
}
こんなに简単にacceのデータを取得することができて、しかしデータを得てどのように使うのがあなた自身を见ます
sensor calibration
一般的に私たちのsensorは工場を出る前に多くの操作をする必要があります.その中にsensorキャリブレーションがあります.ここでmtkプラットフォームにadbを通じてエンジニアリングモードに入ってsensorキャリブレーションを行うコマンドがあります.
adb shell am start -n com.mediatek.engineermode/.EngineerMode
MTKsensorキャリブレーションコードsensorをもう1つ貼ってください.cali