Implements new sensor HAL

Change-Id: Iacc7a6fc17742acc93cf90b1530b81392cd2a5ab
diff --git a/libsensors/AkmSensor.cpp b/libsensors/AkmSensor.cpp
new file mode 100644
index 0000000..6f30744
--- /dev/null
+++ b/libsensors/AkmSensor.cpp
@@ -0,0 +1,256 @@
+/*
+ * 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 <linux/akm8973.h>
+
+#include <cutils/log.h>
+
+#include "AkmSensor.h"
+
+/*****************************************************************************/
+
+AkmSensor::AkmSensor()
+: SensorBase(AKM_DEVICE_NAME, "compass"),
+  mEnabled(0),
+  mInputReader(32),
+  mPendingMask(0),
+  mLastEventIndex(0)
+{
+    memset(mPendingEvents, 0, sizeof(mPendingEvents));
+
+    mPendingEvents[Accelerometer].version = sizeof(sensors_event_t);
+    mPendingEvents[Accelerometer].sensor = ID_A;
+    mPendingEvents[Accelerometer].type = SENSOR_TYPE_ACCELEROMETER;
+    mPendingEvents[Accelerometer].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
+
+    mPendingEvents[MagneticField].version = sizeof(sensors_event_t);
+    mPendingEvents[MagneticField].sensor = ID_M;
+    mPendingEvents[MagneticField].type = SENSOR_TYPE_MAGNETIC_FIELD;
+    mPendingEvents[MagneticField].magnetic.status = SENSOR_STATUS_ACCURACY_HIGH;
+
+    mPendingEvents[Orientation  ].version = sizeof(sensors_event_t);
+    mPendingEvents[Orientation  ].sensor = ID_O;
+    mPendingEvents[Orientation  ].type = SENSOR_TYPE_ORIENTATION;
+    mPendingEvents[Orientation  ].orientation.status = SENSOR_STATUS_ACCURACY_HIGH;
+
+    mPendingEvents[Temperature  ].version = sizeof(sensors_event_t);
+    mPendingEvents[Temperature  ].sensor = ID_T;
+    mPendingEvents[Temperature  ].type = SENSOR_TYPE_TEMPERATURE;
+
+    // read the actual value of all sensors if they're enabled already
+    struct input_absinfo absinfo;
+    short flags;
+    if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_AFLAG, &flags)) {
+        if (flags)  {
+            mEnabled |= 1<<Accelerometer;
+            if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_X), &absinfo)) {
+                mPendingEvents[Accelerometer].acceleration.x = absinfo.value * CONVERT_A_X;
+            }
+            if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Y), &absinfo)) {
+                mPendingEvents[Accelerometer].acceleration.y = absinfo.value * CONVERT_A_Y;
+            }
+            if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ACCEL_Z), &absinfo)) {
+                mPendingEvents[Accelerometer].acceleration.z = absinfo.value * CONVERT_A_Z;
+            }
+        }
+    }
+    if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_MVFLAG, &flags)) {
+        if (flags)  {
+            mEnabled |= 1<<MagneticField;
+            if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_X), &absinfo)) {
+                mPendingEvents[MagneticField].magnetic.x = absinfo.value * CONVERT_M_X;
+            }
+            if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_Y), &absinfo)) {
+                mPendingEvents[MagneticField].magnetic.y = absinfo.value * CONVERT_M_Y;
+            }
+            if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_MAGV_Z), &absinfo)) {
+                mPendingEvents[MagneticField].magnetic.z = absinfo.value * CONVERT_M_Z;
+            }
+        }
+    }
+    if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_MFLAG, &flags)) {
+        if (flags)  {
+            mEnabled |= 1<<Orientation;
+            if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_YAW), &absinfo)) {
+                mPendingEvents[Orientation].orientation.azimuth = absinfo.value;
+            }
+            if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_PITCH), &absinfo)) {
+                mPendingEvents[Orientation].orientation.pitch = absinfo.value;
+            }
+            if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ROLL), &absinfo)) {
+                mPendingEvents[Orientation].orientation.roll = -absinfo.value;
+            }
+            if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_ORIENT_STATUS), &absinfo)) {
+                mPendingEvents[Orientation].orientation.status = uint8_t(absinfo.value & SENSOR_STATE_MASK);
+            }
+        }
+    }
+    if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_TFLAG, &flags)) {
+        if (flags)  {
+            mEnabled |= 1<<Temperature;
+            if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_TEMPERATURE), &absinfo)) {
+                mPendingEvents[Orientation].temperature = absinfo.value;
+            }
+        }
+    }
+}
+
+AkmSensor::~AkmSensor() {
+}
+
+int AkmSensor::enable(int what, int en)
+{
+    if (uint32_t(what) >= numSensors)
+        return -EINVAL;
+
+    int flags = en ? 1 : 0;
+    int err = 0;
+
+    if ((uint32_t(flags)<<what) != (mEnabled & (1<<what))) {
+        int cmd;
+        switch (what) {
+            case Accelerometer: cmd = ECS_IOCTL_APP_SET_AFLAG;  break;
+            case MagneticField: cmd = ECS_IOCTL_APP_SET_MVFLAG; break;
+            case Orientation:   cmd = ECS_IOCTL_APP_SET_MFLAG;  break;
+            case Temperature:   cmd = ECS_IOCTL_APP_SET_TFLAG;  break;
+        }
+        err = ioctl(dev_fd, cmd, &flags);
+        err = err<0 ? -errno : 0;
+        LOGE_IF(err, "ECS_IOCTL_APP_SET_XXX failed (%s)", strerror(-err));
+        if (!err) {
+            mEnabled &= ~(1<<what);
+            mEnabled |= (uint32_t(flags)<<what);
+        }
+    }
+    return err;
+}
+
+int AkmSensor::setDelay(int64_t ns)
+{
+    if (ns < 0)
+        return -EINVAL;
+
+#ifdef ECS_IOCTL_APP_SET_DELAY
+    short delay = ns / 1000000;
+    if (!ioctl(dev_fd, ECS_IOCTL_APP_SET_DELAY, &delay)) {
+        return -errno;
+    }
+    return 0;
+#else
+    return -1;
+#endif
+}
+
+int AkmSensor::readEvents(sensors_event_t* data, int count)
+{
+    if (count < 1)
+        return -EINVAL;
+
+    ssize_t n = mInputReader.fill(data_fd);
+    if (n < 0)
+        return n;
+
+    int numEventReceived = 0;
+    input_event const* event;
+
+    while (count && mInputReader.readEvent(&event)) {
+        int type = event->type;
+        if (type == EV_ABS) {
+            processEvent(event->code, event->value);
+            mInputReader.next();
+        } else if (type == EV_SYN) {
+            if (mPendingMask) {
+                int64_t time = timevalToNano(event->time);
+                for (int j=0 ; count && mPendingMask && j<numSensors ; j++) {
+                    if (mPendingMask & (1<<j)) {
+                        mPendingMask &= ~(1<<j);
+                        mPendingEvents[j].timestamp = time;
+                        *data++ = mPendingEvents[j];
+                        count--;
+                        numEventReceived++;
+                    }
+                }
+                if (!mPendingMask) {
+                    mInputReader.next();
+                }
+            }
+        }
+    }
+
+    return numEventReceived;
+}
+
+void AkmSensor::processEvent(int code, int value)
+{
+    switch (code) {
+        case EVENT_TYPE_ACCEL_X:
+            mPendingMask |= 1<<Accelerometer;
+            mPendingEvents[Accelerometer].acceleration.x = value * CONVERT_A_X;
+            break;
+        case EVENT_TYPE_ACCEL_Y:
+            mPendingMask |= 1<<Accelerometer;
+            mPendingEvents[Accelerometer].acceleration.y = value * CONVERT_A_Y;
+            break;
+        case EVENT_TYPE_ACCEL_Z:
+            mPendingMask |= 1<<Accelerometer;
+            mPendingEvents[Accelerometer].acceleration.z = value * CONVERT_A_Z;
+            break;
+
+        case EVENT_TYPE_MAGV_X:
+            mPendingMask |= 1<<MagneticField;
+            mPendingEvents[MagneticField].magnetic.x = value * CONVERT_M_X;
+            break;
+        case EVENT_TYPE_MAGV_Y:
+            mPendingMask |= 1<<MagneticField;
+            mPendingEvents[MagneticField].magnetic.y = value * CONVERT_M_Y;
+            break;
+        case EVENT_TYPE_MAGV_Z:
+            mPendingMask |= 1<<MagneticField;
+            mPendingEvents[MagneticField].magnetic.z = value * CONVERT_M_Z;
+            break;
+
+        case EVENT_TYPE_YAW:
+            mPendingMask |= 1<<Orientation;
+            mPendingEvents[Orientation].orientation.azimuth = value;
+            break;
+        case EVENT_TYPE_PITCH:
+            mPendingMask |= 1<<Orientation;
+            mPendingEvents[Orientation].orientation.pitch = value;
+            break;
+        case EVENT_TYPE_ROLL:
+            mPendingMask |= 1<<Orientation;
+            mPendingEvents[Orientation].orientation.roll = -value;
+            break;
+        case EVENT_TYPE_ORIENT_STATUS:
+            mPendingMask |= 1<<Orientation;
+            mPendingEvents[Orientation].orientation.status =
+                    uint8_t(value & SENSOR_STATE_MASK);
+            break;
+
+        case EVENT_TYPE_TEMPERATURE:
+            mPendingMask |= 1<<Temperature;
+            mPendingEvents[Temperature].temperature = value;
+            break;
+    }
+}
diff --git a/libsensors/AkmSensor.h b/libsensors/AkmSensor.h
new file mode 100644
index 0000000..b1833c4
--- /dev/null
+++ b/libsensors/AkmSensor.h
@@ -0,0 +1,63 @@
+/*
+ * 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_AKM_SENSOR_H
+#define ANDROID_AKM_SENSOR_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+
+#include "nusensors.h"
+#include "SensorBase.h"
+#include "InputEventReader.h"
+
+/*****************************************************************************/
+
+struct input_event;
+
+class AkmSensor : public SensorBase {
+public:
+    AkmSensor();
+    ~AkmSensor();
+
+    enum {
+        Accelerometer   = 0,
+        MagneticField   = 1,
+        Orientation     = 2,
+        Temperature     = 3,
+        numSensors
+    };
+
+    int enable(int what, int enabled);
+    int readEvents(sensors_event_t* data, int count);
+    int setDelay(int64_t ns);
+    void processEvent(int code, int value);
+
+private:
+    uint32_t mEnabled;
+    InputEventCircularReader mInputReader;
+    uint32_t mPendingMask;
+    sensors_event_t mPendingEvents[numSensors];
+    int mLastEventIndex;
+
+};
+
+/*****************************************************************************/
+
+#endif  // ANDROID_AKM_SENSOR_H
diff --git a/libsensors/Android.mk b/libsensors/Android.mk
index a9bc91e..7c4e6f5 100644
--- a/libsensors/Android.mk
+++ b/libsensors/Android.mk
@@ -27,7 +27,16 @@
 
 LOCAL_MODULE_TAGS := optional
 
