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

从源码找到的一个例子,写的很优雅,不知道HAL怎么写的同学可以好好学习一下:

主要结构分析:

传感器模块封装:

/** * Every hardware module must have a data structure named HAL_MODULE_INFO_SYM * and the fields of this data structure must begin with hw_module_t * followed by module specific information. */struct sensors_module_t {    struct hw_module_t common;    /**     * Enumerate all available sensors. The list is returned in "list".     * @return number of sensors in the list     */    int (*get_sensors_list)(struct sensors_module_t* module,            struct sensor_t const** list);};

传感器封装:

struct sensor_t {    /* name of this sensors */    const char*     name;    /* vendor of the hardware part */    const char*     vendor;    /* version of the hardware part + driver. The value of this field is     * left to the implementation and doesn't have to be monotonically     * increasing.     */        int             version;    /* handle that identifies this sensors. This handle is used to activate     * and deactivate this sensor. The value of the handle must be 8 bits     * in this version of the API.      */    int             handle;    /* this sensor's type. */    int             type;    /* maximaum range of this sensor's value in SI units */    float           maxRange;    /* smallest difference between two values reported by this sensor */    float           resolution;    /* rough estimate of this sensor's power consumption in mA */    float           power;    /* minimum delay allowed between events in microseconds. A value of zero     * means that this sensor doesn't report events at a constant rate, but     * rather only when a new data is available */    int32_t         minDelay;    /* reserved fields, must be zero */    void*           reserved[8];};


与这两个数据相关的操作,主要是提供对外的接口

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

关键操作有open_sensors

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


设备数据的基类

/** * Every device data structure must begin with hw_device_t * followed by module specific public methods and attributes. */typedef struct hw_device_t {    /** tag must be initialized to HARDWARE_DEVICE_TAG */    uint32_t tag;    /** version number for hw_device_t */    uint32_t version;    /** reference to the module this device belongs to */    struct hw_module_t* module;    /** padding reserved for future use */    uint32_t reserved[12];    /** Close this device */    int (*close)(struct hw_device_t* device);} hw_device_t;

传输的函数中name参数为控制或数据(control,data)。

控制设备的上下文

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

其中,sensors_control_device_t 为传感器控制设备提供操作的方法

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

设备数据上下文

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


其中,sensors_data_device_t 为传感器的数据操作提供方法

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


有了以上的数据和控制设备上下文,就可以将驱动层的函数填充到设备山下文中去,主要的函数有如下

control__wake, control__set_delay,control__activate,control__open_data_source,control__close, data__close,data__data_open,data__data_close,data__poll。

经过上述封装,就将传感器的驱动层的操作封装了,以便给上层的framwork层调用。


control__set_delayioctl(dev->akmd_fd, ECS_IOCTL_APP_SET_DELAY, &delay)control__wakeopen_inputsinput_event:EV_SYN,SYN_CONFIG,0write(akm_fd, event, sizeof(event)close(akm_fd)write(p_fd, event, sizeof(event)close(p_fd)write(l_fd, event, sizeof(event)close(l_fd)data__closedata__data_closedata__data_openinput_absinfosensors_data_context_t的填充将文件描述符封装到事件中去native_handle_delete(handle)ioctl(dev->events_fd[1], EVIOCGABS(ABS_DISTANCE), &absinfo)获取proximity sensor initial valuedata__data_closeclose(dev->events_fd[0]),也就是关闭compass:proximity:lightsensor-level匹配的fddata__pollpick_sensordata__poll_process_akm_abs:将得到的值乘以一个系数data__poll_process_syn:同步



更多相关文章

  1. 一句话锁定MySQL数据占用元凶
  2. android 原生GET和POST提交数据
  3. Android学习笔记(21)————利用JDBC连接服务器数据库
  4. Mediacodec
  5. SharedPreferences保存少量的数据
  6. android项目中单实例数据库类
  7. SharedPreferences 数据存储
  8. android sensor传感器
  9. Android(安卓)RSA 公钥加密、解密

随机推荐

  1. Android中几种常用图片加载库的使用
  2. Android(安卓)Service详解(一) 初识Service
  3. Android视图动画
  4. Android Top Camera Libraries 照相机API
  5. Android(安卓)4.3 蓝牙新特性
  6. android仿iPhone滚轮控件实现及源码
  7. android 入门 ListView - ArrayAdapter、
  8. android 控件各种颜色的半透明效果配置
  9. Android 获取设置屏幕横竖屏
  10. android在xml文件中实现背景或按钮颜色渐