Home | History | Annotate | Download | only in sensors
      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 
     25 #include <linux/akm8975.h>
     26 
     27 #include <cutils/log.h>
     28 
     29 #include "AkmSensor.h"
     30 
     31 /*****************************************************************************/
     32 
     33 AkmSensor::AkmSensor()
     34     : SensorBase(AKM_DEVICE_NAME, "compass"),
     35       mEnabled(0),
     36       mPendingMask(0),
     37       mInputReader(32)
     38 {
     39     memset(mPendingEvents, 0, sizeof(mPendingEvents));
     40 
     41     mPendingEvents[Accelerometer].version = sizeof(sensors_event_t);
     42     mPendingEvents[Accelerometer].sensor = ID_A;
     43     mPendingEvents[Accelerometer].type = SENSOR_TYPE_ACCELEROMETER;
     44     mPendingEvents[Accelerometer].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
     45 
     46     mPendingEvents[MagneticField].version = sizeof(sensors_event_t);
     47     mPendingEvents[MagneticField].sensor = ID_M;
     48     mPendingEvents[MagneticField].type = SENSOR_TYPE_MAGNETIC_FIELD;
     49     mPendingEvents[MagneticField].magnetic.status = SENSOR_STATUS_ACCURACY_HIGH;
     50 
     51     mPendingEvents[Orientation  ].version = sizeof(sensors_event_t);
     52     mPendingEvents[Orientation  ].sensor = ID_O;
     53     mPendingEvents[Orientation  ].type = SENSOR_TYPE_ORIENTATION;
     54     mPendingEvents[Orientation  ].orientation.status = SENSOR_STATUS_ACCURACY_HIGH;
     55 
     56     for (int i=0 ; i<numSensors ; i++)
     57         mDelays[i] = 200000000; // 200 ms by default
     58 
     59     // read the actual value of all sensors if they're enabled already
     60     struct input_absinfo absinfo;
     61     short flags = 0;
     62 
     63     open_device();
     64 
     65     if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_AFLAG, &flags)) {
     66         if (flags)  {
     67             mEnabled |= 1<<Accelerometer;
     68         }
     69     }
     70     if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_MVFLAG, &flags)) {
     71         if (flags)  {
     72             mEnabled |= 1<<MagneticField;
     73         }
     74     }
     75     if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_MFLAG, &flags)) {
     76         if (flags)  {
     77             mEnabled |= 1<<Orientation;
     78         }
     79     }
     80     if (!mEnabled) {
     81         close_device();
     82     }
     83 }
     84 
     85 AkmSensor::~AkmSensor() {
     86 }
     87 
     88 int AkmSensor::enable(int32_t handle, int en)
     89 {
     90     int what = -1;
     91     switch (handle) {
     92         case ID_A: what = Accelerometer; break;
     93         case ID_M: what = MagneticField; break;
     94         case ID_O: what = Orientation;   break;
     95     }
     96 
     97     if (uint32_t(what) >= numSensors)
     98         return -EINVAL;
     99 
    100     int newState  = en ? 1 : 0;
    101     int err = 0;
    102 
    103     if ((uint32_t(newState)<<what) != (mEnabled & (1<<what))) {
    104         if (!mEnabled) {
    105             open_device();
    106         }
    107         int cmd;
    108         switch (what) {
    109             case Accelerometer: cmd = ECS_IOCTL_APP_SET_AFLAG;  break;
    110             case MagneticField: cmd = ECS_IOCTL_APP_SET_MVFLAG; break;
    111             case Orientation:   cmd = ECS_IOCTL_APP_SET_MFLAG;  break;
    112         }
    113         short flags = newState;
    114         err = ioctl(dev_fd, cmd, &flags);
    115         err = err<0 ? -errno : 0;
    116         LOGE_IF(err, "ECS_IOCTL_APP_SET_XXX failed (%s)", strerror(-err));
    117         if (!err) {
    118             mEnabled &= ~(1<<what);
    119             mEnabled |= (uint32_t(flags)<<what);
    120             update_delay();
    121         }
    122         if (!mEnabled) {
    123             close_device();
    124         }
    125     }
    126     return err;
    127 }
    128 
    129 int AkmSensor::setDelay(int32_t handle, int64_t ns)
    130 {
    131 #ifdef ECS_IOCTL_APP_SET_DELAY
    132     int what = -1;
    133     switch (handle) {
    134         case ID_A: what = Accelerometer; break;
    135         case ID_M: what = MagneticField; break;
    136         case ID_O: what = Orientation;   break;
    137     }
    138 
    139     if (uint32_t(what) >= numSensors)
    140         return -EINVAL;
    141 
    142     if (ns < 0)
    143         return -EINVAL;
    144 
    145     mDelays[what] = ns;
    146     return update_delay();
    147 #else
    148     return -1;
    149 #endif
    150 }
    151 
    152 int AkmSensor::update_delay()
    153 {
    154     if (mEnabled) {
    155         uint64_t wanted = -1LLU;
    156         for (int i=0 ; i<numSensors ; i++) {
    157             if (mEnabled & (1<<i)) {
    158                 uint64_t ns = mDelays[i];
    159                 wanted = wanted < ns ? wanted : ns;
    160             }
    161         }
    162         short delay = int64_t(wanted) / 1000000;
    163         if (ioctl(dev_fd, ECS_IOCTL_APP_SET_DELAY, &delay)) {
    164             return -errno;
    165         }
    166     }
    167     return 0;
    168 }
    169 
    170 int AkmSensor::readEvents(sensors_event_t* data, int count)
    171 {
    172     if (count < 1)
    173         return -EINVAL;
    174 
    175     ssize_t n = mInputReader.fill(data_fd);
    176     if (n < 0)
    177         return n;
    178 
    179     int numEventReceived = 0;
    180     input_event const* event;
    181 
    182     while (count && mInputReader.readEvent(&event)) {
    183         int type = event->type;
    184         if (type == EV_REL) {
    185             processEvent(event->code, event->value);
    186             mInputReader.next();
    187         } else if (type == EV_SYN) {
    188             int64_t time = timevalToNano(event->time);
    189             for (int j=0 ; count && mPendingMask && j<numSensors ; j++) {
    190                 if (mPendingMask & (1<<j)) {
    191                     mPendingMask &= ~(1<<j);
    192                     mPendingEvents[j].timestamp = time;
    193                     if (mEnabled & (1<<j)) {
    194                         *data++ = mPendingEvents[j];
    195                         count--;
    196                         numEventReceived++;
    197                     }
    198                 }
    199             }
    200             if (!mPendingMask) {
    201                 mInputReader.next();
    202             }
    203         } else {
    204             LOGE("AkmSensor: unknown event (type=%d, code=%d)",
    205                     type, event->code);
    206             mInputReader.next();
    207         }
    208     }
    209 
    210     return numEventReceived;
    211 }
    212 
    213 void AkmSensor::processEvent(int code, int value)
    214 {
    215     switch (code) {
    216         case EVENT_TYPE_ACCEL_X:
    217             mPendingMask |= 1<<Accelerometer;
    218             mPendingEvents[Accelerometer].acceleration.x = value * CONVERT_A_X;
    219             break;
    220         case EVENT_TYPE_ACCEL_Y:
    221             mPendingMask |= 1<<Accelerometer;
    222             mPendingEvents[Accelerometer].acceleration.y = value * CONVERT_A_Y;
    223             break;
    224         case EVENT_TYPE_ACCEL_Z:
    225             mPendingMask |= 1<<Accelerometer;
    226             mPendingEvents[Accelerometer].acceleration.z = value * CONVERT_A_Z;
    227             break;
    228 
    229         case EVENT_TYPE_MAGV_X:
    230             mPendingMask |= 1<<MagneticField;
    231             mPendingEvents[MagneticField].magnetic.x = value * CONVERT_M_X;
    232             break;
    233         case EVENT_TYPE_MAGV_Y:
    234             mPendingMask |= 1<<MagneticField;
    235             mPendingEvents[MagneticField].magnetic.y = value * CONVERT_M_Y;
    236             break;
    237         case EVENT_TYPE_MAGV_Z:
    238             mPendingMask |= 1<<MagneticField;
    239             mPendingEvents[MagneticField].magnetic.z = value * CONVERT_M_Z;
    240             break;
    241 
    242         case EVENT_TYPE_YAW:
    243             mPendingMask |= 1<<Orientation;
    244             mPendingEvents[Orientation].orientation.azimuth = value * CONVERT_O_Y;
    245             break;
    246         case EVENT_TYPE_PITCH:
    247             mPendingMask |= 1<<Orientation;
    248             mPendingEvents[Orientation].orientation.pitch = value * CONVERT_O_P;
    249             break;
    250         case EVENT_TYPE_ROLL:
    251             mPendingMask |= 1<<Orientation;
    252             mPendingEvents[Orientation].orientation.roll = value * CONVERT_O_R;
    253             break;
    254         case EVENT_TYPE_ORIENT_STATUS:
    255             mPendingMask |= 1<<Orientation;
    256             mPendingEvents[Orientation].orientation.status =
    257                     uint8_t(value & SENSOR_STATE_MASK);
    258             break;
    259     }
    260 }
    261