Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1637892
  • 博文数量: 126
  • 博客积分: 1541
  • 博客等级: 上尉
  • 技术积分: 1914
  • 用 户 组: 普通用户
  • 注册时间: 2012-05-20 11:14
文章分类

全部博文(126)

文章存档

2014年(21)

2013年(42)

2012年(63)

分类: LINUX

2013-05-08 12:27:37

原文地址:Android Sensors Development 作者:_mystic

   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;
    
    /**
     * Returns a native_handle_t, which will be the parameter to
     * sensors_data_device_t::open_data().
     * The caller takes ownership of this handle. This is intended to be
     * passed cross processes.
     *
     * @return a native_handle_t if successful, NULL on error
     */

    native_handle_t* (*open_data_source)(struct sensors_control_device_t *dev);
    
    /** Activate/deactivate one sensor.
     *
     * @param handle is the handle of the sensor to change.
     * @param enabled set to 1 to enable, or 0 to disable the sensor.
     *
     * @return 0 on success, negative errno code otherwise
     */

    int (*activate)(struct sensors_control_device_t *dev,
            int handle, int enabled);
    
    /**
     * Set the delay between sensor events in ms
     *
     * @return 0 if successful, < 0 on error
     */

    int (*set_delay)(struct sensors_control_device_t *dev, int32_t ms);

    /**
     * Causes sensors_data_device_t.poll() to return -EWOULDBLOCK immediately.
     */

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


struct sensors_data_device_t {
    struct hw_device_t common;

    /**
     * Prepare to read sensor data.
     *
     * This routine does NOT take ownership of the handle
     * and must not close it. Typically this routine would
     * use a duplicate of the nh parameter.
     *
     * @param nh from sensors_control_open.
     *
     * @return 0 if successful, < 0 on error
     */

    int (*data_open)(struct sensors_data_device_t *dev, native_handle_t* nh);
    
    /**
     * Caller has completed using the sensor data.
     * The caller will not be blocked in sensors_data_poll
     * when this routine is called.
     *
     * @return 0 if successful, < 0 on error
     */

    int (*data_close)(struct sensors_data_device_t *dev);
    
    /**
     * Return sensor data for one of the enabled sensors.
     *
     * @return sensor handle for the returned data, 0x7FFFFFFF when
     * sensors_control_device_t.wake() is called and -errno on error
     *
     */

    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中成员函数定义的功能

/*
 * Copyright (C) 2008 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


#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)

/*****************************************************************************/
/** 封装sensors.h中的数据结构 */
struct sensors_control_context_t {
    struct sensors_control_device_t device;
    int akmd_fd;           //控制接口的fd。用来控制sensors
    uint32_t active_sensors;
};


/** 封装sensors.h中的数据结构 */
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;
};

/*
 * The SENSORS Module
 */


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
};

/** 填充sensors_module_t 必须的 */
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)

/*****************************************************************************/
/* open /dev/input dir, search the file "compass" of it. */

/** 打开数据接口 */
static int open_input(int mode)
{
    /* scan all input drivers and look for "compass" */
    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->d_name[1] == '\0' ||
            (de->d_name[1] == '.' && de->d_name[2] == '\0')))
            continue;
        strcpy(filename, de->d_name);
        fd = open(devname, mode);
        if (fd>=0) {
            char name[80];
            if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
                name[0] = '\0';
            }
            if (!strcmp(name, "compass")) {
                //LOGD("using %s (name=%s)", devname, name);

                break;
            }
            close(fd);
            fd = -1;
        }
    }
    closedir(dir);

    if (fd < 0) {
        LOGE("Couldn't find or open 'compass' driver (%s)", strerror(errno));
    }
    return fd;
}

/* open akm device */
static int open_akm(struct sensors_control_context_t* dev)
{
    if (dev->akmd_fd <= 0) {
        dev->akmd_fd = open(AKM_DEVICE_NAME, O_RDONLY);
        //LOGD("%s, fd=%d", __PRETTY_FUNCTION__, dev->akmd_fd);

        LOGE_IF(dev->akmd_fd<0, "Couldn't open %s (%s)",
                AKM_DEVICE_NAME, strerror(errno));
        if (dev->akmd_fd >= 0) {
            dev->active_sensors = 0;
        }
    }
    return dev->akmd_fd;
}

/* close akm device */
static void close_akm(struct sensors_control_context_t* dev)
{
    if (dev->akmd_fd > 0) {
        //LOGD("%s, fd=%d", __PRETTY_FUNCTION__, dev->akmd_fd);

        close(dev->akmd_fd);
        dev->akmd_fd = -1;
    }
}

