Android Sensors Development

Android Sensors Development

   
   Android系統的傳感器系統,爲開發者提供了統一的程序框架來實現系統中的多個傳感器功能,比如:加速度傳感器,磁力傳感器,溫度傳感器,壓力傳感器。google已經爲我們完成了JNI和Java部分,並且提供了底層的程序框架。所以 Android的Sensor部分主要工作集中在了 $(YourDroid)/hardware/libhardware/modules/sensors/sensors.c文件編寫。
   打開$(YourDroid)/hardware/libhardware/include/hardware目錄,其中包括hardware.h和sensors.h兩個重要的頭文件。
   hardware.h定義了兩個最重要的結構體: struct hw_module_t和struct hw_device_t。比較簡單自己打開就一目瞭然。
   sensors.h封裝了hardware.h的兩個結構體.定義了系統中的傳感器類型,一些國際標準單位,與硬件相關的事件類型。其中也有兩個核心的數據結構。簡單的理解爲:一個是控制接口,管理ioctl。另一個是數據接口,讀取底層數據,並填充數據sensors.h中定義的sensors_data_t。

 

struct sensors_control_device_t {
    struct hw_device_t common;
    
    
    native_handle_t* (*open_data_source)(struct sensors_control_device_t *dev);
    
    
    int (*activate)(struct sensors_control_device_t *dev,
            int handle, int enabled);
    
    
    int (*set_delay)(struct sensors_control_device_t *dev, int32_t ms);

    
    int (*wake)(struct sensors_control_device_t *dev);
};


struct sensors_data_device_t {
    struct hw_device_t common;

    
    int (*data_open)(struct sensors_data_device_t *dev, native_handle_t* nh);
    
    
    int (*data_close)(struct sensors_data_device_t *dev);
    
    
    int (*poll)(struct sensors_data_device_t *dev,
            sensors_data_t* data);
};

這兩個數據結構中的成員函數,就是我們編寫sensors.c中要實現的主要內容。frameworks中的JAVA代碼通過JNI接口調用 sensors.c。 以下是對HTC G1傳感器C程序的分析。 sensors.c需要完成的就是senseors.h中成員函數定義的功能



#define LOG_TAG "Sensors"

#include <hardware/sensors.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>
#include <math.h>
#include <poll.h>
#include <pthread.h>

#include <linux/input.h>
#include <linux/akm8976.h>

#include <cutils/atomic.h>
#include <cutils/log.h>
#include <cutils/native_handle.h>



#define MAX_NUM_SENSORS 4  //系統中的傳感器數量

#define SUPPORTED_SENSORS ((1<<MAX_NUM_SENSORS)-1)

#define ID_A (0)
#define ID_M (1)
#define ID_O (2)
#define ID_T (3)

#define SENSORS_ACCELERATION (1<<ID_A)
#define SENSORS_MAGNETIC_FIELD (1<<ID_M)
#define SENSORS_ORIENTATION (1<<ID_O)
#define SENSORS_TEMPERATURE (1<<ID_T)



struct sensors_control_context_t {
    struct sensors_control_device_t device;
    int akmd_fd;           //控制接口的fd。用來控制sensors
    uint32_t active_sensors;
};



struct sensors_data_context_t {
    struct sensors_data_device_t device;
    int events_fd;       // 數據接口的fd.用來接受數據和事件。
    sensors_data_t sensors[MAX_NUM_SENSORS];
    uint32_t pendingSensors;
};



static const struct sensor_t sSensorList[] = {
        { "AK8976A 3-axis Accelerometer",
                "The Android Open Source Project",
                1, SENSORS_HANDLE_BASE+ID_A,
                SENSOR_TYPE_ACCELEROMETER, 2.8f, 1.0f/4032.0f, 3.0f, { } },
        { "AK8976A 3-axis Magnetic field sensor",
                "The Android Open Source Project",
                1, SENSORS_HANDLE_BASE+ID_M,
                SENSOR_TYPE_MAGNETIC_FIELD, 2000.0f, 1.0f, 6.7f, { } },
        { "AK8976A Orientation sensor",
                "The Android Open Source Project",
                1, SENSORS_HANDLE_BASE+ID_O,
                SENSOR_TYPE_ORIENTATION, 360.0f, 1.0f, 9.7f, { } },
        { "AK8976A Temperature sensor",
                "The Android Open Source Project",
                1, SENSORS_HANDLE_BASE+ID_T,
                SENSOR_TYPE_TEMPERATURE, 80.0f, 1.0f, 0.0f, { } },
};

static int open_sensors(const struct hw_module_t* module, const char* name,
        struct hw_device_t** device);

static uint32_t sensors__get_sensors_list(struct sensors_module_t* module,
        struct sensor_t const** list)
{
    *list = sSensorList;
    return sizeof(sSensorList)/sizeof(sSensorList[0]);
}

static struct hw_module_methods_t sensors_module_methods = {
    .open = open_sensors
};


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 = "AK8976A SENSORS Module",
        .author = "The Android Open Source Project",
        .methods = &sensors_module_methods,
    },
    .get_sensors_list = sensors__get_sensors_list
};


#define AKM_DEVICE_NAME "/dev/akm8976_aot"


// sensor IDs must be a power of two and

// must match values in SensorManager.java

#define EVENT_TYPE_ACCEL_X ABS_X
#define EVENT_TYPE_ACCEL_Y ABS_Z
#define EVENT_TYPE_ACCEL_Z ABS_Y
#define EVENT_TYPE_ACCEL_STATUS ABS_WHEEL

#define EVENT_TYPE_YAW ABS_RX
#define EVENT_TYPE_PITCH ABS_RY
#define EVENT_TYPE_ROLL ABS_RZ
#define EVENT_TYPE_ORIENT_STATUS ABS_RUDDER

#define EVENT_TYPE_MAGV_X ABS_HAT0X
#define EVENT_TYPE_MAGV_Y ABS_HAT0Y
#define EVENT_TYPE_MAGV_Z ABS_BRAKE

#define EVENT_TYPE_TEMPERATURE ABS_THROTTLE
#define EVENT_TYPE_STEP_COUNT ABS_GAS

// 720 LSG = 1G

#define LSG (720.0f)

// conversion of acceleration data to SI units (m/s^2)

#define CONVERT_A (GRAVITY_EARTH / LSG)
#define CONVERT_A_X (-CONVERT_A)
#define CONVERT_A_Y (CONVERT_A)
#define CONVERT_A_Z (-CONVERT_A)

// conversion of magnetic data to uT units

#define CONVERT_M (1.0f/16.0f)
#define CONVERT_M_X (-CONVERT_M)
#define CONVERT_M_Y (-CONVERT_M)
#define CONVERT_M_Z (CONVERT_M)

#define SENSOR_STATE_MASK (0x7FFF)


static int open_input(int mode)
{
    
    int fd = -1;
    const char *dirname = "/dev/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%

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章