您的位置:首页 > 移动开发 > Android开发

android2.3.4增加gsensor

2013-05-13 11:24 381 查看
转载请注明文章出处和作者!

出处: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的调试就基本上完成了,如果还有什么要修改的,那就是一些微调了,如灵敏度等
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  android sensor