我是靠谱客的博主 隐形荷花,最近开发中收集的这篇文章主要介绍Android Sensor分析Android Sensor分析,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Android Sensor分析

目标:检测device的状态

  • 非法状态关闭光机
  • 非法移动关闭手势

步骤分为三步:

  • 1.sensor移植(accelerometer and gyro)
  • 2.framework中注册sensorListenor
  • 3.sensor calibration

sensor移植

本文基于Linux3.18,CPU为MT8163.
第一步是驱动部分的移植,Arm Linux内核从3.x引入DTS.所以需要修改DTS文件. dts修改部分参照原来的配置方案,主要分为两部分,一部分直接挂在root节点下,一部分挂在i2c2控制器下。也就是说,一个Gsensor(or GYRO)会同时作为i2c device和platform device挂载到i2c总线和platform总线上。 至于原因下面慢慢分析。

/ {
    ...
    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/mpu6050g-new/mpu6050.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 failn");

    acc_driver_add(&mpu6050_init_info);
    return 0;
}

内容很少,只有两个函数。先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 NULLn");
        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 timen");
            if (platform_driver_register(&gsensor_driver))
                ACC_ERR("failed to register gensor driver already existn");
        }

        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 errn");
        err = -1;
    }

    return err;
}

关注里面的platform_driver_register,这里就是会和dts中直接挂在root下的node匹配了,那么i2c driver呢?不要急我们继续找。这个函数中关注一下gsensor_init_list[i] = obj,我们只有一个gsensor,所以这里的i等于0.去瞅瞅obj是个什么东东。在mpu6050gse_init看到是mpu6050_init_info的地址,那么我们回到mpu6050.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_initn");

    if (acc_probe()) {
        ACC_ERR("failed to register acc drivern");
        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!n");
        goto exit_alloc_data_failed;
    }
    /* init real acceleration driver */
    err = acc_real_driver_init();
    if (err) {
        ACC_ERR("acc real driver init failn");
        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 registedn");
    /* init input dev */
    err = acc_input_init(acc_context_obj);
    if (err) {
        ACC_ERR("unable to register acc input device!n");
        goto exit_alloc_input_dev_failed;
    }

    ACC_LOG("----accel_probe OK !!n");
    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 +n");
    for (i = 0; i < MAX_CHOOSE_G_NUM; i++) {
        ACC_LOG(" i=%dn", i);
        if (0 != gsensor_init_list[i]) {
            ACC_LOG(" acc try to init driver %sn", gsensor_init_list[i]->name);
            err = gsensor_init_list[i]->init();
            if (0 == err) {
                ACC_LOG(" acc real driver %s probe okn",
                    gsensor_init_list[i]->name);
                break;
            }
        }
    }

    if (i == MAX_CHOOSE_G_NUM) {
        ACC_LOG(" acc_real_driver_init failn");
        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 errorn");
        return -1;
    }
    if (-1 == mpu6050_init_flag)
        return -1;

    return 0;
}

这边注册了i2c driver,至此platform和i2c driver都已经注册完成,之后的数据获取比较简单(无非就是i2c通信),就不贴了。至此,sensor的driver已经调通,并且会上报input事件(acc_input_init),有兴趣自己瞅瞅,标准的input设备框架套用,下面进入framework

framework中注册sensorListenor

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_cali

最后

以上就是隐形荷花为你收集整理的Android Sensor分析Android Sensor分析的全部内容,希望文章能够帮你解决Android Sensor分析Android Sensor分析所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部