Androidセンサー分析

12556 ワード

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デバイスとしてマウントされる.原因についてはゆっくり分析します.
    / {
        ...
        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