-LOCAL_SRC_FILES := sensors.c
+LOCAL_CFLAGS := -DLOG_TAG=\"Sensors\"
+LOCAL_SRC_FILES := 						\
+				sensors.c 				\
+				nusensors.cpp 			\
+				InputEventReader.cpp	\
+				SensorBase.cpp			\
+				LightSensor.cpp			\
+				ProximitySensor.cpp		\
+				AkmSensor.cpp
+				
 LOCAL_SHARED_LIBRARIES := liblog libcutils
 LOCAL_PRELINK_MODULE := false
 
diff --git a/libsensors/InputEventReader.cpp b/libsensors/InputEventReader.cpp
new file mode 100644
index 0000000..b69a1ef
--- /dev/null
+++ b/libsensors/InputEventReader.cpp
@@ -0,0 +1,87 @@
+/*
+ * 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 <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/libsensors/InputEventReader.h b/libsensors/InputEventReader.h
new file mode 100644
index 0000000..180aade
--- /dev/null
+++ b/libsensors/InputEventReader.h
@@ -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/libsensors/LightSensor.cpp b/libsensors/LightSensor.cpp
new file mode 100644
index 0000000..86d1e0b
--- /dev/null
+++ b/libsensors/LightSensor.cpp
@@ -0,0 +1,140 @@
+/*
+ * 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 <linux/lightsensor.h>
+
+#include <cutils/log.h>
+
+#include "LightSensor.h"
+
+/*****************************************************************************/
+
+LightSensor::LightSensor()
+    : SensorBase(LS_DEVICE_NAME, "lightsensor-level"),
+      mHasInitialValue(0),
+      mEnabled(0),
+      mInputReader(4)
+{
+    mPendingEvent.version = sizeof(sensors_event_t);
+    mPendingEvent.sensor = ID_L;
+    mPendingEvent.type = SENSOR_TYPE_LIGHT;
+    mPendingEvent.reserved0 = 0;
+    mPendingEvent.reserved1[0] = 0;
+    mPendingEvent.reserved1[1] = 0;
+    mPendingEvent.reserved1[2] = 0;
+    mPendingEvent.reserved1[3] = 0;
+
+    int flags = 0;
+    if (!ioctl(dev_fd, LIGHTSENSOR_IOCTL_GET_ENABLED, &flags)) {
+        if (flags) {
+            setInitialState();
+        }
+    }
+}
+
+LightSensor::~LightSensor() {
+}
+
+int LightSensor::setInitialState() {
+    struct input_absinfo absinfo;
+    if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_LIGHT), &absinfo)) {
+        mPendingEvent.light = indexToValue(absinfo.value);
+        mHasInitialValue = 1;
+    }
+    return 0;
+}
+
+int LightSensor::enable(int en) {
+    int flags = en ? 1 : 0;
+    int err = 0;
+    if (flags != mEnabled) {
+        err = ioctl(dev_fd, LIGHTSENSOR_IOCTL_ENABLE, &flags);
+        err = err<0 ? -errno : 0;
+        LOGE_IF(err, "LIGHTSENSOR_IOCTL_ENABLE failed (%s)", strerror(-err));
+        if (!err) {
+            mEnabled = en ? 1 : 0;
+            if (en) {
+                setInitialState();
+            }
+        }
+    }
+    return err;
+}
+
+int LightSensor::readEvents(sensors_event_t* data, int count)
+{
+    if (count < 1)
+        return -EINVAL;
+
+    if (mHasInitialValue) {
+        struct timespec t;
+        t.tv_sec = t.tv_nsec = 0;
+        clock_gettime(CLOCK_MONOTONIC, &t);
+        mHasInitialValue = 0;
+        mPendingEvent.timestamp = int64_t(t.tv_sec)*1000000000LL + t.tv_nsec;
+        *data = mPendingEvent;
+        return 1;
+    }
+
+    ssize_t n = mInputReader.fill(data_fd);
+
+    if (n < 0)
+        return n;
+
+    int numEventReceived = 0;
+    input_event const* event;
+
+    while (count && mInputReader.readEvent(&event)) {
+        int type = event->type;
+        if (type == EV_ABS) {
+            if (event->code == EVENT_TYPE_LIGHT) {
+                if (event->value != -1) {
+                    // FIXME: not sure why we're getting -1 sometimes
+                    mPendingEvent.light = indexToValue(event->value);
+                }
+            }
+        } else if (type == EV_SYN) {
+            mPendingEvent.timestamp = timevalToNano(event->time);
+            *data++ = mPendingEvent;
+            count--;
+            numEventReceived++;
+        }
+        mInputReader.next();
+    }
+
+    return numEventReceived;
+}
+
+float LightSensor::indexToValue(size_t index) const
+{
+    static const float luxValues[8] = {
+            10.0, 160.0, 225.0, 320.0,
+            640.0, 1280.0, 2600.0, 10240.0
+    };
+
+    const size_t arraySize = sizeof(luxValues)/sizeof(*luxValues);
+    if (index >= arraySize)
+        index = arraySize;
+    return luxValues[index];
+}
diff --git a/libsensors/LightSensor.h b/libsensors/LightSensor.h
new file mode 100644
index 0000000..16e7f30
--- /dev/null
+++ b/libsensors/LightSensor.h
@@ -0,0 +1,52 @@
+/*
+ * 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_LIGHT_SENSOR_H
+#define ANDROID_LIGHT_SENSOR_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include "nusensors.h"
+#include "SensorBase.h"
+#include "InputEventReader.h"
+
+/*****************************************************************************/
+
+struct input_event;
+
+class LightSensor : public SensorBase {
+    int mHasInitialValue;
+    int mEnabled;
+    InputEventCircularReader mInputReader;
+    sensors_event_t mPendingEvent;
+
+    int setInitialState();
+    float indexToValue(size_t index) const;
+
+public:
+    LightSensor();
+    ~LightSensor();
+
+    int enable(int enabled);
+    int readEvents(sensors_event_t* data, int count);
+};
+
+/*****************************************************************************/
+
+#endif  // ANDROID_LIGHT_SENSOR_H
diff --git a/libsensors/ProximitySensor.cpp b/libsensors/ProximitySensor.cpp
new file mode 100644
index 0000000..89a6de4
--- /dev/null
+++ b/libsensors/ProximitySensor.cpp
@@ -0,0 +1,128 @@
+/*
+ * 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 <linux/capella_cm3602.h>
+
+#include <cutils/log.h>
+
+#include "ProximitySensor.h"
+
+/*****************************************************************************/
+
+ProximitySensor::ProximitySensor()
+    : SensorBase(CM_DEVICE_NAME, "proximity"),
+      mHasInitialValue(0),
+      mEnabled(0),
+      mInputReader(4)
+{
+    mPendingEvent.version = sizeof(sensors_event_t);
+    mPendingEvent.sensor = ID_P;
+    mPendingEvent.type = SENSOR_TYPE_PROXIMITY;
+    mPendingEvent.reserved0 = 0;
+    mPendingEvent.reserved1[0] = 0;
+    mPendingEvent.reserved1[1] = 0;
+    mPendingEvent.reserved1[2] = 0;
+    mPendingEvent.reserved1[3] = 0;
+
+    int flags = 0;
+    if (!ioctl(dev_fd, CAPELLA_CM3602_IOCTL_GET_ENABLED, &flags)) {
+        if (flags) {
+            setInitialState();
+        }
+    }
+}
+
+ProximitySensor::~ProximitySensor() {
+}
+
+int ProximitySensor::setInitialState() {
+    struct input_absinfo absinfo;
+    if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_PROXIMITY), &absinfo)) {
+        mPendingEvent.distance = indexToValue(absinfo.value);
+        mHasInitialValue = 1;
+    }
+    return 0;
+}
+
+int ProximitySensor::enable(int en) {
+    int flags = en ? 1 : 0;
+    int err = 0;
+    if (flags != mEnabled) {
+        err = ioctl(dev_fd, CAPELLA_CM3602_IOCTL_ENABLE, &flags);
+        err = err<0 ? -errno : 0;
+        LOGE_IF(err, "CAPELLA_CM3602_IOCTL_ENABLE failed (%s)", strerror(-err));
+        if (!err) {
+            mEnabled = en ? 1 : 0;
+            if (en) {
+                setInitialState();
+            }
+        }
+    }
+    return err;
+}
+
+int ProximitySensor::readEvents(sensors_event_t* data, int count)
+{
+    if (count < 1)
+        return -EINVAL;
+
+    if (mHasInitialValue) {
+        struct timespec t;
+        t.tv_sec = t.tv_nsec = 0;
+        clock_gettime(CLOCK_MONOTONIC, &t);
+        mHasInitialValue = 0;
+        mPendingEvent.timestamp = int64_t(t.tv_sec)*1000000000LL + t.tv_nsec;
+        *data = mPendingEvent;
+        return 1;
+    }
+
+    ssize_t n = mInputReader.fill(data_fd);
+    if (n < 0)
+        return n;
+
+    int numEventReceived = 0;
+    input_event const* event;
+
+    while (count && mInputReader.readEvent(&event)) {
+        int type = event->type;
+        if (type == EV_ABS) {
+            if (event->code == EVENT_TYPE_PROXIMITY) {
+                mPendingEvent.distance = indexToValue(event->value);
+            }
+        } else if (type == EV_SYN) {
+            mPendingEvent.timestamp = timevalToNano(event->time);
+            *data++ = mPendingEvent;
+            count--;
+            numEventReceived++;
+        }
+        mInputReader.next();
+    }
+
+    return numEventReceived;
+}
+
+float ProximitySensor::indexToValue(size_t index) const
+{
+    return index * PROXIMITY_THRESHOLD_CM;
+}
diff --git a/libsensors/ProximitySensor.h b/libsensors/ProximitySensor.h
new file mode 100644
index 0000000..5dcabf5
--- /dev/null
+++ b/libsensors/ProximitySensor.h
@@ -0,0 +1,52 @@
+/*
+ * 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_PROXIMITY_SENSOR_H
+#define ANDROID_PROXIMITY_SENSOR_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include "nusensors.h"
+#include "SensorBase.h"
+#include "InputEventReader.h"
+
+/*****************************************************************************/
+
+struct input_event;
+
+class ProximitySensor : public SensorBase {
+    int mHasInitialValue;
+    int mEnabled;
+    InputEventCircularReader mInputReader;
+    sensors_event_t mPendingEvent;
+
+    int setInitialState();
+    float indexToValue(size_t index) const;
+
+public:
+    ProximitySensor();
+    ~ProximitySensor();
+
+    int enable(int enabled);
+    int readEvents(sensors_event_t* data, int count);
+};
+
+/*****************************************************************************/
+
+#endif  // ANDROID_PROXIMITY_SENSOR_H
diff --git a/libsensors/SensorBase.cpp b/libsensors/SensorBase.cpp
new file mode 100644
index 0000000..8df1f8c
--- /dev/null
+++ b/libsensors/SensorBase.cpp
@@ -0,0 +1,99 @@
+/*
+ * 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 <cutils/log.h>
+
+#include <linux/input.h>
+
+#include "SensorBase.h"
+
+/*****************************************************************************/
+
+SensorBase::SensorBase(
+        const char* dev_name,
+        const char* data_name)
+    : dev_name(dev_name), data_name(data_name),
+      dev_fd(-1), data_fd(-1)
+{
+    data_fd = openInput(data_name);
+
+    dev_fd = open(dev_name, O_RDONLY);
+    LOGE_IF(dev_fd<0, "Couldn't open %s (%s)", dev_name, strerror(errno));
+}
+
+SensorBase::~SensorBase() {
+    if (data_fd >= 0) {
+        close(data_fd);
+    }
+    if (dev_fd >= 0) {
+        close(dev_fd);
+    }
+}
+
+int SensorBase::getFd() const {
+    return data_fd;
+}
+
+int SensorBase::setDelay(int64_t ns) {
+    // N/A by default
+    return 0;
+}
+
+int SensorBase::openInput(const char* inputName) {
+    int fd = -1;
+    const char *dirname = "/dev/input";
+    char devname[PATH_MAX];
+    char *filename;
+    DIR *dir;
+    struct dirent *de;
+    dir = opendir(dirname);
+    if(dir == NULL)
+        return -1;
+    strcpy(devname, dirname);
+    filename = devname + strlen(devname);
+    *filename++ = '/';
+    while((de = readdir(dir))) {
+        if(de->d_name[0] == '.' &&
+                (de->d_name[1] == '\0' ||
+                        (de->d_name[1] == '.' && de->d_name[2] == '\0')))
+            continue;
+        strcpy(filename, de->d_name);
+        fd = open(devname, O_RDONLY);
+        if (fd>=0) {
+            char name[80];
+            if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
+                name[0] = '\0';
+            }
+            if (!strcmp(name, inputName)) {
+                break;
+            } else {
+                close(fd);
+                fd = -1;
+            }
+        }
+    }
+    closedir(dir);
+    LOGE_IF(fd<0, "couldn't find '%s' input device", inputName);
+    return fd;
+}
diff --git a/libsensors/SensorBase.h b/libsensors/SensorBase.h
new file mode 100644
index 0000000..9bdb522
--- /dev/null
+++ b/libsensors/SensorBase.h
@@ -0,0 +1,54 @@
+/*
+ * 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 <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+
+/*****************************************************************************/
+
+class SensorBase {
+protected:
+    const char* dev_name;
+    const char* data_name;
+    int         dev_fd;
+    int         data_fd;
+
+    static int openInput(const char* inputName);
+
+    static int64_t timevalToNano(timeval const& t) {
+        return t.tv_sec*1000000000LL + t.tv_usec*1000;
+    }
+
+    ~SensorBase();
+
+public:
+    SensorBase(
+            const char* dev_name,
+            const char* data_name);
+
+    int getFd() const;
+    int setDelay(int64_t ns);
+};
+
+/*****************************************************************************/
+
+#endif  // ANDROID_SENSOR_BASE_H
diff --git a/libsensors/nusensors.cpp b/libsensors/nusensors.cpp
new file mode 100644
index 0000000..0dc1d83
--- /dev/null
+++ b/libsensors/nusensors.cpp
@@ -0,0 +1,226 @@
+/*
+ * 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 <hardware/sensors.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+#include <math.h>
+
+#include <poll.h>
+#include <pthread.h>
+#include <sys/select.h>
+
+#include <linux/input.h>
+
+#include <cutils/atomic.h>
+#include <cutils/log.h>
+
+#include "nusensors.h"
+#include "LightSensor.h"
+#include "ProximitySensor.h"
+#include "AkmSensor.h"
+
+/*****************************************************************************/
+
+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:
+    struct pollfd mPollFds[3];
+    LightSensor mLightSensor;
+    ProximitySensor mProximitySensor;
+    AkmSensor mAkmSensor;
+};
+
+/*****************************************************************************/
+
+sensors_poll_context_t::sensors_poll_context_t()
+{
+    mPollFds[0].fd = mLightSensor.getFd();
+    mPollFds[0].events = POLLIN;
+    mPollFds[0].revents = 0;
+
+    mPollFds[1].fd = mProximitySensor.getFd();
+    mPollFds[1].events = POLLIN;
+    mPollFds[1].revents = 0;
+
+    mPollFds[2].fd = mAkmSensor.getFd();
+    mPollFds[2].events = POLLIN;
+    mPollFds[2].revents = 0;
+}
+
+sensors_poll_context_t::~sensors_poll_context_t() {
+}
+
+int sensors_poll_context_t::activate(int handle, int enabled) {
+    int err = -EINVAL;
+    int idx = -1;
+    switch (handle) {
+        case ID_A:
+            err = mAkmSensor.enable(AkmSensor::Accelerometer, enabled);
+            idx = 2;
+            break;
+        case ID_M:
+            err = mAkmSensor.enable(AkmSensor::MagneticField, enabled);
+            idx = 2;
+            break;
+        case ID_O:
+            err = mAkmSensor.enable(AkmSensor::Orientation, enabled);
+            idx = 2;
+            break;
+        case ID_T:
+            err = mAkmSensor.enable(AkmSensor::Temperature, enabled);
+            idx = 2;
+            break;
+        case ID_P:
+            err = mProximitySensor.enable(enabled);
+            idx = 1;
+            break;
+        case ID_L:
+            err = mLightSensor.enable(enabled);
+            idx = 0;
+            break;
+    }
+
+    if (!err && enabled && idx>=0) {
+        // pretend there is an event, so we return "something" asap.
+        mPollFds[idx].revents = POLLIN;
+    }
+
+    return err;
+}
+
+int sensors_poll_context_t::setDelay(int handle, int64_t ns) {
+    switch (handle) {
+        case ID_A:
+        case ID_M:
+        case ID_O:
+        case ID_T:
+            mAkmSensor.setDelay(ns);
+            break;
+        case ID_P:
+            mProximitySensor.setDelay(ns);
+            break;
+        case ID_L:
+            mLightSensor.setDelay(ns);
+            break;
+        default:
+            return -EINVAL;
+    }
+    return 0;
+}
+
+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<3 ; i++) {
+            if (mPollFds[i].revents & POLLIN) {
+                int nb = 0;
+                if (i == 0) {
+                    nb = mLightSensor.readEvents(data, count);
+                } else if (i == 1) {
+                    nb = mProximitySensor.readEvents(data, count);
+                } else if (i == 2) {
+                    nb = mAkmSensor.readEvents(data, count);
+                }
+
+                if (nb < count) {
+                    // no more data for this sensor
+                    mPollFds[i].revents = 0;
+                }
+                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 we we don't have
+            // anything to return
+            n = poll(mPollFds, 3, nbEvents ? 0 : -1);
+            if (n<0) {
+                LOGE("poll() failed (%s)", strerror(errno));
+                return -errno;
+            }
+        }
+        // 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);
+}
+
+/*****************************************************************************/
+
+int init_nusensors(hw_module_t const* module, 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;
+}
diff --git a/libsensors/nusensors.h b/libsensors/nusensors.h
new file mode 100644
index 0000000..1023cf1
--- /dev/null
+++ b/libsensors/nusensors.h
@@ -0,0 +1,107 @@
+/*
+ * 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_H
+#define ANDROID_SENSORS_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <linux/input.h>
+
+#include <hardware/hardware.h>
+#include <hardware/sensors.h>
+
+__BEGIN_DECLS
+
+/*****************************************************************************/
+
+int init_nusensors(hw_module_t const* module, hw_device_t** device);
+
+/*****************************************************************************/
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+#define ID_A  (0)
+#define ID_M  (1)
+#define ID_O  (2)
+#define ID_T  (3)
+#define ID_P  (4)
+#define ID_L  (5)
+
+/*****************************************************************************/
+
+/*
+ * The SENSORS Module
+ */
+
+/* the CM3602 is a binary proximity sensor that triggers around 9 cm on
+ * this hardware */
+#define PROXIMITY_THRESHOLD_CM  9.0f
+
+/*****************************************************************************/
+
+#define AKM_DEVICE_NAME     "/dev/akm8973_aot"
+#define CM_DEVICE_NAME      "/dev/cm3602"
+#define LS_DEVICE_NAME      "/dev/lightsensor"
+
+
+// sensor IDs must be a power of two and
+// must match values in SensorManager.java
+#define EVENT_TYPE_ACCEL_X          ABS_X
+#define EVENT_TYPE_ACCEL_Y          ABS_Z
+#define EVENT_TYPE_ACCEL_Z          ABS_Y
+#define EVENT_TYPE_ACCEL_STATUS     ABS_WHEEL
+
+#define EVENT_TYPE_YAW              ABS_RX
+#define EVENT_TYPE_PITCH            ABS_RY
+#define EVENT_TYPE_ROLL             ABS_RZ
+#define EVENT_TYPE_ORIENT_STATUS    ABS_RUDDER
+
+#define EVENT_TYPE_MAGV_X           ABS_HAT0X
+#define EVENT_TYPE_MAGV_Y           ABS_HAT0Y
+#define EVENT_TYPE_MAGV_Z           ABS_BRAKE
+
+#define EVENT_TYPE_TEMPERATURE      ABS_THROTTLE
+#define EVENT_TYPE_STEP_COUNT       ABS_GAS
+#define EVENT_TYPE_PROXIMITY        ABS_DISTANCE
+#define EVENT_TYPE_LIGHT            ABS_MISC
+
+// 720 LSG = 1G
+#define LSG                         (720.0f)
+
+
+// conversion of acceleration data to SI units (m/s^2)
+#define CONVERT_A                   (GRAVITY_EARTH / LSG)
+#define CONVERT_A_X                 (-CONVERT_A)
+#define CONVERT_A_Y                 (CONVERT_A)
+#define CONVERT_A_Z                 (-CONVERT_A)
+
+// conversion of magnetic data to uT units
+#define CONVERT_M                   (1.0f/16.0f)
+#define CONVERT_M_X                 (-CONVERT_M)
+#define CONVERT_M_Y                 (-CONVERT_M)
+#define CONVERT_M_Z                 (CONVERT_M)
+
+#define SENSOR_STATE_MASK           (0x7FFF)
+
+/*****************************************************************************/
+
+__END_DECLS
+
+#endif  // ANDROID_SENSORS_H
diff --git a/libsensors/sensors.c b/libsensors/sensors.c
index 56f5190..e2210b2 100644
--- a/libsensors/sensors.c
+++ b/libsensors/sensors.c
@@ -14,91 +14,16 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "Sensors"
-
-#define LOG_NDEBUG 1
-
 #include <hardware/sensors.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <dirent.h>
