Home | History | Annotate | Download | only in libsensors
      1 /*
      2  * Copyright (C) 2012 Samsung
      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 #define LOG_TAG "Sensors"
     18 
     19 #include <fcntl.h>
     20 #include <errno.h>
     21 #include <cutils/log.h>
     22 #include <pthread.h>
     23 
     24 #include "IioSensorBase.h"
     25 
     26 char *IioSensorBase::makeSysfsName(const char *input_name,
     27                                        const char *file_name) {
     28     char *name;
     29     int ret;
     30 
     31     ret = asprintf(&name, "/sys/bus/iio/devices/%s/%s", input_name, file_name);
     32     if (ret < 0)
     33         return NULL;
     34 
     35     return name;
     36 }
     37 
     38 void IioSensorBase::handleData(int value) {
     39 }
     40 
     41 IioSensorBase::IioSensorBase(const char *dev_name,
     42                                      const char *data_name,
     43                                      const char *enable_name,
     44                                      const char *chan_name,
     45                                      int iio_chan_type)
     46     : SensorBase(dev_name, data_name),
     47       mEnabled(true),
     48       mHasPendingEvent(false),
     49       mInputReader(MAX_BUFFER_FOR_EVENT),
     50       mIioChanType(iio_chan_type),
     51       mIioSysfsChanFp(NULL)
     52 {
     53     pthread_mutex_init(&mLock, NULL);
     54     ALOGV("%s(): dev_name=%s", __func__, dev_name);
     55     mPendingEvent.version = sizeof(sensors_event_t);
     56     memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
     57     if (!mDataFd)
     58         return;
     59 
     60     mInputSysfsEnable = makeSysfsName(mInputName, enable_name);
     61     if (!mInputSysfsEnable) {
     62         ALOGE("%s: unable to allocate mem for %s:%s", __func__,
     63              data_name, enable_name);
     64         return;
     65     }
     66     mInputSysfsSamplingFrequency = makeSysfsName(mInputName, "sampling_frequency");
     67     if (!mInputSysfsSamplingFrequency) {
     68         ALOGE("%s: unable to allocate mem for %s:poll_delay", __func__,
     69              data_name);
     70         return;
     71     }
     72 
     73     mIioSysfsChan = makeSysfsName(mInputName, chan_name);
     74     if (!mIioSysfsChan) {
     75         ALOGE("%s: unable to allocate mem for %s:%s", __func__, data_name,
     76              chan_name);
     77         return;
     78     }
     79 
     80     mIioSysfsChanFp = fopen(mIioSysfsChan, "r");
     81     if (mIioSysfsChanFp == NULL) {
     82         ALOGE("%s: unable to open %s", __func__, mIioSysfsChan);
     83         return;
     84     }
     85 
     86     int flags = fcntl(mDataFd, F_GETFL, 0);
     87     fcntl(mDataFd, F_SETFL, flags | O_NONBLOCK);
     88 
     89     enable(0, 0);
     90 }
     91 
     92 IioSensorBase::~IioSensorBase() {
     93     if (mEnabled) {
     94         enable(0, 0);
     95     }
     96     if (mIioSysfsChanFp != NULL) {
     97         fclose(mIioSysfsChanFp);
     98     }
     99     free(mInputSysfsEnable);
    100     free(mInputSysfsSamplingFrequency);
    101     free(mIioSysfsChan);
    102 }
    103 
    104 bool IioSensorBase::readValue(int *value) {
    105 
    106     bool ret = true;
    107 
    108     if (mIioSysfsChanFp == NULL)
    109         return false;
    110 
    111     if (fscanf(mIioSysfsChanFp, "%d\n", value) != 1)
    112         ret = false;
    113 
    114     fseek(mIioSysfsChanFp, 0, SEEK_SET);
    115 
    116     return ret;
    117 }
    118 
    119 int IioSensorBase::enable(int32_t handle, int en)
    120 {
    121     int err = 0;
    122 
    123     ALOGI("%s: %s %d", __func__,  mDevName, en);
    124 
    125     pthread_mutex_lock(&mLock);
    126     if (en != mEnabled) {
    127         int fd;
    128         fd = open(mInputSysfsEnable, O_RDWR);
    129         if (fd >= 0) {
    130             err = write(fd, en ? "1" : "0", 2);
    131             close(fd);
    132             if (err < 0) {
    133                 goto cleanup;
    134             }
    135             mEnabled = en;
    136             err = 0;
    137         } else {
    138             err = -1;
    139         }
    140     }
    141 cleanup:
    142     pthread_mutex_unlock(&mLock);
    143     return err;
    144 }
    145 
    146 int IioSensorBase::setDelay(int32_t handle, int64_t ns)
    147 {
    148     int fd;
    149     int result = 0;
    150     char buf[21]; /* 21 = log10(max long long int) + 1 for sign + '\0' */
    151     pthread_mutex_lock(&mLock);
    152     if (!ns) {
    153         result = -1;
    154         goto done;
    155     }
    156     fd = open(mInputSysfsSamplingFrequency, O_RDWR);
    157     if (fd < 0) {
    158         result = -1;
    159         goto done;
    160     }
    161     /* round up ((NSEC_PER_SEC - 1) + ns) / ns */
    162     sprintf(buf, "%lld", ((1000000000 - 1) + ns) / ns);
    163     write(fd, buf, strlen(buf)+1);
    164     close(fd);
    165 done:
    166     pthread_mutex_unlock(&mLock);
    167     return result;
    168 }
    169 
    170 int IioSensorBase::readEvents(sensors_event_t* data, int count)
    171 {
    172     if (count < 1)
    173         return -EINVAL;
    174 
    175     pthread_mutex_lock(&mLock);
    176     int numEventReceived = 0;
    177 
    178     if (mHasPendingEvent) {
    179         mHasPendingEvent = false;
    180         if (mEnabled) {
    181             mPendingEvent.timestamp = getTimestamp();
    182             *data = mPendingEvent;
    183             numEventReceived++;
    184         }
    185         goto done;
    186     }
    187 
    188     iio_event_data const* event;
    189 
    190     while (count && mInputReader.readEvent(mDataFd, &event)) {
    191         int value;
    192         if (IIO_EVENT_CODE_EXTRACT_CHAN_TYPE(event->id) == mIioChanType) {
    193             if (mEnabled && readValue(&value)) {
    194                 handleData(value);
    195                 mPendingEvent.timestamp = event->timestamp;
    196                 *data++ = mPendingEvent;
    197                 count--;
    198                 numEventReceived++;
    199             }
    200         }
    201         mInputReader.next();
    202     }
    203 
    204 done:
    205     pthread_mutex_unlock(&mLock);
    206     return numEventReceived;
    207 }
    208