blob: b904a008aa5f5a8e95a846ad091d3e723f0852d5 [file] [log] [blame]
/*
* 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;
}