OSDN Git Service

libsensors framework
authorsrinivas pandruvada <srinivas.pandruvada@intel.com>
Mon, 14 May 2012 21:28:43 +0000 (14:28 -0700)
committerMattias Pettersson <mattias.pettersson@intel.com>
Wed, 4 Dec 2013 14:13:11 +0000 (15:13 +0100)
Copied libsensors from Medfield and kept only sensor core files.
Removed all sensor specific files.

The commiters includes:
ommit 21964ccb08d199672cdf986cca91a714f55302ab
Author: Dragos Tatulea <dragos.tatulea@intel.com>

    libsensors: remove unneeded double close error

commit f5d69164ee57a048c4aa0f4747e43d8e894cca2f
Author: Dragos Tatulea <dragos.tatulea@intel.com>

    libsensors: refactor sensors to close fd on disable

commit a66c57c95532739c2e05c3aa40a26e0dc91da05b
Author: Dragos Tatulea <dragos.tatulea@intel.com>

    libsensors: check & skip sensor poll errors

commit 664ec9c48708a177eee9f68f3d11e57a35400a7b
Author: Dragos Tatulea <dragos.tatulea@intel.com>

    libsensors: base class enhancements

commit 9d16e254aab71082adf16749e771a54c84d26e24
Author: Dragos Tatulea <dragos.tatulea@intel.com>

    libsensors: move to vendor and split in platform and common

Change-Id: I0fbb737155331a60e362bba9402a6a036a2ec2f6
Signed-off-by: srinivas pandruvada <srinivas.pandruvada@intel.com>
13 files changed:
common/libsensors/BoardConfig.h [new file with mode: 0644]
common/libsensors/Helpers.cpp [new file with mode: 0644]
common/libsensors/Helpers.h [new file with mode: 0644]
common/libsensors/InputEventReader.cpp [new file with mode: 0644]
common/libsensors/InputEventReader.h [new file with mode: 0644]
common/libsensors/README.txt [new file with mode: 0644]
common/libsensors/SensorBase.cpp [new file with mode: 0644]
common/libsensors/SensorBase.h [new file with mode: 0644]
common/libsensors/SensorCharDev.h [new file with mode: 0644]
common/libsensors/SensorInputDev.cpp [new file with mode: 0644]
common/libsensors/SensorInputDev.h [new file with mode: 0644]
common/libsensors/common.h [new file with mode: 0644]
common/libsensors/sensors.cpp [new file with mode: 0644]

diff --git a/common/libsensors/BoardConfig.h b/common/libsensors/BoardConfig.h
new file mode 100644 (file)
index 0000000..ab25916
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * 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
diff --git a/common/libsensors/Helpers.cpp b/common/libsensors/Helpers.cpp
new file mode 100644 (file)
index 0000000..bcbe18e
--- /dev/null
@@ -0,0 +1,86 @@
+/*
+ * 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("");
+}
diff --git a/common/libsensors/Helpers.h b/common/libsensors/Helpers.h
new file mode 100644 (file)
index 0000000..99b9173
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * 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
diff --git a/common/libsensors/InputEventReader.cpp b/common/libsensors/InputEventReader.cpp
new file mode 100644 (file)
index 0000000..1014f29
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * 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;
+    }
+}
diff --git a/common/libsensors/InputEventReader.h b/common/libsensors/InputEventReader.h
new file mode 100644 (file)
index 0000000..180aade
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * 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
diff --git a/common/libsensors/README.txt b/common/libsensors/README.txt
new file mode 100644 (file)
index 0000000..ee52346
--- /dev/null
@@ -0,0 +1,33 @@
+= 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.
diff --git a/common/libsensors/SensorBase.cpp b/common/libsensors/SensorBase.cpp
new file mode 100644 (file)
index 0000000..8e3886c
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * 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);
+}
diff --git a/common/libsensors/SensorBase.h b/common/libsensors/SensorBase.h
new file mode 100644 (file)
index 0000000..4d52194
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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
diff --git a/common/libsensors/SensorCharDev.h b/common/libsensors/SensorCharDev.h
new file mode 100644 (file)
index 0000000..274a9ba
--- /dev/null
@@ -0,0 +1,28 @@
+/*
+ * 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
diff --git a/common/libsensors/SensorInputDev.cpp b/common/libsensors/SensorInputDev.cpp
new file mode 100644 (file)
index 0000000..0205acf
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * 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;
+}
diff --git a/common/libsensors/SensorInputDev.h b/common/libsensors/SensorInputDev.h
new file mode 100644 (file)
index 0000000..8121f67
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * 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
diff --git a/common/libsensors/common.h b/common/libsensors/common.h
new file mode 100644 (file)
index 0000000..dbbfef8
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * 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
diff --git a/common/libsensors/sensors.cpp b/common/libsensors/sensors.cpp
new file mode 100644 (file)
index 0000000..6ff9e5c
--- /dev/null
@@ -0,0 +1,254 @@
+/*
+ * 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;
+}