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 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 38 void IioSensorBase::handleData(int value) { 39 } 40 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 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 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 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 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 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