Home | History | Annotate | Download | only in libsensors
      1 /*
      2  * Copyright (C) 2012 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 #define LOG_TAG "Sensors"
     18 
     19 #include <fcntl.h>
     20 #include <errno.h>
     21 #include <math.h>
     22 #include <poll.h>
     23 #include <unistd.h>
     24 #include <dirent.h>
     25 #include <sys/select.h>
     26 
     27 #include <cutils/log.h>
     28 
     29 #include "SensorBase.h"
     30 #include "iio/events.h"
     31 
     32 #define IIO_MAX_NAME_LENGTH 30
     33 
     34 const char *iio_dir = "/sys/bus/iio/devices/";
     35 
     36 /*****************************************************************************/
     37 
     38 SensorBase::SensorBase(
     39         const char* dev_name,
     40         const char* data_name)
     41     : mDevName(dev_name), mDataName(data_name),
     42       mDevFd(-1), mDataFd(-1)
     43 {
     44     ALOGV("%s(): dev_name=%s", __func__, dev_name);
     45     if (mDataName) {
     46         mDataFd = openInput(mDataName);
     47     }
     48 }
     49 
     50 SensorBase::~SensorBase() {
     51     if (mDataFd >= 0) {
     52         close(mDataFd);
     53     }
     54     if (mDevFd >= 0) {
     55         close(mDevFd);
     56     }
     57 }
     58 
     59 int SensorBase::openDevice() {
     60     if ((mDevFd < 0) && mDevName) {
     61         mDevFd = open(mDevName, O_RDONLY);
     62         ALOGE_IF(mDevFd < 0, "Couldn't open %s (%s)", mDevName, strerror(errno));
     63     }
     64     return 0;
     65 }
     66 
     67 int SensorBase::closeDevice() {
     68     if (mDevFd >= 0) {
     69         close(mDevFd);
     70         mDevFd = -1;
     71     }
     72     return 0;
     73 }
     74 
     75 int SensorBase::getFd() const {
     76     if (!mDataName) {
     77         return mDevFd;
     78     }
     79     return mDataFd;
     80 }
     81 
     82 int SensorBase::setDelay(int32_t handle, int64_t ns) {
     83     return 0;
     84 }
     85 
     86 bool SensorBase::hasPendingEvents() const {
     87     return false;
     88 }
     89 
     90 int64_t SensorBase::getTimestamp() {
     91     struct timespec t;
     92     t.tv_sec = t.tv_nsec = 0;
     93     clock_gettime(CLOCK_MONOTONIC, &t);
     94     return int64_t(t.tv_sec)*1000000000LL + t.tv_nsec;
     95 }
     96 
     97 /*
     98  * find_type_by_name() - function to match top level types by name
     99  * @name: top level type instance name
    100  * @type: the type of top level instance being sort
    101  *
    102  * Typical types this is used for are device and trigger.
    103  *
    104  * NOTE: This function is copied from drivers/staging/iio/Documentation/iio_utils.h
    105  * and modified.
    106  */
    107 int SensorBase::findTypeByName(const char *name, const char *type)
    108 {
    109     const struct dirent *ent;
    110     int iio_id;
    111     int ret = -ENODEV;
    112 
    113     FILE *nameFile;
    114     DIR *dp;
    115     char thisname[IIO_MAX_NAME_LENGTH];
    116     char filename[PATH_MAX];
    117 
    118     dp = opendir(iio_dir);
    119     if (dp == NULL) {
    120         ALOGE("No industrialio devices available");
    121         return ret;
    122     }
    123 
    124     while (ent = readdir(dp), ent != NULL) {
    125         if (strcmp(ent->d_name, ".") != 0 &&
    126             strcmp(ent->d_name, "..") != 0 &&
    127             strlen(ent->d_name) > strlen(type) &&
    128             strncmp(ent->d_name, type, strlen(type)) == 0) {
    129             if (sscanf(ent->d_name + strlen(type), "%d", &iio_id) != 1)
    130                 continue;
    131 
    132             sprintf(filename, "%s%s%d/name", iio_dir, type, iio_id);
    133             nameFile = fopen(filename, "r");
    134             if (!nameFile)
    135                 continue;
    136 
    137             if (fscanf(nameFile, "%s", thisname) == 1) {
    138                 if (strcmp(name, thisname) == 0) {
    139                     fclose(nameFile);
    140                     ret = iio_id;
    141                     break;
    142                 }
    143             }
    144             fclose(nameFile);
    145         }
    146     }
    147     closedir(dp);
    148     return ret;
    149 }
    150 
    151 int SensorBase::openInput(const char* inputName) {
    152     int event_fd = -1;
    153     char devname[PATH_MAX];
    154     int dev_num;
    155 
    156     dev_num =  findTypeByName(inputName, "iio:device");
    157     if (dev_num >= 0) {
    158         int fd;
    159         sprintf(devname, "/dev/iio:device%d", dev_num);
    160         fd = open(devname, O_RDONLY);
    161         if (fd >= 0) {
    162             if (ioctl(fd, IIO_GET_EVENT_FD_IOCTL, &event_fd) >= 0)
    163                 strcpy(mInputName, devname + 5);
    164             else
    165                 ALOGE("couldn't get a event fd from %s", devname);
    166             close(fd); /* close /dev/iio:device* */
    167         } else {
    168             ALOGE("couldn't open %s (%s)", devname, strerror(errno));
    169         }
    170     } else {
    171        ALOGE("couldn't find the device %s", inputName);
    172     }
    173 
    174     return event_fd;
    175 }
    176