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)(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(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     for (int i=0 ; i<numSensors ; i++)
     83         mDelays[i] = 200000000; // 200 ms by default
     84 
     85     // read the actual value of all sensors if they're enabled already
     86     struct input_absinfo absinfo;
     87     short flags = 0;
     88 
     89     if (akm_is_sensor_enabled(SENSOR_TYPE_ACCELEROMETER))  {
     90         mEnabled |= 1<<Accelerometer;
     91         if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_X), &absinfo)) {
     92             mPendingEvents[Accelerometer].acceleration.x = absinfo.value * CONVERT_A_X;
     93         }
     94         if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Y), &absinfo)) {
     95             mPendingEvents[Accelerometer].acceleration.y = absinfo.value * CONVERT_A_Y;
     96         }
     97         if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Z), &absinfo)) {
     98             mPendingEvents[Accelerometer].acceleration.z = absinfo.value * CONVERT_A_Z;
     99         }
    100     }
    101     if (akm_is_sensor_enabled(SENSOR_TYPE_MAGNETIC_FIELD))  {
    102         mEnabled |= 1<<MagneticField;
    103         if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_X), &absinfo)) {
    104             mPendingEvents[MagneticField].magnetic.x = absinfo.value * CONVERT_M_X;
    105         }
    106         if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_Y), &absinfo)) {
    107             mPendingEvents[MagneticField].magnetic.y = absinfo.value * CONVERT_M_Y;
    108         }
    109         if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_Z), &absinfo)) {
    110             mPendingEvents[MagneticField].magnetic.z = absinfo.value * CONVERT_M_Z;
    111         }
    112     }
    113     if (akm_is_sensor_enabled(SENSOR_TYPE_ORIENTATION))  {
    114         mEnabled |= 1<<Orientation;
    115         if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_YAW), &absinfo)) {
    116             mPendingEvents[Orientation].orientation.azimuth = absinfo.value;
    117         }
    118         if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_PITCH), &absinfo)) {
    119             mPendingEvents[Orientation].orientation.pitch = absinfo.value;
    120         }
    121         if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ROLL), &absinfo)) {
    122             mPendingEvents[Orientation].orientation.roll = -absinfo.value;
    123         }
    124         if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ORIENT_STATUS), &absinfo)) {
    125             mPendingEvents[Orientation].orientation.status = uint8_t(absinfo.value & SENSOR_STATE_MASK);
    126         }
    127     }
    128 
    129     // disable temperature sensor, since it is not supported
    130     akm_disable_sensor(SENSOR_TYPE_TEMPERATURE);
    131 }
    132 
    133 AkmSensor::~AkmSensor()
    134 {
    135     if (mLibAKM) {
    136         unsigned ref = ::dlclose(mLibAKM);
    137     }
    138 }
    139 
    140 int AkmSensor::enable(int32_t handle, int en)
    141 {
    142     int what = -1;
    143 
    144     switch (handle) {
    145         case ID_A: what = Accelerometer; break;
    146         case ID_M: what = MagneticField; break;
    147         case ID_O: what = Orientation;   break;
    148     }
    149 
    150     if (uint32_t(what) >= numSensors)
    151         return -EINVAL;
    152 
    153     int newState  = en ? 1 : 0;
    154     int err = 0;
    155 
    156     if ((uint32_t(newState)<<what) != (mEnabled & (1<<what))) {
    157         uint32_t sensor_type;
    158         switch (what) {
    159             case Accelerometer: sensor_type = SENSOR_TYPE_ACCELEROMETER;  break;
    160             case MagneticField: sensor_type = SENSOR_TYPE_MAGNETIC_FIELD; break;
    161             case Orientation:   sensor_type = SENSOR_TYPE_ORIENTATION;  break;
    162         }
    163         short flags = newState;
    164         if (en)
    165             err = akm_enable_sensor(sensor_type);
    166         else
    167             err = akm_disable_sensor(sensor_type);
    168 
    169         LOGE_IF(err, "Could not change sensor state (%s)", strerror(-err));
    170         if (!err) {
    171             mEnabled &= ~(1<<what);
    172             mEnabled |= (uint32_t(flags)<<what);
    173             update_delay();
    174         }
    175     }
    176     return err;
    177 }
    178 
    179 int AkmSensor::setDelay(int32_t handle, int64_t ns)
    180 {
    181     int what = -1;
    182     switch (handle) {
    183         case ID_A: what = Accelerometer; break;
    184         case ID_M: what = MagneticField; break;
    185         case ID_O: what = Orientation;   break;
    186     }
    187 
    188     if (uint32_t(what) >= numSensors)
    189         return -EINVAL;
    190 
    191     if (ns < 0)
    192         return -EINVAL;
    193 
    194     mDelays[what] = ns;
    195     return update_delay();
    196 }
    197 
    198 int AkmSensor::update_delay()
    199 {
    200     if (mEnabled) {
    201         uint64_t wanted = -1LLU;
    202         for (int i=0 ; i<numSensors ; i++) {
    203             if (mEnabled & (1<<i)) {
    204                 uint64_t ns = mDelays[i];
    205                 wanted = wanted < ns ? wanted : ns;
    206             }
    207         }
    208         return akm_set_delay(int64_t(wanted));
    209     }
    210     return 0;
    211 }
    212 
    213 int AkmSensor::loadAKMLibrary()
    214 {
    215     mLibAKM = dlopen("libakm.so", RTLD_NOW);
    216 
    217     if (!mLibAKM) {
    218         akm_is_sensor_enabled = stub_is_sensor_enabled;
    219         akm_enable_sensor = stub_enable_disable_sensor;
    220         akm_disable_sensor = stub_enable_disable_sensor;
    221         akm_set_delay = stub_set_delay;
    222         LOGE("AkmSensor: unable to load AKM Library, %s", dlerror());
    223         return -ENOENT;
    224     }
    225 
    226     *(void **)&akm_is_sensor_enabled = dlsym(mLibAKM, "akm_is_sensor_enabled");
    227     *(void **)&akm_enable_sensor = dlsym(mLibAKM, "akm_enable_sensor");
    228     *(void **)&akm_disable_sensor = dlsym(mLibAKM, "akm_disable_sensor");
    229     *(void **)&akm_set_delay = dlsym(mLibAKM, "akm_set_delay");
    230 
    231     return 0;
    232 }
    233 
    234 int AkmSensor::readEvents(sensors_event_t* data, int count)
    235 {
    236     if (count < 1)
    237         return -EINVAL;
    238 
    239     ssize_t n = mInputReader.fill(data_fd);
    240     if (n < 0)
    241         return n;
    242 
    243     int numEventReceived = 0;
    244     input_event const* event;
    245 
    246     while (count && mInputReader.readEvent(&event)) {
    247         int type = event->type;
    248         if (type == EV_REL) {
    249             processEvent(event->code, event->value);
    250             mInputReader.next();
    251         } else if (type == EV_SYN) {
    252             int64_t time = timevalToNano(event->time);
    253             for (int j=0 ; count && mPendingMask && j<numSensors ; j++) {
    254                 if (mPendingMask & (1<<j)) {
    255                     mPendingMask &= ~(1<<j);
    256                     mPendingEvents[j].timestamp = time;
    257                     if (mEnabled & (1<<j)) {
    258                         *data++ = mPendingEvents[j];
    259                         count--;
    260                         numEventReceived++;
    261                     }
    262                 }
    263             }
    264             if (!mPendingMask) {
    265                 mInputReader.next();
    266             }
    267         } else {
    268             LOGE("AkmSensor: unknown event (type=%d, code=%d)",
    269                     type, event->code);
    270             mInputReader.next();
    271         }
    272     }
    273     return numEventReceived;
    274 }
    275 
    276 void AkmSensor::processEvent(int code, int value)
    277 {
    278     switch (code) {
    279         case EVENT_TYPE_ACCEL_X:
    280             mPendingMask |= 1<<Accelerometer;
    281             mPendingEvents[Accelerometer].acceleration.x = value * CONVERT_A_X;
    282             break;
    283         case EVENT_TYPE_ACCEL_Y:
    284             mPendingMask |= 1<<Accelerometer;
    285             mPendingEvents[Accelerometer].acceleration.y = value * CONVERT_A_Y;
    286             break;
    287         case EVENT_TYPE_ACCEL_Z:
    288             mPendingMask |= 1<<Accelerometer;
    289             mPendingEvents[Accelerometer].acceleration.z = value * CONVERT_A_Z;
    290             break;
    291 
    292         case EVENT_TYPE_MAGV_X:
    293             mPendingMask |= 1<<MagneticField;
    294             mPendingEvents[MagneticField].magnetic.x = value * CONVERT_M_X;
    295             break;
    296         case EVENT_TYPE_MAGV_Y:
    297             mPendingMask |= 1<<MagneticField;
    298             mPendingEvents[MagneticField].magnetic.y = value * CONVERT_M_Y;
    299             break;
    300         case EVENT_TYPE_MAGV_Z:
    301             mPendingMask |= 1<<MagneticField;
    302             mPendingEvents[MagneticField].magnetic.z = value * CONVERT_M_Z;
    303             break;
    304 
    305         case EVENT_TYPE_YAW:
    306             mPendingMask |= 1<<Orientation;
    307             mPendingEvents[Orientation].orientation.azimuth = value * CONVERT_O_A;
    308             break;
    309         case EVENT_TYPE_PITCH:
    310             mPendingMask |= 1<<Orientation;
    311             mPendingEvents[Orientation].orientation.pitch = value * CONVERT_O_P;
    312             break;
    313         case EVENT_TYPE_ROLL:
    314             mPendingMask |= 1<<Orientation;
    315             mPendingEvents[Orientation].orientation.roll = value * CONVERT_O_R;
    316             break;
    317         case EVENT_TYPE_ORIENT_STATUS:
    318             mPendingMask |= 1<<Orientation;
    319             mPendingEvents[Orientation].orientation.status =
    320                     uint8_t(value & SENSOR_STATE_MASK);
    321             break;
    322     }
    323 }
    324