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 <dlfcn.h>
     25 
     26 #include "ak8973b.h"
     27 
     28 #include <cutils/log.h>
     29 
     30 #include "AkmSensor.h"
     31 
     32 /*****************************************************************************/
     33 
     34 int (*akm_is_sensor_enabled)(uint32_t sensor_type);
     35 int (*akm_enable_sensor)(uint32_t sensor_type);
     36 int (*akm_disable_sensor)(uint32_t sensor_type);
     37 int (*akm_set_delay)(uint32_t sensor_type, uint64_t delay);
     38 
     39 int stub_is_sensor_enabled(uint32_t sensor_type) {
     40     return 0;
     41 }
     42 
     43 int stub_enable_disable_sensor(uint32_t sensor_type) {
     44     return -ENODEV;
     45 }
     46 
     47 int stub_set_delay(uint32_t sensor_type, uint64_t delay) {
     48     return -ENODEV;
     49 }
     50 
     51 AkmSensor::AkmSensor()
     52 : SensorBase(NULL, NULL),
     53       mEnabled(0),
     54       mPendingMask(0),
     55       mInputReader(32)
     56 {
     57     /* Open the library before opening the input device.  The library
     58      * creates a uinput device.
     59      */
     60     if (loadAKMLibrary() == 0) {
     61         data_name = "compass";
     62         data_fd = openInput("compass");
     63     }
     64 
     65     memset(mPendingEvents, 0, sizeof(mPendingEvents));
     66 
     67     mPendingEvents[Accelerometer].version = sizeof(sensors_event_t);
     68     mPendingEvents[Accelerometer].sensor = ID_A;
     69     mPendingEvents[Accelerometer].type = SENSOR_TYPE_ACCELEROMETER;
     70     mPendingEvents[Accelerometer].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
     71 
     72     mPendingEvents[MagneticField].version = sizeof(sensors_event_t);
     73     mPendingEvents[MagneticField].sensor = ID_M;
     74     mPendingEvents[MagneticField].type = SENSOR_TYPE_MAGNETIC_FIELD;
     75     mPendingEvents[MagneticField].magnetic.status = SENSOR_STATUS_ACCURACY_HIGH;
     76 
     77     mPendingEvents[Orientation  ].version = sizeof(sensors_event_t);
     78     mPendingEvents[Orientation  ].sensor = ID_O;
     79     mPendingEvents[Orientation  ].type = SENSOR_TYPE_ORIENTATION;
     80     mPendingEvents[Orientation  ].orientation.status = SENSOR_STATUS_ACCURACY_HIGH;
     81 
     82     // read the actual value of all sensors if they're enabled already
     83     struct input_absinfo absinfo;
     84     short flags = 0;
     85 
     86     if (akm_is_sensor_enabled(SENSOR_TYPE_ACCELEROMETER))  {
     87         mEnabled |= 1<<Accelerometer;
     88         if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_X), &absinfo)) {
     89             mPendingEvents[Accelerometer].acceleration.x = absinfo.value * CONVERT_A_X;
     90         }
     91         if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Y), &absinfo)) {
     92             mPendingEvents[Accelerometer].acceleration.y = absinfo.value * CONVERT_A_Y;
     93         }
     94         if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Z), &absinfo)) {
     95             mPendingEvents[Accelerometer].acceleration.z = absinfo.value * CONVERT_A_Z;
     96         }
     97     }
     98     if (akm_is_sensor_enabled(SENSOR_TYPE_MAGNETIC_FIELD))  {
     99         mEnabled |= 1<<MagneticField;
    100         if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_X), &absinfo)) {
    101             mPendingEvents[MagneticField].magnetic.x = absinfo.value * CONVERT_M_X;
    102         }
    103         if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_Y), &absinfo)) {
    104             mPendingEvents[MagneticField].magnetic.y = absinfo.value * CONVERT_M_Y;
    105         }
    106         if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_Z), &absinfo)) {
    107             mPendingEvents[MagneticField].magnetic.z = absinfo.value * CONVERT_M_Z;
    108         }
    109     }
    110     if (akm_is_sensor_enabled(SENSOR_TYPE_ORIENTATION))  {
    111         mEnabled |= 1<<Orientation;
    112         if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_YAW), &absinfo)) {
    113             mPendingEvents[Orientation].orientation.azimuth = absinfo.value;
    114         }
    115         if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_PITCH), &absinfo)) {
    116             mPendingEvents[Orientation].orientation.pitch = absinfo.value;
    117         }
    118         if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ROLL), &absinfo)) {
    119             mPendingEvents[Orientation].orientation.roll = -absinfo.value;
    120         }
    121         if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ORIENT_STATUS), &absinfo)) {
    122             mPendingEvents[Orientation].orientation.status = uint8_t(absinfo.value & SENSOR_STATE_MASK);
    123         }
    124     }
    125 
    126     // disable temperature sensor, since it is not supported
    127     akm_disable_sensor(SENSOR_TYPE_TEMPERATURE);
    128 }
    129 
    130 AkmSensor::~AkmSensor()
    131 {
    132     if (mLibAKM) {
    133         unsigned ref = ::dlclose(mLibAKM);
    134     }
    135 }
    136 
    137 int AkmSensor::enable(int32_t handle, int en)
    138 {
    139     int what = -1;
    140 
    141     switch (handle) {
    142         case ID_A: what = Accelerometer; break;
    143         case ID_M: what = MagneticField; break;
    144         case ID_O: what = Orientation;   break;
    145     }
    146 
    147     if (uint32_t(what) >= numSensors)
    148         return -EINVAL;
    149 
    150     int newState  = en ? 1 : 0;
    151     int err = 0;
    152 
    153     if ((uint32_t(newState)<<what) != (mEnabled & (1<<what))) {
    154         uint32_t sensor_type;
    155         switch (what) {
    156             case Accelerometer: sensor_type = SENSOR_TYPE_ACCELEROMETER;  break;
    157             case MagneticField: sensor_type = SENSOR_TYPE_MAGNETIC_FIELD; break;
    158             case Orientation:   sensor_type = SENSOR_TYPE_ORIENTATION;  break;
    159         }
    160         short flags = newState;
    161         if (en)
    162             err = akm_enable_sensor(sensor_type);
    163         else
    164             err = akm_disable_sensor(sensor_type);
    165 
    166         ALOGE_IF(err, "Could not change sensor state (%s)", strerror(-err));
    167         if (!err) {
    168             mEnabled &= ~(1<<what);
    169             mEnabled |= (uint32_t(flags)<<what);
    170         }
    171     }
    172     return err;
    173 }
    174 
    175 int AkmSensor::setDelay(int32_t handle, int64_t ns)
    176 {
    177     uint32_t sensor_type = 0;
    178 
    179     if (ns < 0)
    180         return -EINVAL;
    181 
    182     switch (handle) {
    183         case ID_A: sensor_type = SENSOR_TYPE_ACCELEROMETER; break;
    184         case ID_M: sensor_type = SENSOR_TYPE_MAGNETIC_FIELD; break;
    185         case ID_O: sensor_type = SENSOR_TYPE_ORIENTATION; break;
    186     }
    187 
    188     if (sensor_type == 0)
    189         return -EINVAL;
    190 
    191     return akm_set_delay(sensor_type, ns);
    192 }
    193 
    194 int AkmSensor::loadAKMLibrary()
    195 {
    196     mLibAKM = dlopen("libakm.so", RTLD_NOW);
    197 
    198     if (!mLibAKM) {
    199         akm_is_sensor_enabled = stub_is_sensor_enabled;
    200         akm_enable_sensor = stub_enable_disable_sensor;
    201         akm_disable_sensor = stub_enable_disable_sensor;
    202         akm_set_delay = stub_set_delay;
    203         ALOGE("AkmSensor: unable to load AKM Library, %s", dlerror());
    204         return -ENOENT;
    205     }
    206 
    207     *(void **)&akm_is_sensor_enabled = dlsym(mLibAKM, "akm_is_sensor_enabled");
    208     *(void **)&akm_enable_sensor = dlsym(mLibAKM, "akm_enable_sensor");
    209     *(void **)&akm_disable_sensor = dlsym(mLibAKM, "akm_disable_sensor");
    210     *(void **)&akm_set_delay = dlsym(mLibAKM, "akm_set_delay");
    211 
    212     return 0;
    213 }
    214 
    215 int AkmSensor::readEvents(sensors_event_t* data, int count)
    216 {
    217     if (count < 1)
    218         return -EINVAL;
    219 
    220     ssize_t n = mInputReader.fill(data_fd);
    221     if (n < 0)
    222         return n;
    223 
    224     int numEventReceived = 0;
    225     input_event const* event;
    226 
    227     while (count && mInputReader.readEvent(&event)) {
    228         int type = event->type;
    229         if (type == EV_REL) {
    230             processEvent(event->code, event->value);
    231             mInputReader.next();
    232         } else if (type == EV_SYN) {
    233             int64_t time = timevalToNano(event->time);
    234             for (int j=0 ; count && mPendingMask && j<numSensors ; j++) {
    235                 if (mPendingMask & (1<<j)) {
    236                     mPendingMask &= ~(1<<j);
    237                     mPendingEvents[j].timestamp = time;
    238                     if (mEnabled & (1<<j)) {
    239                         *data++ = mPendingEvents[j];
    240                         count--;
    241                         numEventReceived++;
    242                     }
    243                 }
    244             }
    245             if (!mPendingMask) {
    246                 mInputReader.next();
    247             }
    248         } else {
    249             ALOGE("AkmSensor: unknown event (type=%d, code=%d)",
    250                     type, event->code);
    251             mInputReader.next();
    252         }
    253     }
    254     return numEventReceived;
    255 }
    256 
    257 void AkmSensor::processEvent(int code, int value)
    258 {
    259     switch (code) {
    260         case EVENT_TYPE_ACCEL_X:
    261             mPendingMask |= 1<<Accelerometer;
    262             mPendingEvents[Accelerometer].acceleration.x = value * CONVERT_A_X;
    263             break;
    264         case EVENT_TYPE_ACCEL_Y:
    265             mPendingMask |= 1<<Accelerometer;
    266             mPendingEvents[Accelerometer].acceleration.y = value * CONVERT_A_Y;
    267             break;
    268         case EVENT_TYPE_ACCEL_Z:
    269             mPendingMask |= 1<<Accelerometer;
    270             mPendingEvents[Accelerometer].acceleration.z = value * CONVERT_A_Z;
    271             break;
    272 
    273         case EVENT_TYPE_MAGV_X:
    274             mPendingMask |= 1<<MagneticField;
    275             mPendingEvents[MagneticField].magnetic.x = value * CONVERT_M_X;
    276             break;
    277         case EVENT_TYPE_MAGV_Y:
    278             mPendingMask |= 1<<MagneticField;
    279             mPendingEvents[MagneticField].magnetic.y = value * CONVERT_M_Y;
    280             break;
    281         case EVENT_TYPE_MAGV_Z:
    282             mPendingMask |= 1<<MagneticField;
    283             mPendingEvents[MagneticField].magnetic.z = value * CONVERT_M_Z;
    284             break;
    285 
    286         case EVENT_TYPE_YAW:
    287             mPendingMask |= 1<<Orientation;
    288             mPendingEvents[Orientation].orientation.azimuth = value * CONVERT_O_A;
    289             break;
    290         case EVENT_TYPE_PITCH:
    291             mPendingMask |= 1<<Orientation;
    292             mPendingEvents[Orientation].orientation.pitch = value * CONVERT_O_P;
    293             break;
    294         case EVENT_TYPE_ROLL:
    295             mPendingMask |= 1<<Orientation;
    296             mPendingEvents[Orientation].orientation.roll = value * CONVERT_O_R;
    297             break;
    298         case EVENT_TYPE_ORIENT_STATUS:
    299             uint8_t status = uint8_t(value & SENSOR_STATE_MASK);
    300             if (status == 4)
    301                 status = 0;
    302             mPendingMask |= 1<<Orientation;
    303             mPendingEvents[Orientation].orientation.status = status;
    304             break;
    305     }
    306 }
    307