zoukankan      html  css  js  c++  java
  • 修改系统android2.3.4增加gsensor

    工作之余抽点时间出来写写博文,希望对新接触的朋友有帮助。今天在这里和大家一起学习一下修改系统

        转载请注明文章出处和作者!

        出处:http://blog.csdn.net/xl19862005

        作者:大熊(Xandy

        硬件平台:TI DM37XX  
    sensor:lsm330dlc(acc + gyr)
    1、将lsm330dlc驱动代码放到drivers/input/misc目录下,修改此上当下的kconfig和Makefile文件分别增加如下字段:

        Kconfig
    config SENSORS_LSM330DLC 
    tristate "ST's family of MEMS sensor modules of LSM330DLC"
    depends on I2C && INPUT && MACH_ZT6810
    select INPUT_POLLDEV
    default y
    help
    This driver provides support for the LSM330DLC gyroscope and accelerator connected via I2C.

        
    Makefile
    obj-$(CONFIG_SENSORS_LSM330DLC)+= lsm330dlc_acc.o lsm330dlc_gyr.o

        2、对比硬件原理图,修改lsm330dlc.h中的响应中断IO及数据万能IO,如:

        /*Xandy modify the accelerator and gyro interrupt pins @2012/9/12*/
    #define INT1_GPIO_ACC 178
    #define INT2_GPIO_ACC 179  
    #define INT1_GPIO_GYR 181
    #define INT2_GPIO_GYR 180  
    /*Xandy add Sensors enable pin*/
    #define SENSOR_EN_GPIO 38

        3、修改BSP响应文件(既对应的board-xx.c文件),对lsm330dlc进行驱动注册(I2C总线),如:

        #ifdef CONFIG_SENSORS_LSM330DLC
    static struct i2c_board_info __initdata zt6810_i2c_LSM330DLC[] = {
           {
                   I2C_BOARD_INFO("lsm330dlc_acc", 0x19),
           },
           {
          I2C_BOARD_INFO("lsm330dlc_gyr", 0x6B), 
    },
    };
    #endif
    static int __init zt6810_i2c_init(void)
    {
    omap_register_i2c_bus(1, 2600, zt6810_i2c_boardinfo,
    ARRAY_SIZE(zt6810_i2c_boardinfo));
    /* Bus 2 is used for Battery ckeck(bq27410) */
    #ifdef CONFIG_BATTERY_MAX17049
    omap_register_i2c_bus(2, 100, zt6810_i2c_MAX17049, ARRAY_SIZE(zt6810_i2c_MAX17049));
    #else
    omap_register_i2c_bus(2, 100, NULL, 0);
    #endif
    /* projector don't work reliably with 400kHz */
    #ifdef CONFIG_SENSORS_LSM330DLC  
    omap_register_i2c_bus(3, 200, zt6810_i2c_LSM330DLC, ARRAY_SIZE(zt6810_i2c_LSM330DLC));
    #endif
    return 0;
    }

        内核编译通过之后,将uImage烧录到样机,如果不出不测,在串口终端进入响应目录,ls一下将会看到如下内容:

        修改和系统

        修改和系统

        修改和系统

        可以看出acc在I2C总线注册胜利,响应的I2C总线号及address为3-0019,而gyr则为3-006B
    4、在串口终端里输入如下命令:

        # cat /proc/bus/input/devices

        将会失掉如下信息:

        # cat /proc/bus/input/devices
    I: Bus=0019 Vendor=0001 Product=0001 Version=0100
    N: Name="gpio-keys"
    P: Phys=gpio-keys/input0
    S: Sysfs=/devices/platform/gpio-keys/input/input0
    U: Uniq=
    H: Handlers=kbd event0 
    B: EV=3
    B: KEY=4 0 0 0 100000 0 0 0
    I: Bus=0019 Vendor=0001 Product=0001 Version=0003
    N: Name="TWL4030 Keypad"
    P: Phys=twl4030_keypad/input0
    S: Sysfs=/devices/platform/omap/omap_i2c.1/i2c-1/1-004a/twl4030_keypad/input/input1
    U: Uniq=
    H: Handlers=kbd event1 
    B: EV=100013
    B: KEY=800 c1680 0 2000000 100000aa
    B: MSC=10
    I: Bus=0000 Vendor=0000 Product=0000 Version=0000
    N: Name="ADS7846 Touchscreen"
    P: Phys=spi1.0/input0
    S: Sysfs=/devices/platform/omap2_mcspi.1/spi1.0/input/input2
    U: Uniq=
    H: Handlers=mouse0 event2 
    B: EV=b
    B: KEY=400 0 0 0 0 0 0 0 0 0 0
    B: ABS=1000003
    I: Bus=0000 Vendor=0000 Product=0000 Version=0000
    N: Name="twl4030_pwrbutton"
    P: Phys=twl4030_pwrbutton/input0
    S: Sysfs=/devices/platform/omap/omap_i2c.1/i2c-1/1-0049/twl4030_pwrbutton/input/input3
    U: Uniq=
    H: Handlers=kbd event3 
    B: EV=3
    B: KEY=100000 0 0 0
    I: Bus=0018 Vendor=0000 Product=0000 Version=0000
    N: Name="lsm330dlc_acc"
    P: Phys=
    S: Sysfs=/devices/platform/omap/omap_i2c.3/i2c-3/3-0019/input/input4
    U: Uniq=
    H: Handlers=js0 event4 
    B: EV=9
    B: ABS=100 107
    I: Bus=0018 Vendor=0000 Product=0000 Version=0000
    N: Name="lsm330dlc_gyr"
    P: Phys=
    S: Sysfs=/devices/platform/omap/omap_i2c.3/i2c-3/3-006b/input/input5
    U: Uniq=
    H: Handlers=js1 event5 
    B: EV=9
    B: ABS=7

        

        这里列出的是现在系统已经注册的input设备的一些信息,最后两项就是之前加入的sensor(acc + gyr)注册的响应input设备

        为什么sensor会注册成input设备,看看响应的驱动源码里有如下内容:

        static int lsm330dlc_acc_input_init(struct lsm330dlc_acc_data *acc)
    {
    int err;
    INIT_DELAYED_WORK(&acc->input_work, lsm330dlc_acc_input_work_func);
    acc->input_dev = input_allocate_device();
    if (!acc->input_dev) {
    err = -ENOMEM;
    dev_err(&acc->client->dev, "input device allocation failed\n");
    goto err0;
    }
    acc->input_dev->open = lsm330dlc_acc_input_open;
    acc->input_dev->close = lsm330dlc_acc_input_close;
    acc->input_dev->name = LSM330DLC_ACC_DEV_NAME;
    //acc->input_dev->name = "accelerometer";
    acc->input_dev->id.bustype = BUS_I2C;
    acc->input_dev->dev.parent = &acc->client->dev;
    input_set_drvdata(acc->input_dev, acc);
    set_bit(EV_ABS, acc->input_dev->evbit);
    /* next is used for interruptA sources data if the case */
    set_bit(ABS_MISC, acc->input_dev->absbit);
    /* next is used for interruptB sources data if the case */
    set_bit(ABS_WHEEL, acc->input_dev->absbit);
    input_set_abs_params(acc->input_dev, ABS_X, -G_MAX, G_MAX, FUZZ, FLAT);
    input_set_abs_params(acc->input_dev, ABS_Y, -G_MAX, G_MAX, FUZZ, FLAT);
    input_set_abs_params(acc->input_dev, ABS_Z, -G_MAX, G_MAX, FUZZ, FLAT);
    /* next is used for interruptA sources data if the case */
    input_set_abs_params(acc->input_dev, ABS_MISC, INT_MIN, INT_MAX, 0, 0);
    /* next is used for interruptB sources data if the case */
    input_set_abs_params(acc->input_dev, ABS_WHEEL, INT_MIN, INT_MAX, 0, 0);
    err = input_register_device(acc->input_dev);
    if (err) {
    dev_err(&acc->client->dev,
    "unable to register input device %s\n",
    acc->input_dev->name);
    goto err1;
    }
     
    return 0;
    err1:
    input_free_device(acc->input_dev);
    err0:
    return err;
    }

        每日一道理
    喜马拉雅直冲霄汉,可上面有攀爬者的旗帜;撒哈拉沙漠一望无垠,可里头有跋涉者的脚印;阿尔卑斯山壁立千仞,可其中有探险者的身影;雅鲁藏布江湍急浩荡,可其中有勇敢者的故事。

        我们在终端里再输入如下命令:
    # getevent
    将失掉如下信息:
    # getevent
    could not get driver version for /dev/input/mice, Not a typewriter
    add device 1: /dev/input/event2
      name:     "ADS7846 Touchscreen"
    could not get driver version for /dev/input/mouse0, Not a typewriter
    add device 2: /dev/input/event0
      name:     "gpio-keys"
    add device 3: /dev/input/event5
      name:     "lsm330dlc_gyr"
    could not get driver version for /dev/input/js1, Invalid argument
    add device 4: /dev/input/event4
      name:     "lsm330dlc_acc"
    could not get driver version for /dev/input/js0, Invalid argument
    add device 5: /dev/input/event1
      name:     "TWL4030 Keypad"
    add device 6: /dev/input/event3
      name:     "twl4030_pwrbutton"
    /dev/input/event4: 0003 0000 00000001
    /dev/input/event4: 0003 0001 ffffff5f
    /dev/input/event4: 0003 0002 000003df
    /dev/input/event4: 0000 0000 00000000
    /dev/input/event4: 0003 0000 fffffffe
    /dev/input/event4: 0003 0001 ffffff5e
    /dev/input/event4: 0003 0002 000003e2
    /dev/input/event4: 0000 0000 00000000
    /dev/input/event4: 0003 0000 00000002
    /dev/input/event4: 0003 0001 ffffff5d
    /dev/input/event4: 0003 0002 000003e5
    /dev/input/event4: 0000 0000 00000000
    /dev/input/event4: 0003 0000 00000001
    /dev/input/event4: 0003 0001 ffffff5f
    /dev/input/event4: 0003 0002 000003df
    /dev/input/event4: 0000 0000 00000000
    /dev/input/event4: 0003 0000 fffffffe
    /dev/input/event4: 0003 0001 ffffff66
    /dev/input/event4: 0003 0002 000003e4
    ......

        
    getevent命令是用来获取系统输入事件的,很轻易看出,以后系统一直有event4的事件发生,对比上面的信息:
    add device 4: /dev/input/event4
      name:     "lsm330dlc_acc"
    可见前面加入的sensor(acc)已经开始工作了并不停地往系统上报以后的加速度事件!
    如果畸形配置且编译通过了sensor的驱动,但无法失掉这些信息,那么你就有必要查查你的硬件是否畸形了,如:芯片是否是分歧;有无虚焊,最后找个示波器挂一下,看看响应的I2C波形正不畸形!
    5、完成了上面的工作,并不等于完成了全部的工作,现在虽然sensor已经开始工作了,但当你进入到具有重力感到的界面,如:系统设置。
    发明UI现在是不会转动的,或者你下一个sensor测试工具,也是一样的。
    这是因为在HAL里头,还没有打通sensor事件上报的通道,下面来看看HAL里头的代码要如何修改。
    sensor HAL层的代码在
    hardware/ti/omap3/libsensors
    目录下面。
    先来看看sensors.cpp这个文件。这里是sensor进行HAL层封装的,在这里可以看到有
    struct sensors_module_t HAL_MODULE_INFO_SYM = {
            common: {
                    tag: HARDWARE_MODULE_TAG,
                    version_major: 1,
                    version_minor: 0,
                    id: SENSORS_HARDWARE_MODULE_ID,
                    name: "Sensor module",
                    author: "Texas Instruments Inc.",
                    methods: &sensors_module_methods,
            },
            get_sensors_list: sensors__get_sensors_list,
    };
    这是HAL层封装的一个标准结构,我们主要来看看下面这段代码:
    sensors_poll_context_t::sensors_poll_context_t()
    {
    mSensors[accel] = new AccelSensor();
    mPollFds[accel].fd = mSensors[accel]->getFd();
    mPollFds[accel].events = POLLIN;
    mPollFds[accel].revents = 0;
    mSensors[gyro] = new GyroSensor();
    mPollFds[gyro].fd = mSensors[gyro]->getFd();
    mPollFds[gyro].events = POLLIN;
    mPollFds[gyro].revents = 0;
    int wakeFds[2];
    int result = pipe(wakeFds);
    LOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno));
    fcntl(wakeFds[0], F_SETFL, O_NONBLOCK);
    fcntl(wakeFds[1], F_SETFL, O_NONBLOCK);
    mWritePipeFd = wakeFds[1];
    mPollFds[wake].fd = wakeFds[0];
    mPollFds[wake].events = POLLIN;
    mPollFds[wake].revents = 0;
    }
    可以看出,这里new了两个sensor设备,一个是ACC,另外一个则是GYR!进入到accelSensor.cpp,在下面这个构造函数里:
    AccelSensor::AccelSensor()
        : SensorBase(NULL, "lsm330dlc_acc"),
          mEnabled(0),
          mInputReader(4),
          mHasPendingEvent(false)

        memset(&mPendingEvent, 0, sizeof(mPendingEvent));
        mPendingEvent.version = sizeof(sensors_event_t);
        mPendingEvent.sensor = ID_A;
        mPendingEvent.type = SENSOR_TYPE_ACCELEROMETER;
    mPendingEvent.acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
        if (data_fd) 
    {
            strcpy(input_sysfs_path, ACCEL_SENSOR_NAME);
            input_sysfs_path_len = strlen(input_sysfs_path);
            enable(0, 1);
        }
    }




    黄色背景标注的是须要修改的,其中ACCEL_SENSOR_NAME的宏定义响应如下:
    /*Xandy add AccelSensor name and GyroSensor name macro definition*/
    #ifdef CONFIG_SENSOR_LSM330DLC 
    #define ACCEL_SENSOR_NAME"/sys/bus/i2c/drivers/lsm330dlc_acc/3-0019/"
    #define GYRO_SENSOR_NAME "/sys/bus/i2c/drivers/lsm330dlc_gyr/3-006b/"   

    #else
    #define ACCEL_SENSOR_NAME "/sys/bus/i2c/drivers/lis331dlh/1-0018/"
    #define GYRO_SENSOR_NAME "/sys/bus/i2c/drivers/l3g4200dh_i2c/1-0068/" 
    #endif
    其中CONFIG_SENSOR_LSM330DLC这个宏开关我在响应的Android.mk里作了如下定义:
    # Xandy add macro define for accel and gyro sensors
    ifeq ($(SENSOR_LSM330DLC), true)
    LOCAL_CFLAGS += -DCONFIG_SENSOR_LSM330DLC
    endif
    而SENSOR_LSM330DLC则在响应工程(device目录下对应你此时的vendor)的BoardConfig.mk里作如下定义:
    #Xandy add accel and gyro sensors
    BOARD_HAS_SENSOR := true
    SENSOR_LSM330DLC := true
    这些其实都是宏定义及编译开关设置的问题,这样做的目标是方便不同工程(vendor)之间的切换及添加新的设备支撑
    GYR HAL的修改和ACC的一样,这里未几提了!
    经过这些修改之后,用mm编译响应的lib,并将lib通过adb push 到样机的文件系统里对应目录下,重启系统之后如果一切畸形,现在进入到有UI旋转的界面,就会起作用了,
    但是,很有很可此时的旋转方向和你运行的方向是不分歧的,那么你还得修改一下Sensor HAL中sensors.h里头的如下宏:
    #ifdef CONFIG_SENSOR_LSM330DLC
    #define EVENT_TYPE_ACCEL_X          REL_X
    #define EVENT_TYPE_ACCEL_Y          REL_Y
    #define EVENT_TYPE_ACCEL_Z          REL_Z
    #else
    #error you must define ACCEL X Y Z
    #endif 


    #ifdef CONFIG_SENSOR_LSM330DLC
    #define EVENT_TYPE_GYRO_X           REL_X//REL_RX
    #define EVENT_TYPE_GYRO_Y           REL_Y//REL_RY
    #define EVENT_TYPE_GYRO_Z           REL_Z//REL_RZ
    #else
    #error you must define GYRO X Y Z
    #endif 
    修改这些 x、y、z的定义,例如改成如下顺遂:
    #ifdef CONFIG_SENSOR_LSM330DLC
    #define EVENT_TYPE_GYRO_X           REL_Z
    #define EVENT_TYPE_GYRO_Y           REL_X
    #define EVENT_TYPE_GYRO_Z           REL_Y
    #else
    #error you must define GYRO X Y Z
    #endif 
    详细顺遂怎样,根据你的硬件摆放位置来定


    至此sensor的调试就基本上完成了,如果还有什么要修改的,那就是一些微调了,如灵敏度等

    文章结束给大家分享下程序员的一些笑话语录: 很多所谓的牛人也不过如此,离开了你,微软还是微软,Google还是Google,苹果还是苹果,暴雪还是暴雪,而这些牛人离开了公司,自己什么都不是。

  • 相关阅读:
    每天拿出来2小时浪费(文/王路) 作者: 王路
    objective-c自学总结(二)---init/set/get方法
    objective-c自学总结(一)---面向对象
    水仙花数
    独木舟上的旅行
    阶乘之和
    小明的调查统计
    管闲事的小明
    重温《STL源码剖析》笔记 第一章
    重温《STL源码剖析》笔记 第三章
  • 原文地址:https://www.cnblogs.com/jiangu66/p/3076746.html
Copyright © 2011-2022 走看看