/* 打开和关闭传感器 需要ioctl接口 */
static void enable_disable(int fd, uint32_t sensors, uint32_t mask)
{
    if (fd<0) return;
    short flags;
    
    if (mask & SENSORS_ORIENTATION) {
        flags = (sensors & SENSORS_ORIENTATION) ? 1 : 0;
        if (ioctl(fd, ECS_IOCTL_APP_SET_MFLAG, &flags) < 0) {
            LOGE("ECS_IOCTL_APP_SET_MFLAG error (%s)", strerror(errno));
        }
    }
    if (mask & SENSORS_ACCELERATION) {
        flags = (sensors & SENSORS_ACCELERATION) ? 1 : 0;
        if (ioctl(fd, ECS_IOCTL_APP_SET_AFLAG, &flags) < 0) {
            LOGE("ECS_IOCTL_APP_SET_AFLAG error (%s)", strerror(errno));
        }
    }
    if (mask & SENSORS_TEMPERATURE) {
        flags = (sensors & SENSORS_TEMPERATURE) ? 1 : 0;
        if (ioctl(fd, ECS_IOCTL_APP_SET_TFLAG, &flags) < 0) {
            LOGE("ECS_IOCTL_APP_SET_TFLAG error (%s)", strerror(errno));
        }
    }
    if (mask & SENSORS_MAGNETIC_FIELD) {
        flags = (sensors & SENSORS_MAGNETIC_FIELD) ? 1 : 0;
        if (ioctl(fd, ECS_IOCTL_APP_SET_MVFLAG, &flags) < 0) {
            LOGE("ECS_IOCTL_APP_SET_MVFLAG error (%s)", strerror(errno));
        }
    }
}

/* 查找该芯片上传感器的状态 */
static uint32_t read_sensors_state(int fd)
{
    if (fd<0) return 0;
    short flags;
    uint32_t sensors = 0;
    // read the actual value of all sensors

    if (!ioctl(fd, ECS_IOCTL_APP_GET_MFLAG, &flags)) {
        if (flags) sensors |= SENSORS_ORIENTATION;
        else sensors &= ~SENSORS_ORIENTATION;
    }
    if (!ioctl(fd, ECS_IOCTL_APP_GET_AFLAG, &flags)) {
        if (flags) sensors |= SENSORS_ACCELERATION;
        else sensors &= ~SENSORS_ACCELERATION;
    }
    if (!ioctl(fd, ECS_IOCTL_APP_GET_TFLAG, &flags)) {
        if (flags) sensors |= SENSORS_TEMPERATURE;
        else sensors &= ~SENSORS_TEMPERATURE;
    }
    if (!ioctl(fd, ECS_IOCTL_APP_GET_MVFLAG, &flags)) {
        if (flags) sensors |= SENSORS_MAGNETIC_FIELD;
        else sensors &= ~SENSORS_MAGNETIC_FIELD;
    }
    return sensors;
}

/*****************************************************************************/

static native_handle_t* control__open_data_source(struct sensors_control_context_t *dev)
{
    native_handle_t* handle;
    int fd = open_input(O_RDONLY);
    if (fd < 0) {
        return NULL;
    }

    handle = native_handle_create(1, 0);
    handle->data[0] = fd;
    return handle;
}

/** 激活或关闭一个传感器。 关闭也只是不读取该传感器事件,并不真正关闭设备 */
static int control__activate(struct sensors_control_context_t *dev,
        int handle, int enabled)
{
    if ((handle<SENSORS_HANDLE_BASE) ||
            (handle>=SENSORS_HANDLE_BASE+MAX_NUM_SENSORS)) {
        return -1;
    }

    uint32_t mask = (1<<handle);
    uint32_t sensors = enabled ? mask : 0;
    
    uint32_t active = dev->active_sensors;
    uint32_t new_sensors = (active & ~mask) | (sensors & mask);
    uint32_t changed = active ^ new_sensors;
    if (changed) {
        int fd = open_akm(dev);
        if (fd >= 0) {
            if (!active && new_sensors) {
                // force all sensors to be updated

                changed = SUPPORTED_SENSORS;
            }

            enable_disable(fd, new_sensors, changed);

            LOGD("sensors=%08x, real=%08x",
                    new_sensors, read_sensors_state(fd));

            if (active && !new_sensors) {
                // close the driver

                close_akm(dev);
            }
            dev->active_sensors = active = new_sensors;
        } else {
            active = -1;
        }
    }
    return 0;
}