-#include <math.h>
-#include <poll.h>
-#include <pthread.h>
-#include <sys/select.h>
 
-#include <linux/input.h>
-#include <linux/akm8973.h>
-#include <linux/capella_cm3602.h>
-#include <linux/lightsensor.h>
-
-#include <cutils/atomic.h>
-#include <cutils/log.h>
-#include <cutils/native_handle.h>
-
-#define __MAX(a,b) ((a)>=(b)?(a):(b))
+#include "nusensors.h"
 
 /*****************************************************************************/
 
-#define MAX_NUM_SENSORS 6
-
-#define SUPPORTED_SENSORS  ((1<<MAX_NUM_SENSORS)-1)
-
-#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
-
-#define ID_A  (0)
-#define ID_M  (1)
-#define ID_O  (2)
-#define ID_T  (3)
-#define ID_P  (4)
-#define ID_L  (5)
-
-static int id_to_sensor[MAX_NUM_SENSORS] = {
-    [ID_A] = SENSOR_TYPE_ACCELEROMETER,
-    [ID_M] = SENSOR_TYPE_MAGNETIC_FIELD,
-    [ID_O] = SENSOR_TYPE_ORIENTATION,
-    [ID_T] = SENSOR_TYPE_TEMPERATURE,
-    [ID_P] = SENSOR_TYPE_PROXIMITY,
-    [ID_L] = SENSOR_TYPE_LIGHT,
-};
-
-#define SENSORS_AKM_ACCELERATION   (1<<ID_A)
-#define SENSORS_AKM_MAGNETIC_FIELD (1<<ID_M)
-#define SENSORS_AKM_ORIENTATION    (1<<ID_O)
-#define SENSORS_AKM_TEMPERATURE    (1<<ID_T)
-#define SENSORS_AKM_GROUP          ((1<<ID_A)|(1<<ID_M)|(1<<ID_O)|(1<<ID_T))
-
-#define SENSORS_CM_PROXIMITY       (1<<ID_P)
-#define SENSORS_CM_GROUP           (1<<ID_P)
-
-#define SENSORS_LIGHT              (1<<ID_L)
-#define SENSORS_LIGHT_GROUP        (1<<ID_L)
-
-/*****************************************************************************/
-
-struct sensors_control_context_t {
-    struct sensors_control_device_t device; // must be first
-    int akmd_fd;
-    int cmd_fd;
-    int lsd_fd;
-    uint32_t active_sensors;
-};
-
-struct sensors_data_context_t {
-    struct sensors_data_device_t device; // must be first
-    int events_fd[3];
-    sensors_data_t sensors[MAX_NUM_SENSORS];
-    uint32_t pendingSensors;
-};
-
 /*
  * The SENSORS Module
  */
 
