Andriod Sensor HAL實現

http://www.54xue.com/w/07/n-31107.html
 Android sensor構建

Android4.1系統內置對傳感器的支持達13種,他們分別是:加速度傳感器(accelerometer)、磁力傳感器(magnetic field)、方向傳感器(orientation)、陀螺儀(gyroscope)、環境光照傳感器(light)、壓力傳感器(pressure)、溫度傳感器(temperature)和距離傳感器(proximity)等。Android實現傳感器系統包括以下幾個部分:

n        java

n        JNI 

n        HAL

n        驅動層

各部分之間架構圖如下:



2 Sensor HAL層接口

GoogleSensor提供了統一的HAL接口,不同的硬件廠商需要根據該接口來實現並完成具體的硬件抽象層,AndroidSensorHAL接口定義在:

hardware/libhardware/include/hardware/sensors.h

n        對傳感器類型的定義:

#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

 

n        傳感器模塊的定義結構體如下:

struct sensors_module_t {

   struct hw_module_t common;

   int (*get_sensors_list)(struct sensors_module_t* module,

           struct sensor_t const** list);

};

該接口的定義實際上是對標準的硬件模塊hw_module_t的一個擴展,增加了一個get_sensors_list函數,用於獲取傳感器的列表。

n        對任意一個sensor設備都會有一個sensor_t結構體,其定義如下:

struct sensor_t {

   const char*    name;      //傳感器名字

   const char*    vendor;

   int            version;    //版本

   int            handle;    //傳感器的handle句柄

   int            type;      //傳感器類型

   float          maxRange;  //最大範圍

   float          resolution;   //解析度

   float          power;      //消耗能源

   int32_t        minDelay;   //事件間隔最小時間

   void*          reserved[8];  //保留字段,必須爲0

};

n        每個傳感器的數據sensors_event_t結構體表示,定義如下:

typedef struct sensors_event_t {

   int32_t version;

   int32_t sensor;           //標識符

   int32_t type;            //傳感器類型

   int32_t reserved0;

   int64_t timestamp;       //時間戳

   union {

       float          data[16];

       sensors_vec_t  acceleration;  //加速度

       sensors_vec_t  magnetic;     //磁矢量

       sensors_vec_t  orientation;    //方向

       sensors_vec_t  gyro;         //陀螺儀

       float          temperature;    //溫度

       float          distance;       //距離

       float          light;          //光照

       float          pressure;        //壓力

       float          relative_humidity; //相對溼度

   };

   uint32_t       reserved1[4];

} sensors_event_t;

其中,sensor爲傳感器的標誌符,而不同的傳感器則採用union方式來表示,sensors_vec_t結構體用來表示不同傳感器的數據,

n        sensors_vec_t定義如下:

typedef struct {

   union {

       float v[3];

       struct {

           float x;

           float y;

           float z;

       };

       struct {

           float azimuth;

           float pitch;

           float roll;

       };

   };

   int8_t status;

   uint8_t reserved[3];

} sensors_vec_t;

n        Sensor設備結構體sensors_poll_device_t,對標準硬件設備hw_device_t結構體的擴展,主要完成讀取底層數據,並將數據存儲在struct sensors_poll_device_t結構體中,poll函數用來獲取底層數據,調用時將被阻塞定義如下:

struct sensors_poll_device_t {

struct hw_device_t common;

//Activate/deactivate one sensor

   int (*activate)(struct sensors_poll_device_t *dev,

           int handle, int enabled);

   //Set the delay between sensor events in nanoseconds for a given sensor.

   int (*setDelay)(struct sensors_poll_device_t *dev,

           int handle, int64_t ns);

   //獲取數據

   int (*poll)(struct sensors_poll_device_t *dev,

           sensors_event_t* data, int count);

};

n        控制設備打開/關閉結構體定義如下:

static inline int sensors_open(const struct hw_module_t* module,

       struct sensors_poll_device_t** device) {

   return module->methods->open(module,

           SENSORS_HARDWARE_POLL, (struct hw_device_t**)device);

}

 

static inline int sensors_close(struct sensors_poll_device_t* device) {

   return device->common.close(&device->common);

}

3 Sensor HAL實現(bma250爲例子)

3.1打開設備流程圖



SensorDevice屬於JNI層,與HAL進行通信的接口,JNI層調用了HAL層的open_sensors()方法打開設備模塊,再調用poll__activate()對設備使能,然後調用poll__poll讀取數據。

3.2實現代碼分析

bma250傳感器中,只有加速度傳感器,所以在sensor.cpp中,首先需要定義傳感器數組sSensorList,其實就是初始化struct sensor_t結構體,只有加速傳感器,初始化如下:

