android传感器(sensor)分析(以mma8451重力感应器为基础)

android传感器(sensor)分析(以mma8451重力感应器为基础)

转载地址:http://blog.csdn.net/dkleikesa/article/details/9532869

一、前言

 传感器是现在手机上不可或缺的的一部分,到了android4.0系统总共支持13类的传感器分别为

  1. #define SENSOR_TYPE_ACCELEROMETER       1  
  2. #define SENSOR_TYPE_MAGNETIC_FIELD      2  
  3. #define SENSOR_TYPE_ORIENTATION         3  
  4. #define SENSOR_TYPE_GYROSCOPE           4  
  5. #define SENSOR_TYPE_LIGHT               5  
  6. #define SENSOR_TYPE_PRESSURE            6  
  7. #define SENSOR_TYPE_TEMPERATURE         7     
  8. #define SENSOR_TYPE_PROXIMITY           8  
  9. #define SENSOR_TYPE_GRAVITY             9  
  10. #define SENSOR_TYPE_LINEAR_ACCELERATION 10  
  11. #define SENSOR_TYPE_ROTATION_VECTOR     11  
  12. #define SENSOR_TYPE_RELATIVE_HUMIDITY   12  
  13. #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. //1、取得重力感应器Sensor对象  
  2. //在 Activity 中定义以下成员变量:  
  3. private SensorManager mManager = null;  
  4. private Sensor mSensor = null;  
  5. //以下代码加入到 onCreate() 方法中:  
  6. mManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);  //创建SensorManager  
  7. mSensor = manager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);//得到重力感应器  
  8. //2、创建监听器  
  9. //在 Activity 中定义以下成员变量:  
  10. private SensorEventListener mListener = null;  
  11. //以下代码加入到 onCreate() 方法中:  
  12. mListener = new SensorEventListener() {  
  13. public void onAccuracyChanged(Sensor sensor, int accuracy) {  
  14. public void onSensorChanged(SensorEvent event) {  
  15. float x = event.values[SensorManager.DATA_X];  
  16. float y = event.values[SensorManager.DATA_Y];  
  17. float z = event.values[SensorManager.DATA_Z];  
  18. doSomething(x, y, z);  
  19. }  
  20. };  
  21. //3、注册监听器  
  22. //以下代码加入到 onResume() 方法中:  
  23. mManager.registerListener(mListener, mSensor, SensorManager.SENSOR_DELAY_GAME);  
  24. //这里 SENSOR_DELAY_GAME 还可以是以下常量:  
  25. //SENSOR_DELAY_FASTEST  
  26. //SENSOR_DELAY_UI  
  27. //SENSOR_DELAY_NORMAL  
  28. //4、取消监听器  
  29. //以下代码加入到 onPause() 方法中:  
  30. mManager.unregisterListener(mListener);  
  31. 参考: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中它的入口代码为:

  1. struct sensors_module_t HAL_MODULE_INFO_SYM = {  
  2.         common: {  
  3.                 tag: HARDWARE_MODULE_TAG,  
  4.                 version_major: 1,  
  5.                 version_minor: 1,  
  6.                 id: SENSORS_HARDWARE_MODULE_ID,  
  7.                 name: "Freescale Sensor module",  
  8.                 author: "Freescale Semiconductor Inc.",  
  9.                 methods: &sensors_module_methods,//链接库的操作集  
  10.         },  
  11.         get_sensors_list: sensors__get_sensors_list,    //sensorlist实现  
  12. };  
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

  1. static int sensors__get_sensors_list(struct sensors_module_t* module,  
  2.                                      struct sensor_t const** list)  
  3. {  
  4.         *list = sSensorList;  
  5.         return ARRAY_SIZE(sSensorList);  
  6. }  
  7. static const struct sensor_t sSensorList[] = {  
  8.         { "MMA 3-axis Accelerometer",  
  9.           "Freescale Semiconductor Inc.",  
  10.           1, SENSORS_ACCELERATION_HANDLE,  
  11.           SENSOR_TYPE_ACCELEROMETER, RANGE_A, CONVERT_A, 0.30f, 20000, { } },  
  12.         { "MAG3110 3-axis Magnetic field sensor",  
  13.           "Freescale Semiconductor Inc.",  
  14.           1, SENSORS_MAGNETIC_FIELD_HANDLE,  
  15.           SENSOR_TYPE_MAGNETIC_FIELD, 1500.0f, CONVERT_M, 0.50f, 100000, { } },  
  16.         { "MAG3110 Orientation sensor",  
  17.           "Freescale Semiconductor Inc.",  
  18.           1, SENSORS_ORIENTATION_HANDLE,  
  19.           SENSOR_TYPE_ORIENTATION, 360.0f, CONVERT_O, 0.50f, 100000, { } },  
  20.         { "MPL3115 Pressure sensor",  
  21.           "Freescale Semiconductor Inc.",  
  22.           1, SENSORS_PRESSURE_HANDLE,  
  23.           SENSOR_TYPE_PRESSURE, 1100.0f, CONVERT_PRESSURE, 0.35f, 0, { } },  
  24.         { "MPL3115 Temperature sensor",  
  25.           "Freescale Semiconductor Inc.",  
  26.           1, SENSORS_TEMPERATURE_HANDLE,  
  27.           SENSOR_TYPE_TEMPERATURE, 85.0f, CONVERT_TEMPERATURE, 0.35f, 0, { } },  
  28.         { "ISL29023 Light sensor",  
  29.           "Intersil",  
  30.           1, SENSORS_LIGHT_HANDLE,  
  31.           SENSOR_TYPE_LIGHT, 16000.0f, 1.0f, 0.35f, 0, { } },  
  32. };  
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传感器操作集

  1. static struct hw_module_methods_t sensors_module_methods = {  
  2.         open: open_sensors  
  3. };  
  4. static int open_sensors(const struct hw_module_t* module, const char* id,  
  5.                         struct hw_device_t** device)  
  6. {  
  7.         int status = -EINVAL;  
  8.         sensors_poll_context_t *dev = new sensors_poll_context_t();  
  9.   
  10.         memset(&dev->device, 0, sizeof(sensors_poll_device_t));  
  11.   
  12.         dev->device.common.tag = HARDWARE_DEVICE_TAG;  
  13.         dev->device.common.version  = 0;  
  14.         dev->device.common.module   = const_cast<hw_module_t*>(module);  
  15.         dev->device.common.close    = poll__close;  
  16.         dev->device.activate        = poll__activate;  
  17.         dev->device.setDelay        = poll__setDelay;  
  18.         dev->device.poll            = poll__poll;  
  19.   
  20.         *device = &dev->device.common;  
  21.         status = 0;  
  22.   
  23.         return status;  
  24. }  
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
我们来看这四个函数分别实现什么功能

  1. static int poll__close(struct hw_device_t *dev) //直接删除设备上下文  
  2. {  
  3.     sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;  
  4.     if (ctx) {  
  5.         delete ctx;  
  6.     }  
  7.     return 0;  
  8. }  
  9.   
  10. static int poll__activate(struct sensors_poll_device_t *dev,  
  11.         int handle, int enabled) {  
  12.     sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;  
  13.     return ctx->activate(handle, enabled);  
  14. }               |  
  15.                 V  
  16. int sensors_poll_context_t::activate(int handle, int enabled) {  
  17.     int index = handleToDriver(handle);  
  18.     int err = 0 ;  
  19.   
  20.     if (index < 0) return index;  
  21.     if(handle == ID_O || handle ==  ID_M){  
  22.         err = mSensors[accel]->enable(ID_A, enabled);  
  23.         if(err)  
  24.             return err;  
  25.     }  
  26.     err |=  mSensors[index]->enable(handle, enabled);  
  27.     if (enabled && !err) {  
  28.         const char wakeMessage(WAKE_MESSAGE);  
  29.         int result = write(mWritePipeFd, &wakeMessage, 1);  
  30.         LOGE_IF(result<0, "error sending wake message (%s)", strerror(errno));  
  31.     }  
  32.     return err;  
  33. }  
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中

  1. int SensorBase::enable(int32_t handle, int enabled)  
  2. {  
  3.     sensorBaseEnable(handle,enabled);  
  4.     return 0;  
  5. }  
  6.   
  7. int SensorBase::sensorBaseEnable(int32_t handle,int enabled){  
  8.   。。。。。。。。。。。。。  
  9.     if((enable && mUser[what] == 1) || (enable ==0  &&  mUser[what] == 0 )) {  
  10.         snprintf(buf,sizeof(buf),"%d",enable);  
  11.         write_sysfs(sysfs_enable,buf,strlen(buf));  //向sysfs文件系统中写入数据,这里涉及到了文件系统的操作进入了内核空间。  
  12.         mEnabled &= ~(1<<what);  
  13.         mEnabled |= (uint32_t(enable)<<what);  
  14.     }  
  15.   
  16.   。。。。。。。。。。。。。。  
  17. }  
  18.   
  19.   
  20. static int poll__setDelay(struct sensors_poll_device_t *dev,  
  21.         int handle, int64_t ns) {  
  22.     sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;  
  23.     return ctx->setDelay(handle, ns);  
  24. }                   |  
  25.                     V  
  26. int SensorBase::sensorBaseSetDelay(int32_t handle, int64_t ns){  
  27.     char buf[6];  
  28.     int ms;  
  29.     ms = ns/1000/1000;  
  30.     if(ms < mMinPollDelay)  
  31.         ms = mMinPollDelay ;  
  32.     else if(ms > mMaxPollDelay)  
  33.         ms = mMaxPollDelay;  
  34.     snprintf(buf,sizeof(buf),"%d",ms);  
  35.     return write_sysfs(sysfs_poll,buf,strlen(buf)); //想文件系统中写入数据 进入内核空间  
  36. }  
  37.   
  38. static int poll__poll(struct sensors_poll_device_t *dev,  
  39.         sensors_event_t* data, int count) {  
  40.     sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;  
  41.     return ctx->pollEvents(data, count);  
  42. }                   |  
  43.                     V  
  44. static int poll__poll(struct sensors_poll_device_t *dev,  
  45.         sensors_event_t* data, int count) {  
  46.     sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;  
  47.     return ctx->pollEvents(data, count);  
  48. }                     
  49. 我们来看pollEvents这个函数实现了设备事件的读取  
  50. int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)  
  51. {  
  52.     int nbEvents = 0;  
  53.     int n = 0;  
  54.   
  55.     do {  
  56.         // see if we have some leftover from the last poll()  
  57.         for (int i=0 ; count && i<numSensorDrivers ; i++) {     //循环读取所有sensorlist中设备的event  
  58.             SensorBase* const sensor(mSensors[i]);  
  59.   
  60.             if ((mPollFds[i].revents & POLLIN) || (sensor->hasPendingEvents())) {  
  61.                 int nb = sensor->readEvents(data, count);       //读取事件  
  62.                 if (nb < count) {  
  63.                     // no more data for this sensor  
  64.                     mPollFds[i].revents = 0;  
  65.                 }  
  66.                 count -= nb;  
  67.                 nbEvents += nb;  
  68.                 data += nb;  
  69.             }  
  70.         }  
  71. 。。。。。。。。。。。。。。。。  
  72.   
  73.     return nbEvents;  
  74. }  
  75. 继续看  
  76.   
  77. int SensorBase::readEvents(sensors_event_t* data, int count)  
  78. {  
  79.     。。。。。。  
  80.     ssize_t n = mInputReader.fill(data_fd);     //填充eventbuf  
  81.        //mInputReader代码在android\hardware\imx\libsensors\InputEventReader.cpp中这个类,在这里就不多做分析了,  
  82.        //内容比较简单,就是从设备文件中读取数据然后进行一定的处理传送给上层  
  83.  。。。。。。。。  
  84.             for (int j=0 ; count && mPendingMask && j<numSensors ; j++) {  
  85.   
  86.                 if (mPendingMask & (1<<j)) {  
  87.                     mPendingMask &= ~(1<<j);  
  88.                     mPendingEvents[j].timestamp = time;  
  89.                     if (mEnabled & (1<<j)) {  
  90.                         *data++ = mPendingEvents[j];  //数据复制到buf中    
  91.                         count--;  
  92.                         numEventReceived++;   
  93.                     }  
  94.                 }  
  95.             }  
  96.         。。。。。。。。。。  
  97.     return numEventReceived;    //返回读数个数  
  98. }  
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的构造函数中:

  1. SensorBase::SensorBase(  
  2.         const char* dev_name,   //打开的设备文件的名字  
  3.         const char* data_name)  
  4.     : dev_name(dev_name), data_name(data_name),  
  5.       dev_fd(-1), data_fd(-1),  
  6.       mInputReader(64)  
  7. {  
  8.     if (data_name)  
  9.         data_fd = openInput(data_name);  
  10. }                       |  
  11.                         |  
  12.                         V  
  13. int SensorBase::openInput(const char* inputName)  
  14. {  
  15.     int fd = -1;  
  16.     int input_id = -1;  
  17.     const char *dirname = "/dev/input";  
  18.     const char *inputsysfs = "/sys/class/input";  
  19.     char devname[PATH_MAX];  
  20.     char *filename;  
  21.     DIR *dir;  
  22.     struct dirent *de;  
  23.   
  24.     dir = opendir(dirname);  
  25.     if(dir == NULL)  
  26.         return -1;  
  27.     strcpy(devname, dirname);  
  28.     filename = devname + strlen(devname);  
  29.     *filename++ = '/';  
  30.     while((de = readdir(dir))) {  
  31.         if(de->d_name[0] == '.' &&  
  32.                 (de->d_name[1] == '\0' ||  
  33.                         (de->d_name[1] == '.' && de->d_name[2] == '\0')))  
  34.             continue;  
  35.         strcpy(filename, de->d_name);  
  36.         fd = open(devname, O_RDONLY);       //这里涉及到打开设备文件  
  37.   
  38.        。。。。。。。。。。。。。。。。。。。。。。。。  
  39.     }  
  40.     closedir(dir);  
  41.     LOGE_IF(fd<0, "couldn't find '%s' input device", inputName);  
  42.     return fd;  
  43. }  
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发送的函数

  1. static int __devinit mma8451_probe(struct i2c_client *client,  
  2.                    const struct i2c_device_id *id)  
  3. {  
  4.     int result, client_id;  
  5.     struct input_dev *idev;  
  6.     struct i2c_adapter *adapter;  
  7.   
  8.     mma8451_i2c_client = client;  
  9.     adapter = to_i2c_adapter(client->dev.parent);  
  10.     result = i2c_check_functionality(adapter,   //检测此i2c设备是否支持I2C_FUNC_SMBUS_BYTE和I2C_FUNC_SMBUS_BYTE_DATA这两个属性  
  11.                      I2C_FUNC_SMBUS_BYTE |  
  12.                      I2C_FUNC_SMBUS_BYTE_DATA);  
  13.     if (!result)  
  14.         goto err_out;  
  15.   
  16.     client_id = i2c_smbus_read_byte_data(client, MMA8451_WHO_AM_I);//读ID  
  17.   
  18.     if (client_id != MMA8451_ID && client_id != MMA8452_ID  
  19.         && client_id != MMA8453_ID) {  
  20.         dev_err(&client->dev,  
  21.             "read chip ID 0x%x is not equal to 0x%x or 0x%x!\n",  
  22.             result, MMA8451_ID, MMA8452_ID);  
  23.         result = -EINVAL;  
  24.         goto err_out;  
  25.     }  
  26.   
  27.     /* Initialize the MMA8451 chip */  
  28.     result = mma8451_change_mode(client, senstive_mode);   //初始化mma8451 就是配置一些寄存器  
  29.     if (result) {  
  30.         dev_err(&client->dev,  
  31.             "error when init mma8451 chip:(%d)\n", result);  
  32.         goto err_out;  
  33.     }  
  34.   
  35.     hwmon_dev = hwmon_device_register(&client->dev);//创建一个硬件监听设备  
  36.     if (!hwmon_dev) {  
  37.         result = -ENOMEM;  
  38.         dev_err(&client->dev, "error when register hwmon device\n");  
  39.         goto err_out;  
  40.     }  
  41.   
  42.     mma8451_idev = input_allocate_polled_device();  //分配一个poll类型的input设备  
  43.     if (!mma8451_idev) {  
  44.         result = -ENOMEM;  
  45.         dev_err(&client->dev, "alloc poll device failed!\n");  
  46.         goto err_alloc_poll_device;  
  47.     }  
  48.     mma8451_idev->poll = mma8451_dev_poll;//poll回调函数  
  49.     mma8451_idev->poll_interval = POLL_INTERVAL;  
  50.     mma8451_idev->poll_interval_min = POLL_INTERVAL_MIN;  
  51.     mma8451_idev->poll_interval_max = POLL_INTERVAL_MAX;  
  52.     idev = mma8451_idev->input;  
  53.     idev->name = "mma845x";//这个名字必须和hal层的名字对应上否则找不到设备文件  
  54.     idev->id.bustype = BUS_I2C;  
  55.     idev->evbit[0] = BIT_MASK(EV_ABS);  
  56.   
  57.     input_set_abs_params(idev, ABS_X, -8192, 8191, INPUT_FUZZ, INPUT_FLAT); //设备支持的3个数据  
  58.     input_set_abs_params(idev, ABS_Y, -8192, 8191, INPUT_FUZZ, INPUT_FLAT);  
  59.     input_set_abs_params(idev, ABS_Z, -8192, 8191, INPUT_FUZZ, INPUT_FLAT);  
  60.   
  61.     result = input_register_polled_device(mma8451_idev);//注册这个poll设备  
  62.     if (result) {  
  63.         dev_err(&client->dev, "register poll device failed!\n");  
  64.         goto err_register_polled_device;  
  65.     }  
  66.     result = sysfs_create_group(&idev->dev.kobj, &mma8451_attr_group);//为这个设备创建sysfs 设备文件  
  67.     if (result) {  
  68.         dev_err(&client->dev, "create device file failed!\n");  
  69.         result = -EINVAL;  
  70.         goto err_register_polled_device;  
  71.     }  
  72.     mma_status.position = *(int *)client->dev.platform_data;  
  73.     return 0;  
  74. err_register_polled_device:  
  75.     input_free_polled_device(mma8451_idev);  
  76. err_alloc_poll_device:  
  77.     hwmon_device_unregister(&client->dev);  
  78. err_out:  
  79.     return result;  
  80. }  
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回调函数

  1. static void mma8451_dev_poll(struct input_polled_dev *dev)  
  2. {  
  3.     report_abs();  
  4. }  
  5.   
  6. static void report_abs(void)  
  7. {  
  8.     short x, y, z;  
  9.     int result;  
  10.     int retry = 3;  
  11.   
  12.     mutex_lock(&mma8451_lock);  
  13.     if (mma_status.active == MMA_STANDBY)  
  14.         goto out;  
  15.     /* wait for the data ready */  
  16.     do {  
  17.         result = i2c_smbus_read_byte_data(mma8451_i2c_client,  
  18.                           MMA8451_STATUS);  
  19.         retry--;  
  20.         msleep(1);  
  21.     } while (!(result & MMA8451_STATUS_ZYXDR) && retry > 0);  
  22.     if (retry == 0)  
  23.         goto out;  
  24.     if (mma8451_read_data(&x, &y, &z) != 0)  
  25.         goto out;  
  26.     mma8451_adjust_position(&x, &y, &z); //调整xyz 三轴  
  27.     input_report_abs(mma8451_idev->input, ABS_X, x);    //报告事件  
  28.     input_report_abs(mma8451_idev->input, ABS_Y, y);  
  29.     input_report_abs(mma8451_idev->input, ABS_Z, z);  
  30.     input_sync(mma8451_idev->input);  
  31. out:  
  32.     mutex_unlock(&mma8451_lock);  
  33. }  
  34. //从这个函数可以看出 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层来实现相应的功能。当然由于灵活性,当我们为整个系统添加或者删除一个传感器时,也要修改更多的代码。有利也有弊吧。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值