/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define LOG_TAG "Sensors" #include <fcntl.h> #include <errno.h> #include <math.h> #include <poll.h> #include <unistd.h> #include <dirent.h> #include <sys/select.h> #include <cutils/log.h> #include "SensorBase.h" #include "iio/events.h" #define IIO_MAX_NAME_LENGTH 30 const char *iio_dir = "/sys/bus/iio/devices/"; /*****************************************************************************/ SensorBase::SensorBase( const char* dev_name, const char* data_name) : mDevName(dev_name), mDataName(data_name), mDevFd(-1), mDataFd(-1) { ALOGV("%s(): dev_name=%s", __func__, dev_name); if (mDataName) { mDataFd = openInput(mDataName); } } SensorBase::~SensorBase() { if (mDataFd >= 0) { close(mDataFd); } if (mDevFd >= 0) { close(mDevFd); } } int SensorBase::openDevice() { if ((mDevFd < 0) && mDevName) { mDevFd = open(mDevName, O_RDONLY); ALOGE_IF(mDevFd < 0, "Couldn't open %s (%s)", mDevName, strerror(errno)); } return 0; } int SensorBase::closeDevice() { if (mDevFd >= 0) { close(mDevFd); mDevFd = -1; } return 0; } int SensorBase::getFd() const { if (!mDataName) { return mDevFd; } return mDataFd; } int SensorBase::setDelay(int32_t handle, int64_t ns) { return 0; } bool SensorBase::hasPendingEvents() const { return false; } int64_t SensorBase::getTimestamp() { struct timespec t; t.tv_sec = t.tv_nsec = 0; clock_gettime(CLOCK_MONOTONIC, &t); return int64_t(t.tv_sec)*1000000000LL + t.tv_nsec; } /* * find_type_by_name() - function to match top level types by name * @name: top level type instance name * @type: the type of top level instance being sort * * Typical types this is used for are device and trigger. * * NOTE: This function is copied from drivers/staging/iio/Documentation/iio_utils.h * and modified. */ int SensorBase::findTypeByName(const char *name, const char *type) { const struct dirent *ent; int iio_id; int ret = -ENODEV; FILE *nameFile; DIR *dp; char thisname[IIO_MAX_NAME_LENGTH]; char filename[PATH_MAX]; dp = opendir(iio_dir); if (dp == NULL) { ALOGE("No industrialio devices available"); return ret; } while (ent = readdir(dp), ent != NULL) { if (strcmp(ent->d_name, ".") != 0 && strcmp(ent->d_name, "..") != 0 && strlen(ent->d_name) > strlen(type) && strncmp(ent->d_name, type, strlen(type)) == 0) { if (sscanf(ent->d_name + strlen(type), "%d", &iio_id) != 1) continue; sprintf(filename, "%s%s%d/name", iio_dir, type, iio_id); nameFile = fopen(filename, "r"); if (!nameFile) continue; if (fscanf(nameFile, "%s", thisname) == 1) { if (strcmp(name, thisname) == 0) { fclose(nameFile); ret = iio_id; break; } } fclose(nameFile); } } closedir(dp); return ret; } int SensorBase::openInput(const char* inputName) { int event_fd = -1; char devname[PATH_MAX]; int dev_num; dev_num = findTypeByName(inputName, "iio:device"); if (dev_num >= 0) { int fd; sprintf(devname, "/dev/iio:device%d", dev_num); fd = open(devname, O_RDONLY); if (fd >= 0) { if (ioctl(fd, IIO_GET_EVENT_FD_IOCTL, &event_fd) >= 0) strcpy(mInputName, devname + 5); else ALOGE("couldn't get a event fd from %s", devname); close(fd); /* close /dev/iio:device* */ } else { ALOGE("couldn't open %s (%s)", devname, strerror(errno)); } } else { ALOGE("couldn't find the device %s", inputName); } return event_fd; }