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 <hardware/sensors.h>
     18 #include <fcntl.h>
     19 #include <errno.h>
     20 #include <dirent.h>
     21 #include <math.h>
     22 
     23 #include <poll.h>
     24 #include <pthread.h>
     25 
     26 #include <linux/input.h>
     27 
     28 #include <cutils/atomic.h>
     29 #include <cutils/log.h>
     30 
     31 #include "nusensors.h"
     32 #include "LightSensor.h"
     33 #include "ProximitySensor.h"
     34 #include "AkmSensor.h"
     35 
     36 /*****************************************************************************/
     37 
     38 struct sensors_poll_context_t {
     39     struct sensors_poll_device_t device; // must be first
     40 
     41         sensors_poll_context_t();
     42         ~sensors_poll_context_t();
     43     int activate(int handle, int enabled);
     44     int setDelay(int handle, int64_t ns);
     45     int pollEvents(sensors_event_t* data, int count);
     46 
     47 private:
     48     enum {
     49         light           = 0,
     50         proximity       = 1,
     51         akm             = 2,
     52         numSensorDrivers,
     53         numFds,
     54     };
     55 
     56     static const size_t wake = numFds - 1;
     57     static const char WAKE_MESSAGE = 'W';
     58     struct pollfd mPollFds[numFds];
     59     int mWritePipeFd;
     60     SensorBase* mSensors[numSensorDrivers];
     61 
     62     int handleToDriver(int handle) const {
     63         switch (handle) {
     64             case ID_A:
     65             case ID_M:
     66             case ID_O:
     67                 return akm;
     68             case ID_P:
     69                 return proximity;
     70             case ID_L:
     71                 return light;
     72         }
     73         return -EINVAL;
     74     }
     75 };
     76 
     77 /*****************************************************************************/
     78 
     79 sensors_poll_context_t::sensors_poll_context_t()
     80 {
     81     mSensors[light] = new LightSensor();
     82     mPollFds[light].fd = mSensors[light]->getFd();
     83     mPollFds[light].events = POLLIN;
     84     mPollFds[light].revents = 0;
     85 
     86     mSensors[proximity] = new ProximitySensor();
     87     mPollFds[proximity].fd = mSensors[proximity]->getFd();
     88     mPollFds[proximity].events = POLLIN;
     89     mPollFds[proximity].revents = 0;
     90 
     91     mSensors[akm] = new AkmSensor();
     92     mPollFds[akm].fd = mSensors[akm]->getFd();
     93     mPollFds[akm].events = POLLIN;
     94     mPollFds[akm].revents = 0;
     95 
     96     int wakeFds[2];
     97     int result = pipe(wakeFds);
     98     LOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno));
     99     fcntl(wakeFds[0], F_SETFL, O_NONBLOCK);
    100     fcntl(wakeFds[1], F_SETFL, O_NONBLOCK);
    101     mWritePipeFd = wakeFds[1];
    102 
    103     mPollFds[wake].fd = wakeFds[0];
    104     mPollFds[wake].events = POLLIN;
    105     mPollFds[wake].revents = 0;
    106 }
    107 
    108 sensors_poll_context_t::~sensors_poll_context_t() {
    109     for (int i=0 ; i<numSensorDrivers ; i++) {
    110         delete mSensors[i];
    111     }
    112     close(mPollFds[wake].fd);
    113     close(mWritePipeFd);
    114 }
    115 
    116 int sensors_poll_context_t::activate(int handle, int enabled) {
    117     int index = handleToDriver(handle);
    118     if (index < 0) return index;
    119     int err =  mSensors[index]->enable(handle, enabled);
    120     if (enabled && !err) {
    121         const char wakeMessage(WAKE_MESSAGE);
    122         int result = write(mWritePipeFd, &wakeMessage, 1);
    123         LOGE_IF(result<0, "error sending wake message (%s)", strerror(errno));
    124     }
    125     return err;
    126 }
    127 
    128 int sensors_poll_context_t::setDelay(int handle, int64_t ns) {
    129 
    130     int index = handleToDriver(handle);
    131     if (index < 0) return index;
    132     return mSensors[index]->setDelay(handle, ns);
    133 }
    134 
    135 int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
    136 {
    137     int nbEvents = 0;
    138     int n = 0;
    139 
    140     do {
    141         // see if we have some leftover from the last poll()
    142         for (int i=0 ; count && i<numSensorDrivers ; i++) {
    143             SensorBase* const sensor(mSensors[i]);
    144             if ((mPollFds[i].revents & POLLIN) || (sensor->hasPendingEvents())) {
    145                 int nb = sensor->readEvents(data, count);
    146                 if (nb < count) {
    147                     // no more data for this sensor
    148                     mPollFds[i].revents = 0;
    149                 }
    150                 count -= nb;
    151                 nbEvents += nb;
    152                 data += nb;
    153             }
    154         }
    155 
    156         if (count) {
    157             // we still have some room, so try to see if we can get
    158             // some events immediately or just wait if we don't have
    159             // anything to return
    160             n = poll(mPollFds, numFds, nbEvents ? 0 : -1);
    161             if (n<0) {
    162                 LOGE("poll() failed (%s)", strerror(errno));
    163                 return -errno;
    164             }
    165             if (mPollFds[wake].revents & POLLIN) {
    166                 char msg;
    167                 int result = read(mPollFds[wake].fd, &msg, 1);
    168                 LOGE_IF(result<0, "error reading from wake pipe (%s)", strerror(errno));
    169                 LOGE_IF(msg != WAKE_MESSAGE, "unknown message on wake queue (0x%02x)", int(msg));
    170                 mPollFds[wake].revents = 0;
    171             }
    172         }
    173         // if we have events and space, go read them
    174     } while (n && count);
    175 
    176     return nbEvents;
    177 }
    178 
    179 /*****************************************************************************/
    180 
    181 static int poll__close(struct hw_device_t *dev)
    182 {
    183     sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
    184     if (ctx) {
    185         delete ctx;
    186     }
    187     return 0;
    188 }
    189 
    190 static int poll__activate(struct sensors_poll_device_t *dev,
    191         int handle, int enabled) {
    192     sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
    193     return ctx->activate(handle, enabled);
    194 }
    195 
    196 static int poll__setDelay(struct sensors_poll_device_t *dev,
    197         int handle, int64_t ns) {
    198     sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
    199     return ctx->setDelay(handle, ns);
    200 }
    201 
    202 static int poll__poll(struct sensors_poll_device_t *dev,
    203         sensors_event_t* data, int count) {
    204     sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
    205     return ctx->pollEvents(data, count);
    206 }
    207 
    208 /*****************************************************************************/
    209 
    210 int init_nusensors(hw_module_t const* module, hw_device_t** device)
    211 {
    212     int status = -EINVAL;
    213 
    214     sensors_poll_context_t *dev = new sensors_poll_context_t();
    215     memset(&dev->device, 0, sizeof(sensors_poll_device_t));
    216 
    217     dev->device.common.tag = HARDWARE_DEVICE_TAG;
    218     dev->device.common.version  = 0;
    219     dev->device.common.module   = const_cast<hw_module_t*>(module);
    220     dev->device.common.close    = poll__close;
    221     dev->device.activate        = poll__activate;
    222     dev->device.setDelay        = poll__setDelay;
    223     dev->device.poll            = poll__poll;
    224 
    225     *device = &dev->device.common;
    226     status = 0;
    227     return status;
    228 }
    229