从源码找到的一个例子,写的很优雅,不知道HAL怎么写的同学可以好好学习一下:
view plaincopy to clipboardprint?
/*  * 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.apache.org/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"   #define LOG_NDEBUG 1   #include <hardware/sensors.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>
#include <math.h>
#include <poll.h>
#include <pthread.h>
#include <sys/select.h>   #include <linux/input.h>
#include <linux/akm8973.h>
#include <linux/capella_cm3602.h>
#include <linux/lightsensor.h>   #include <cutils/atomic.h>
#include <cutils/log.h>
#include <cutils/native_handle.h>   #define __MAX(a,b) ((a)>=(b)?(a):(b))   /*****************************************************************************/  #define MAX_NUM_SENSORS 6   #define SUPPORTED_SENSORS  ((1<<MAX_NUM_SENSORS)-1)   #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))   #define ID_A  (0)
#define ID_M  (1)
#define ID_O  (2)
#define ID_T  (3)
#define ID_P  (4)
#define ID_L  (5)   static int id_to_sensor[MAX_NUM_SENSORS] = {   [ID_A] = SENSOR_TYPE_ACCELEROMETER,   [ID_M] = SENSOR_TYPE_MAGNETIC_FIELD,   [ID_O] = SENSOR_TYPE_ORIENTATION,   [ID_T] = SENSOR_TYPE_TEMPERATURE,   [ID_P] = SENSOR_TYPE_PROXIMITY,   [ID_L] = SENSOR_TYPE_LIGHT,
};   #define SENSORS_AKM_ACCELERATION   (1<<ID_A)
#define SENSORS_AKM_MAGNETIC_FIELD (1<<ID_M)
#define SENSORS_AKM_ORIENTATION    (1<<ID_O)
#define SENSORS_AKM_TEMPERATURE    (1<<ID_T)
#define SENSORS_AKM_GROUP          ((1<<ID_A)|(1<<ID_M)|(1<<ID_O)|(1<<ID_T))   #define SENSORS_CM_PROXIMITY       (1<<ID_P)
#define SENSORS_CM_GROUP           (1<<ID_P)   #define SENSORS_LIGHT              (1<<ID_L)
#define SENSORS_LIGHT_GROUP        (1<<ID_L)   /*****************************************************************************/  struct sensors_control_context_t {   struct sensors_control_device_t device; // must be first   int akmd_fd;   int cmd_fd;   int lsd_fd;   uint32_t active_sensors;
};   struct sensors_data_context_t {   struct sensors_data_device_t device; // must be first   int events_fd[3];   sensors_data_t sensors[MAX_NUM_SENSORS];   uint32_t pendingSensors;
};   /*  * The SENSORS Module  */  /* the CM3602 is a binary proximity sensor that triggers around 9 cm on  * this hardware */
#define PROXIMITY_THRESHOLD_CM  9.0f   /*  * the AK8973 has a 8-bit ADC but the firmware seems to average 16 samples,  * or at least makes its calibration on 12-bits values. This increases the  * resolution by 4 bits.  */  static const struct sensor_t sSensorList[] = {   { "BMA150 3-axis Accelerometer",   "Bosh",   1, SENSORS_HANDLE_BASE+ID_A,   SENSOR_TYPE_ACCELEROMETER, 4.0f*9.81f, (4.0f*9.81f)/256.0f, 0.2f, { } },   { "AK8973 3-axis Magnetic field sensor",   "Asahi Kasei",   1, SENSORS_HANDLE_BASE+ID_M,   SENSOR_TYPE_MAGNETIC_FIELD, 2000.0f, 1.0f/16.0f, 6.8f, { } },   { "AK8973 Orientation sensor",   "Asahi Kasei",   1, SENSORS_HANDLE_BASE+ID_O,   SENSOR_TYPE_ORIENTATION, 360.0f, 1.0f, 7.0f, { } },   { "CM3602 Proximity sensor",   "Capella Microsystems",   1, SENSORS_HANDLE_BASE+ID_P,   SENSOR_TYPE_PROXIMITY,   PROXIMITY_THRESHOLD_CM, PROXIMITY_THRESHOLD_CM,   0.5f, { } },   { "CM3602 Light sensor",   "Capella Microsystems",   1, SENSORS_HANDLE_BASE+ID_L,   SENSOR_TYPE_LIGHT, 10240.0f, 1.0f, 0.5f, { } },
};   static const float sLuxValues[8] = {   10.0,   160.0,   225.0,   320.0,   640.0,   1280.0,   2600.0,   10240.0
};   static int open_sensors(const struct hw_module_t* module, const char* name,   struct hw_device_t** device);   static int sensors__get_sensors_list(struct sensors_module_t* module,   struct sensor_t const** list)
{   *list = sSensorList;   return ARRAY_SIZE(sSensorList);
}   static struct hw_module_methods_t sensors_module_methods = {   .open = open_sensors
};   const 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 = "AK8973A & CM3602 Sensors Module",   .author = "The Android Open Source Project",   .methods = &sensors_module_methods,   },   .get_sensors_list = sensors__get_sensors_list
};   /*****************************************************************************/  #define AKM_DEVICE_NAME     "/dev/akm8973_aot"
#define CM_DEVICE_NAME      "/dev/cm3602"
#define LS_DEVICE_NAME      "/dev/lightsensor"   // 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
#define EVENT_TYPE_PROXIMITY        ABS_DISTANCE
#define EVENT_TYPE_LIGHT            ABS_MISC   // 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_inputs(int mode, int *akm_fd, int *p_fd, int *l_fd)
{   /* 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++ = '/';   *akm_fd = *p_fd = -1;   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")) {   LOGV("using %s (name=%s)", devname, name);   *akm_fd = fd;   }   else if (!strcmp(name, "proximity")) {   LOGV("using %s (name=%s)", devname, name);   *p_fd = fd;   }   else if (!strcmp(name, "lightsensor-level")) {   LOGV("using %s (name=%s)", devname, name);   *l_fd = fd;   }   else  close(fd);   }   }   closedir(dir);   fd = 0;   if (*akm_fd < 0) {   LOGE("Couldn't find or open 'compass' driver (%s)", strerror(errno));   fd = -1;   }   if (*p_fd < 0) {   LOGE("Couldn't find or open 'proximity' driver (%s)", strerror(errno));   fd = -1;   }   if (*l_fd < 0) {   LOGE("Couldn't find or open 'light' driver (%s)", strerror(errno));   fd = -1;   }   return fd;
}   static int open_akm(struct sensors_control_context_t* dev)
{   if (dev->akmd_fd < 0) {   dev->akmd_fd = open(AKM_DEVICE_NAME, O_RDONLY);   LOGV("%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 &= ~SENSORS_AKM_GROUP;   }   }   return dev->akmd_fd;
}   static void close_akm(struct sensors_control_context_t* dev)
{   if (dev->akmd_fd >= 0) {   LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->akmd_fd);   close(dev->akmd_fd);   dev->akmd_fd = -1;   }
}   static uint32_t read_akm_sensors_state(int fd)
{   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_AKM_ORIENTATION;   else        sensors &= ~SENSORS_AKM_ORIENTATION;   }   if (!ioctl(fd, ECS_IOCTL_APP_GET_AFLAG, &flags)) {   if (flags)  sensors |= SENSORS_AKM_ACCELERATION;   else        sensors &= ~SENSORS_AKM_ACCELERATION;   }   if (!ioctl(fd, ECS_IOCTL_APP_GET_TFLAG, &flags)) {   if (flags)  sensors |= SENSORS_AKM_TEMPERATURE;   else        sensors &= ~SENSORS_AKM_TEMPERATURE;   }   if (!ioctl(fd, ECS_IOCTL_APP_GET_MVFLAG, &flags)) {   if (flags)  sensors |= SENSORS_AKM_MAGNETIC_FIELD;   else        sensors &= ~SENSORS_AKM_MAGNETIC_FIELD;   }   return sensors;
}   static uint32_t enable_disable_akm(struct sensors_control_context_t *dev,   uint32_t active, uint32_t sensors,   uint32_t mask)
{   uint32_t now_active_akm_sensors;   int fd = open_akm(dev);   if (fd < 0)   return 0;   LOGV("(before) akm sensors = %08x, real = %08x",   sensors, read_akm_sensors_state(fd));   short flags;   if (mask & SENSORS_AKM_ORIENTATION) {   flags = (sensors & SENSORS_AKM_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_AKM_ACCELERATION) {   flags = (sensors & SENSORS_AKM_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_AKM_TEMPERATURE) {   flags = (sensors & SENSORS_AKM_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_AKM_MAGNETIC_FIELD) {   flags = (sensors & SENSORS_AKM_MAGNETIC_FIELD) ? 1 : 0;   if (ioctl(fd, ECS_IOCTL_APP_SET_MVFLAG, &flags) < 0) {   LOGE("ECS_IOCTL_APP_SET_MVFLAG error (%s)", strerror(errno));   }   }   now_active_akm_sensors = read_akm_sensors_state(fd);   LOGV("(after) akm sensors = %08x, real = %08x",   sensors, now_active_akm_sensors);   if (!sensors)   close_akm(dev);   return now_active_akm_sensors;
}   static uint32_t read_cm_sensors_state(int fd)
{   int flags;   uint32_t sensors = 0;   // read the actual value of all sensors   if (!ioctl(fd, CAPELLA_CM3602_IOCTL_GET_ENABLED, &flags)) {   if (flags)  sensors |= SENSORS_CM_PROXIMITY;   else        sensors &= ~SENSORS_CM_PROXIMITY;   }   return sensors;
}   static int open_cm(struct sensors_control_context_t* dev)
{   if (dev->cmd_fd < 0) {   dev->cmd_fd = open(CM_DEVICE_NAME, O_RDONLY);   LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->cmd_fd);   LOGE_IF(dev->cmd_fd<0, "Couldn't open %s (%s)",   CM_DEVICE_NAME, strerror(errno));   if (dev->cmd_fd >= 0) {   dev->active_sensors &= ~SENSORS_CM_GROUP;   }   }   return dev->cmd_fd;
}   static void close_cm(struct sensors_control_context_t* dev)
{   if (dev->cmd_fd >= 0) {   LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->cmd_fd);   close(dev->cmd_fd);   dev->cmd_fd = -1;   }
}   static int enable_disable_cm(struct sensors_control_context_t *dev,   uint32_t active, uint32_t sensors, uint32_t mask)
{   int rc = 0;   uint32_t now_active_cm_sensors;   int fd = open_cm(dev);   if (fd < 0) {   LOGE("Couldn't open %s (%s)", CM_DEVICE_NAME, strerror(errno));   return 0;   }   LOGV("(before) cm sensors = %08x, real = %08x",   sensors, read_cm_sensors_state(fd));   if (mask & SENSORS_CM_PROXIMITY) {   int flags = (sensors & SENSORS_CM_PROXIMITY) ? 1 : 0;   rc = ioctl(fd, CAPELLA_CM3602_IOCTL_ENABLE, &flags);   if (rc < 0)   LOGE("CAPELLA_CM3602_IOCTL_ENABLE error (%s)", strerror(errno));   }   now_active_cm_sensors = read_cm_sensors_state(fd);   LOGV("(after) cm sensors = %08x, real = %08x",   sensors, now_active_cm_sensors);   return now_active_cm_sensors;
}   static uint32_t read_ls_sensors_state(int fd)
{   int flags;   uint32_t sensors = 0;   // read the actual value of all sensors   if (!ioctl(fd, LIGHTSENSOR_IOCTL_GET_ENABLED, &flags)) {   if (flags)  sensors |= SENSORS_LIGHT;   else        sensors &= ~SENSORS_LIGHT;   }   return sensors;
}   static int open_ls(struct sensors_control_context_t* dev)
{   if (dev->lsd_fd < 0) {   dev->lsd_fd = open(LS_DEVICE_NAME, O_RDONLY);   LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->lsd_fd);   LOGE_IF(dev->lsd_fd<0, "Couldn't open %s (%s)",   LS_DEVICE_NAME, strerror(errno));   if (dev->lsd_fd >= 0) {   dev->active_sensors &= ~SENSORS_LIGHT_GROUP;   }   }   return dev->lsd_fd;
}   static void close_ls(struct sensors_control_context_t* dev)
{   if (dev->lsd_fd >= 0) {   LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->lsd_fd);   close(dev->lsd_fd);   dev->lsd_fd = -1;   }
}   static int enable_disable_ls(struct sensors_control_context_t *dev,   uint32_t active, uint32_t sensors, uint32_t mask)
{   int rc = 0;   uint32_t now_active_ls_sensors;   int fd = open_ls(dev);   if (fd < 0) {   LOGE("Couldn't open %s (%s)", LS_DEVICE_NAME, strerror(errno));   return 0;   }   LOGV("(before) ls sensors = %08x, real = %08x",   sensors, read_ls_sensors_state(fd));   if (mask & SENSORS_LIGHT) {   int flags = (sensors & SENSORS_LIGHT) ? 1 : 0;   rc = ioctl(fd, LIGHTSENSOR_IOCTL_ENABLE, &flags);   if (rc < 0)   LOGE("LIGHTSENSOR_IOCTL_ENABLE error (%s)", strerror(errno));   }   now_active_ls_sensors = read_ls_sensors_state(fd);   LOGV("(after) ls sensors = %08x, real = %08x",   sensors, now_active_ls_sensors);   return now_active_ls_sensors;
}   /*****************************************************************************/  static native_handle_t* control__open_data_source(struct sensors_control_context_t *dev)
{   native_handle_t* handle;   int akm_fd, p_fd, l_fd;   if (open_inputs(O_RDONLY, &akm_fd, &p_fd, &l_fd) < 0 ||   akm_fd < 0 || p_fd < 0 || l_fd < 0) {   return NULL;   }   handle = native_handle_create(3, 0);   handle->data[0] = akm_fd;   handle->data[1] = p_fd;   handle->data[2] = l_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) {   if (!active && new_sensors)   // force all sensors to be updated   changed = SUPPORTED_SENSORS;   dev->active_sensors =   enable_disable_akm(dev,   active & SENSORS_AKM_GROUP,   new_sensors & SENSORS_AKM_GROUP,   changed & SENSORS_AKM_GROUP) |   enable_disable_cm(dev,   active & SENSORS_CM_GROUP,   new_sensors & SENSORS_CM_GROUP,   changed & SENSORS_CM_GROUP) |   enable_disable_ls(dev,   active & SENSORS_LIGHT_GROUP,   new_sensors & SENSORS_LIGHT_GROUP,   changed & SENSORS_LIGHT_GROUP);   }   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 akm_fd, p_fd, l_fd;   if (open_inputs(O_RDWR, &akm_fd, &p_fd, &l_fd) < 0 ||   akm_fd < 0 || p_fd < 0 || l_fd < 0) {   return -1;   }   struct input_event event[1];   event[0].type = EV_SYN;   event[0].code = SYN_CONFIG;   event[0].value = 0;   err = write(akm_fd, event, sizeof(event));   LOGV_IF(err<0, "control__wake(compass), fd=%d (%s)",   akm_fd, strerror(errno));   close(akm_fd);   err = write(p_fd, event, sizeof(event));   LOGV_IF(err<0, "control__wake(proximity), fd=%d (%s)",   p_fd, strerror(errno));   close(p_fd);   err = write(l_fd, event, sizeof(event));   LOGV_IF(err<0, "control__wake(light), fd=%d (%s)",   l_fd, strerror(errno));   close(l_fd);   return err;
}   /*****************************************************************************/  static int data__data_open(struct sensors_data_context_t *dev, native_handle_t* handle)
{   int i;   struct input_absinfo absinfo;   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->sensors[ID_A].sensor = SENSOR_TYPE_ACCELEROMETER;   dev->sensors[ID_M].sensor = SENSOR_TYPE_MAGNETIC_FIELD;   dev->sensors[ID_O].sensor = SENSOR_TYPE_ORIENTATION;   dev->sensors[ID_T].sensor = SENSOR_TYPE_TEMPERATURE;   dev->sensors[ID_P].sensor = SENSOR_TYPE_PROXIMITY;   dev->sensors[ID_L].sensor = SENSOR_TYPE_LIGHT;   dev->events_fd[0] = dup(handle->data[0]);   dev->events_fd[1] = dup(handle->data[1]);   dev->events_fd[2] = dup(handle->data[2]);   LOGV("data__data_open: compass fd = %d", handle->data[0]);   LOGV("data__data_open: proximity fd = %d", handle->data[1]);   LOGV("data__data_open: light fd = %d", handle->data[2]);   // Framework will close the handle
    native_handle_delete(handle);   dev->pendingSensors = 0;   if (!ioctl(dev->events_fd[1], EVIOCGABS(ABS_DISTANCE), &absinfo)) {   LOGV("proximity sensor initial value %d\n", absinfo.value);   dev->pendingSensors |= SENSORS_CM_PROXIMITY;   // FIXME: we should save here absinfo.{minimum, maximum, etc}   //        and use them to scale the return value according to   //        the sensor description.   dev->sensors[ID_P].distance = (float)absinfo.value;   }   else LOGE("Cannot get proximity sensor initial value: %s\n",   strerror(errno));   return 0;
}   static int data__data_close(struct sensors_data_context_t *dev)
{   if (dev->events_fd[0] >= 0) {   //LOGV("(data close) about to close compass fd=%d", dev->events_fd[0]);   close(dev->events_fd[0]);   dev->events_fd[0] = -1;   }   if (dev->events_fd[1] >= 0) {   //LOGV("(data close) about to close proximity fd=%d", dev->events_fd[1]);   close(dev->events_fd[1]);   dev->events_fd[1] = -1;   }   if (dev->events_fd[2] >= 0) {   //LOGV("(data close) about to close light fd=%d", dev->events_fd[1]);   close(dev->events_fd[2]);   dev->events_fd[2] = -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 = id_to_sensor[i];   LOGV_IF(0, "%d [%f, %f, %f]",   values->sensor,   values->vector.x,   values->vector.y,   values->vector.z);   return i;   }   }   LOGE("no sensor to return: pendingSensors = %08x", dev->pendingSensors);   return -1;
}   static uint32_t data__poll_process_akm_abs(struct sensors_data_context_t *dev,   int fd __attribute__((unused)),   struct input_event *event)
{   uint32_t new_sensors = 0;   if (event->type == EV_ABS) {   LOGV("compass 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_AKM_ACCELERATION;   dev->sensors[ID_A].acceleration.x = event->value * CONVERT_A_X;   break;   case EVENT_TYPE_ACCEL_Y:   new_sensors |= SENSORS_AKM_ACCELERATION;   dev->sensors[ID_A].acceleration.y = event->value * CONVERT_A_Y;   break;   case EVENT_TYPE_ACCEL_Z:   new_sensors |= SENSORS_AKM_ACCELERATION;   dev->sensors[ID_A].acceleration.z = event->value * CONVERT_A_Z;   break;   case EVENT_TYPE_MAGV_X:   new_sensors |= SENSORS_AKM_MAGNETIC_FIELD;   dev->sensors[ID_M].magnetic.x = event->value * CONVERT_M_X;   break;   case EVENT_TYPE_MAGV_Y:   new_sensors |= SENSORS_AKM_MAGNETIC_FIELD;   dev->sensors[ID_M].magnetic.y = event->value * CONVERT_M_Y;   break;   case EVENT_TYPE_MAGV_Z:   new_sensors |= SENSORS_AKM_MAGNETIC_FIELD;   dev->sensors[ID_M].magnetic.z = event->value * CONVERT_M_Z;   break;   case EVENT_TYPE_YAW:   new_sensors |= SENSORS_AKM_ORIENTATION;   dev->sensors[ID_O].orientation.azimuth =  event->value;   break;   case EVENT_TYPE_PITCH:   new_sensors |= SENSORS_AKM_ORIENTATION;   dev->sensors[ID_O].orientation.pitch = event->value;   break;   case EVENT_TYPE_ROLL:   new_sensors |= SENSORS_AKM_ORIENTATION;   dev->sensors[ID_O].orientation.roll = -event->value;   break;   case EVENT_TYPE_TEMPERATURE:   new_sensors |= SENSORS_AKM_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!)   //LOGV("G-Sensor status %d", event->value);   break;   case EVENT_TYPE_ORIENT_STATUS: {   // accuracy of the calibration   uint32_t v = (uint32_t)(event->value & SENSOR_STATE_MASK);   LOGV_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;   }   }   return new_sensors;
}   static uint32_t data__poll_process_cm_abs(struct sensors_data_context_t *dev,   int fd __attribute__((unused)),   struct input_event *event)
{   uint32_t new_sensors = 0;   if (event->type == EV_ABS) {   LOGV("proximity type: %d code: %d value: %-5d time: %ds",   event->type, event->code, event->value,   (int)event->time.tv_sec);   if (event->code == EVENT_TYPE_PROXIMITY) {   new_sensors |= SENSORS_CM_PROXIMITY;   /* event->value seems to be 0 or 1, scale it to the threshold */  dev->sensors[ID_P].distance = event->value * PROXIMITY_THRESHOLD_CM;   }   }   return new_sensors;
}   static uint32_t data__poll_process_ls_abs(struct sensors_data_context_t *dev,   int fd __attribute__((unused)),   struct input_event *event)
{   uint32_t new_sensors = 0;   if (event->type == EV_ABS) {   LOGV("light-level type: %d code: %d value: %-5d time: %ds",   event->type, event->code, event->value,   (int)event->time.tv_sec);   if (event->code == EVENT_TYPE_LIGHT) {   struct input_absinfo absinfo;   int index;   if (!ioctl(fd, EVIOCGABS(ABS_DISTANCE), &absinfo)) {   index = event->value;   if (index >= 0) {   new_sensors |= SENSORS_LIGHT;   if (index >= ARRAY_SIZE(sLuxValues)) {   index = ARRAY_SIZE(sLuxValues) - 1;   }   dev->sensors[ID_L].light = sLuxValues[index];   }   }   }   }   return new_sensors;
}   static void data__poll_process_syn(struct sensors_data_context_t *dev,   struct input_event *event,   uint32_t new_sensors)
{   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;   }   }
}   static int data__poll(struct sensors_data_context_t *dev, sensors_data_t* values)
{   int akm_fd = dev->events_fd[0];   int cm_fd = dev->events_fd[1];   int ls_fd = dev->events_fd[2];   if (akm_fd < 0) {   LOGE("invalid compass file descriptor, fd=%d", akm_fd);   return -1;   }   if (cm_fd < 0) {   LOGE("invalid proximity-sensor file descriptor, fd=%d", cm_fd);   return -1;   }   if (ls_fd < 0) {   LOGE("invalid light-sensor file descriptor, fd=%d", ls_fd);   return -1;   }   // there are pending sensors, returns them now...   if (dev->pendingSensors) {   LOGV("pending sensors 0x%08x", 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; first, read the compass event, then the  proximity event */  struct input_event event;   int got_syn = 0;   int exit = 0;   int nread;   fd_set rfds;   int n;   FD_ZERO(&rfds);   FD_SET(akm_fd, &rfds);   FD_SET(cm_fd, &rfds);   FD_SET(ls_fd, &rfds);   n = select(__MAX(akm_fd, __MAX(cm_fd, ls_fd)) + 1, &rfds,   NULL, NULL, NULL);   LOGV("return from select: %d\n", n);   if (n < 0) {   LOGE("%s: error from select(%d, %d): %s",   __FUNCTION__,   akm_fd, cm_fd, strerror(errno));   return -1;   }   if (FD_ISSET(akm_fd, &rfds)) {   nread = read(akm_fd, &event, sizeof(event));   if (nread == sizeof(event)) {   new_sensors |= data__poll_process_akm_abs(dev, akm_fd, &event);   LOGV("akm abs %08x", new_sensors);   got_syn = event.type == EV_SYN;   exit = got_syn && event.code == SYN_CONFIG;   if (got_syn) {   LOGV("akm syn %08x", new_sensors);   data__poll_process_syn(dev, &event, new_sensors);   new_sensors = 0;   }   }   else LOGE("akm read too small %d", nread);   }   else LOGV("akm fd is not set");   if (FD_ISSET(cm_fd, &rfds)) {   nread = read(cm_fd, &event, sizeof(event));   if (nread == sizeof(event)) {   new_sensors |= data__poll_process_cm_abs(dev, cm_fd, &event);   LOGV("cm abs %08x", new_sensors);   got_syn |= event.type == EV_SYN;   exit |= got_syn && event.code == SYN_CONFIG;   if (got_syn) {   LOGV("cm syn %08x", new_sensors);   data__poll_process_syn(dev, &event, new_sensors);   new_sensors = 0;   }   }   else LOGE("cm read too small %d", nread);   }   else LOGV("cm fd is not set");   if (FD_ISSET(ls_fd, &rfds)) {   nread = read(ls_fd, &event, sizeof(event));   if (nread == sizeof(event)) {   new_sensors |= data__poll_process_ls_abs(dev, ls_fd, &event);   LOGV("ls abs %08x", new_sensors);   got_syn |= event.type == EV_SYN;   exit |= got_syn && event.code == SYN_CONFIG;   if (got_syn) {   LOGV("ls syn %08x", new_sensors);   data__poll_process_syn(dev, &event, new_sensors);   new_sensors = 0;   }   }   else LOGE("ls read too small %d", nread);   }   else LOGV("ls fd is not set");   if (exit) {   // we use SYN_CONFIG to signal that we need to exit the   // main loop.   //LOGV("got empty message: value=%d", event->value);   LOGV("exit");   return 0x7FFFFFFF;   }   if (got_syn && dev->pendingSensors) {   LOGV("got syn, picking sensor");   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) {   close_akm(ctx);   close_cm(ctx);   close_ls(ctx);   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) {   data__data_close(ctx);   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->cmd_fd = -1;   dev->lsd_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, 0, sizeof(*dev));   dev->events_fd[0] = -1;   dev->events_fd[1] = -1;   dev->events_fd[2] = -1;   dev->device.common.tag = HARDWARE_DEVICE_TAG;   dev->device.common.version = 0;   dev->device.common.module = module;   dev->device.common.close = data__close;   dev->device.data_open = data__data_open;   dev->device.data_close = data__data_close;   dev->device.poll = data__poll;   *device = &dev->device.common;   }   return status;
}
/** 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.apache.org/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"
#define LOG_NDEBUG 1
#include <hardware/sensors.h>
#include <fcntl.h>
#include <errno.h>
#include <dirent.h>
#include <math.h>
#include <poll.h>
#include <pthread.h>
#include <sys/select.h>
#include <linux/input.h>
#include <linux/akm8973.h>
#include <linux/capella_cm3602.h>
#include <linux/lightsensor.h>
#include <cutils/atomic.h>
#include <cutils/log.h>
#include <cutils/native_handle.h>
#define __MAX(a,b) ((a)>=(b)?(a):(b))
/*****************************************************************************/
#define MAX_NUM_SENSORS 6
#define SUPPORTED_SENSORS  ((1<<MAX_NUM_SENSORS)-1)
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
#define ID_A  (0)
#define ID_M  (1)
#define ID_O  (2)
#define ID_T  (3)
#define ID_P  (4)
#define ID_L  (5)
static int id_to_sensor[MAX_NUM_SENSORS] = {[ID_A] = SENSOR_TYPE_ACCELEROMETER,[ID_M] = SENSOR_TYPE_MAGNETIC_FIELD,[ID_O] = SENSOR_TYPE_ORIENTATION,[ID_T] = SENSOR_TYPE_TEMPERATURE,[ID_P] = SENSOR_TYPE_PROXIMITY,[ID_L] = SENSOR_TYPE_LIGHT,
};
#define SENSORS_AKM_ACCELERATION   (1<<ID_A)
#define SENSORS_AKM_MAGNETIC_FIELD (1<<ID_M)
#define SENSORS_AKM_ORIENTATION    (1<<ID_O)
#define SENSORS_AKM_TEMPERATURE    (1<<ID_T)
#define SENSORS_AKM_GROUP          ((1<<ID_A)|(1<<ID_M)|(1<<ID_O)|(1<<ID_T))
#define SENSORS_CM_PROXIMITY       (1<<ID_P)
#define SENSORS_CM_GROUP           (1<<ID_P)
#define SENSORS_LIGHT              (1<<ID_L)
#define SENSORS_LIGHT_GROUP        (1<<ID_L)
/*****************************************************************************/
struct sensors_control_context_t {struct sensors_control_device_t device; // must be firstint akmd_fd;int cmd_fd;int lsd_fd;uint32_t active_sensors;
};
struct sensors_data_context_t {struct sensors_data_device_t device; // must be firstint events_fd[3];sensors_data_t sensors[MAX_NUM_SENSORS];uint32_t pendingSensors;
};
/** The SENSORS Module*/
/* the CM3602 is a binary proximity sensor that triggers around 9 cm on* this hardware */
#define PROXIMITY_THRESHOLD_CM  9.0f
/** the AK8973 has a 8-bit ADC but the firmware seems to average 16 samples,* or at least makes its calibration on 12-bits values. This increases the* resolution by 4 bits.*/
static const struct sensor_t sSensorList[] = {{ "BMA150 3-axis Accelerometer","Bosh",1, SENSORS_HANDLE_BASE+ID_A,SENSOR_TYPE_ACCELEROMETER, 4.0f*9.81f, (4.0f*9.81f)/256.0f, 0.2f, { } },{ "AK8973 3-axis Magnetic field sensor","Asahi Kasei",1, SENSORS_HANDLE_BASE+ID_M,SENSOR_TYPE_MAGNETIC_FIELD, 2000.0f, 1.0f/16.0f, 6.8f, { } },{ "AK8973 Orientation sensor","Asahi Kasei",1, SENSORS_HANDLE_BASE+ID_O,SENSOR_TYPE_ORIENTATION, 360.0f, 1.0f, 7.0f, { } },{ "CM3602 Proximity sensor","Capella Microsystems",1, SENSORS_HANDLE_BASE+ID_P,SENSOR_TYPE_PROXIMITY,PROXIMITY_THRESHOLD_CM, PROXIMITY_THRESHOLD_CM,0.5f, { } },{ "CM3602 Light sensor","Capella Microsystems",1, SENSORS_HANDLE_BASE+ID_L,SENSOR_TYPE_LIGHT, 10240.0f, 1.0f, 0.5f, { } },
};
static const float sLuxValues[8] = {10.0,160.0,225.0,320.0,640.0,1280.0,2600.0,10240.0
};
static int open_sensors(const struct hw_module_t* module, const char* name,struct hw_device_t** device);
static int sensors__get_sensors_list(struct sensors_module_t* module,struct sensor_t const** list)
{*list = sSensorList;return ARRAY_SIZE(sSensorList);
}
static struct hw_module_methods_t sensors_module_methods = {.open = open_sensors
};
const 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 = "AK8973A & CM3602 Sensors Module",.author = "The Android Open Source Project",.methods = &sensors_module_methods,},.get_sensors_list = sensors__get_sensors_list
};
/*****************************************************************************/
#define AKM_DEVICE_NAME     "/dev/akm8973_aot"
#define CM_DEVICE_NAME      "/dev/cm3602"
#define LS_DEVICE_NAME      "/dev/lightsensor"// 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
#define EVENT_TYPE_PROXIMITY        ABS_DISTANCE
#define EVENT_TYPE_LIGHT            ABS_MISC
// 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_inputs(int mode, int *akm_fd, int *p_fd, int *l_fd)
{/* 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++ = '/';*akm_fd = *p_fd = -1;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")) {LOGV("using %s (name=%s)", devname, name);*akm_fd = fd;}else if (!strcmp(name, "proximity")) {LOGV("using %s (name=%s)", devname, name);*p_fd = fd;}else if (!strcmp(name, "lightsensor-level")) {LOGV("using %s (name=%s)", devname, name);*l_fd = fd;}elseclose(fd);}}closedir(dir);fd = 0;if (*akm_fd < 0) {LOGE("Couldn't find or open 'compass' driver (%s)", strerror(errno));fd = -1;}if (*p_fd < 0) {LOGE("Couldn't find or open 'proximity' driver (%s)", strerror(errno));fd = -1;}if (*l_fd < 0) {LOGE("Couldn't find or open 'light' driver (%s)", strerror(errno));fd = -1;}return fd;
}
static int open_akm(struct sensors_control_context_t* dev)
{if (dev->akmd_fd < 0) {dev->akmd_fd = open(AKM_DEVICE_NAME, O_RDONLY);LOGV("%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 &= ~SENSORS_AKM_GROUP;}}return dev->akmd_fd;
}
static void close_akm(struct sensors_control_context_t* dev)
{if (dev->akmd_fd >= 0) {LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->akmd_fd);close(dev->akmd_fd);dev->akmd_fd = -1;}
}
static uint32_t read_akm_sensors_state(int fd)
{short flags;uint32_t sensors = 0;// read the actual value of all sensorsif (!ioctl(fd, ECS_IOCTL_APP_GET_MFLAG, &flags)) {if (flags)  sensors |= SENSORS_AKM_ORIENTATION;else        sensors &= ~SENSORS_AKM_ORIENTATION;}if (!ioctl(fd, ECS_IOCTL_APP_GET_AFLAG, &flags)) {if (flags)  sensors |= SENSORS_AKM_ACCELERATION;else        sensors &= ~SENSORS_AKM_ACCELERATION;}if (!ioctl(fd, ECS_IOCTL_APP_GET_TFLAG, &flags)) {if (flags)  sensors |= SENSORS_AKM_TEMPERATURE;else        sensors &= ~SENSORS_AKM_TEMPERATURE;}if (!ioctl(fd, ECS_IOCTL_APP_GET_MVFLAG, &flags)) {if (flags)  sensors |= SENSORS_AKM_MAGNETIC_FIELD;else        sensors &= ~SENSORS_AKM_MAGNETIC_FIELD;}return sensors;
}
static uint32_t enable_disable_akm(struct sensors_control_context_t *dev,uint32_t active, uint32_t sensors,uint32_t mask)
{uint32_t now_active_akm_sensors;int fd = open_akm(dev);if (fd < 0)return 0;LOGV("(before) akm sensors = %08x, real = %08x",sensors, read_akm_sensors_state(fd));short flags;if (mask & SENSORS_AKM_ORIENTATION) {flags = (sensors & SENSORS_AKM_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_AKM_ACCELERATION) {flags = (sensors & SENSORS_AKM_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_AKM_TEMPERATURE) {flags = (sensors & SENSORS_AKM_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_AKM_MAGNETIC_FIELD) {flags = (sensors & SENSORS_AKM_MAGNETIC_FIELD) ? 1 : 0;if (ioctl(fd, ECS_IOCTL_APP_SET_MVFLAG, &flags) < 0) {LOGE("ECS_IOCTL_APP_SET_MVFLAG error (%s)", strerror(errno));}}now_active_akm_sensors = read_akm_sensors_state(fd);LOGV("(after) akm sensors = %08x, real = %08x",sensors, now_active_akm_sensors);if (!sensors)close_akm(dev);return now_active_akm_sensors;
}
static uint32_t read_cm_sensors_state(int fd)
{int flags;uint32_t sensors = 0;// read the actual value of all sensorsif (!ioctl(fd, CAPELLA_CM3602_IOCTL_GET_ENABLED, &flags)) {if (flags)  sensors |= SENSORS_CM_PROXIMITY;else        sensors &= ~SENSORS_CM_PROXIMITY;}return sensors;
}
static int open_cm(struct sensors_control_context_t* dev)
{if (dev->cmd_fd < 0) {dev->cmd_fd = open(CM_DEVICE_NAME, O_RDONLY);LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->cmd_fd);LOGE_IF(dev->cmd_fd<0, "Couldn't open %s (%s)",CM_DEVICE_NAME, strerror(errno));if (dev->cmd_fd >= 0) {dev->active_sensors &= ~SENSORS_CM_GROUP;}}return dev->cmd_fd;
}
static void close_cm(struct sensors_control_context_t* dev)
{if (dev->cmd_fd >= 0) {LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->cmd_fd);close(dev->cmd_fd);dev->cmd_fd = -1;}
}
static int enable_disable_cm(struct sensors_control_context_t *dev,uint32_t active, uint32_t sensors, uint32_t mask)
{int rc = 0;uint32_t now_active_cm_sensors;int fd = open_cm(dev);if (fd < 0) {LOGE("Couldn't open %s (%s)", CM_DEVICE_NAME, strerror(errno));return 0;}LOGV("(before) cm sensors = %08x, real = %08x",sensors, read_cm_sensors_state(fd));if (mask & SENSORS_CM_PROXIMITY) {int flags = (sensors & SENSORS_CM_PROXIMITY) ? 1 : 0;rc = ioctl(fd, CAPELLA_CM3602_IOCTL_ENABLE, &flags);if (rc < 0)LOGE("CAPELLA_CM3602_IOCTL_ENABLE error (%s)", strerror(errno));}now_active_cm_sensors = read_cm_sensors_state(fd);LOGV("(after) cm sensors = %08x, real = %08x",sensors, now_active_cm_sensors);return now_active_cm_sensors;
}
static uint32_t read_ls_sensors_state(int fd)
{int flags;uint32_t sensors = 0;// read the actual value of all sensorsif (!ioctl(fd, LIGHTSENSOR_IOCTL_GET_ENABLED, &flags)) {if (flags)  sensors |= SENSORS_LIGHT;else        sensors &= ~SENSORS_LIGHT;}return sensors;
}
static int open_ls(struct sensors_control_context_t* dev)
{if (dev->lsd_fd < 0) {dev->lsd_fd = open(LS_DEVICE_NAME, O_RDONLY);LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->lsd_fd);LOGE_IF(dev->lsd_fd<0, "Couldn't open %s (%s)",LS_DEVICE_NAME, strerror(errno));if (dev->lsd_fd >= 0) {dev->active_sensors &= ~SENSORS_LIGHT_GROUP;}}return dev->lsd_fd;
}
static void close_ls(struct sensors_control_context_t* dev)
{if (dev->lsd_fd >= 0) {LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->lsd_fd);close(dev->lsd_fd);dev->lsd_fd = -1;}
}
static int enable_disable_ls(struct sensors_control_context_t *dev,uint32_t active, uint32_t sensors, uint32_t mask)
{int rc = 0;uint32_t now_active_ls_sensors;int fd = open_ls(dev);if (fd < 0) {LOGE("Couldn't open %s (%s)", LS_DEVICE_NAME, strerror(errno));return 0;}LOGV("(before) ls sensors = %08x, real = %08x",sensors, read_ls_sensors_state(fd));if (mask & SENSORS_LIGHT) {int flags = (sensors & SENSORS_LIGHT) ? 1 : 0;rc = ioctl(fd, LIGHTSENSOR_IOCTL_ENABLE, &flags);if (rc < 0)LOGE("LIGHTSENSOR_IOCTL_ENABLE error (%s)", strerror(errno));}now_active_ls_sensors = read_ls_sensors_state(fd);LOGV("(after) ls sensors = %08x, real = %08x",sensors, now_active_ls_sensors);return now_active_ls_sensors;
}
/*****************************************************************************/
static native_handle_t* control__open_data_source(struct sensors_control_context_t *dev)
{native_handle_t* handle;int akm_fd, p_fd, l_fd;if (open_inputs(O_RDONLY, &akm_fd, &p_fd, &l_fd) < 0 ||akm_fd < 0 || p_fd < 0 || l_fd < 0) {return NULL;}handle = native_handle_create(3, 0);handle->data[0] = akm_fd;handle->data[1] = p_fd;handle->data[2] = l_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) {if (!active && new_sensors)// force all sensors to be updatedchanged = SUPPORTED_SENSORS;dev->active_sensors =enable_disable_akm(dev,active & SENSORS_AKM_GROUP,new_sensors & SENSORS_AKM_GROUP,changed & SENSORS_AKM_GROUP) |enable_disable_cm(dev,active & SENSORS_CM_GROUP,new_sensors & SENSORS_CM_GROUP,changed & SENSORS_CM_GROUP) |enable_disable_ls(dev,active & SENSORS_LIGHT_GROUP,new_sensors & SENSORS_LIGHT_GROUP,changed & SENSORS_LIGHT_GROUP);}return 0;
}
static int control__set_delay(struct sensors_control_context_t *dev, int32_t ms)
{
#ifdef ECS_IOCTL_APP_SET_DELAYif (dev->akmd_fd <= 0) {return -1;}short delay = ms;if (!ioctl(dev->akmd_fd, ECS_IOCTL_APP_SET_DELAY, &delay)) {return -errno;}return 0;
#elsereturn -1;
#endif
}
static int control__wake(struct sensors_control_context_t *dev)
{int err = 0;int akm_fd, p_fd, l_fd;if (open_inputs(O_RDWR, &akm_fd, &p_fd, &l_fd) < 0 ||akm_fd < 0 || p_fd < 0 || l_fd < 0) {return -1;}struct input_event event[1];event[0].type = EV_SYN;event[0].code = SYN_CONFIG;event[0].value = 0;err = write(akm_fd, event, sizeof(event));LOGV_IF(err<0, "control__wake(compass), fd=%d (%s)",akm_fd, strerror(errno));close(akm_fd);err = write(p_fd, event, sizeof(event));LOGV_IF(err<0, "control__wake(proximity), fd=%d (%s)",p_fd, strerror(errno));close(p_fd);err = write(l_fd, event, sizeof(event));LOGV_IF(err<0, "control__wake(light), fd=%d (%s)",l_fd, strerror(errno));close(l_fd);return err;
}
/*****************************************************************************/
static int data__data_open(struct sensors_data_context_t *dev, native_handle_t* handle)
{int i;struct input_absinfo absinfo;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->sensors[ID_A].sensor = SENSOR_TYPE_ACCELEROMETER;dev->sensors[ID_M].sensor = SENSOR_TYPE_MAGNETIC_FIELD;dev->sensors[ID_O].sensor = SENSOR_TYPE_ORIENTATION;dev->sensors[ID_T].sensor = SENSOR_TYPE_TEMPERATURE;dev->sensors[ID_P].sensor = SENSOR_TYPE_PROXIMITY;dev->sensors[ID_L].sensor = SENSOR_TYPE_LIGHT;dev->events_fd[0] = dup(handle->data[0]);dev->events_fd[1] = dup(handle->data[1]);dev->events_fd[2] = dup(handle->data[2]);LOGV("data__data_open: compass fd = %d", handle->data[0]);LOGV("data__data_open: proximity fd = %d", handle->data[1]);LOGV("data__data_open: light fd = %d", handle->data[2]);// Framework will close the handle
    native_handle_delete(handle);dev->pendingSensors = 0;if (!ioctl(dev->events_fd[1], EVIOCGABS(ABS_DISTANCE), &absinfo)) {LOGV("proximity sensor initial value %d\n", absinfo.value);dev->pendingSensors |= SENSORS_CM_PROXIMITY;// FIXME: we should save here absinfo.{minimum, maximum, etc}//        and use them to scale the return value according to//        the sensor description.dev->sensors[ID_P].distance = (float)absinfo.value;}else LOGE("Cannot get proximity sensor initial value: %s\n",strerror(errno));return 0;
}
static int data__data_close(struct sensors_data_context_t *dev)
{if (dev->events_fd[0] >= 0) {//LOGV("(data close) about to close compass fd=%d", dev->events_fd[0]);close(dev->events_fd[0]);dev->events_fd[0] = -1;}if (dev->events_fd[1] >= 0) {//LOGV("(data close) about to close proximity fd=%d", dev->events_fd[1]);close(dev->events_fd[1]);dev->events_fd[1] = -1;}if (dev->events_fd[2] >= 0) {//LOGV("(data close) about to close light fd=%d", dev->events_fd[1]);close(dev->events_fd[2]);dev->events_fd[2] = -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 = id_to_sensor[i];LOGV_IF(0, "%d [%f, %f, %f]",values->sensor,values->vector.x,values->vector.y,values->vector.z);return i;}}LOGE("no sensor to return: pendingSensors = %08x", dev->pendingSensors);return -1;
}
static uint32_t data__poll_process_akm_abs(struct sensors_data_context_t *dev,int fd __attribute__((unused)),struct input_event *event)
{uint32_t new_sensors = 0;if (event->type == EV_ABS) {LOGV("compass 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_AKM_ACCELERATION;dev->sensors[ID_A].acceleration.x = event->value * CONVERT_A_X;break;case EVENT_TYPE_ACCEL_Y:new_sensors |= SENSORS_AKM_ACCELERATION;dev->sensors[ID_A].acceleration.y = event->value * CONVERT_A_Y;break;case EVENT_TYPE_ACCEL_Z:new_sensors |= SENSORS_AKM_ACCELERATION;dev->sensors[ID_A].acceleration.z = event->value * CONVERT_A_Z;break;case EVENT_TYPE_MAGV_X:new_sensors |= SENSORS_AKM_MAGNETIC_FIELD;dev->sensors[ID_M].magnetic.x = event->value * CONVERT_M_X;break;case EVENT_TYPE_MAGV_Y:new_sensors |= SENSORS_AKM_MAGNETIC_FIELD;dev->sensors[ID_M].magnetic.y = event->value * CONVERT_M_Y;break;case EVENT_TYPE_MAGV_Z:new_sensors |= SENSORS_AKM_MAGNETIC_FIELD;dev->sensors[ID_M].magnetic.z = event->value * CONVERT_M_Z;break;case EVENT_TYPE_YAW:new_sensors |= SENSORS_AKM_ORIENTATION;dev->sensors[ID_O].orientation.azimuth =  event->value;break;case EVENT_TYPE_PITCH:new_sensors |= SENSORS_AKM_ORIENTATION;dev->sensors[ID_O].orientation.pitch = event->value;break;case EVENT_TYPE_ROLL:new_sensors |= SENSORS_AKM_ORIENTATION;dev->sensors[ID_O].orientation.roll = -event->value;break;case EVENT_TYPE_TEMPERATURE:new_sensors |= SENSORS_AKM_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!)//LOGV("G-Sensor status %d", event->value);break;case EVENT_TYPE_ORIENT_STATUS: {// accuracy of the calibrationuint32_t v = (uint32_t)(event->value & SENSOR_STATE_MASK);LOGV_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;}}return new_sensors;
}
static uint32_t data__poll_process_cm_abs(struct sensors_data_context_t *dev,int fd __attribute__((unused)),struct input_event *event)
{uint32_t new_sensors = 0;if (event->type == EV_ABS) {LOGV("proximity type: %d code: %d value: %-5d time: %ds",event->type, event->code, event->value,(int)event->time.tv_sec);if (event->code == EVENT_TYPE_PROXIMITY) {new_sensors |= SENSORS_CM_PROXIMITY;/* event->value seems to be 0 or 1, scale it to the threshold */dev->sensors[ID_P].distance = event->value * PROXIMITY_THRESHOLD_CM;}}return new_sensors;
}
static uint32_t data__poll_process_ls_abs(struct sensors_data_context_t *dev,int fd __attribute__((unused)),struct input_event *event)
{uint32_t new_sensors = 0;if (event->type == EV_ABS) {LOGV("light-level type: %d code: %d value: %-5d time: %ds",event->type, event->code, event->value,(int)event->time.tv_sec);if (event->code == EVENT_TYPE_LIGHT) {struct input_absinfo absinfo;int index;if (!ioctl(fd, EVIOCGABS(ABS_DISTANCE), &absinfo)) {index = event->value;if (index >= 0) {new_sensors |= SENSORS_LIGHT;if (index >= ARRAY_SIZE(sLuxValues)) {index = ARRAY_SIZE(sLuxValues) - 1;}dev->sensors[ID_L].light = sLuxValues[index];}}}}return new_sensors;
}
static void data__poll_process_syn(struct sensors_data_context_t *dev,struct input_event *event,uint32_t new_sensors)
{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;}}
}
static int data__poll(struct sensors_data_context_t *dev, sensors_data_t* values)
{int akm_fd = dev->events_fd[0];int cm_fd = dev->events_fd[1];int ls_fd = dev->events_fd[2];if (akm_fd < 0) {LOGE("invalid compass file descriptor, fd=%d", akm_fd);return -1;}if (cm_fd < 0) {LOGE("invalid proximity-sensor file descriptor, fd=%d", cm_fd);return -1;}if (ls_fd < 0) {LOGE("invalid light-sensor file descriptor, fd=%d", ls_fd);return -1;}// there are pending sensors, returns them now...if (dev->pendingSensors) {LOGV("pending sensors 0x%08x", dev->pendingSensors);return pick_sensor(dev, values);}// wait until we get a complete event for an enabled sensoruint32_t new_sensors = 0;while (1) {/* read the next event; first, read the compass event, then theproximity event */struct input_event event;int got_syn = 0;int exit = 0;int nread;fd_set rfds;int n;FD_ZERO(&rfds);FD_SET(akm_fd, &rfds);FD_SET(cm_fd, &rfds);FD_SET(ls_fd, &rfds);n = select(__MAX(akm_fd, __MAX(cm_fd, ls_fd)) + 1, &rfds,NULL, NULL, NULL);LOGV("return from select: %d\n", n);if (n < 0) {LOGE("%s: error from select(%d, %d): %s",__FUNCTION__,akm_fd, cm_fd, strerror(errno));return -1;}if (FD_ISSET(akm_fd, &rfds)) {nread = read(akm_fd, &event, sizeof(event));if (nread == sizeof(event)) {new_sensors |= data__poll_process_akm_abs(dev, akm_fd, &event);LOGV("akm abs %08x", new_sensors);got_syn = event.type == EV_SYN;exit = got_syn && event.code == SYN_CONFIG;if (got_syn) {LOGV("akm syn %08x", new_sensors);data__poll_process_syn(dev, &event, new_sensors);new_sensors = 0;}}else LOGE("akm read too small %d", nread);}else LOGV("akm fd is not set");if (FD_ISSET(cm_fd, &rfds)) {nread = read(cm_fd, &event, sizeof(event));if (nread == sizeof(event)) {new_sensors |= data__poll_process_cm_abs(dev, cm_fd, &event);LOGV("cm abs %08x", new_sensors);got_syn |= event.type == EV_SYN;exit |= got_syn && event.code == SYN_CONFIG;if (got_syn) {LOGV("cm syn %08x", new_sensors);data__poll_process_syn(dev, &event, new_sensors);new_sensors = 0;}}else LOGE("cm read too small %d", nread);}else LOGV("cm fd is not set");if (FD_ISSET(ls_fd, &rfds)) {nread = read(ls_fd, &event, sizeof(event));if (nread == sizeof(event)) {new_sensors |= data__poll_process_ls_abs(dev, ls_fd, &event);LOGV("ls abs %08x", new_sensors);got_syn |= event.type == EV_SYN;exit |= got_syn && event.code == SYN_CONFIG;if (got_syn) {LOGV("ls syn %08x", new_sensors);data__poll_process_syn(dev, &event, new_sensors);new_sensors = 0;}}else LOGE("ls read too small %d", nread);}else LOGV("ls fd is not set");if (exit) {// we use SYN_CONFIG to signal that we need to exit the// main loop.//LOGV("got empty message: value=%d", event->value);LOGV("exit");return 0x7FFFFFFF;}if (got_syn && dev->pendingSensors) {LOGV("got syn, picking sensor");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) {close_akm(ctx);close_cm(ctx);close_ls(ctx);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) {data__data_close(ctx);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->cmd_fd = -1;dev->lsd_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, 0, sizeof(*dev));dev->events_fd[0] = -1;dev->events_fd[1] = -1;dev->events_fd[2] = -1;dev->device.common.tag = HARDWARE_DEVICE_TAG;dev->device.common.version = 0;dev->device.common.module = module;dev->device.common.close = data__close;dev->device.data_open = data__data_open;dev->device.data_close = data__data_close;dev->device.poll = data__poll;*device = &dev->device.common;}return status;
}http://blog.csdn.net/zmyde2010/archive/2011/03/21/6266384.aspx

转载于:https://www.cnblogs.com/MMLoveMeMM/articles/4124782.html

Android: android sensors, HAL范例相关推荐

  1. Android深度探索--HAL与驱动开发----第五章读书笔记

    第五章主要学习了搭建S3C6410开发板的测试环境.首先要了解到S3C6410是一款低功耗.高性价比的RISC处理器它是基于ARMI1内核,广泛应用于移动电话和通用处理等领域. 开发板从技术上说与我们 ...

  2. Android R camera Hal启动(下)

    文章目录 前言 代码流程分析 总结 前言 接上一篇Android R camera Hal启动(上)接着写,把谷歌的代码都分析完成,高通/MTK的代码就不贴了. 代码流程分析 上一篇说到getProv ...

  3. 2. android 直接使用hal库播放pcm demo

    目录 一:概述 二:实现 环境 原理说明: 注意问题: 上源代码: 编译执行: 一:概述 这是一个c语言demo程序,android源码环境,编译得到 bin文件,push到设备上在shell环境运行 ...

  4. 图解Android - Android GUI 系统 (2) - 窗口管理 (View, Canvas, Window Manager)

    Android 的窗口管理系统 (View, Canvas, WindowManager) 在图解Android - Zygote 和 System Server 启动分析一 文里,我们已经知道And ...

  5. Android | Android 系统架构

    参考: Android Developers (https://developer.android.google.cn/) 平台架构 Android 是基于 Linux 的开源软件栈,下图为官网给出的 ...

  6. 什么是Android——Android平台简介

    什么是Android --Android平台简介 Keyword: Google Android,Linux内核,开源,应用领域,开放手机联盟(Open Handset Alliance) 在网上看到 ...

  7. Android - Android Studio 解决访问被墙的问题

    Android - Android Studio 解决访问被墙的问题 参考文章: (1)Android - Android Studio 解决访问被墙的问题 (2)https://www.cnblog ...

  8. OpenCV2.4.9 For Android + Android Studio (with gradle)配置教程

    OpenCV2.4.9 For Android + Android Studio (with gradle)配置教程 10 回复 / 9501 浏览 本页底部本帖地址 4king2 年前 - 2014 ...

  9. [Android]Android端ORM框架——RapidORM(v2.1)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/6020412.html [Android]Android端ORM ...

最新文章

  1. ListView优化的代码
  2. 修改记录功能--jsp,servlet
  3. windows安装mongodb(快速简易版)
  4. 穷人最缺少的是什么?
  5. 【elasticsearch系列】双击elasticsearch.bat闪退,日志排查报错信息
  6. java调用linux命令
  7. 你正在学 Web 自动化测试?Selenium 基本操作你了解嘛? | 原力计划
  8. 27款实用高效的腾讯热门开源项目推荐
  9. 111wqdqwdwedwedwdwededwedwe
  10. 微信小游戏加载图片失败问题
  11. c语言 饱和加法,[转载]优化饱和加法运算
  12. 数据库的数据文件和日志文件
  13. 学习python的摸鱼日常
  14. codeforces 1567 B. MEXor Mixup
  15. 静态网站和动态网站的区别
  16. 非华为电脑使用EMUI10多屏协同教程
  17. 武汉2022专技公需课必修答案
  18. CAD2018安装计算机黑屏,简单几步解决cad2019在win10上打不开的问题
  19. 广义线性模型(Generalized Linear Model)之二:Logistic回归
  20. 代码加密:加密Java源代码,保护自己的版权!

热门文章

  1. Apollo安装部署
  2. JavaScript UI选型及Jquery EasyUI使用经验谈
  3. Mac系统home目录权限修改
  4. JNI 调用崩溃问题分析
  5. 德国公司注册优势 德国注册公司流程 海外公司设立
  6. WIN7系统“无线网络显示用于网络的保存在该计算机上的设置与网络的要求不匹配”解决办法
  7. 宝马全新i5电动车首曝光:突显创新与高性能选择
  8. Type and Value
  9. 计算机博士生选择自杀,在论文中了顶会之后
  10. 软件工程——颗粒归仓