Android Sensors Development

来源:互联网 发布:禾川plc编程软件下载 编辑:程序博客网 时间:2024/04/30 08:18

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%