-/* the CM3602 is a binary proximity sensor that triggers around 9 cm on
- * this hardware */
-#define PROXIMITY_THRESHOLD_CM  9.0f
-
 /*
  * the AK8973 has a 8-bit ADC but the firmware seems to average 16 samples,
  * or at least makes its calibration on 12-bits values. This increases the
@@ -130,17 +55,6 @@
                 SENSOR_TYPE_LIGHT, 10240.0f, 1.0f, 0.5f, { } },
 };
 
-static const float sLuxValues[8] = {
-    10.0,
-    160.0,
-    225.0,
-    320.0,
-    640.0,
-    1280.0,
-    2600.0,
-    10240.0
-};
-
 static int open_sensors(const struct hw_module_t* module, const char* name,
         struct hw_device_t** device);
 
@@ -170,852 +84,8 @@
 
 /*****************************************************************************/
 
-#define AKM_DEVICE_NAME     "/dev/akm8973_aot"
-#define CM_DEVICE_NAME      "/dev/cm3602"
-#define LS_DEVICE_NAME      "/dev/lightsensor"
-
-
-// sensor IDs must be a power of two and
-// must match values in SensorManager.java
-#define EVENT_TYPE_ACCEL_X          ABS_X
-#define EVENT_TYPE_ACCEL_Y          ABS_Z
-#define EVENT_TYPE_ACCEL_Z          ABS_Y
-#define EVENT_TYPE_ACCEL_STATUS     ABS_WHEEL
-
-#define EVENT_TYPE_YAW              ABS_RX
-#define EVENT_TYPE_PITCH            ABS_RY
-#define EVENT_TYPE_ROLL             ABS_RZ
-#define EVENT_TYPE_ORIENT_STATUS    ABS_RUDDER
-
-#define EVENT_TYPE_MAGV_X           ABS_HAT0X
-#define EVENT_TYPE_MAGV_Y           ABS_HAT0Y
-#define EVENT_TYPE_MAGV_Z           ABS_BRAKE
-
-#define EVENT_TYPE_TEMPERATURE      ABS_THROTTLE
-#define EVENT_TYPE_STEP_COUNT       ABS_GAS
-#define EVENT_TYPE_PROXIMITY        ABS_DISTANCE
-#define EVENT_TYPE_LIGHT            ABS_MISC
-
-// 720 LSG = 1G
-#define LSG                         (720.0f)
-
-
-// conversion of acceleration data to SI units (m/s^2)
-#define CONVERT_A                   (GRAVITY_EARTH / LSG)
-#define CONVERT_A_X                 (-CONVERT_A)
-#define CONVERT_A_Y                 (CONVERT_A)
-#define CONVERT_A_Z                 (-CONVERT_A)
-
-// conversion of magnetic data to uT units
-#define CONVERT_M                   (1.0f/16.0f)
-#define CONVERT_M_X                 (-CONVERT_M)
-#define CONVERT_M_Y                 (-CONVERT_M)
-#define CONVERT_M_Z                 (CONVERT_M)
-
-#define SENSOR_STATE_MASK           (0x7FFF)
-
-/*****************************************************************************/
-
-static int open_inputs(int mode, int *akm_fd, int *p_fd, int *l_fd)
-{
-    /* scan all input drivers and look for "compass" */
-    int fd = -1;
-    const char *dirname = "/dev/input";
-    char devname[PATH_MAX];
-    char *filename;
-    DIR *dir;
-    struct dirent *de;
-    dir = opendir(dirname);
-    if(dir == NULL)
-        return -1;
-    strcpy(devname, dirname);
-    filename = devname + strlen(devname);
-    *filename++ = '/';
-    *akm_fd = *p_fd = -1;
-    while((de = readdir(dir))) {
-        if(de->d_name[0] == '.' &&
-           (de->d_name[1] == '\0' ||
-            (de->d_name[1] == '.' && de->d_name[2] == '\0')))
-            continue;
-        strcpy(filename, de->d_name);
-        fd = open(devname, mode);
-        if (fd>=0) {
-            char name[80];
-            if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
-                name[0] = '\0';
-            }
-            if (!strcmp(name, "compass")) {
-                LOGV("using %s (name=%s)", devname, name);
-                *akm_fd = fd;
-            }
-            else if (!strcmp(name, "proximity")) {
-                LOGV("using %s (name=%s)", devname, name);
-                *p_fd = fd;
-            }
-            else if (!strcmp(name, "lightsensor-level")) {
-                LOGV("using %s (name=%s)", devname, name);
-                *l_fd = fd;
-            }
-            else
-                close(fd);
-        }
-    }
-    closedir(dir);
-
-    fd = 0;
-    if (*akm_fd < 0) {
-        LOGE("Couldn't find or open 'compass' driver (%s)", strerror(errno));
-        fd = -1;
-    }
-    if (*p_fd < 0) {
-        LOGE("Couldn't find or open 'proximity' driver (%s)", strerror(errno));
-        fd = -1;
-    }
-    if (*l_fd < 0) {
-        LOGE("Couldn't find or open 'light' driver (%s)", strerror(errno));
-        fd = -1;
-    }
-    return fd;
-}
-
-static int open_akm(struct sensors_control_context_t* dev)
-{
-    if (dev->akmd_fd < 0) {
-        dev->akmd_fd = open(AKM_DEVICE_NAME, O_RDONLY);
-        LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->akmd_fd);
-        LOGE_IF(dev->akmd_fd<0, "Couldn't open %s (%s)",
-                AKM_DEVICE_NAME, strerror(errno));
-        if (dev->akmd_fd >= 0) {
-            dev->active_sensors &= ~SENSORS_AKM_GROUP;
-        }
-    }
-    return dev->akmd_fd;
-}
-
-static void close_akm(struct sensors_control_context_t* dev)
-{
-    if (dev->akmd_fd >= 0) {
-        LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->akmd_fd);
-        close(dev->akmd_fd);
-        dev->akmd_fd = -1;
-    }
-}
-
-static uint32_t read_akm_sensors_state(int fd)
-{
-    short flags;
-    uint32_t sensors = 0;
-    // read the actual value of all sensors
-    if (!ioctl(fd, ECS_IOCTL_APP_GET_MFLAG, &flags)) {
-        if (flags)  sensors |= SENSORS_AKM_ORIENTATION;
-        else        sensors &= ~SENSORS_AKM_ORIENTATION;
-    }
-    if (!ioctl(fd, ECS_IOCTL_APP_GET_AFLAG, &flags)) {
-        if (flags)  sensors |= SENSORS_AKM_ACCELERATION;
-        else        sensors &= ~SENSORS_AKM_ACCELERATION;
-    }
-    if (!ioctl(fd, ECS_IOCTL_APP_GET_TFLAG, &flags)) {
-        if (flags)  sensors |= SENSORS_AKM_TEMPERATURE;
-        else        sensors &= ~SENSORS_AKM_TEMPERATURE;
-    }
-    if (!ioctl(fd, ECS_IOCTL_APP_GET_MVFLAG, &flags)) {
-        if (flags)  sensors |= SENSORS_AKM_MAGNETIC_FIELD;
-        else        sensors &= ~SENSORS_AKM_MAGNETIC_FIELD;
-    }
-    return sensors;
-}
-
-static uint32_t enable_disable_akm(struct sensors_control_context_t *dev,
-                                   uint32_t active, uint32_t sensors,
-                                   uint32_t mask)
-{
-    uint32_t now_active_akm_sensors;
-
-    int fd = open_akm(dev);
-    if (fd < 0)
-        return 0;
-
-    LOGV("(before) akm sensors = %08x, real = %08x",
-         sensors, read_akm_sensors_state(fd));
-
-    short flags;
-    if (mask & SENSORS_AKM_ORIENTATION) {
-        flags = (sensors & SENSORS_AKM_ORIENTATION) ? 1 : 0;
-        if (ioctl(fd, ECS_IOCTL_APP_SET_MFLAG, &flags) < 0) {
-            LOGE("ECS_IOCTL_APP_SET_MFLAG error (%s)", strerror(errno));
-        }
-    }
-    if (mask & SENSORS_AKM_ACCELERATION) {
-        flags = (sensors & SENSORS_AKM_ACCELERATION) ? 1 : 0;
-        if (ioctl(fd, ECS_IOCTL_APP_SET_AFLAG, &flags) < 0) {
-            LOGE("ECS_IOCTL_APP_SET_AFLAG error (%s)", strerror(errno));
-        }
-    }
-    if (mask & SENSORS_AKM_TEMPERATURE) {
-        flags = (sensors & SENSORS_AKM_TEMPERATURE) ? 1 : 0;
-        if (ioctl(fd, ECS_IOCTL_APP_SET_TFLAG, &flags) < 0) {
-            LOGE("ECS_IOCTL_APP_SET_TFLAG error (%s)", strerror(errno));
-        }
-    }
-    if (mask & SENSORS_AKM_MAGNETIC_FIELD) {
-        flags = (sensors & SENSORS_AKM_MAGNETIC_FIELD) ? 1 : 0;
-        if (ioctl(fd, ECS_IOCTL_APP_SET_MVFLAG, &flags) < 0) {
-            LOGE("ECS_IOCTL_APP_SET_MVFLAG error (%s)", strerror(errno));
-        }
-    }
-
-    now_active_akm_sensors = read_akm_sensors_state(fd);
-
-    LOGV("(after) akm sensors = %08x, real = %08x",
-         sensors, now_active_akm_sensors);
-
-    if (!sensors)
-        close_akm(dev);
-
-    return now_active_akm_sensors;
-}
-
-static uint32_t read_cm_sensors_state(int fd)
-{
-    int flags;
-    uint32_t sensors = 0;
-    // read the actual value of all sensors
-    if (!ioctl(fd, CAPELLA_CM3602_IOCTL_GET_ENABLED, &flags)) {
-        if (flags)  sensors |= SENSORS_CM_PROXIMITY;
-        else        sensors &= ~SENSORS_CM_PROXIMITY;
-    }
-
-    return sensors;
-}
-
-static int open_cm(struct sensors_control_context_t* dev)
-{
-    if (dev->cmd_fd < 0) {
-        dev->cmd_fd = open(CM_DEVICE_NAME, O_RDONLY);
-        LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->cmd_fd);
-        LOGE_IF(dev->cmd_fd<0, "Couldn't open %s (%s)",
-                CM_DEVICE_NAME, strerror(errno));
-        if (dev->cmd_fd >= 0) {
-            dev->active_sensors &= ~SENSORS_CM_GROUP;
-        }
-    }
-    return dev->cmd_fd;
-}
-
-static void close_cm(struct sensors_control_context_t* dev)
-{
-    if (dev->cmd_fd >= 0) {
-        LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->cmd_fd);
-        close(dev->cmd_fd);
-        dev->cmd_fd = -1;
-    }
-}
-
-static int enable_disable_cm(struct sensors_control_context_t *dev,
-                             uint32_t active, uint32_t sensors, uint32_t mask)
-{
-    int rc = 0;
-    uint32_t now_active_cm_sensors;
-    int fd = open_cm(dev);
-
-    if (fd < 0) {
-        LOGE("Couldn't open %s (%s)", CM_DEVICE_NAME, strerror(errno));
-        return 0;
-    }
-
-    LOGV("(before) cm sensors = %08x, real = %08x",
-         sensors, read_cm_sensors_state(fd));
-
-    if (mask & SENSORS_CM_PROXIMITY) {
-        int flags = (sensors & SENSORS_CM_PROXIMITY) ? 1 : 0;
-        rc = ioctl(fd, CAPELLA_CM3602_IOCTL_ENABLE, &flags);
-        if (rc < 0)
-            LOGE("CAPELLA_CM3602_IOCTL_ENABLE error (%s)", strerror(errno));
-    }
-
-    now_active_cm_sensors = read_cm_sensors_state(fd);
-
-    LOGV("(after) cm sensors = %08x, real = %08x",
-         sensors, now_active_cm_sensors);
-
-    return now_active_cm_sensors;
-}
-
-static uint32_t read_ls_sensors_state(int fd)
-{
-    int flags;
-    uint32_t sensors = 0;
-    // read the actual value of all sensors
-    if (!ioctl(fd, LIGHTSENSOR_IOCTL_GET_ENABLED, &flags)) {
-        if (flags)  sensors |= SENSORS_LIGHT;
-        else        sensors &= ~SENSORS_LIGHT;
-    }
-
-    return sensors;
-}
-
-static int open_ls(struct sensors_control_context_t* dev)
-{
-    if (dev->lsd_fd < 0) {
-        dev->lsd_fd = open(LS_DEVICE_NAME, O_RDONLY);
-        LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->lsd_fd);
-        LOGE_IF(dev->lsd_fd<0, "Couldn't open %s (%s)",
-                LS_DEVICE_NAME, strerror(errno));
-        if (dev->lsd_fd >= 0) {
-            dev->active_sensors &= ~SENSORS_LIGHT_GROUP;
-        }
-    }
-    return dev->lsd_fd;
-}
-
-static void close_ls(struct sensors_control_context_t* dev)
-{
-    if (dev->lsd_fd >= 0) {
-        LOGV("%s, fd=%d", __PRETTY_FUNCTION__, dev->lsd_fd);
-        close(dev->lsd_fd);
-        dev->lsd_fd = -1;
-    }
-}
-
-static int enable_disable_ls(struct sensors_control_context_t *dev,
-                             uint32_t active, uint32_t sensors, uint32_t mask)
-{
-    int rc = 0;
-    uint32_t now_active_ls_sensors;
-    int fd = open_ls(dev);
-
-    if (fd < 0) {
-        LOGE("Couldn't open %s (%s)", LS_DEVICE_NAME, strerror(errno));
-        return 0;
-    }
-
-    LOGV("(before) ls sensors = %08x, real = %08x",
-         sensors, read_ls_sensors_state(fd));
-
-    if (mask & SENSORS_LIGHT) {
-        int flags = (sensors & SENSORS_LIGHT) ? 1 : 0;
-        rc = ioctl(fd, LIGHTSENSOR_IOCTL_ENABLE, &flags);
-        if (rc < 0)
-            LOGE("LIGHTSENSOR_IOCTL_ENABLE error (%s)", strerror(errno));
-    }
-
-    now_active_ls_sensors = read_ls_sensors_state(fd);
-
-    LOGV("(after) ls sensors = %08x, real = %08x",
-         sensors, now_active_ls_sensors);
-
-    return now_active_ls_sensors;
-}
-
-/*****************************************************************************/
-
-static native_handle_t* control__open_data_source(struct sensors_control_context_t *dev)
-{
-    native_handle_t* handle;
-    int akm_fd, p_fd, l_fd;
-
-    if (open_inputs(O_RDONLY, &akm_fd, &p_fd, &l_fd) < 0 ||
-            akm_fd < 0 || p_fd < 0 || l_fd < 0) {
-        return NULL;
-    }
-
-    handle = native_handle_create(3, 0);
-    handle->data[0] = akm_fd;
-    handle->data[1] = p_fd;
-    handle->data[2] = l_fd;
-
-    return handle;
-}
-
-static int control__activate(struct sensors_control_context_t *dev,
-        int handle, int enabled)
-{
-    if ((handle < SENSORS_HANDLE_BASE) ||
-            (handle >= SENSORS_HANDLE_BASE+MAX_NUM_SENSORS))
-        return -1;
-
-    uint32_t mask = (1 << handle);
-    uint32_t sensors = enabled ? mask : 0;
-
-    uint32_t active = dev->active_sensors;
-    uint32_t new_sensors = (active & ~mask) | (sensors & mask);
-    uint32_t changed = active ^ new_sensors;
-
-    if (changed) {
-        if (!active && new_sensors)
-            // force all sensors to be updated
-            changed = SUPPORTED_SENSORS;
-
-        dev->active_sensors =
-            enable_disable_akm(dev,
-                               active & SENSORS_AKM_GROUP,
-                               new_sensors & SENSORS_AKM_GROUP,
-                               changed & SENSORS_AKM_GROUP) |
-            enable_disable_cm(dev,
-                              active & SENSORS_CM_GROUP,
-                              new_sensors & SENSORS_CM_GROUP,
-                              changed & SENSORS_CM_GROUP) |
-            enable_disable_ls(dev,
-                              active & SENSORS_LIGHT_GROUP,
-                              new_sensors & SENSORS_LIGHT_GROUP,
-                              changed & SENSORS_LIGHT_GROUP);
-    }
-
-    return 0;
-}
-
-static int control__set_delay(struct sensors_control_context_t *dev, int32_t ms)
-{
-#ifdef ECS_IOCTL_APP_SET_DELAY
-    if (dev->akmd_fd <= 0) {
-        return -1;
-    }
-    short delay = ms;
-    if (!ioctl(dev->akmd_fd, ECS_IOCTL_APP_SET_DELAY, &delay)) {
-        return -errno;
-    }
-    return 0;
-#else
-    return -1;
-#endif
-}
-
-static int control__wake(struct sensors_control_context_t *dev)
-{
-    int err = 0;
-    int akm_fd, p_fd, l_fd;
-    if (open_inputs(O_RDWR, &akm_fd, &p_fd, &l_fd) < 0 ||
-            akm_fd < 0 || p_fd < 0 || l_fd < 0) {
-        return -1;
-    }
-
-    struct input_event event[1];
-    event[0].type = EV_SYN;
-    event[0].code = SYN_CONFIG;
-    event[0].value = 0;
-
-    err = write(akm_fd, event, sizeof(event));
-    LOGV_IF(err<0, "control__wake(compass), fd=%d (%s)",
-            akm_fd, strerror(errno));
-    close(akm_fd);
-
-    err = write(p_fd, event, sizeof(event));
-    LOGV_IF(err<0, "control__wake(proximity), fd=%d (%s)",
-            p_fd, strerror(errno));
-    close(p_fd);
-
-    err = write(l_fd, event, sizeof(event));
-    LOGV_IF(err<0, "control__wake(light), fd=%d (%s)",
-            l_fd, strerror(errno));
-    close(l_fd);
-
-    return err;
-}
-
-/*****************************************************************************/
-
-static int data__data_open(struct sensors_data_context_t *dev, native_handle_t* handle)
-{
-    int i;
-    struct input_absinfo absinfo;
-    memset(&dev->sensors, 0, sizeof(dev->sensors));
-
-    for (i = 0; i < MAX_NUM_SENSORS; i++) {
-        // by default all sensors have high accuracy
-        // (we do this because we don't get an update if the value doesn't
-        // change).
-        dev->sensors[i].vector.status = SENSOR_STATUS_ACCURACY_HIGH;
-    }
-
-    dev->sensors[ID_A].sensor = SENSOR_TYPE_ACCELEROMETER;
-    dev->sensors[ID_M].sensor = SENSOR_TYPE_MAGNETIC_FIELD;
-    dev->sensors[ID_O].sensor = SENSOR_TYPE_ORIENTATION;
-    dev->sensors[ID_T].sensor = SENSOR_TYPE_TEMPERATURE;
-    dev->sensors[ID_P].sensor = SENSOR_TYPE_PROXIMITY;
-    dev->sensors[ID_L].sensor = SENSOR_TYPE_LIGHT;
-
-    dev->events_fd[0] = dup(handle->data[0]);
-    dev->events_fd[1] = dup(handle->data[1]);
-    dev->events_fd[2] = dup(handle->data[2]);
-    LOGV("data__data_open: compass fd = %d", handle->data[0]);
-    LOGV("data__data_open: proximity fd = %d", handle->data[1]);
-    LOGV("data__data_open: light fd = %d", handle->data[2]);
-    // Framework will close the handle
-    native_handle_delete(handle);
-
-    dev->pendingSensors = 0;
-    if (!ioctl(dev->events_fd[1], EVIOCGABS(ABS_DISTANCE), &absinfo)) {
-        LOGV("proximity sensor initial value %d\n", absinfo.value);
-        dev->pendingSensors |= SENSORS_CM_PROXIMITY;
-        // FIXME: we should save here absinfo.{minimum, maximum, etc}
-        //        and use them to scale the return value according to
-        //        the sensor description.
-        dev->sensors[ID_P].distance = (float)absinfo.value;
-    }
-    else LOGE("Cannot get proximity sensor initial value: %s\n",
-              strerror(errno));
-
-    return 0;
-}
-
-static int data__data_close(struct sensors_data_context_t *dev)
-{
-    if (dev->events_fd[0] >= 0) {
-        //LOGV("(data close) about to close compass fd=%d", dev->events_fd[0]);
-        close(dev->events_fd[0]);
-        dev->events_fd[0] = -1;
-    }
-    if (dev->events_fd[1] >= 0) {
-        //LOGV("(data close) about to close proximity fd=%d", dev->events_fd[1]);
-        close(dev->events_fd[1]);
-        dev->events_fd[1] = -1;
-    }
-    if (dev->events_fd[2] >= 0) {
-        //LOGV("(data close) about to close light fd=%d", dev->events_fd[1]);
-        close(dev->events_fd[2]);
-        dev->events_fd[2] = -1;
-    }
-    return 0;
-}
-
-static int pick_sensor(struct sensors_data_context_t *dev,
-        sensors_data_t* values)
-{
-    uint32_t mask = SUPPORTED_SENSORS;
-    while (mask) {
-        uint32_t i = 31 - __builtin_clz(mask);
-        mask &= ~(1<<i);
-        if (dev->pendingSensors & (1<<i)) {
-            dev->pendingSensors &= ~(1<<i);
-            *values = dev->sensors[i];
-            values->sensor = id_to_sensor[i];
-            LOGV_IF(0, "%d [%f, %f, %f]",
-                    values->sensor,
-                    values->vector.x,
-                    values->vector.y,
-                    values->vector.z);
-            return i;
-        }
-    }
-
-    LOGE("no sensor to return: pendingSensors = %08x", dev->pendingSensors);
-    return -1;
-}
-
-static uint32_t data__poll_process_akm_abs(struct sensors_data_context_t *dev,
-                                           int fd __attribute__((unused)),
-                                           struct input_event *event)
-{
-    uint32_t new_sensors = 0;
-    if (event->type == EV_ABS) {
-        LOGV("compass type: %d code: %d value: %-5d time: %ds",
-             event->type, event->code, event->value,
-             (int)event->time.tv_sec);
-        switch (event->code) {
-        case EVENT_TYPE_ACCEL_X:
-            new_sensors |= SENSORS_AKM_ACCELERATION;
-            dev->sensors[ID_A].acceleration.x = event->value * CONVERT_A_X;
-            break;
-        case EVENT_TYPE_ACCEL_Y:
-            new_sensors |= SENSORS_AKM_ACCELERATION;
-            dev->sensors[ID_A].acceleration.y = event->value * CONVERT_A_Y;
-            break;
-        case EVENT_TYPE_ACCEL_Z:
-            new_sensors |= SENSORS_AKM_ACCELERATION;
-            dev->sensors[ID_A].acceleration.z = event->value * CONVERT_A_Z;
-            break;
-        case EVENT_TYPE_MAGV_X:
-            new_sensors |= SENSORS_AKM_MAGNETIC_FIELD;
-            dev->sensors[ID_M].magnetic.x = event->value * CONVERT_M_X;
-            break;
-        case EVENT_TYPE_MAGV_Y:
-            new_sensors |= SENSORS_AKM_MAGNETIC_FIELD;
-            dev->sensors[ID_M].magnetic.y = event->value * CONVERT_M_Y;
-            break;
-        case EVENT_TYPE_MAGV_Z:
-            new_sensors |= SENSORS_AKM_MAGNETIC_FIELD;
-            dev->sensors[ID_M].magnetic.z = event->value * CONVERT_M_Z;
-            break;
-        case EVENT_TYPE_YAW:
-            new_sensors |= SENSORS_AKM_ORIENTATION;
-            dev->sensors[ID_O].orientation.azimuth =  event->value;
-            break;
-        case EVENT_TYPE_PITCH:
-            new_sensors |= SENSORS_AKM_ORIENTATION;
-            dev->sensors[ID_O].orientation.pitch = event->value;
-            break;
-        case EVENT_TYPE_ROLL:
-            new_sensors |= SENSORS_AKM_ORIENTATION;
-            dev->sensors[ID_O].orientation.roll = -event->value;
-            break;
-        case EVENT_TYPE_TEMPERATURE:
-            new_sensors |= SENSORS_AKM_TEMPERATURE;
-            dev->sensors[ID_T].temperature = event->value;
-            break;
-        case EVENT_TYPE_STEP_COUNT:
-            // step count (only reported in MODE_FFD)
-            // we do nothing with it for now.
-            break;
-        case EVENT_TYPE_ACCEL_STATUS:
-            // accuracy of the calibration (never returned!)
-            //LOGV("G-Sensor status %d", event->value);
-            break;
-        case EVENT_TYPE_ORIENT_STATUS: {
-            // accuracy of the calibration
-            uint32_t v = (uint32_t)(event->value & SENSOR_STATE_MASK);
-            LOGV_IF(dev->sensors[ID_O].orientation.status != (uint8_t)v,
-                    "M-Sensor status %d", v);
-            dev->sensors[ID_O].orientation.status = (uint8_t)v;
-        }
-            break;
-        }
-    }
-
-    return new_sensors;
-}
-
-static uint32_t data__poll_process_cm_abs(struct sensors_data_context_t *dev,
-                                           int fd __attribute__((unused)),
-                                          struct input_event *event)
-{
-    uint32_t new_sensors = 0;
-    if (event->type == EV_ABS) {
-        LOGV("proximity type: %d code: %d value: %-5d time: %ds",
-             event->type, event->code, event->value,
-             (int)event->time.tv_sec);
-        if (event->code == EVENT_TYPE_PROXIMITY) {
-            new_sensors |= SENSORS_CM_PROXIMITY;
-            /* event->value seems to be 0 or 1, scale it to the threshold */
-            dev->sensors[ID_P].distance = event->value * PROXIMITY_THRESHOLD_CM;
-        }
-    }
-    return new_sensors;
-}
-
-static uint32_t data__poll_process_ls_abs(struct sensors_data_context_t *dev,
-                                          int fd __attribute__((unused)),
-                                          struct input_event *event)
-{
-    uint32_t new_sensors = 0;
-    if (event->type == EV_ABS) {
-        LOGV("light-level type: %d code: %d value: %-5d time: %ds",
-             event->type, event->code, event->value,
-             (int)event->time.tv_sec);
-        if (event->code == EVENT_TYPE_LIGHT) {
-            struct input_absinfo absinfo;
-            int index;
-            if (!ioctl(fd, EVIOCGABS(ABS_DISTANCE), &absinfo)) {
-                index = event->value;
-                if (index >= 0) {
-                    new_sensors |= SENSORS_LIGHT;
-                    if (index >= ARRAY_SIZE(sLuxValues)) {
-                        index = ARRAY_SIZE(sLuxValues) - 1;
-                    }
-                    dev->sensors[ID_L].light = sLuxValues[index];
-                }
-            }
-        }
-    }
-    return new_sensors;
-}
-
-static void data__poll_process_syn(struct sensors_data_context_t *dev,
-                                   struct input_event *event,
-                                   uint32_t new_sensors)
-{
-    if (new_sensors) {
-        dev->pendingSensors |= new_sensors;
-        int64_t t = event->time.tv_sec*1000000000LL +
-            event->time.tv_usec*1000;
-        while (new_sensors) {
-            uint32_t i = 31 - __builtin_clz(new_sensors);
-            new_sensors &= ~(1<<i);
-            dev->sensors[i].time = t;
-        }
-    }
-}
-
-static int data__poll(struct sensors_data_context_t *dev, sensors_data_t* values)
-{
-    int akm_fd = dev->events_fd[0];
-    int cm_fd = dev->events_fd[1];
-    int ls_fd = dev->events_fd[2];
-
-    if (akm_fd < 0) {
-        LOGE("invalid compass file descriptor, fd=%d", akm_fd);
-        return -1;
-    }
-
-    if (cm_fd < 0) {
-        LOGE("invalid proximity-sensor file descriptor, fd=%d", cm_fd);
-        return -1;
-    }
-
-    if (ls_fd < 0) {
-        LOGE("invalid light-sensor file descriptor, fd=%d", ls_fd);
-        return -1;
-    }
-
-    // there are pending sensors, returns them now...
-    if (dev->pendingSensors) {
-        LOGV("pending sensors 0x%08x", dev->pendingSensors);
-        return pick_sensor(dev, values);
-    }
-
-    // wait until we get a complete event for an enabled sensor
-    uint32_t new_sensors = 0;
-    while (1) {
-        /* read the next event; first, read the compass event, then the
-           proximity event */
-        struct input_event event;
-        int got_syn = 0;
-        int exit = 0;
-        int nread;
-        fd_set rfds;
-        int n;
-
-        FD_ZERO(&rfds);
-        FD_SET(akm_fd, &rfds);
-        FD_SET(cm_fd, &rfds);
-        FD_SET(ls_fd, &rfds);
-        n = select(__MAX(akm_fd, __MAX(cm_fd, ls_fd)) + 1, &rfds,
-                   NULL, NULL, NULL);
-        LOGV("return from select: %d\n", n);
-        if (n < 0) {
-            LOGE("%s: error from select(%d, %d): %s",
-                 __FUNCTION__,
-                 akm_fd, cm_fd, strerror(errno));
-            return -1;
-        }
-
-        if (FD_ISSET(akm_fd, &rfds)) {
-            nread = read(akm_fd, &event, sizeof(event));
-            if (nread == sizeof(event)) {
-                new_sensors |= data__poll_process_akm_abs(dev, akm_fd, &event);
-                LOGV("akm abs %08x", new_sensors);
-                got_syn = event.type == EV_SYN;
-                exit = got_syn && event.code == SYN_CONFIG;
-                if (got_syn) {
-                    LOGV("akm syn %08x", new_sensors);
-                    data__poll_process_syn(dev, &event, new_sensors);
-                    new_sensors = 0;
-                }
-            }
-            else LOGE("akm read too small %d", nread);
-        }
-        else LOGV("akm fd is not set");
-
-        if (FD_ISSET(cm_fd, &rfds)) {
-            nread = read(cm_fd, &event, sizeof(event));
-            if (nread == sizeof(event)) {
-                new_sensors |= data__poll_process_cm_abs(dev, cm_fd, &event);
-                LOGV("cm abs %08x", new_sensors);
-                got_syn |= event.type == EV_SYN;
-                exit |= got_syn && event.code == SYN_CONFIG;
-                if (got_syn) {
-                    LOGV("cm syn %08x", new_sensors);
-                    data__poll_process_syn(dev, &event, new_sensors);
-                    new_sensors = 0;
-                }
-            }
-            else LOGE("cm read too small %d", nread);
-        }
-        else LOGV("cm fd is not set");
-
-        if (FD_ISSET(ls_fd, &rfds)) {
-            nread = read(ls_fd, &event, sizeof(event));
-            if (nread == sizeof(event)) {
-                new_sensors |= data__poll_process_ls_abs(dev, ls_fd, &event);
-                LOGV("ls abs %08x", new_sensors);
-                got_syn |= event.type == EV_SYN;
-                exit |= got_syn && event.code == SYN_CONFIG;
-                if (got_syn) {
-                    LOGV("ls syn %08x", new_sensors);
-                    data__poll_process_syn(dev, &event, new_sensors);
-                    new_sensors = 0;
-                }
-            }
-            else LOGE("ls read too small %d", nread);
-        }
-        else LOGV("ls fd is not set");
-
-        if (exit) {
-            // we use SYN_CONFIG to signal that we need to exit the
-            // main loop.
-            //LOGV("got empty message: value=%d", event->value);
-            LOGV("exit");
-            return 0x7FFFFFFF;
-        }
-
-        if (got_syn && dev->pendingSensors) {
-            LOGV("got syn, picking sensor");
-            return pick_sensor(dev, values);
-        }
-    }
-}
-
-/*****************************************************************************/
-
-static int control__close(struct hw_device_t *dev)
-{
-    struct sensors_control_context_t* ctx =
-        (struct sensors_control_context_t*)dev;
-    if (ctx) {
-        close_akm(ctx);
-        close_cm(ctx);
-        close_ls(ctx);
-        free(ctx);
-    }
-    return 0;
-}
-
-static int data__close(struct hw_device_t *dev)
-{
-    struct sensors_data_context_t* ctx = (struct sensors_data_context_t*)dev;
-    if (ctx) {
-        data__data_close(ctx);
-        free(ctx);
-    }
-    return 0;
-}
-
-
-/** Open a new instance of a sensor device using name */
 static int open_sensors(const struct hw_module_t* module, const char* name,
         struct hw_device_t** device)
 {
-    int status = -EINVAL;
-    if (!strcmp(name, SENSORS_HARDWARE_CONTROL)) {
-        struct sensors_control_context_t *dev;
-        dev = malloc(sizeof(*dev));
-        memset(dev, 0, sizeof(*dev));
-        dev->akmd_fd = -1;
-        dev->cmd_fd = -1;
-        dev->lsd_fd = -1;
-        dev->device.common.tag = HARDWARE_DEVICE_TAG;
-        dev->device.common.version = 0;
-        dev->device.common.module = module;
-        dev->device.common.close = control__close;
-        dev->device.open_data_source = control__open_data_source;
-        dev->device.activate = control__activate;
-        dev->device.set_delay= control__set_delay;
-        dev->device.wake = control__wake;
-        *device = &dev->device.common;
-    } else if (!strcmp(name, SENSORS_HARDWARE_DATA)) {
-        struct sensors_data_context_t *dev;
-        dev = malloc(sizeof(*dev));
-        memset(dev, 0, sizeof(*dev));
-        dev->events_fd[0] = -1;
-        dev->events_fd[1] = -1;
-        dev->events_fd[2] = -1;
-        dev->device.common.tag = HARDWARE_DEVICE_TAG;
-        dev->device.common.version = 0;
-        dev->device.common.module = module;
-        dev->device.common.close = data__close;
-        dev->device.data_open = data__data_open;
-        dev->device.data_close = data__data_close;
-        dev->device.poll = data__poll;
-        *device = &dev->device.common;
-    }
-    return status;
+    return init_nusensors(module, device);
 }