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 
     25 #include <linux/akm8973.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             if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_X), &absinfo)) {
     69                 mPendingEvents[Accelerometer].acceleration.x = absinfo.value * CONVERT_A_X;
     70             }
     71             if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Y), &absinfo)) {
     72                 mPendingEvents[Accelerometer].acceleration.y = absinfo.value * CONVERT_A_Y;
     73             }
     74             if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Z), &absinfo)) {
     75                 mPendingEvents[Accelerometer].acceleration.z = absinfo.value * CONVERT_A_Z;
     76             }
     77         }
     78     }
     79     if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_MVFLAG, &flags)) {
     80         if (flags)  {
     81             mEnabled |= 1<<MagneticField;
     82             if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_X), &absinfo)) {
     83                 mPendingEvents[MagneticField].magnetic.x = absinfo.value * CONVERT_M_X;
     84             }
     85             if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_Y), &absinfo)) {
     86                 mPendingEvents[MagneticField].magnetic.y = absinfo.value * CONVERT_M_Y;
     87             }
     88             if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_Z), &absinfo)) {
     89                 mPendingEvents[MagneticField].magnetic.z = absinfo.value * CONVERT_M_Z;
     90             }
     91         }
     92     }
     93     if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_MFLAG, &flags)) {
     94         if (flags)  {
     95             mEnabled |= 1<<Orientation;
     96             if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_YAW), &absinfo)) {
     97                 mPendingEvents[Orientation].orientation.azimuth = absinfo.value;
     98             }
     99             if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_PITCH), &absinfo)) {
    100                 mPendingEvents[Orientation].orientation.pitch = absinfo.value;
    101             }
    102             if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ROLL), &absinfo)) {
    103                 mPendingEvents[Orientation].orientation.roll = -absinfo.value;
    104             }
    105             if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ORIENT_STATUS), &absinfo)) {
    106                 mPendingEvents[Orientation].orientation.status = uint8_t(absinfo.value & SENSOR_STATE_MASK);
    107             }
    108         }
    109     }
    110 
    111     // disable temperature sensor, since it is not reported
    112     flags = 0;
    113     ioctl(dev_fd, ECS_IOCTL_APP_SET_TFLAG, &flags);
    114 
    115     if (!mEnabled) {
    116         close_device();
    117     }
    118 }
    119 
    120 AkmSensor::~AkmSensor() {
    121 }
    122 
    123 int AkmSensor::enable(int32_t handle, int en)
    124 {
    125     int what = -1;
    126     switch (handle) {
    127         case ID_A: what = Accelerometer; break;
    128         case ID_M: what = MagneticField; break;
    129         case ID_O: what = Orientation;   break;
    130     }
    131 
    132     if (uint32_t(what) >= numSensors)
    133         return -EINVAL;
    134 
    135     int newState  = en ? 1 : 0;
    136     int err = 0;
    137 
    138     if ((uint32_t(newState)<<what) != (mEnabled & (1<<what))) {
    139         if (!mEnabled) {
    140             open_device();
    141         }
    142         int cmd;
    143         switch (what) {
    144             case Accelerometer: cmd = ECS_IOCTL_APP_SET_AFLAG;  break;
    145             case MagneticField: cmd = ECS_IOCTL_APP_SET_MVFLAG; break;
    146             case Orientation:   cmd = ECS_IOCTL_APP_SET_MFLAG;  break;
    147         }
    148         short flags = newState;
    149         err = ioctl(dev_fd, cmd, &flags);
    150         err = err<0 ? -errno : 0;
    151         LOGE_IF(err, "ECS_IOCTL_APP_SET_XXX failed (%s)", strerror(-err));
    152         if (!err) {
    153             mEnabled &= ~(1<<what);
    154             mEnabled |= (uint32_t(flags)<<what);
    155             update_delay();
    156         }
    157         if (!mEnabled) {
    158             close_device();
    159         }
    160     }
    161     return err;
    162 }
    163 
    164 int AkmSensor::setDelay(int32_t handle, int64_t ns)
    165 {
    166 #ifdef ECS_IOCTL_APP_SET_DELAY
    167     int what = -1;
    168     switch (handle) {
    169         case ID_A: what = Accelerometer; break;
    170         case ID_M: what = MagneticField; break;
    171         case ID_O: what = Orientation;   break;
    172     }
    173 
    174     if (uint32_t(what) >= numSensors)
    175         return -EINVAL;
    176 
    177     if (ns < 0)
    178         return -EINVAL;
    179 
    180     mDelays[what] = ns;
    181     return update_delay();
    182 #else
    183     return -1;
    184 #endif
    185 }
    186 
    187 int AkmSensor::update_delay()
    188 {
    189     if (mEnabled) {
    190         uint64_t wanted = -1LLU;
    191         for (int i=0 ; i<numSensors ; i++) {
    192             if (mEnabled & (1<<i)) {
    193                 uint64_t ns = mDelays[i];
    194                 wanted = wanted < ns ? wanted : ns;
    195             }
    196         }
    197         short delay = int64_t(wanted) / 1000000;
    198         if (ioctl(dev_fd, ECS_IOCTL_APP_SET_DELAY, &delay)) {
    199             return -errno;
    200         }
    201     }
    202     return 0;
    203 }
    204 
    205 int AkmSensor::readEvents(sensors_event_t* data, int count)
    206 {
    207     if (count < 1)
    208         return -EINVAL;
    209 
    210     ssize_t n = mInputReader.fill(data_fd);
    211     if (n < 0)
    212         return n;
    213 
    214     int numEventReceived = 0;
    215     input_event const* event;
    216 
    217     while (count && mInputReader.readEvent(&event)) {
    218         int type = event->type;
    219         if (type == EV_ABS) {
    220             processEvent(event->code, event->value);
    221             mInputReader.next();
    222         } else if (type == EV_SYN) {
    223             int64_t time = timevalToNano(event->time);
    224             for (int j=0 ; count && mPendingMask && j<numSensors ; j++) {
    225                 if (mPendingMask & (1<<j)) {
    226                     mPendingMask &= ~(1<<j);
    227                     mPendingEvents[j].timestamp = time;
    228                     if (mEnabled & (1<<j)) {
    229                         *data++ = mPendingEvents[j];
    230                         count--;
    231                         numEventReceived++;
    232                     }
    233                 }
    234             }
    235             if (!mPendingMask) {
    236                 mInputReader.next();
    237             }
    238         } else {
    239             LOGE("AkmSensor: unknown event (type=%d, code=%d)",
    240                     type, event->code);
    241             mInputReader.next();
    242         }
    243     }
    244 
    245     return numEventReceived;
    246 }
    247 
    248 void AkmSensor::processEvent(int code, int value)
    249 {
    250     switch (code) {
    251         case EVENT_TYPE_ACCEL_X:
    252             mPendingMask |= 1<<Accelerometer;
    253             mPendingEvents[Accelerometer].acceleration.x = value * CONVERT_A_X;
    254             break;
    255         case EVENT_TYPE_ACCEL_Y:
    256             mPendingMask |= 1<<Accelerometer;
    257             mPendingEvents[Accelerometer].acceleration.y = value * CONVERT_A_Y;
    258             break;
    259         case EVENT_TYPE_ACCEL_Z:
    260             mPendingMask |= 1<<Accelerometer;
    261             mPendingEvents[Accelerometer].acceleration.z = value * CONVERT_A_Z;
    262             break;
    263 
    264         case EVENT_TYPE_MAGV_X:
    265             mPendingMask |= 1<<MagneticField;
    266             mPendingEvents[MagneticField].magnetic.x = value * CONVERT_M_X;
    267             break;
    268         case EVENT_TYPE_MAGV_Y:
    269             mPendingMask |= 1<<MagneticField;
    270             mPendingEvents[MagneticField].magnetic.y = value * CONVERT_M_Y;
    271             break;
    272         case EVENT_TYPE_MAGV_Z:
    273             mPendingMask |= 1<<MagneticField;
    274             mPendingEvents[MagneticField].magnetic.z = value * CONVERT_M_Z;
    275             break;
    276 
    277         case EVENT_TYPE_YAW:
    278             mPendingMask |= 1<<Orientation;
    279             mPendingEvents[Orientation].orientation.azimuth = value * CONVERT_O_Y;
    280             break;
    281         case EVENT_TYPE_PITCH:
    282             mPendingMask |= 1<<Orientation;
    283             mPendingEvents[Orientation].orientation.pitch = value * CONVERT_O_P;
    284             break;
    285         case EVENT_TYPE_ROLL:
    286             mPendingMask |= 1<<Orientation;
    287             mPendingEvents[Orientation].orientation.roll = value * CONVERT_O_R;
    288             break;
    289         case EVENT_TYPE_ORIENT_STATUS:
    290             mPendingMask |= 1<<Orientation;
    291             mPendingEvents[Orientation].orientation.status =
    292                     uint8_t(value & SENSOR_STATE_MASK);
    293             break;
    294     }
    295 }
    296