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 * * http://www./licenses/LICENSE-2.0 * * 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
|
|