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);
}