• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
makeSysfsName(const char * input_name,const char * file_name)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 
handleData(int value)38 void IioSensorBase::handleData(int value) {
39 }
40 
IioSensorBase(const char * dev_name,const char * data_name,const char * enable_name,const char * chan_name,int iio_chan_type)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 
~IioSensorBase()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 
readValue(int * value)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 
enable(int32_t handle,int en)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 
setDelay(int32_t handle,int64_t ns)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 
readEvents(sensors_event_t * data,int count)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