static int control__set_delay(struct sensors_control_context_t *dev, int32_t ms)
{
#ifdef ECS_IOCTL_APP_SET_DELAY
    if (dev->akmd_fd <= 0) {
        return -1;
    }
    short delay = ms;
    if (!ioctl(dev->akmd_fd, ECS_IOCTL_APP_SET_DELAY, &delay)) {
        return -errno;
    }
    return 0;
#else
    return -1;
#endif
}

static int control__wake(struct sensors_control_context_t *dev)
{
    int err = 0;
    int fd = open_input(O_WRONLY);
    if (fd > 0) {
        struct input_event event[1];
        event[0].type = EV_SYN;
        event[0].code = SYN_CONFIG;
        event[0].value = 0;
        err = write(fd, event, sizeof(event));
        LOGD_IF(err<0, "control__wake, err=%d (%s)", errno, strerror(errno));
        close(fd);
    }
    return err;
}

/*****************************************************************************/

static int data__data_open(struct sensors_data_context_t *dev, native_handle_t* handle)
{
    int i;
    memset(&dev->sensors, 0, sizeof(dev->sensors));
    
    for (i=0 ; i<MAX_NUM_SENSORS ; i++) {
        // by default all sensors have high accuracy

        // (we do this because we don't get an update if the value doesn't

        // change).

        dev->sensors[i].vector.status = SENSOR_STATUS_ACCURACY_HIGH;
    }
    dev->pendingSensors = 0;
    dev->events_fd = dup(handle->data[0]);
    //LOGD("data__data_open: fd = %d", handle->data[0]);

    native_handle_close(handle);
    native_handle_delete(handle);
    return 0;
}

static int data__data_close(struct sensors_data_context_t *dev)
{
    if (dev->events_fd > 0) {
        //LOGD("(data close) about to close fd=%d", dev->events_fd);

        close(dev->events_fd);
        dev->events_fd = -1;
    }
    return 0;
}

static int pick_sensor(struct sensors_data_context_t *dev,
        sensors_data_t* values)
{
    uint32_t mask = SUPPORTED_SENSORS;
    while (mask) {
        uint32_t i = 31 - __builtin_clz(mask);
        mask &= ~(1<<i);
        if (dev->pendingSensors & (1<<i)) {
            dev->pendingSensors &= ~(1<<i);
            *values = dev->sensors[i];
            values->sensor = (1<<i);
            LOGD_IF(0, "%d [%f, %f, %f]", (1<<i),
                    values->vector.x,
                    values->vector.y,
                    values->vector.z);
            return i;
        }
    }
    LOGE("No sensor to return!!! pendingSensors=%08x", dev->pendingSensors);
    // we may end-up in a busy loop, slow things down, just in case.

    usleep(100000);
    return -1;
}