static const struct sensor_t sSensorList[] = {

 

       {    "BMA250 3-axis Accelerometer",

               "Bosch",

               1, 0,

               SENSOR_TYPE_ACCELEROMETER,

             4.0f*9.81f,

             (4.0f*9.81f)/1024.0f,

             0.2f,

             0,

             { }

      },

};

static const struct sensor_t sSensorList[] = {

 

       {    "BMA250 3-axis Accelerometer",

               "Bosch",

               1, 0,

               SENSOR_TYPE_ACCELEROMETER,

             4.0f*9.81f,

             (4.0f*9.81f)/1024.0f,

             0.2f,

             0,

             { }

      },

};

static const struct sensor_t sSensorList[] = {

 

       {    "BMA250 3-axis Accelerometer",

               "Bosch",

               1, 0,

               SENSOR_TYPE_ACCELEROMETER,

             4.0f*9.81f,

             (4.0f*9.81f)/1024.0f,

             0.2f,

             0,

             { }

      },

};

static const struct sensor_t sSensorList[] = {

 

       {    "BMA250 3-axis Accelerometer",

               "Bosch",

               1, 0,

               SENSOR_TYPE_ACCELEROMETER,

             4.0f*9.81f,

             (4.0f*9.81f)/1024.0f,

             0.2f,

             0,

             { }

      },

};

static const struct sensor_t sSensorList[] = {

 

       {    "BMA250 3-axis Accelerometer",

               "Bosch",

               1, 0,

               SENSOR_TYPE_ACCELEROMETER,

             4.0f*9.81f,

             (4.0f*9.81f)/1024.0f,

             0.2f,

             0,

             { }

      },

};

n        定義open_sensors函數,來打開Sensor模塊,代碼如下:

static struct hw_module_methods_t sensors_module_methods = {

      open : open_sensors

};

static int open_sensors(const struct hw_module_t* module, const char* name,

       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;

 

      if(sensor_get_class_path(dev) < 0) {

             ALOGD("g sensor get class path error \n");

             return -1;

      }

 

      dev->fd = open_input_device();

      *device = &dev->device.common;

      status = 0;

 

      return status;

}

在這個方法中,首先需要爲hw_device_t分配內存空間,並對其初始化,設置重要方法的實現,然後調用open_input_device打開設備節點,返回文件描述符。

 

n        poll__activate()對設備使能

static int poll__activate(struct sensors_poll_device_t *device,

       int handle, int enabled) {

      sensors_poll_context_t *dev = (sensors_poll_context_t *)device;

      char buffer[20];

      int bytes = sprintf(buffer, "%d\n", enabled);

      set_sysfs_input_attr(dev->class_path,"enable",buffer,bytes);

      return 0;

}

static int set_sysfs_input_attr(char *class_path,

                           const char *attr, char *value, int len)

{

      char path[256];

      int fd;

      if (class_path == NULL || *class_path == '\0'

         || attr == NULL || value == NULL || len < 1) {

             return -EINVAL;

      }

      snprintf(path, sizeof(path), "%s/%s", class_path, attr);

      path[sizeof(path) - 1] = '\0';

      fd = open(path, O_RDWR);

      if (fd < 0) {

             return -errno;

      }

      if (write(fd, value, len) < 0) {

             close(fd);

             return -errno;

      }

      close(fd);

      return 0;

}

代碼很簡單,通過系統調用open方法打開設備,然後調用write()方法寫指令使能。

n        poll__poll(),讀取數據

static int poll__poll(struct sensors_poll_device_t *device,

       sensors_event_t* data, int count) {

      

      struct input_event event;

      int ret;

      sensors_poll_context_t *dev = (sensors_poll_context_t *)device;

 

      if (dev->fd < 0)

      return 0;

      while (1) {

             ret = read(dev->fd, &event, sizeof(event));

             if (event.type == EV_ABS) {

 

                    switch (event.code) {

                           #ifdef GSENSOR_XY_REVERT

                    case ABS_Y:

                           data->acceleration.x =

                                         event.value * CONVERT_X;

                           break;

                    case ABS_X:

                           data->acceleration.y =

                                         event.value * CONVERT_Y;

                           break;                         

                           #else

                    case ABS_X:

                          data->acceleration.x =

                                         event.value * CONVERT_X;

                           break;

                    case ABS_Y:

                           data->acceleration.y =

                                         event.value * CONVERT_Y;

                           break;

                           #endif

                    case ABS_Z:

                           data->acceleration.z =

  

發佈了20 篇原創文章 · 獲贊 14 · 訪問量 38萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章