--- /dev/null
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#ifndef BOARD_CONFIG_H
+#define BOARD_CONFIG_H
+
+struct sensors_poll_context_t;
+class SensorBase;
+
+/* implementations are located in board specific dirs */
+class BoardConfig {
+
+public:
+ static const struct sensor_t* sensorList();
+ static int sensorListSize();
+
+private:
+ static int handleToDriver(int handle);
+ static void initSensors(SensorBase* sensors[]);
+
+ friend struct sensors_poll_context_t;
+};
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include "Helpers.h"
+
+int PathOps::write(const std::string &path, const std::string &buf)
+{
+ std::string p = mBasePath + path;
+ int fd = ::open(p.c_str(), O_WRONLY);
+ if (fd < 0)
+ return -errno;
+
+ int ret = ::write(fd, buf.c_str(), buf.size());
+ close(fd);
+
+ return ret;
+}
+
+int PathOps::write(const std::string &path, unsigned int data)
+{
+ std::ostringstream os;
+ os << data;
+ return PathOps::write(path, os.str());
+}
+
+int PathOps::read(const std::string &path, char *buf, int len)
+{
+ std::string p = mBasePath + path;
+ int fd = ::open(p.c_str(), O_RDONLY);
+ if (fd < 0)
+ return -errno;
+
+ int ret = ::read(fd, buf, len);
+ close(fd);
+
+ return ret;
+}
+
+int PathOps::read(const std::string &path, std::string &buf)
+{
+ std::string p = mBasePath + path;
+ /* Using fstream for reading stuff into std::string */
+ std::ifstream f(p.c_str(), std::fstream::in);
+ if (f.fail())
+ return -EINVAL;
+
+ int ret = 0;
+ f >> buf;
+ if (f.bad())
+ ret = -EIO;
+ f.close();
+
+ return ret;
+}
+
+bool PathOps::exists(const std::string &path)
+{
+ struct stat s;
+ return (bool) (stat((mBasePath + path).c_str(), &s) == 0);
+}
+
+bool PathOps::exists()
+{
+ return PathOps::exists("");
+}
--- /dev/null
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#ifndef ANDROID_SENSOR_HELPERS_H
+#define ANDROID_SENSOR_HELPERS_H
+
+#include <string>
+
+class PathOps {
+ std::string mBasePath;
+
+public:
+ PathOps():mBasePath("") {};
+ PathOps(const char *basePath):mBasePath(basePath) {}
+
+ /* write data to base path (dir) + provided path */
+ int write(const std::string &path, const std::string &buf);
+ int write(const std::string &path, unsigned int data);
+
+ /* read data from base path (dir) + provided path */
+ int read(const std::string &path, char *buf, int len);
+ int read(const std::string &path, std::string &buf);
+
+ const char *basePath() { return mBasePath.c_str(); }
+
+ bool exists(const std::string &path);
+ bool exists();
+};
+
+inline unsigned int nsToMs(int64_t ns) { return ns/1000000; }
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#include <stdint.h>
+#include <errno.h>
+#include <unistd.h>
+#include <poll.h>
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <linux/input.h>
+
+#include <cutils/log.h>
+
+#include "InputEventReader.h"
+
+/*****************************************************************************/
+
+struct input_event;
+
+InputEventCircularReader::InputEventCircularReader(size_t numEvents)
+ : mBuffer(new input_event[numEvents * 2]),
+ mBufferEnd(mBuffer + numEvents),
+ mHead(mBuffer),
+ mCurr(mBuffer),
+ mFreeSpace(numEvents)
+{
+}
+
+InputEventCircularReader::~InputEventCircularReader()
+{
+ delete [] mBuffer;
+}
+
+ssize_t InputEventCircularReader::fill(int fd)
+{
+ size_t numEventsRead = 0;
+ if (mFreeSpace) {
+ const ssize_t nread = read(fd, mHead, mFreeSpace * sizeof(input_event));
+ if (nread<0 || nread % sizeof(input_event)) {
+ // we got a partial event!!
+ return nread<0 ? -errno : -EINVAL;
+ }
+
+ numEventsRead = nread / sizeof(input_event);
+ if (numEventsRead) {
+ mHead += numEventsRead;
+ mFreeSpace -= numEventsRead;
+ if (mHead > mBufferEnd) {
+ size_t s = mHead - mBufferEnd;
+ memcpy(mBuffer, mBufferEnd, s * sizeof(input_event));
+ mHead = mBuffer + s;
+ }
+ }
+ }
+
+ return numEventsRead;
+}
+
+ssize_t InputEventCircularReader::readEvent(input_event const** events)
+{
+ *events = mCurr;
+ ssize_t available = (mBufferEnd - mBuffer) - mFreeSpace;
+ return available ? 1 : 0;
+}
+
+void InputEventCircularReader::next()
+{
+ mCurr++;
+ mFreeSpace++;
+ if (mCurr >= mBufferEnd) {
+ mCurr = mBuffer;
+ }
+}
--- /dev/null
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#ifndef ANDROID_INPUT_EVENT_READER_H
+#define ANDROID_INPUT_EVENT_READER_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+/*****************************************************************************/
+
+struct input_event;
+
+class InputEventCircularReader
+{
+ struct input_event* const mBuffer;
+ struct input_event* const mBufferEnd;
+ struct input_event* mHead;
+ struct input_event* mCurr;
+ ssize_t mFreeSpace;
+
+public:
+ InputEventCircularReader(size_t numEvents);
+ ~InputEventCircularReader();
+ ssize_t fill(int fd);
+ ssize_t readEvent(input_event const** events);
+ void next();
+};
+
+/*****************************************************************************/
+
+#endif // ANDROID_INPUT_EVENT_READER_H
--- /dev/null
+= How to add/config a new board =
+
+ Look into vendor/intel/<board>/libsensors for inspiration/templates.
+BUT don't just copy paste without understanding what you are doing. The idea
+is to select the necessary sensors via sensor headers, fill in the sensor list
+with each sensor's sSensorInfo, instantiate sensors in initSensors and map id's
+in handleToDriver.
+
+= How to add a new Sensor implementation =
+
+ What type of sensor driver are you using?
+
+- Input device? Use SensorInputDev. The advantage of using this class is that
+the readEvents loop exists already, only processEvent must be implemented
+for that pourpouse. Of course, if you need a special kind of readEvents loop,
+it can be re-implemented.
+
+- Basic char device? use SensorCharDev. You are on your own here regarding
+readEvent.
+
+- Something else? This means you are using some other type of driver and a
+new Sensor<Type>Dev class must be implementad first and then the sensor
+implementation must inherit from that.
+
+= Do's & Don'ts =
+
+- For sensor implementations, don't inherit from SensorBase class directly.
+- Don't copy paste code without understanding what it does.
+- Do use references instead of pointers as much as possible.
+- Do use std::string's instead of C strings. It avoids many extra dubious
+operations.
+- Don't use streams on sysfs entries. Streams can do impartial writes and mess
+up the sysfs data.
--- /dev/null
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#include <fcntl.h>
+#include <errno.h>
+#include <math.h>
+#include <poll.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <sys/select.h>
+#include <assert.h>
+
+#include <cutils/log.h>
+
+#include <linux/input.h>
+
+#include "SensorBase.h"
+
+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;
+}
+
+int SensorBase::open()
+{
+ mFd = ::open(mDevPath.c_str(), O_RDONLY);
+ LOGE_IF(mFd < 0, "%s: device %s err:%d", __func__, mDevPath.c_str(), -errno);
+ LOGV("%s: device path:%s, fd:%d", __func__, mDevPath.c_str(), mFd);
+ return mFd;
+}
+
+void SensorBase::close()
+{
+ int ret = ::close(mFd);
+ mFd = -1;
+ LOGV("%s: device path:%s, fd:%d", __func__, mDevPath.c_str(), mFd);
+}
--- /dev/null
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#ifndef ANDROID_SENSOR_BASE_H
+#define ANDROID_SENSOR_BASE_H
+
+#include <string>
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <hardware/sensors.h>
+
+#include "InputEventReader.h"
+
+struct sensors_event_t;
+
+/**
+ * The base class defines how it's supposed to be used by sensors.cpp.
+ * Never use this class directly for sensor implementations. A new
+ * Sensor<DevType>Dev class must be created.
+ *
+ * This class does opening & closing of mDevPath which is supposed to be
+ * set in the constructor. Open happens on enable(1) & close on enable(0).
+ *
+ * The sensor is closed & disabled when mFd is -1;
+ *
+ * Sensor implementations/Sensor<Type>Dev classes must set mPendingEvent
+ * flag to true/false by themselves in the readEvent loop.
+ */
+class SensorBase {
+
+protected:
+ std::string mDevPath;
+ int mFd;
+ bool mHasPendingEvent;
+ bool mEnabled;
+ sensors_event_t mPendingEvent;
+
+ static int64_t getTimestamp();
+ static int64_t timevalToNano(timeval const& t) {
+ return t.tv_sec*1000000000LL + t.tv_usec*1000;
+ }
+
+ virtual int setInitialState() { return 0; };
+
+public:
+ SensorBase():
+ mFd(-1),
+ mHasPendingEvent(false),
+ mEnabled(false) {};
+
+ virtual ~SensorBase() { close(); };
+
+ virtual int open();
+ virtual void close();
+ virtual int enable(int enabled) = 0;
+
+ virtual int readEvents(sensors_event_t *data, int count) = 0;
+ virtual int setDelay(int64_t ns) = 0;
+
+ int fd() const { return mFd; };
+ virtual bool hasPendingEvents() const { return mHasPendingEvent; };
+};
+#endif // ANDROID_SENSOR_BASE_H
--- /dev/null
+/*
+ * Copyright (C) 2010-2012 Intel Corporation
+ *
+ * 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.
+ */
+#ifndef ANDROID_SENSOR_CHAR_DEV_H
+#define ANDROID_SENSOR_CHAR_DEV_H
+
+#include "SensorBase.h"
+
+class SensorCharDev: public SensorBase {
+
+public:
+ SensorCharDev(std::string dev)
+ : SensorBase()
+ { mDevPath = dev; };
+};
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2010-2012 Intel Corporation
+ *
+ * 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 <dirent.h>
+#include <fcntl.h>
+#include <linux/input.h>
+#include <cutils/log.h>
+
+#include "SensorInputDev.h"
+
+SensorInputDev::SensorInputDev(std::string dev)
+ : SensorBase(),
+ mInputReader(4)
+{
+ findInputDev(dev, mDevPath);
+}
+
+int SensorInputDev::readEvents(sensors_event_t* data, int count)
+{
+ if (count < 1)
+ return -EINVAL;
+
+ if (mHasPendingEvent) {
+ mHasPendingEvent = false;
+ mPendingEvent.timestamp = getTimestamp();
+ *data = mPendingEvent;
+ return 1;
+ }
+
+ if (mFd < 0)
+ return -EBADF;
+
+ ssize_t n = mInputReader.fill(mFd);
+ if (n < 0)
+ return n;
+
+ int numEventReceived = 0;
+ input_event const* event;
+
+#if FETCH_FULL_EVENT_BEFORE_RETURN
+again:
+#endif
+ while (count && mInputReader.readEvent(&event)) {
+ /* do sensor specific stuff */
+ processEvent(*event);
+
+ if (event->type == EV_SYN) {
+ mPendingEvent.timestamp = timevalToNano(event->time);
+ if (mEnabled) {
+ *data++ = mPendingEvent;
+ count--;
+ numEventReceived++;
+ }
+ LOGV("%s:%s:, in type = EV_SYN, after, count = %d, numEventReceived = %d, mEnabled = %d",
+ __func__, mDevPath.c_str(), count, numEventReceived, mEnabled);
+ }
+
+ mInputReader.next();
+ }
+
+#if FETCH_FULL_EVENT_BEFORE_RETURN
+ /* if we didn't read a complete event, see if we can fill and
+ try again instead of returning with nothing and redoing poll. */
+ if (numEventReceived == 0 && mEnabled == 1) {
+ n = mInputReader.fill(mFd);
+ if (n)
+ goto again;
+ }
+#endif
+
+ return numEventReceived;
+}
+
+bool SensorInputDev::findInputDev(const std::string &inputName,
+ std::string &foundPath)
+{
+ bool found = false;
+ std::string dev = "/dev/input";
+ DIR *dir = opendir(dev.c_str());
+ if (!dir)
+ return false;
+
+ struct dirent *de;
+ while ((de = readdir(dir))) {
+ if(de->d_name[0] == '.' &&
+ (de->d_name[1] == '\0' ||
+ (de->d_name[1] == '.' && de->d_name[2] == '\0')))
+ continue;
+
+ int fd = ::open((dev + "/" + de->d_name).c_str(), O_RDONLY);
+ if (fd < 0)
+ continue;
+
+ LOGV("%s: probing path %s against %s", __func__, (dev + "/" + de->d_name).c_str(), inputName.c_str());
+ char readName[80];
+ if (ioctl(fd, EVIOCGNAME(sizeof(readName) - 1), &readName) < 1)
+ readName[0] = '\0';
+
+ ::close(fd);
+
+ if (inputName.compare(readName) == 0) {
+ foundPath = (dev + "/" + de->d_name);
+ found = true;
+ LOGV("%s: found %s", __func__, foundPath.c_str());
+ break;
+ }
+ }
+
+ closedir(dir);
+
+ LOGE_IF(!found, "couldn't find '%s' input device", inputName.c_str());
+
+ return found;
+}
--- /dev/null
+/*
+ * Copyright (C) 2010-2012 Intel Corporation
+ *
+ * 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.
+ */
+
+#ifndef ANDROID_SENSOR_INPUT_DEV_H
+#define ANDROID_SENSOR_INPUT_DEV_H
+
+#include <string>
+
+#include "SensorBase.h"
+
+/**
+ * Input device based sensors must inherit this class.
+ * The readEvents loop is already defined by this base class,
+ * inheritors need to define only processEvent for doing sensor-specific
+ * event computations.
+ */
+class SensorInputDev: public SensorBase {
+
+protected:
+ InputEventCircularReader mInputReader;
+
+ bool findInputDev(const std::string &inputName,
+ std::string &foundPath);
+ virtual int processEvent(struct input_event const &ev) = 0;
+
+public:
+ SensorInputDev(std::string);
+
+ virtual int readEvents(sensors_event_t *data, int count);
+};
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2008 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.
+ */
+
+#ifndef ANDROID_SENSORS_COMMON_H
+#define ANDROID_SENSORS_COMMON_H
+
+#include <linux/input.h>
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+#define ID_A (0)
+#define ID_M (1)
+#define ID_O (2)
+#define ID_L (3)
+#define ID_P (4)
+#define ID_GY (5)
+#define ID_PR (6)
+#define ID_T (7)
+
+#define SENSORS_ACCELERATION (1<<ID_A)
+#define SENSORS_MAGNETIC_FIELD (1<<ID_M)
+#define SENSORS_ORIENTATION (1<<ID_O)
+#define SENSORS_LIGHT (1<<ID_L)
+#define SENSORS_PROXIMITY (1<<ID_P)
+#define SENSORS_GYROSCOPE (1<<ID_GY)
+#define SENSORS_PRESSURE (1<<ID_PR)
+#define SENSORS_TEMPERATURE (1<<ID_T)
+
+#define SENSORS_ACCELERATION_HANDLE 0
+#define SENSORS_MAGNETIC_FIELD_HANDLE 1
+#define SENSORS_ORIENTATION_HANDLE 2
+#define SENSORS_LIGHT_HANDLE 3
+#define SENSORS_PROXIMITY_HANDLE 4
+#define SENSORS_GYROSCOPE_HANDLE 5
+#define SENSORS_PRESSURE_HANDLE 6
+#define SENSORS_TEMPERATURE_HANDLE 7
+
+/* The next one is used to set the timeout used for polling the file
+ * descriptors.
+ */
+#define POLL_TIMEOUT_MSEC 3000L
+
+#endif
--- /dev/null
+/*
+ * Copyright (C) 2008 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 <hardware/sensors.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+#include <math.h>
+#include <poll.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+#include <linux/input.h>
+#include <linux/akm8973.h>
+
+#include <utils/Atomic.h>
+#include <utils/Log.h>
+
+#include "common.h"
+#include "SensorBase.h"
+
+#include "SensorConfig.h"
+#include "BoardConfig.h"
+
+/*****************************************************************************/
+
+/* The SENSORS Module */
+static int open_sensors(const struct hw_module_t* module, const char* id,
+ struct hw_device_t** device);
+
+
+static int sensors__get_sensors_list(struct sensors_module_t* module,
+ struct sensor_t const** list)
+{
+ *list = BoardConfig::sensorList();
+ return BoardConfig::sensorListSize();
+}
+
+static struct hw_module_methods_t sensors_module_methods = {
+ open: open_sensors
+};
+
+struct sensors_module_t HAL_MODULE_INFO_SYM = {
+ common: {
+ tag: HARDWARE_MODULE_TAG,
+ version_major: 1,
+ version_minor: 0,
+ id: SENSORS_HARDWARE_MODULE_ID,
+ name: "Samsung Sensor module",
+ author: "Samsung Electronic Company",
+ methods: &sensors_module_methods,
+ },
+ get_sensors_list: sensors__get_sensors_list,
+};
+
+struct sensors_poll_context_t {
+ struct sensors_poll_device_t device; // must be first
+
+ sensors_poll_context_t();
+ ~sensors_poll_context_t();
+ int activate(int handle, int enabled);
+ int setDelay(int handle, int64_t ns);
+ int pollEvents(sensors_event_t* data, int count);
+
+private:
+ static const size_t wake = numFds - 1;
+ static const char WAKE_MESSAGE = 'W';
+ struct pollfd mPollFds[numFds];
+ int mWritePipeFd;
+ SensorBase* mSensors[numSensorDrivers];
+};
+
+/*****************************************************************************/
+
+sensors_poll_context_t::sensors_poll_context_t()
+{
+ BoardConfig::initSensors(mSensors);
+
+ for (int i=0; i < numSensorDrivers; i++) {
+ mPollFds[i].fd = mSensors[i]->fd();
+ mPollFds[i].events = POLLIN;
+ mPollFds[i].revents = 0;
+ }
+
+ int wakeFds[2];
+ int result = pipe(wakeFds);
+ LOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno));
+ fcntl(wakeFds[0], F_SETFL, O_NONBLOCK);
+ fcntl(wakeFds[1], F_SETFL, O_NONBLOCK);
+ mWritePipeFd = wakeFds[1];
+
+ mPollFds[wake].fd = wakeFds[0];
+ mPollFds[wake].events = POLLIN;
+ mPollFds[wake].revents = 0;
+}
+
+sensors_poll_context_t::~sensors_poll_context_t() {
+ for (int i=0 ; i<numSensorDrivers ; i++) {
+ delete mSensors[i];
+ }
+ close(mPollFds[wake].fd);
+ close(mWritePipeFd);
+}
+
+int sensors_poll_context_t::activate(int handle, int enabled) {
+ int index = BoardConfig::handleToDriver(handle);
+ if (index < 0) return index;
+
+ LOGD("%s: %s sensor %d", __func__, enabled?"enable":"disable", index);
+ SensorBase* const s(mSensors[index]);
+ int err = 0;
+ if (enabled) {
+ if (((err = s->open()) > 0) && (err = s->enable(1)) == 0) {
+ const char wakeMessage(WAKE_MESSAGE);
+ int result = write(mWritePipeFd, &wakeMessage, 1);
+ LOGE_IF(result<0, "error sending wake message (%s)", strerror(errno));
+ } else
+ s->close();
+ } else {
+ s->enable(0);
+ s->close();
+ }
+
+ /* If the file descriptor is closed or opened the stored desciptor
+ should be updated. Even when not opened/closed the fd should
+ return correct value */
+ mPollFds[index].fd = s->fd();
+ return err;
+}
+
+int sensors_poll_context_t::setDelay(int handle, int64_t ns) {
+
+ int index = BoardConfig::handleToDriver(handle);
+ if (index < 0) return index;
+ return mSensors[index]->setDelay(ns);
+}
+
+int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
+{
+ int nbEvents = 0;
+ int n = 0;
+
+ do {
+ // see if we have some leftover from the last poll()
+ for (int i=0 ; count && i<numSensorDrivers ; i++) {
+ SensorBase* const sensor(mSensors[i]);
+ if ((mPollFds[i].revents & POLLIN) || (sensor->hasPendingEvents())) {
+ int nb = sensor->readEvents(data, count);
+ if (nb < count) {
+ // no more data for this sensor
+ mPollFds[i].revents = 0;
+
+ if (nb < 0) {
+ LOGD("%s: handle:%d error:%d", __func__, i, nb);
+ continue;
+ }
+ }
+ count -= nb;
+ nbEvents += nb;
+ data += nb;
+ }
+ }
+
+ if (count) {
+ // we still have some room, so try to see if we can get
+ // some events immediately or just wait if we don't have
+ // anything to return
+ n = poll(mPollFds, numFds, nbEvents ? 0 : POLL_TIMEOUT_MSEC);
+ if (n<0) {
+ LOGE("poll() failed (%s)", strerror(errno));
+ return -errno;
+ }
+ if (mPollFds[wake].revents & POLLIN) {
+ char msg;
+ int result = read(mPollFds[wake].fd, &msg, 1);
+ LOGE_IF(result<0, "error reading from wake pipe (%s)", strerror(errno));
+ LOGE_IF(msg != WAKE_MESSAGE, "unknown message on wake queue (0x%02x)", int(msg));
+ mPollFds[wake].revents = 0;
+ }
+ }
+ // if we have events and space, go read them
+ } while (n && count);
+
+ return nbEvents;
+}
+
+/*****************************************************************************/
+
+static int poll__close(struct hw_device_t *dev)
+{
+ sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
+ if (ctx) {
+ delete ctx;
+ }
+ return 0;
+}
+
+static int poll__activate(struct sensors_poll_device_t *dev,
+ int handle, int enabled) {
+ sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
+ return ctx->activate(handle, enabled);
+}
+
+static int poll__setDelay(struct sensors_poll_device_t *dev,
+ int handle, int64_t ns) {
+ sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
+ return ctx->setDelay(handle, ns);
+}
+
+static int poll__poll(struct sensors_poll_device_t *dev,
+ sensors_event_t* data, int count) {
+ sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
+ return ctx->pollEvents(data, count);
+}
+
+/*****************************************************************************/
+
+/** Open a new instance of a sensor device using name */
+static int open_sensors(const struct hw_module_t* module, const char* id,
+ struct hw_device_t** device)
+{
+ int status = -EINVAL;
+ sensors_poll_context_t *dev = new sensors_poll_context_t();
+
+ memset(&dev->device, 0, sizeof(sensors_poll_device_t));
+
+ dev->device.common.tag = HARDWARE_DEVICE_TAG;
+ dev->device.common.version = 0;
+ dev->device.common.module = const_cast<hw_module_t*>(module);
+ dev->device.common.close = poll__close;
+ dev->device.activate = poll__activate;
+ dev->device.setDelay = poll__setDelay;
+ dev->device.poll = poll__poll;
+
+ *device = &dev->device.common;
+ status = 0;
+
+ return status;
+}