/* * Copyright (C) 2011 Samsung * * 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. */ #include #include #include #include #include #include #include #include #include #include #include #include "SamsungSensorBase.h" char *SamsungSensorBase::makeSysfsName(const char *input_name, const char *file_name) { char *name; int length = strlen("/sys/class/input/") + strlen(input_name) + strlen("/device/") + strlen(file_name); name = new char[length + 1]; if (name) { strcpy(name, "/sys/class/input/"); strcat(name, input_name); strcat(name, "/device/"); strcat(name, file_name); } return name; } bool SamsungSensorBase::handleEvent(input_event const * event __unused) { return true; } int SamsungSensorBase::handleEnable(int en __unused) { return 0; } SamsungSensorBase::SamsungSensorBase(const char *data_name, int sensor_code) : SensorBase(data_name), mEnabled(true), mHasPendingEvent(false), mInputReader(4), mSensorCode(sensor_code), mLock(PTHREAD_MUTEX_INITIALIZER) { mPendingEvent.version = sizeof(sensors_event_t); memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data)); if (!data_fd) return; mInputSysfsEnable = makeSysfsName(input_name, "enable"); if (!mInputSysfsEnable) { ALOGE("%s: unable to allocate mem for %s:enable", __func__, data_name); return; } mInputSysfsPollDelay = makeSysfsName(input_name, "poll_delay"); if (!mInputSysfsPollDelay) { ALOGE("%s: unable to allocate mem for %s:poll_delay", __func__, data_name); return; } int flags = fcntl(data_fd, F_GETFL, 0); fcntl(data_fd, F_SETFL, flags | O_NONBLOCK); enable(0, 0); } SamsungSensorBase::~SamsungSensorBase() { if (mEnabled) { enable(0, 0); } delete[] mInputSysfsEnable; delete[] mInputSysfsPollDelay; } int SamsungSensorBase::enable(int32_t handle __unused, int en) { int err = 0; pthread_mutex_lock(&mLock); if (en != mEnabled) { int fd; fd = open(mInputSysfsEnable, O_RDWR); if (fd >= 0) { err = write(fd, en ? "1" : "0", 2); close(fd); if (err < 0) { goto cleanup; } mEnabled = en; err = handleEnable(en); } else { err = -1; } } cleanup: pthread_mutex_unlock(&mLock); return err; } int SamsungSensorBase::setDelay(int32_t handle __unused, int64_t ns) { int fd; int result = 0; char buf[21]; pthread_mutex_lock(&mLock); fd = open(mInputSysfsPollDelay, O_RDWR); if (fd < 0) { result = -1; goto done; } sprintf(buf, "%lld", ns); write(fd, buf, strlen(buf)+1); close(fd); done: pthread_mutex_unlock(&mLock); return result; } int64_t SamsungSensorBase::getTimestamp() { struct timespec t; t.tv_sec = t.tv_nsec = 0; clock_gettime(CLOCK_BOOTTIME, &t); return int64_t(t.tv_sec)*1000000000LL + t.tv_nsec; } int SamsungSensorBase::readEvents(sensors_event_t* data, int count) { if (count < 1) return -EINVAL; pthread_mutex_lock(&mLock); int numEventReceived = 0; if (mHasPendingEvent) { mHasPendingEvent = false; if (mEnabled) { mPendingEvent.timestamp = getTimestamp(); *data = mPendingEvent; numEventReceived++; } goto done; } input_event const* event; while (count && mInputReader.readEvent(data_fd, &event)) { if (event->type == EV_ABS) { if (event->code == mSensorCode) { if (mEnabled && handleEvent(event)) { mPendingEvent.timestamp = timevalToNano(event->time); *data++ = mPendingEvent; count--; numEventReceived++; } } } mInputReader.next(); } done: pthread_mutex_unlock(&mLock); return numEventReceived; }