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
SensorBase(const char * dev_name,const char * data_name)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
~SensorBase()50 SensorBase::~SensorBase() {
51 if (mDataFd >= 0) {
52 close(mDataFd);
53 }
54 if (mDevFd >= 0) {
55 close(mDevFd);
56 }
57 }
58
openDevice()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
closeDevice()67 int SensorBase::closeDevice() {
68 if (mDevFd >= 0) {
69 close(mDevFd);
70 mDevFd = -1;
71 }
72 return 0;
73 }
74
getFd() const75 int SensorBase::getFd() const {
76 if (!mDataName) {
77 return mDevFd;
78 }
79 return mDataFd;
80 }
81
setDelay(int32_t handle,int64_t ns)82 int SensorBase::setDelay(int32_t handle, int64_t ns) {
83 return 0;
84 }
85
hasPendingEvents() const86 bool SensorBase::hasPendingEvents() const {
87 return false;
88 }
89
getTimestamp()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 */
findTypeByName(const char * name,const char * type)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
openInput(const char * inputName)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