android传感器(sensor)分析(以mma8451重力感应器为基础)
转载地址:http://blog.csdn.net/dkleikesa/article/details/9532869
传感器是现在手机上不可或缺的的一部分,到了android4.0系统总共支持13类的传感器分别为
- #define SENSOR_TYPE_ACCELEROMETER 1
- #define SENSOR_TYPE_MAGNETIC_FIELD 2
- #define SENSOR_TYPE_ORIENTATION 3
- #define SENSOR_TYPE_GYROSCOPE 4
- #define SENSOR_TYPE_LIGHT 5
- #define SENSOR_TYPE_PRESSURE 6
- #define SENSOR_TYPE_TEMPERATURE 7
- #define SENSOR_TYPE_PROXIMITY 8
- #define SENSOR_TYPE_GRAVITY 9
- #define SENSOR_TYPE_LINEAR_ACCELERATION 10
- #define SENSOR_TYPE_ROTATION_VECTOR 11
- #define SENSOR_TYPE_RELATIVE_HUMIDITY 12
- #define SENSOR_TYPE_AMBIENT_TEMPERATURE 13
#define SENSOR_TYPE_ACCELEROMETER 1
#define SENSOR_TYPE_MAGNETIC_FIELD 2
#define SENSOR_TYPE_ORIENTATION 3
#define SENSOR_TYPE_GYROSCOPE 4
#define SENSOR_TYPE_LIGHT 5
#define SENSOR_TYPE_PRESSURE 6
#define SENSOR_TYPE_TEMPERATURE 7
#define SENSOR_TYPE_PROXIMITY 8
#define SENSOR_TYPE_GRAVITY 9
#define SENSOR_TYPE_LINEAR_ACCELERATION 10
#define SENSOR_TYPE_ROTATION_VECTOR 11
#define SENSOR_TYPE_RELATIVE_HUMIDITY 12
#define SENSOR_TYPE_AMBIENT_TEMPERATURE 13
对于这么多类别的传感器,android提供一个统一的架构来方便开发者使用。我们下面就要来分析这个架构。
本文以飞思卡尔mma8451 三轴重力感应器为基础来分析的。传感器架构遵循了标准的android架构,包括应用程序层-> framework层->jni层->hal层->内核空间->设备驱动。
对于应用程序层,framework层和jni层我们仅仅做简单的介绍,重点放在分析hal层、内核空间和驱动中,因为作为一个驱动工程师这才是重点!
二、架构分析
1.应用程序层
从网上找到一个Android应用程序访问传感器的方法,流程如下
- //1、取得重力感应器Sensor对象
- //在 Activity 中定义以下成员变量:
- private SensorManager mManager = null;
- private Sensor mSensor = null;
- //以下代码加入到 onCreate() 方法中:
- mManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); //创建SensorManager
- mSensor = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);//得到重力感应器
- //2、创建监听器
- //在 Activity 中定义以下成员变量:
- private SensorEventListener mListener = null;
- //以下代码加入到 onCreate() 方法中:
- mListener = new SensorEventListener() {
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- public void onSensorChanged(SensorEvent event) {
- float x = event.values[SensorManager.DATA_X];
- float y = event.values[SensorManager.DATA_Y];
- float z = event.values[SensorManager.DATA_Z];
- doSomething(x, y, z);
- }
- };
- //3、注册监听器
- //以下代码加入到 onResume() 方法中:
- mManager.registerListener(mListener, mSensor, SensorManager.SENSOR_DELAY_GAME);
- //这里 SENSOR_DELAY_GAME 还可以是以下常量:
- //SENSOR_DELAY_FASTEST
- //SENSOR_DELAY_UI
- //SENSOR_DELAY_NORMAL
- //4、取消监听器
- //以下代码加入到 onPause() 方法中:
- mManager.unregisterListener(mListener);
- 参考:http://www.oschina.net/code/snippet_12_687
//1、取得重力感应器Sensor对象
//在 Activity 中定义以下成员变量:
private SensorManager mManager = null;
private Sensor mSensor = null;
//以下代码加入到 onCreate() 方法中:
mManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE); //创建SensorManager
mSensor = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);//得到重力感应器
//2、创建监听器
//在 Activity 中定义以下成员变量:
private SensorEventListener mListener = null;
//以下代码加入到 onCreate() 方法中:
mListener = new SensorEventListener() {
public void onAccuracyChanged(Sensor sensor, int accuracy) {
public void onSensorChanged(SensorEvent event) {
float x = event.values[SensorManager.DATA_X];
float y = event.values[SensorManager.DATA_Y];
float z = event.values[SensorManager.DATA_Z];
doSomething(x, y, z);
}
};
//3、注册监听器
//以下代码加入到 onResume() 方法中:
mManager.registerListener(mListener, mSensor, SensorManager.SENSOR_DELAY_GAME);
//这里 SENSOR_DELAY_GAME 还可以是以下常量:
//SENSOR_DELAY_FASTEST
//SENSOR_DELAY_UI
//SENSOR_DELAY_NORMAL
//4、取消监听器
//以下代码加入到 onPause() 方法中:
mManager.unregisterListener(mListener);
参考:http://www.oschina.net/code/snippet_12_687
从上面流程来看,首先我们要获取sensorservice,然后创建一个SensorManager,再从SensorManager从获取到具体传感器
最后创建一个监听来监听这个传感器的事件。因此下面来看framework层。
2.framework层
SensorService代码在android\frameworks\base\services\sensorservice\SensorService.cpp中,
app中通过getSystemService()方法可以访问到getSystemService
SensorManager代码在android\frameworks\base\core\Java\android\hardware\SensorManager.java中,
他是sensor事件的总管理器,包括打开设备读取事件 分发事件等功能
3jni层
jni层主要包含两个文件
android\frameworks\base\core\jni\android_hardware_SensorManager.cpp//主要是method的注册,为java提供下层访问接口
android\frameworks\base\services\sensorservice\SensorDevice.cpp//主要是动态链接库访问,jni层和hal层访问方式是通过
动态链接库来实现的,这个文件里实现了动态链接库的打开,和访问函数封装等一些操作
4.hal层
在这个层里,我们主要就分析动态链接库的实现的主要功能有哪些
这个库实现代码在android\hardware\imx\libsensors\sensors.cpp中它的入口代码为:
- struct sensors_module_t HAL_MODULE_INFO_SYM = {
- common: {
- tag: HARDWARE_MODULE_TAG,
- version_major: 1,
- version_minor: 1,
- id: SENSORS_HARDWARE_MODULE_ID,
- name: "Freescale Sensor module",
- author: "Freescale Semiconductor Inc.",
- methods: &sensors_module_methods,//链接库的操作集
- },
- get_sensors_list: sensors__get_sensors_list, //sensorlist实现
- };
struct sensors_module_t HAL_MODULE_INFO_SYM = {
common: {
tag: HARDWARE_MODULE_TAG,
version_major: 1,
version_minor: 1,
id: SENSORS_HARDWARE_MODULE_ID,
name: "Freescale Sensor module",
author: "Freescale Semiconductor Inc.",
methods: &sensors_module_methods,//链接库的操作集
},
get_sensors_list: sensors__get_sensors_list, //sensorlist实现
};
从上面可以看出上层访问sensor的话主要的是两个,一是操作集sensors_module_methods,一个是sensorlist我们分别来看
首先是sensorlist
- static int sensors__get_sensors_list(struct sensors_module_t* module,
- struct sensor_t const** list)
- {
- *list = sSensorList;
- return ARRAY_SIZE(sSensorList);
- }
- static const struct sensor_t sSensorList[] = {
- { "MMA 3-axis Accelerometer",
- "Freescale Semiconductor Inc.",
- 1, SENSORS_ACCELERATION_HANDLE,
- SENSOR_TYPE_ACCELEROMETER, RANGE_A, CONVERT_A, 0.30f, 20000, { } },
- { "MAG3110 3-axis Magnetic field sensor",
- "Freescale Semiconductor Inc.",
- 1, SENSORS_MAGNETIC_FIELD_HANDLE,
- SENSOR_TYPE_MAGNETIC_FIELD, 1500.0f, CONVERT_M, 0.50f, 100000, { } },
- { "MAG3110 Orientation sensor",
- "Freescale Semiconductor Inc.",
- 1, SENSORS_ORIENTATION_HANDLE,
- SENSOR_TYPE_ORIENTATION, 360.0f, CONVERT_O, 0.50f, 100000, { } },
- { "MPL3115 Pressure sensor",
- "Freescale Semiconductor Inc.",
- 1, SENSORS_PRESSURE_HANDLE,
- SENSOR_TYPE_PRESSURE, 1100.0f, CONVERT_PRESSURE, 0.35f, 0, { } },
- { "MPL3115 Temperature sensor",
- "Freescale Semiconductor Inc.",
- 1, SENSORS_TEMPERATURE_HANDLE,
- SENSOR_TYPE_TEMPERATURE, 85.0f, CONVERT_TEMPERATURE, 0.35f, 0, { } },
- { "ISL29023 Light sensor",
- "Intersil",
- 1, SENSORS_LIGHT_HANDLE,
- SENSOR_TYPE_LIGHT, 16000.0f, 1.0f, 0.35f, 0, { } },
- };
static int sensors__get_sensors_list(struct sensors_module_t* module,
struct sensor_t const** list)
{
*list = sSensorList;
return ARRAY_SIZE(sSensorList);
}
static const struct sensor_t sSensorList[] = {
{ "MMA 3-axis Accelerometer",
"Freescale Semiconductor Inc.",
1, SENSORS_ACCELERATION_HANDLE,
SENSOR_TYPE_ACCELEROMETER, RANGE_A, CONVERT_A, 0.30f, 20000, { } },
{ "MAG3110 3-axis Magnetic field sensor",
"Freescale Semiconductor Inc.",
1, SENSORS_MAGNETIC_FIELD_HANDLE,
SENSOR_TYPE_MAGNETIC_FIELD, 1500.0f, CONVERT_M, 0.50f, 100000, { } },
{ "MAG3110 Orientation sensor",
"Freescale Semiconductor Inc.",
1, SENSORS_ORIENTATION_HANDLE,
SENSOR_TYPE_ORIENTATION, 360.0f, CONVERT_O, 0.50f, 100000, { } },
{ "MPL3115 Pressure sensor",
"Freescale Semiconductor Inc.",
1, SENSORS_PRESSURE_HANDLE,
SENSOR_TYPE_PRESSURE, 1100.0f, CONVERT_PRESSURE, 0.35f, 0, { } },
{ "MPL3115 Temperature sensor",
"Freescale Semiconductor Inc.",
1, SENSORS_TEMPERATURE_HANDLE,
SENSOR_TYPE_TEMPERATURE, 85.0f, CONVERT_TEMPERATURE, 0.35f, 0, { } },
{ "ISL29023 Light sensor",
"Intersil",
1, SENSORS_LIGHT_HANDLE,
SENSOR_TYPE_LIGHT, 16000.0f, 1.0f, 0.35f, 0, { } },
};
从这里可以看出getsensorlist就是得到我们预先写好的一个结构体数据的指针.这个数组是根据我们硬件的情况来的
根据不同的平台需要不同的裁剪的修改。
然后来看sensors_module_methods传感器操作集
- static struct hw_module_methods_t sensors_module_methods = {
- open: open_sensors
- };
- static int open_sensors(const struct hw_module_t* module, const char* id,
- struct hw_device_t** device)
- {
- int status = -EINVAL;
- sensors_poll_context_t *dev = new sensors_poll_context_t();
- memset(&dev->device, 0, sizeof(sensors_poll_device_t));
- dev->device.common.tag = HARDWARE_DEVICE_TAG;
- dev->device.common.version = 0;
- dev->device.common.module = const_cast<hw_module_t*>(module);
- dev->device.common.close = poll__close;
- dev->device.activate = poll__activate;
- dev->device.setDelay = poll__setDelay;
- dev->device.poll = poll__poll;
- *device = &dev->device.common;
- status = 0;
- return status;
- }
static struct hw_module_methods_t sensors_module_methods = {
open: open_sensors
};
static int open_sensors(const struct hw_module_t* module, const char* id,
struct hw_device_t** device)
{
int status = -EINVAL;
sensors_poll_context_t *dev = new sensors_poll_context_t();
memset(&dev->device, 0, sizeof(sensors_poll_device_t));
dev->device.common.tag = HARDWARE_DEVICE_TAG;
dev->device.common.version = 0;
dev->device.common.module = const_cast<hw_module_t*>(module);
dev->device.common.close = poll__close;
dev->device.activate = poll__activate;
dev->device.setDelay = poll__setDelay;
dev->device.poll = poll__poll;
*device = &dev->device.common;
status = 0;
return status;
}
从上面可以看出一个传感器dev的操作有最终有4个:poll__close、poll__activate、poll__setDelay、poll__poll
我们来看这四个函数分别实现什么功能
- static int poll__close(struct hw_device_t *dev) //直接删除设备上下文
- {
- sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
- if (ctx) {
- delete ctx;
- }
- return 0;
- }
- static int poll__activate(struct sensors_poll_device_t *dev,
- int handle, int enabled) {
- sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
- return ctx->activate(handle, enabled);
- } |
- V
- int sensors_poll_context_t::activate(int handle, int enabled) {
- int index = handleToDriver(handle);
- int err = 0 ;
- if (index < 0) return index;
- if(handle == ID_O || handle == ID_M){
- err = mSensors[accel]->enable(ID_A, enabled);
- if(err)
- return err;
- }
- err |= mSensors[index]->enable(handle, enabled);
- if (enabled && !err) {
- const char wakeMessage(WAKE_MESSAGE);
- int result = write(mWritePipeFd, &wakeMessage, 1);
- LOGE_IF(result<0, "error sending wake message (%s)", strerror(errno));
- }
- return err;
- }
static int poll__close(struct hw_device_t *dev) //直接删除设备上下文
{
sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
if (ctx) {
delete ctx;
}
return 0;
}
static int poll__activate(struct sensors_poll_device_t *dev,
int handle, int enabled) {
sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
return ctx->activate(handle, enabled);
} |
V
int sensors_poll_context_t::activate(int handle, int enabled) {
int index = handleToDriver(handle);
int err = 0 ;
if (index < 0) return index;
if(handle == ID_O || handle == ID_M){
err = mSensors[accel]->enable(ID_A, enabled);
if(err)
return err;
}
err |= mSensors[index]->enable(handle, enabled);
if (enabled && !err) {
const char wakeMessage(WAKE_MESSAGE);
int result = write(mWritePipeFd, &wakeMessage, 1);
LOGE_IF(result<0, "error sending wake message (%s)", strerror(errno));
}
return err;
}
//注意这里的mSensors的定义为SensorBase* mSensors;也就是说这是SensorBase这个类的一个实例化那么enable这个桉树应该在SensorBase类里实现的
代码在android\hardware\imx\libsensors\SensorBase.cpp中
- int SensorBase::enable(int32_t handle, int enabled)
- {
- sensorBaseEnable(handle,enabled);
- return 0;
- }
- int SensorBase::sensorBaseEnable(int32_t handle,int enabled){
- 。。。。。。。。。。。。。
- if((enable && mUser[what] == 1) || (enable ==0 && mUser[what] == 0 )) {
- snprintf(buf,sizeof(buf),"%d",enable);
- write_sysfs(sysfs_enable,buf,strlen(buf)); //向sysfs文件系统中写入数据,这里涉及到了文件系统的操作进入了内核空间。
- mEnabled &= ~(1<<what);
- mEnabled |= (uint32_t(enable)<<what);
- }
- 。。。。。。。。。。。。。。
- }
- static int poll__setDelay(struct sensors_poll_device_t *dev,
- int handle, int64_t ns) {
- sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
- return ctx->setDelay(handle, ns);
- } |
- V
- int SensorBase::sensorBaseSetDelay(int32_t handle, int64_t ns){
- char buf[6];
- int ms;
- ms = ns/1000/1000;
- if(ms < mMinPollDelay)
- ms = mMinPollDelay ;
- else if(ms > mMaxPollDelay)
- ms = mMaxPollDelay;
- snprintf(buf,sizeof(buf),"%d",ms);
- return write_sysfs(sysfs_poll,buf,strlen(buf)); //想文件系统中写入数据 进入内核空间
- }
- static int poll__poll(struct sensors_poll_device_t *dev,
- sensors_event_t* data, int count) {
- sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
- return ctx->pollEvents(data, count);
- } |
- V
- static int poll__poll(struct sensors_poll_device_t *dev,
- sensors_event_t* data, int count) {
- sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
- return ctx->pollEvents(data, count);
- }
- 我们来看pollEvents这个函数实现了设备事件的读取
- int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
- {
- int nbEvents = 0;
- int n = 0;
- do {
- // see if we have some leftover from the last poll()
- for (int i=0 ; count && i<numSensorDrivers ; i++) { //循环读取所有sensorlist中设备的event
- SensorBase* const sensor(mSensors[i]);
- if ((mPollFds[i].revents & POLLIN) || (sensor->hasPendingEvents())) {
- int nb = sensor->readEvents(data, count); //读取事件
- if (nb < count) {
- // no more data for this sensor
- mPollFds[i].revents = 0;
- }
- count -= nb;
- nbEvents += nb;
- data += nb;
- }
- }
- 。。。。。。。。。。。。。。。。
- return nbEvents;
- }
- 继续看
- int SensorBase::readEvents(sensors_event_t* data, int count)
- {
- 。。。。。。
- ssize_t n = mInputReader.fill(data_fd); //填充eventbuf
- //mInputReader代码在android\hardware\imx\libsensors\InputEventReader.cpp中这个类,在这里就不多做分析了,
- //内容比较简单,就是从设备文件中读取数据然后进行一定的处理传送给上层
- 。。。。。。。。
- for (int j=0 ; count && mPendingMask && j<numSensors ; j++) {
- if (mPendingMask & (1<<j)) {
- mPendingMask &= ~(1<<j);
- mPendingEvents[j].timestamp = time;
- if (mEnabled & (1<<j)) {
- *data++ = mPendingEvents[j]; //数据复制到buf中
- count--;
- numEventReceived++;
- }
- }
- }
- 。。。。。。。。。。
- return numEventReceived; //返回读数个数
- }
int SensorBase::enable(int32_t handle, int enabled)
{
sensorBaseEnable(handle,enabled);
return 0;
}
int SensorBase::sensorBaseEnable(int32_t handle,int enabled){
。。。。。。。。。。。。。
if((enable && mUser[what] == 1) || (enable ==0 && mUser[what] == 0 )) {
snprintf(buf,sizeof(buf),"%d",enable);
write_sysfs(sysfs_enable,buf,strlen(buf)); //向sysfs文件系统中写入数据,这里涉及到了文件系统的操作进入了内核空间。
mEnabled &= ~(1<<what);
mEnabled |= (uint32_t(enable)<<what);
}
。。。。。。。。。。。。。。
}
static int poll__setDelay(struct sensors_poll_device_t *dev,
int handle, int64_t ns) {
sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
return ctx->setDelay(handle, ns);
} |
V
int SensorBase::sensorBaseSetDelay(int32_t handle, int64_t ns){
char buf[6];
int ms;
ms = ns/1000/1000;
if(ms < mMinPollDelay)
ms = mMinPollDelay ;
else if(ms > mMaxPollDelay)
ms = mMaxPollDelay;
snprintf(buf,sizeof(buf),"%d",ms);
return write_sysfs(sysfs_poll,buf,strlen(buf)); //想文件系统中写入数据 进入内核空间
}
static int poll__poll(struct sensors_poll_device_t *dev,
sensors_event_t* data, int count) {
sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
return ctx->pollEvents(data, count);
} |
V
static int poll__poll(struct sensors_poll_device_t *dev,
sensors_event_t* data, int count) {
sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
return ctx->pollEvents(data, count);
}
我们来看pollEvents这个函数实现了设备事件的读取
int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
{
int nbEvents = 0;
int n = 0;
do {
// see if we have some leftover from the last poll()
for (int i=0 ; count && i<numSensorDrivers ; i++) { //循环读取所有sensorlist中设备的event
SensorBase* const sensor(mSensors[i]);
if ((mPollFds[i].revents & POLLIN) || (sensor->hasPendingEvents())) {
int nb = sensor->readEvents(data, count); //读取事件
if (nb < count) {
// no more data for this sensor
mPollFds[i].revents = 0;
}
count -= nb;
nbEvents += nb;
data += nb;
}
}
。。。。。。。。。。。。。。。。
return nbEvents;
}
继续看
int SensorBase::readEvents(sensors_event_t* data, int count)
{
。。。。。。
ssize_t n = mInputReader.fill(data_fd); //填充eventbuf
//mInputReader代码在android\hardware\imx\libsensors\InputEventReader.cpp中这个类,在这里就不多做分析了,
//内容比较简单,就是从设备文件中读取数据然后进行一定的处理传送给上层
。。。。。。。。
for (int j=0 ; count && mPendingMask && j<numSensors ; j++) {
if (mPendingMask & (1<<j)) {
mPendingMask &= ~(1<<j);
mPendingEvents[j].timestamp = time;
if (mEnabled & (1<<j)) {
*data++ = mPendingEvents[j]; //数据复制到buf中
count--;
numEventReceived++;
}
}
}
。。。。。。。。。。
return numEventReceived; //返回读数个数
}
从上面可以看出这个函数是将event的数据复制到 data这个buf中然后返回,我们仔细看这里的一个参数data_fd
这是event读取的关键,它是初始化是在SensorBase的构造函数中:
- SensorBase::SensorBase(
- const char* dev_name, //打开的设备文件的名字
- const char* data_name)
- : dev_name(dev_name), data_name(data_name),
- dev_fd(-1), data_fd(-1),
- mInputReader(64)
- {
- if (data_name)
- data_fd = openInput(data_name);
- } |
- |
- V
- int SensorBase::openInput(const char* inputName)
- {
- int fd = -1;
- int input_id = -1;
- const char *dirname = "/dev/input";
- const char *inputsysfs = "/sys/class/input";
- char devname[PATH_MAX];
- char *filename;
- DIR *dir;
- struct dirent *de;
- dir = opendir(dirname);
- if(dir == NULL)
- return -1;
- strcpy(devname, dirname);
- filename = devname + strlen(devname);
- *filename++ = '/';
- while((de = readdir(dir))) {
- if(de->d_name[0] == '.' &&
- (de->d_name[1] == '\0' ||
- (de->d_name[1] == '.' && de->d_name[2] == '\0')))
- continue;
- strcpy(filename, de->d_name);
- fd = open(devname, O_RDONLY); //这里涉及到打开设备文件
- 。。。。。。。。。。。。。。。。。。。。。。。。
- }
- closedir(dir);
- LOGE_IF(fd<0, "couldn't find '%s' input device", inputName);
- return fd;
- }
SensorBase::SensorBase(
const char* dev_name, //打开的设备文件的名字
const char* data_name)
: dev_name(dev_name), data_name(data_name),
dev_fd(-1), data_fd(-1),
mInputReader(64)
{
if (data_name)
data_fd = openInput(data_name);
} |
|
V
int SensorBase::openInput(const char* inputName)
{
int fd = -1;
int input_id = -1;
const char *dirname = "/dev/input";
const char *inputsysfs = "/sys/class/input";
char devname[PATH_MAX];
char *filename;
DIR *dir;
struct dirent *de;
dir = opendir(dirname);
if(dir == NULL)
return -1;
strcpy(devname, dirname);
filename = devname + strlen(devname);
*filename++ = '/';
while((de = readdir(dir))) {
if(de->d_name[0] == '.' &&
(de->d_name[1] == '\0' ||
(de->d_name[1] == '.' && de->d_name[2] == '\0')))
continue;
strcpy(filename, de->d_name);
fd = open(devname, O_RDONLY); //这里涉及到打开设备文件
。。。。。。。。。。。。。。。。。。。。。。。。
}
closedir(dir);
LOGE_IF(fd<0, "couldn't find '%s' input device", inputName);
return fd;
}
到了这里hal层的分析已经完成了,总结一下:当android上层打开这个动态链接库的时候,sensors_poll_context_t这个类会
自动对每个sensor进行例化,然后打开所有的sensor。当上层访问PollEvent时,就会直接将读取到的event返回给上层。hal层
对内核设备文件的访问,并不是标准的接口,而是厂家自己规定的,因此要访问不同的设备,还要根据驱动的不同配合着来
5.kernel层
对于kernel的input系统分析,我们前边有篇文章专门介绍过http://blog.csdn.NET/dkleikesa/article/details/9384009大家可以参考
6.内核驱动
剩下的主要是设备驱动。在kernel中传感器设备都是hwmon类的,hwmon全名hardware monitor,是Linux规定的硬件监测的设备类,这个类为我们提供了,设备文件和设备属性设定的通用方法,不过在freescale的android平台中貌似都没用到,这个平台android层和kernel层是通过input设备来通信的,下面 我们以mma8451三轴重力感应器为例子来讲述sensor驱动的具体写法
mma8451是一款i2c接口的传感器,驱动的整体架构也是跟其他i2c设备一样的,因此我们重点来开 probe 和 event发送的函数
- static int __devinit mma8451_probe(struct i2c_client *client,
- const struct i2c_device_id *id)
- {
- int result, client_id;
- struct input_dev *idev;
- struct i2c_adapter *adapter;
- mma8451_i2c_client = client;
- adapter = to_i2c_adapter(client->dev.parent);
- result = i2c_check_functionality(adapter, //检测此i2c设备是否支持I2C_FUNC_SMBUS_BYTE和I2C_FUNC_SMBUS_BYTE_DATA这两个属性
- I2C_FUNC_SMBUS_BYTE |
- I2C_FUNC_SMBUS_BYTE_DATA);
- if (!result)
- goto err_out;
- client_id = i2c_smbus_read_byte_data(client, MMA8451_WHO_AM_I);//读ID
- if (client_id != MMA8451_ID && client_id != MMA8452_ID
- && client_id != MMA8453_ID) {
- dev_err(&client->dev,
- "read chip ID 0x%x is not equal to 0x%x or 0x%x!\n",
- result, MMA8451_ID, MMA8452_ID);
- result = -EINVAL;
- goto err_out;
- }
- /* Initialize the MMA8451 chip */
- result = mma8451_change_mode(client, senstive_mode); //初始化mma8451 就是配置一些寄存器
- if (result) {
- dev_err(&client->dev,
- "error when init mma8451 chip:(%d)\n", result);
- goto err_out;
- }
- hwmon_dev = hwmon_device_register(&client->dev);//创建一个硬件监听设备
- if (!hwmon_dev) {
- result = -ENOMEM;
- dev_err(&client->dev, "error when register hwmon device\n");
- goto err_out;
- }
- mma8451_idev = input_allocate_polled_device(); //分配一个poll类型的input设备
- if (!mma8451_idev) {
- result = -ENOMEM;
- dev_err(&client->dev, "alloc poll device failed!\n");
- goto err_alloc_poll_device;
- }
- mma8451_idev->poll = mma8451_dev_poll;//poll回调函数
- mma8451_idev->poll_interval = POLL_INTERVAL;
- mma8451_idev->poll_interval_min = POLL_INTERVAL_MIN;
- mma8451_idev->poll_interval_max = POLL_INTERVAL_MAX;
- idev = mma8451_idev->input;
- idev->name = "mma845x";//这个名字必须和hal层的名字对应上否则找不到设备文件
- idev->id.bustype = BUS_I2C;
- idev->evbit[0] = BIT_MASK(EV_ABS);
- input_set_abs_params(idev, ABS_X, -8192, 8191, INPUT_FUZZ, INPUT_FLAT); //设备支持的3个数据
- input_set_abs_params(idev, ABS_Y, -8192, 8191, INPUT_FUZZ, INPUT_FLAT);
- input_set_abs_params(idev, ABS_Z, -8192, 8191, INPUT_FUZZ, INPUT_FLAT);
- result = input_register_polled_device(mma8451_idev);//注册这个poll设备
- if (result) {
- dev_err(&client->dev, "register poll device failed!\n");
- goto err_register_polled_device;
- }
- result = sysfs_create_group(&idev->dev.kobj, &mma8451_attr_group);//为这个设备创建sysfs 设备文件
- if (result) {
- dev_err(&client->dev, "create device file failed!\n");
- result = -EINVAL;
- goto err_register_polled_device;
- }
- mma_status.position = *(int *)client->dev.platform_data;
- return 0;
- err_register_polled_device:
- input_free_polled_device(mma8451_idev);
- err_alloc_poll_device:
- hwmon_device_unregister(&client->dev);
- err_out:
- return result;
- }
static int __devinit mma8451_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
int result, client_id;
struct input_dev *idev;
struct i2c_adapter *adapter;
mma8451_i2c_client = client;
adapter = to_i2c_adapter(client->dev.parent);
result = i2c_check_functionality(adapter, //检测此i2c设备是否支持I2C_FUNC_SMBUS_BYTE和I2C_FUNC_SMBUS_BYTE_DATA这两个属性
I2C_FUNC_SMBUS_BYTE |
I2C_FUNC_SMBUS_BYTE_DATA);
if (!result)
goto err_out;
client_id = i2c_smbus_read_byte_data(client, MMA8451_WHO_AM_I);//读ID
if (client_id != MMA8451_ID && client_id != MMA8452_ID
&& client_id != MMA8453_ID) {
dev_err(&client->dev,
"read chip ID 0x%x is not equal to 0x%x or 0x%x!\n",
result, MMA8451_ID, MMA8452_ID);
result = -EINVAL;
goto err_out;
}
/* Initialize the MMA8451 chip */
result = mma8451_change_mode(client, senstive_mode); //初始化mma8451 就是配置一些寄存器
if (result) {
dev_err(&client->dev,
"error when init mma8451 chip:(%d)\n", result);
goto err_out;
}
hwmon_dev = hwmon_device_register(&client->dev);//创建一个硬件监听设备
if (!hwmon_dev) {
result = -ENOMEM;
dev_err(&client->dev, "error when register hwmon device\n");
goto err_out;
}
mma8451_idev = input_allocate_polled_device(); //分配一个poll类型的input设备
if (!mma8451_idev) {
result = -ENOMEM;
dev_err(&client->dev, "alloc poll device failed!\n");
goto err_alloc_poll_device;
}
mma8451_idev->poll = mma8451_dev_poll;//poll回调函数
mma8451_idev->poll_interval = POLL_INTERVAL;
mma8451_idev->poll_interval_min = POLL_INTERVAL_MIN;
mma8451_idev->poll_interval_max = POLL_INTERVAL_MAX;
idev = mma8451_idev->input;
idev->name = "mma845x";//这个名字必须和hal层的名字对应上否则找不到设备文件
idev->id.bustype = BUS_I2C;
idev->evbit[0] = BIT_MASK(EV_ABS);
input_set_abs_params(idev, ABS_X, -8192, 8191, INPUT_FUZZ, INPUT_FLAT); //设备支持的3个数据
input_set_abs_params(idev, ABS_Y, -8192, 8191, INPUT_FUZZ, INPUT_FLAT);
input_set_abs_params(idev, ABS_Z, -8192, 8191, INPUT_FUZZ, INPUT_FLAT);
result = input_register_polled_device(mma8451_idev);//注册这个poll设备
if (result) {
dev_err(&client->dev, "register poll device failed!\n");
goto err_register_polled_device;
}
result = sysfs_create_group(&idev->dev.kobj, &mma8451_attr_group);//为这个设备创建sysfs 设备文件
if (result) {
dev_err(&client->dev, "create device file failed!\n");
result = -EINVAL;
goto err_register_polled_device;
}
mma_status.position = *(int *)client->dev.platform_data;
return 0;
err_register_polled_device:
input_free_polled_device(mma8451_idev);
err_alloc_poll_device:
hwmon_device_unregister(&client->dev);
err_out:
return result;
}
从这个函数可知,重力感应器是属于poll类型的设备,不是普通的input设备,event格式走的是标准的input_event格式,但是只有
EV_ABS 这一个属性,为的是event不会被android标准input子系统获取走。这个设备的event只有三个数 分别为三轴的重力的大小
下面我们看,poll设备注册的poll回调函数
- static void mma8451_dev_poll(struct input_polled_dev *dev)
- {
- report_abs();
- }
- static void report_abs(void)
- {
- short x, y, z;
- int result;
- int retry = 3;
- mutex_lock(&mma8451_lock);
- if (mma_status.active == MMA_STANDBY)
- goto out;
- /* wait for the data ready */
- do {
- result = i2c_smbus_read_byte_data(mma8451_i2c_client,
- MMA8451_STATUS);
- retry--;
- msleep(1);
- } while (!(result & MMA8451_STATUS_ZYXDR) && retry > 0);
- if (retry == 0)
- goto out;
- if (mma8451_read_data(&x, &y, &z) != 0)
- goto out;
- mma8451_adjust_position(&x, &y, &z); //调整xyz 三轴
- input_report_abs(mma8451_idev->input, ABS_X, x); //报告事件
- input_report_abs(mma8451_idev->input, ABS_Y, y);
- input_report_abs(mma8451_idev->input, ABS_Z, z);
- input_sync(mma8451_idev->input);
- out:
- mutex_unlock(&mma8451_lock);
- }
- //从这个函数可以看出 sensor的事件报告方式是标准的input_report_abs()函数,并没什么特殊性不多做说明
static void mma8451_dev_poll(struct input_polled_dev *dev)
{
report_abs();
}
static void report_abs(void)
{
short x, y, z;
int result;
int retry = 3;
mutex_lock(&mma8451_lock);
if (mma_status.active == MMA_STANDBY)
goto out;
/* wait for the data ready */
do {
result = i2c_smbus_read_byte_data(mma8451_i2c_client,
MMA8451_STATUS);
retry--;
msleep(1);
} while (!(result & MMA8451_STATUS_ZYXDR) && retry > 0);
if (retry == 0)
goto out;
if (mma8451_read_data(&x, &y, &z) != 0)
goto out;
mma8451_adjust_position(&x, &y, &z); //调整xyz 三轴
input_report_abs(mma8451_idev->input, ABS_X, x); //报告事件
input_report_abs(mma8451_idev->input, ABS_Y, y);
input_report_abs(mma8451_idev->input, ABS_Z, z);
input_sync(mma8451_idev->input);
out:
mutex_unlock(&mma8451_lock);
}
//从这个函数可以看出 sensor的事件报告方式是标准的input_report_abs()函数,并没什么特殊性不多做说明
到了这里整个的sensor访问流程就完成了。这个流程,内核部分走的是标准的input设备 ,hal层将内核设备访问封装成动态链接库,jni层通过访问动态链接库,来访问硬件设备。kernel和动态链接库直接并没有标准的接口,这里把传感器作为input设备只是实现功能的一种方法,我们也可以把传感器设置为一个字符设备,然后通过修改hal层来实现相应的功能。当然由于灵活性,当我们为整个系统添加或者删除一个传感器时,也要修改更多的代码。有利也有弊吧。