static int data__poll(struct sensors_data_context_t *dev, sensors_data_t* values)
{
    int fd = dev->events_fd;
    if (fd < 0) {
        LOGE("invalid file descriptor, fd=%d", fd);
        return -1;
    }

    // there are pending sensors, returns them now...

    if (dev->pendingSensors) {
        return pick_sensor(dev, values);
    }

    // wait until we get a complete event for an enabled sensor

    uint32_t new_sensors = 0;
    while (1) {
        /* read the next event */
        struct input_event event;
        int nread = read(fd, &event, sizeof(event));
        if (nread == sizeof(event)) {
            uint32_t v;
            if (event.type == EV_ABS) {
                //LOGD("type: %d code: %d value: %-5d time: %ds",

                // event.type, event.code, event.value,

                // (int)event.time.tv_sec);

                switch (event.code) {

                    case EVENT_TYPE_ACCEL_X:
                        new_sensors |= SENSORS_ACCELERATION;
                        dev->sensors[ID_A].acceleration.x = event.value * CONVERT_A_X;
                        break;
                    case EVENT_TYPE_ACCEL_Y:
                        new_sensors |= SENSORS_ACCELERATION;
                        dev->sensors[ID_A].acceleration.y = event.value * CONVERT_A_Y;
                        break;
                    case EVENT_TYPE_ACCEL_Z:
                        new_sensors |= SENSORS_ACCELERATION;
                        dev->sensors[ID_A].acceleration.z = event.value * CONVERT_A_Z;
                        break;

                    case EVENT_TYPE_MAGV_X:
                        new_sensors |= SENSORS_MAGNETIC_FIELD;
                        dev->sensors[ID_M].magnetic.x = event.value * CONVERT_M_X;
                        break;
                    case EVENT_TYPE_MAGV_Y:
                        new_sensors |= SENSORS_MAGNETIC_FIELD;
                        dev->sensors[ID_M].magnetic.y = event.value * CONVERT_M_Y;
                        break;
                    case EVENT_TYPE_MAGV_Z:
                        new_sensors |= SENSORS_MAGNETIC_FIELD;
                        dev->sensors[ID_M].magnetic.z = event.value * CONVERT_M_Z;
                        break;

                    case EVENT_TYPE_YAW:
                        new_sensors |= SENSORS_ORIENTATION;
                        dev->sensors[ID_O].orientation.azimuth = event.value;
                        break;
                    case EVENT_TYPE_PITCH:
                        new_sensors |= SENSORS_ORIENTATION;
                        dev->sensors[ID_O].orientation.pitch = event.value;
                        break;
                    case EVENT_TYPE_ROLL:
                        new_sensors |= SENSORS_ORIENTATION;
                        dev->sensors[ID_O].orientation.roll = -event.value;
                        break;

                    case EVENT_TYPE_TEMPERATURE:
                        new_sensors |= SENSORS_TEMPERATURE;
                        dev->sensors[ID_T].temperature = event.value;
                        break;

                    case EVENT_TYPE_STEP_COUNT:
                        // step count (only reported in MODE_FFD)

                        // we do nothing with it for now.

                        break;
                    case EVENT_TYPE_ACCEL_STATUS:
                        // accuracy of the calibration (never returned!)

                        //LOGD("G-Sensor status %d", event.value);

                        break;
                    case EVENT_TYPE_ORIENT_STATUS:
                        // accuracy of the calibration

                        v = (uint32_t)(event.value & SENSOR_STATE_MASK);
                        LOGD_IF(dev->sensors[ID_O].orientation.status != (uint8_t)v,
                                "M-Sensor status %d", v);
                        dev->sensors[ID_O].orientation.status = (uint8_t)v;
                        break;
                }
            } else if (event.type == EV_SYN) {
                if (event.code == SYN_CONFIG) {
                    // we use SYN_CONFIG to signal that we need to exit the

                    // main loop.

                    //LOGD("got empty message: value=%d", event.value);

                    return 0x7FFFFFFF;
                }
                if (new_sensors) {
                    dev->pendingSensors = new_sensors;
                    int64_t t = event.time.tv_sec*1000000000LL +
                            event.time.tv_usec*1000;
                    while (new_sensors) {
                        uint32_t i = 31 - __builtin_clz(new_sensors);
                        new_sensors &= ~(1<<i);
                        dev->sensors[i].time = t;
                    }
                    return pick_sensor(dev, values);
                }
            }
        }
    }
}

/*****************************************************************************/

static int control__close(struct hw_device_t *dev)
{
    struct sensors_control_context_t* ctx = (struct sensors_control_context_t*)dev;
    if (ctx) {
        if (ctx->akmd_fd > 0)
            close(ctx->akmd_fd);
        free(ctx);
    }
    return 0;
}

static int data__close(struct hw_device_t *dev)
{
    struct sensors_data_context_t* ctx = (struct sensors_data_context_t*)dev;
    if (ctx) {
        if (ctx->events_fd > 0) {
            //LOGD("(device close) about to close fd=%d", ctx->events_fd);

            close(ctx->events_fd);
        }
        free(ctx);
    }
    return 0;
}



/** Open a new instance of a sensor device using name */
static int open_sensors(const struct hw_module_t* module, const char* name,
        struct hw_device_t** device)
{
    int status = -EINVAL;
    if (!strcmp(name, SENSORS_HARDWARE_CONTROL)) {
        struct sensors_control_context_t *dev;
        dev = malloc(sizeof(*dev));
        memset(dev, 0, sizeof(*dev));
        dev->akmd_fd = -1;
        dev->device.common.tag = HARDWARE_DEVICE_TAG;
        dev->device.common.version = 0;
        dev->device.common.module = module;
        dev->device.common.close = control__close;
        dev->device.open_data_source = control__open_data_source;
        dev->device.activate = control__activate;
        dev->device.set_delay= control__set_delay;
        dev->device.wake = control__wake;
        *device = &dev->device.common;
    } else if (!strcmp(name, SENSORS_HARDWARE_DATA)) {
        struct sensors_data_context_t *dev;
        dev = malloc(sizeof(*dev));
        memset(dev



高速稳定不限流量的SSH代理
阅读(1127) | 评论(0) | 转发(0) |
0

上一篇:cp 复制整个目录

下一篇:set的用法

给主人留下些什么吧!~~