Home | History | Annotate | Download | only in libsensors
      1 /*
      2  * Copyright (C) 2008 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <fcntl.h>
     18 #include <errno.h>
     19 #include <math.h>
     20 #include <poll.h>
     21 #include <unistd.h>
     22 #include <dirent.h>
     23 #include <sys/select.h>
     24 #include <cutils/log.h>
     25 
     26 #include "GyroSensor.h"
     27 
     28 #define FETCH_FULL_EVENT_BEFORE_RETURN 1
     29 #define IGNORE_EVENT_TIME 350000000
     30 /*****************************************************************************/
     31 
     32 GyroSensor::GyroSensor()
     33     : SensorBase(NULL, "gyro"),
     34       mEnabled(0),
     35       mInputReader(4),
     36       mHasPendingEvent(false),
     37       mEnabledTime(0)
     38 {
     39     mPendingEvent.version = sizeof(sensors_event_t);
     40     mPendingEvent.sensor = ID_GY;
     41     mPendingEvent.type = SENSOR_TYPE_GYROSCOPE;
     42     memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
     43 
     44     if (data_fd) {
     45         strcpy(input_sysfs_path, "/sys/class/input/");
     46         strcat(input_sysfs_path, input_name);
     47         strcat(input_sysfs_path, "/device/");
     48         input_sysfs_path_len = strlen(input_sysfs_path);
     49         enable(0, 1);
     50     }
     51 }
     52 
     53 GyroSensor::~GyroSensor() {
     54     if (mEnabled) {
     55         enable(0, 0);
     56     }
     57 }
     58 
     59 int GyroSensor::setInitialState() {
     60     struct input_absinfo absinfo_x;
     61     struct input_absinfo absinfo_y;
     62     struct input_absinfo absinfo_z;
     63     float value;
     64     if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_x) &&
     65         !ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_y) &&
     66         !ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_z)) {
     67         value = absinfo_x.value;
     68         mPendingEvent.data[0] = value * CONVERT_GYRO_X;
     69         value = absinfo_x.value;
     70         mPendingEvent.data[1] = value * CONVERT_GYRO_Y;
     71         value = absinfo_x.value;
     72         mPendingEvent.data[2] = value * CONVERT_GYRO_Z;
     73         mHasPendingEvent = true;
     74     }
     75     return 0;
     76 }
     77 
     78 int GyroSensor::enable(int32_t, int en) {
     79     int flags = en ? 1 : 0;
     80     if (flags != mEnabled) {
     81         int fd;
     82         strcpy(&input_sysfs_path[input_sysfs_path_len], "enable");
     83         fd = open(input_sysfs_path, O_RDWR);
     84         if (fd >= 0) {
     85             char buf[2];
     86             int err;
     87             buf[1] = 0;
     88             if (flags) {
     89                 buf[0] = '1';
     90                 mEnabledTime = getTimestamp() + IGNORE_EVENT_TIME;
     91             } else {
     92                 buf[0] = '0';
     93             }
     94             err = write(fd, buf, sizeof(buf));
     95             close(fd);
     96             mEnabled = flags;
     97             setInitialState();
     98             return 0;
     99         }
    100         return -1;
    101     }
    102     return 0;
    103 }
    104 
    105 bool GyroSensor::hasPendingEvents() const {
    106     return mHasPendingEvent;
    107 }
    108 
    109 int GyroSensor::setDelay(int32_t handle, int64_t delay_ns)
    110 {
    111     int fd;
    112     strcpy(&input_sysfs_path[input_sysfs_path_len], "poll_delay");
    113     fd = open(input_sysfs_path, O_RDWR);
    114     if (fd >= 0) {
    115         char buf[80];
    116         sprintf(buf, "%lld", delay_ns);
    117         write(fd, buf, strlen(buf)+1);
    118         close(fd);
    119         return 0;
    120     }
    121     return -1;
    122 }
    123 
    124 int GyroSensor::readEvents(sensors_event_t* data, int count)
    125 {
    126     if (count < 1)
    127         return -EINVAL;
    128 
    129     if (mHasPendingEvent) {
    130         mHasPendingEvent = false;
    131         mPendingEvent.timestamp = getTimestamp();
    132         *data = mPendingEvent;
    133         return mEnabled ? 1 : 0;
    134     }
    135 
    136     ssize_t n = mInputReader.fill(data_fd);
    137     if (n < 0)
    138         return n;
    139 
    140     int numEventReceived = 0;
    141     input_event const* event;
    142 
    143 #if FETCH_FULL_EVENT_BEFORE_RETURN
    144 again:
    145 #endif
    146     while (count && mInputReader.readEvent(&event)) {
    147         int type = event->type;
    148         if (type == EV_REL) {
    149             float value = event->value;
    150             if (event->code == EVENT_TYPE_GYRO_X) {
    151                 mPendingEvent.data[0] = value * CONVERT_GYRO_X;
    152             } else if (event->code == EVENT_TYPE_GYRO_Y) {
    153                 mPendingEvent.data[1] = value * CONVERT_GYRO_Y;
    154             } else if (event->code == EVENT_TYPE_GYRO_Z) {
    155                 mPendingEvent.data[2] = value * CONVERT_GYRO_Z;
    156             }
    157         } else if (type == EV_SYN) {
    158             mPendingEvent.timestamp = timevalToNano(event->time);
    159             if (mEnabled) {
    160                 if (mPendingEvent.timestamp >= mEnabledTime) {
    161                     *data++ = mPendingEvent;
    162                     numEventReceived++;
    163                 }
    164                 count--;
    165             }
    166         } else {
    167             ALOGE("GyroSensor: unknown event (type=%d, code=%d)",
    168                     type, event->code);
    169         }
    170         mInputReader.next();
    171     }
    172 
    173 #if FETCH_FULL_EVENT_BEFORE_RETURN
    174     /* if we didn't read a complete event, see if we can fill and
    175        try again instead of returning with nothing and redoing poll. */
    176     if (numEventReceived == 0 && mEnabled == 1) {
    177         n = mInputReader.fill(data_fd);
    178         if (n)
    179             goto again;
    180     }
    181 #endif
    182 
    183     return numEventReceived;
    184 }
    185 
    186