summaryrefslogtreecommitdiffstats
path: root/libsensors
diff options
context:
space:
mode:
authoratinm <atin.malaviya@gmail.com>2011-05-17 11:12:26 -0400
committeratinm <atin.malaviya@gmail.com>2011-05-17 11:12:26 -0400
commit93a7e5951c8dfcdf609161875493ef6925f68ca7 (patch)
tree4f6a18bc3d66a41021e627412a54bb80567264c3 /libsensors
parent306e030c5772b1cd1d38a4801db2bc128021003a (diff)
downloaddevice_samsung_aries-common-93a7e5951c8dfcdf609161875493ef6925f68ca7.zip
device_samsung_aries-common-93a7e5951c8dfcdf609161875493ef6925f68ca7.tar.gz
device_samsung_aries-common-93a7e5951c8dfcdf609161875493ef6925f68ca7.tar.bz2
moved to device/samsung/aries-common
Diffstat (limited to 'libsensors')
-rw-r--r--libsensors/Android.mk50
-rw-r--r--libsensors/BoschYamaha.cpp500
-rw-r--r--libsensors/BoschYamaha.h83
-rw-r--r--libsensors/CompassSensor.cpp166
-rw-r--r--libsensors/CompassSensor.h54
-rw-r--r--libsensors/GyroSensor.cpp181
-rw-r--r--libsensors/GyroSensor.h54
-rw-r--r--libsensors/InputEventReader.cpp88
-rw-r--r--libsensors/InputEventReader.h47
-rw-r--r--libsensors/LightSensor.cpp180
-rw-r--r--libsensors/LightSensor.h57
-rw-r--r--libsensors/OrientationSensor.cpp163
-rw-r--r--libsensors/OrientationSensor.h54
-rw-r--r--libsensors/ProximitySensor.cpp144
-rw-r--r--libsensors/ProximitySensor.h54
-rw-r--r--libsensors/SensorBase.cpp128
-rw-r--r--libsensors/SensorBase.h65
-rw-r--r--libsensors/Smb380Sensor.cpp165
-rw-r--r--libsensors/Smb380Sensor.h69
-rw-r--r--libsensors/sensors.cpp335
-rw-r--r--libsensors/sensors.h117
21 files changed, 2754 insertions, 0 deletions
diff --git a/libsensors/Android.mk b/libsensors/Android.mk
new file mode 100644
index 0000000..228bfe7
--- /dev/null
+++ b/libsensors/Android.mk
@@ -0,0 +1,50 @@
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+ifneq ($(TARGET_SIMULATOR),true)
+
+# HAL module implemenation, not prelinked, and stored in
+# hw/<SENSORS_HARDWARE_MODULE_ID>.<ro.product.board>.so
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := sensors.aries
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
+
+LOCAL_MODULE_TAGS := optional
+
+LOCAL_CFLAGS := -DLOG_TAG=\"Sensors\"
+
+ifeq ($(TARGET_DEVICE),captivate)
+ LOCAL_CFLAGS += -DCAPTIVATE
+endif
+
+LOCAL_SRC_FILES := \
+ sensors.cpp \
+ SensorBase.cpp \
+ LightSensor.cpp \
+ ProximitySensor.cpp \
+ Smb380Sensor.cpp \
+ CompassSensor.cpp \
+ OrientationSensor.cpp \
+ InputEventReader.cpp
+
+LOCAL_SHARED_LIBRARIES := liblog libcutils libdl
+LOCAL_PRELINK_MODULE := false
+
+include $(BUILD_SHARED_LIBRARY)
+
+endif
diff --git a/libsensors/BoschYamaha.cpp b/libsensors/BoschYamaha.cpp
new file mode 100644
index 0000000..ba88ff9
--- /dev/null
+++ b/libsensors/BoschYamaha.cpp
@@ -0,0 +1,500 @@
+/*
+ * 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 <dlfcn.h>
+
+#include <cutils/log.h>
+
+#include "BoschYamaha.h"
+
+/*****************************************************************************/
+
+int stub_is_sensor_enabled(uint32_t sensor_type) {
+ return 0;
+}
+
+int stub_enable_disable_sensor(uint32_t sensor_type) {
+ return -ENODEV;
+}
+
+int stub_set_delay(uint64_t delay) {
+ return -ENODEV;
+}
+
+BoschYamaha::BoschYamaha()
+: SensorBase(NULL, NULL),
+ //mEnabled(0),
+ mPendingMask(0),
+ mInputReaderMagnetic(4),
+ mInputReaderAccel(4)
+{
+
+ counterAccel = 0;
+
+ /* FIXME set input device name for magnetic sensor */
+ data_name = "input0";
+ data_compass_fd = openInput("geomagnetic");
+
+
+ //Open Compass
+ if (data_compass_fd) {
+ strcpy(input_sysfs_path, "/sys/class/input/");
+ strcat(input_sysfs_path, input_name);
+ strcat(input_sysfs_path, "/device/");
+ input_sysfs_path_len = strlen(input_sysfs_path);
+ //enable(MagneticField, 1);
+
+ }
+
+ /* FIXME set input device name for accelereometer sensor */
+ data_accel_name = "event6";
+ data_fd = openInput("SMB380-Sensor");
+
+ //Open Compass
+ if (data_fd) {
+ strcpy(input_accel_sysfs_path, "/sys/class/input/");
+ strcat(input_accel_sysfs_path, data_accel_name);
+ strcat(input_accel_sysfs_path, "/device/");
+ input_accel_sysfs_path_len = strlen(input_accel_sysfs_path);
+
+ enable(Accelerometer, 1);
+
+ }
+
+
+ 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;
+
+
+
+
+ for (int i=0 ; i<numSensors ; i++)
+ mDelays[i] = 200000000; // 200 ms by default
+
+}
+
+BoschYamaha::~BoschYamaha()
+{
+ if(compassEnabled){
+ enable(MagneticField, 0);
+ }
+ if(accelEnabled){
+ enable(Accelerometer, 0);
+ }
+
+}
+
+int BoschYamaha::enable(int32_t handle, int en)
+{
+ int what = -1;
+
+ switch (handle) {
+ case ID_A: what = Accelerometer; break;
+ case ID_M: what = MagneticField; break;
+ case ID_O: what = Orientation; break;
+ }
+
+ if (uint32_t(what) >= numSensors)
+ return -EINVAL;
+
+ int newState = en ? 1 : 0;
+ int err = 0;
+
+ /*
+ //FIXME enabling the right sensor over sysfs interface
+ if(what == MagneticField){
+ what = Accelerometer; //Enable also Accel
+ //Compass
+ LOGD("BoschYamaha::~enable Compass(0, %d)", en);
+ int flags = en ? 1 : 0;
+ if (flags != compassEnabled) {
+ int fd;
+ strcpy(&input_sysfs_path[input_sysfs_path_len], "enable");
+ LOGD("BoschYamaha::~enable Compass(0, %d) open %s",en, input_sysfs_path);
+ fd = open(input_sysfs_path, O_RDWR);
+ if (fd >= 0) {
+ LOGD("CompassSensor::~enable(0, %d) opened %s",en, input_sysfs_path);
+ char buf[2];
+ int err;
+ buf[1] = 0;
+ if (flags) {
+ buf[0] = '1';
+ } else {
+ buf[0] = '0';
+ }
+ err = write(fd, buf, sizeof(buf));
+ close(fd);
+ //mEnabled = flags;
+ compassEnabled = flags;
+ return 0;
+ }
+ }
+ }
+ */
+
+ if(what == Accelerometer){
+ //Accelerometer
+ LOGD("BoschYamaha::~enable Accel(0, %d)", en);
+ int flags = en ? 1 : 0;
+ if (flags != accelEnabled) {
+ int fd;
+ strcpy(&input_accel_sysfs_path[input_accel_sysfs_path_len], "enable");
+ LOGD("BoschYamaha::~enable Accel(0, %d) open %s",en, input_accel_sysfs_path);
+ fd = open(input_accel_sysfs_path, O_RDWR);
+ if (fd >= 0) {
+ LOGD("CompassSensor::~enable(0, %d) opened %s",en, input_accel_sysfs_path);
+ char buf[2];
+ int err;
+ buf[1] = 0;
+ if (flags) {
+ // counterAccel++;
+ buf[0] = '1';
+ } else {
+ // counterAccel--;
+ buf[0] = '0';
+ }
+ //if(counterAccel <= 1){
+ err = write(fd, buf, sizeof(buf));
+ //}
+ close(fd);
+ //mEnabled = flags;
+ accelEnabled = flags;
+ return 0;
+ }
+ }
+ }
+
+
+ return err;
+}
+
+int BoschYamaha::setDelay(int32_t handle, int64_t ns)
+{
+ int what = -1;
+ switch (handle) {
+ case ID_A: what = Accelerometer; break;
+ case ID_M: what = MagneticField; break;
+ case ID_O: what = Orientation; break;
+ }
+
+ if (uint32_t(what) >= numSensors)
+ return -EINVAL;
+
+ if (ns < 0)
+ return -EINVAL;
+
+ mDelays[what] = ns;
+ return update_delay();
+}
+
+int BoschYamaha::update_delay()
+{
+ return 0;
+}
+
+
+bool BoschYamaha::hasPendingEvents() {
+
+ //LOGD("hasPendingEvents was called");
+ if(accelEnabled || compassEnabled){
+ //LOGD("hasPendingEvents will return true");
+ return true;
+ }
+ else {
+ //LOGD("hasPendingEvents will return false");
+ return false;
+ }
+}
+
+
+
+int BoschYamaha::readEvents(sensors_event_t* data, int count)
+{
+ if (count < 1)
+ return -EINVAL;
+
+
+ int numEventReceived = 0;
+
+ //LOGD("Sensor: Read events was called with count: %d", count);
+
+ if(compassEnabled)
+ {
+ //LOGD("Sensor: Compass is enabled, going to take care of it, count: %d", count);
+ ssize_t n = mInputReaderMagnetic.fill(data_compass_fd);
+ if (n < 0)
+ return n;
+
+ input_event const* event;
+
+ while ( count && mInputReaderMagnetic.readEvent(&event)) {
+ int type = event->type;
+ //Everything is ABS!
+ if (type == EV_ABS) {
+ float value = event->value;
+ if (event->code == EVENT_TYPE_MAGV_X) {
+ mPendingEvents[MagneticField].magnetic.x = (value * CONVERT_M_X);
+ } else if (event->code == EVENT_TYPE_MAGV_Y) {
+ mPendingEvents[MagneticField].magnetic.y = (value * CONVERT_M_Y);
+ } else if (event->code == EVENT_TYPE_MAGV_Z) {
+ mPendingEvents[MagneticField].magnetic.z = (value * CONVERT_M_Z);
+ }
+ }
+ else if (type == EV_SYN) {
+ mPendingEvents[MagneticField].timestamp = timevalToNano(event->time);
+ if (compassEnabled) {
+ //LOGD("Sensor: Compass was enabled, made a read and received a Sync");
+ compassDataReady = 1;
+ compassLastRead[0] = mPendingEvents[MagneticField].magnetic.x;
+ compassLastRead[1] = mPendingEvents[MagneticField].magnetic.y;
+ compassLastRead[2] = mPendingEvents[MagneticField].magnetic.z;
+
+ *data++ = mPendingEvents[MagneticField];
+ count--;
+ numEventReceived++;
+ }
+ } else {
+ LOGE("BoschYamaha: unknown event (type=%d, code=%d)", type, event->code);
+
+ }
+ mInputReaderMagnetic.next();
+ }
+ }
+
+ //LOGD("Sensor: Compass read quited, count: %d", count);
+
+
+ if(accelEnabled)
+ {
+ //LOGD("Sensor: Accel is enabled, going to take care of it, count: %d", count);
+
+ ssize_t n = mInputReaderAccel.fill(data_fd);
+ //LOGD("Sensor: Accel Input Reader was filled up: %d", count);
+ if (n < 0)
+ return n;
+
+ input_event const* event;
+
+ while (count && mInputReaderAccel.readEvent(&event)) {
+ int type = event->type;
+ if (type == EV_ABS) {
+ //LOGD("Sensor: Received one EV_ABS Event");
+ float value = event->value;
+ if (event->code == EVENT_TYPE_ACCEL_X) {
+ mPendingEvents[Accelerometer].acceleration.x = value * CONVERT_A_X;
+ } else if (event->code == EVENT_TYPE_ACCEL_Y) {
+ mPendingEvents[Accelerometer].acceleration.y = value * CONVERT_A_Y;
+ } else if (event->code == EVENT_TYPE_ACCEL_Z) {
+ mPendingEvents[Accelerometer].acceleration.z = value * CONVERT_A_Z;
+ }
+ } else if (type == EV_SYN) {
+ mPendingEvents[Accelerometer].timestamp = timevalToNano(event->time);
+ if (accelEnabled) {
+ //LOGD("Sensor: Accel was enabled, made a read and received a Sync");
+ accelDataReady = 1;
+ accelLastRead[0] = mPendingEvents[Accelerometer].acceleration.x;
+ accelLastRead[1] = mPendingEvents[Accelerometer].acceleration.y;
+ accelLastRead[2] = mPendingEvents[Accelerometer].acceleration.z;
+ *data++ = mPendingEvents[Accelerometer];
+ count--;
+ numEventReceived++;
+ }
+ }
+ else {
+ LOGE("BoschYamaha: unknown event (type=%d, code=%d)", type, event->code);
+
+ }
+ mInputReaderAccel.next();
+ }
+ }
+
+ //LOGD("Sensor: Accel read quited, count: %d, acceldata Ready: %d, compassData Ready = %d", count, accelDataReady, compassDataReady);
+
+ if( (accelDataReady == 1) && (compassDataReady == 1)){
+ //LOGD("BoschYamaha: Going to Process Orientation Data");
+ accelDataReady = 0;
+ compassDataReady = 0;
+ processOrientation();
+ *data++ = mPendingEvents[Orientation];
+ numEventReceived++;
+ }
+
+
+ return numEventReceived;
+}
+
+
+int BoschYamaha::processOrientation(){
+
+ float matrix[9], euler[3];
+ int rt, i;
+
+
+ rt = get_rotation_matrix(accelLastRead, compassLastRead, matrix);
+
+
+ if (rt < 0) {
+ for (i = 0; i < 3; i++) {
+ euler[i] = 0;
+ }
+ }
+ else {
+ get_euler(matrix, euler);
+ }
+
+ //LOGD("BoschYamaha: azimuth is %d", (int)(euler[0]));
+ //LOGD("BoschYamaha: pitch is %d", (int)(euler[1]));
+ //LOGD("BoschYamaha: roll is %d", (int)(euler[2]));
+
+ //Use CONVERT_O_A
+ mPendingEvents[Orientation].orientation.azimuth = (int)(euler[0]);
+ mPendingEvents[Orientation].orientation.pitch = (int)(euler[1]);
+ mPendingEvents[Orientation].orientation.roll = (int)(euler[2]);
+ //mPendingEvents[Orientation].orientation.status = uint8_t(value & SENSOR_STATE_MASK);
+
+ return 1;
+
+}
+
+
+float BoschYamaha::calc_intensity(float x, float y, float z)
+{
+ return sqrt(x*x + y*y + z*z);
+}
+
+
+int BoschYamaha::get_rotation_matrix(const float *gsdata, const float *msdata, float *matrix)
+{
+ float m_intensity, g_intensity, a_intensity, b_intensity;
+ float gdata[3], mdata[3], adata[3], bdata[3];
+ int i;
+
+ if (gsdata == NULL || msdata == NULL || matrix == NULL) {
+ return -1;
+ }
+ g_intensity = calc_intensity(gsdata[0], gsdata[1], gsdata[2]);
+ m_intensity = calc_intensity(msdata[0], msdata[1], msdata[2]);
+ if (g_intensity == 0 || m_intensity == 0) {
+ return -1;
+ }
+ for (i = 0; i < 3; i++) {
+ gdata[i] = -gsdata[i] / g_intensity;
+ mdata[i] = msdata[i] / m_intensity;
+ }
+
+ adata[0] = (gdata[1] * mdata[2] - gdata[2] * mdata[1]);
+ adata[1] = (gdata[2] * mdata[0] - gdata[0] * mdata[2]);
+ adata[2] = (gdata[0] * mdata[1] - gdata[1] * mdata[0]);
+ a_intensity = calc_intensity(adata[0], adata[1], adata[2]);
+ if (a_intensity == 0) {
+ return -1;
+ }
+ for (i = 0; i < 3; i++) {
+ adata[i] /= a_intensity;
+ }
+
+ bdata[0] = (adata[1] * gdata[2] - adata[2] * gdata[1]);
+ bdata[1] = (adata[2] * gdata[0] - adata[0] * gdata[2]);
+ bdata[2] = (adata[0] * gdata[1] - adata[1] * gdata[0]);
+ b_intensity = calc_intensity(bdata[0], bdata[1], bdata[2]);
+ if (b_intensity == 0) {
+ return -1;
+ }
+ for (i = 0; i < 3; i++) {
+ bdata[i] /= b_intensity;
+ }
+
+ matrix[0] = adata[0];
+ matrix[1] = adata[1];
+ matrix[2] = adata[2];
+ matrix[3] = bdata[0];
+ matrix[4] = bdata[1];
+ matrix[5] = bdata[2];
+ matrix[6] = -gdata[0];
+ matrix[7] = -gdata[1];
+ matrix[8] = -gdata[2];
+
+ return 0;
+}
+
+int BoschYamaha::get_euler(const float *matrix, float *euler)
+{
+ float m11, m12;
+ float m21, m22;
+ float m31, m32, m33;
+ float yaw = 0, roll = 0, pitch = 0;
+
+ if (matrix == NULL || euler == NULL) {
+ return -1;
+ }
+
+ m11 = matrix[0];
+ m12 = matrix[1];
+ m21 = matrix[3];
+ m22 = matrix[4];
+ m31 = matrix[6];
+ m32 = matrix[7];
+ m33 = matrix[8];
+
+ yaw = atan2(m12-m21, m11+m22);
+ pitch = -asin(m32);
+ roll = asin(m31);
+
+ yaw *= 180.0 / M_PI;
+ pitch *= 180.0 / M_PI;
+ roll *= 180.0 / M_PI;
+
+ if (m33 < 0) {
+ pitch = -180 - pitch;
+ if (pitch < -180) {
+ pitch += 360;
+ }
+ }
+ if (yaw < 0) {
+ yaw += 360.0f;
+ }
+
+ euler[0] = (float)(int)yaw; /* yaw */
+
+ euler[1] = (float)(int)pitch; /* pitch */
+ euler[2] = (float)(int)roll; /* roll */
+
+ return 0;
+}
+
+
+
diff --git a/libsensors/BoschYamaha.h b/libsensors/BoschYamaha.h
new file mode 100644
index 0000000..52af86b
--- /dev/null
+++ b/libsensors/BoschYamaha.h
@@ -0,0 +1,83 @@
+/*
+ * 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_BOSCHYAMAHA_SENSOR_H
+#define ANDROID_BOSCHYAMAHA_SENSOR_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+
+#include "sensors.h"
+#include "SensorBase.h"
+#include "InputEventReader.h"
+
+/*****************************************************************************/
+
+struct input_event;
+
+class BoschYamaha : public SensorBase {
+public:
+ BoschYamaha();
+ virtual ~BoschYamaha();
+
+
+
+ enum {
+ Accelerometer = 0,
+ MagneticField = 1,
+ Orientation = 2,
+ numSensors
+ };
+
+ virtual int setDelay(int32_t handle, int64_t ns);
+ virtual int enable(int32_t handle, int enabled);
+ virtual int readEvents(sensors_event_t* data, int count);
+ virtual bool hasPendingEvents();
+ int processOrientation();
+ float calc_intensity(float x, float y, float z);
+ int get_rotation_matrix(const float *gsdata, const float *msdata, float *matrix);
+ int get_euler(const float *matrix, float *euler);
+
+private:
+ const char* data_accel_name;
+ int data_compass_fd;
+ int update_delay();
+ //uint32_t mEnabled;
+ int compassEnabled;
+ int accelEnabled;
+ float accelLastRead[3];
+ float compassLastRead[3];
+ int compassDataReady;
+ int accelDataReady;
+ int counterAccel;
+ uint32_t mPendingMask;
+ InputEventCircularReader mInputReaderMagnetic;
+ InputEventCircularReader mInputReaderAccel;
+ sensors_event_t mPendingEvents[numSensors];
+ uint64_t mDelays[numSensors];
+ char input_sysfs_path[PATH_MAX];
+ int input_sysfs_path_len;
+ char input_accel_sysfs_path[PATH_MAX];
+ int input_accel_sysfs_path_len;
+
+};
+
+/*****************************************************************************/
+
+#endif // ANDROID_BOSCHYAMAHA_SENSOR_H
diff --git a/libsensors/CompassSensor.cpp b/libsensors/CompassSensor.cpp
new file mode 100644
index 0000000..c4b6822
--- /dev/null
+++ b/libsensors/CompassSensor.cpp
@@ -0,0 +1,166 @@
+/*
+ * 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 "CompassSensor.h"
+
+
+/*****************************************************************************/
+CompassSensor::CompassSensor()
+ : SensorBase(NULL, "magnetic_sensor"),
+ //mEnabled(0),
+ mInputReader(4),
+ mHasPendingEvent(false)
+{
+ LOGD("CompassSensor::CompassSensor()");
+ mPendingEvent.version = sizeof(sensors_event_t);
+ mPendingEvent.sensor = ID_M;
+ mPendingEvent.type = SENSOR_TYPE_MAGNETIC_FIELD;
+ mPendingEvent.magnetic.status = SENSOR_STATUS_ACCURACY_HIGH;
+
+
+ memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
+
+ LOGD("CompassSensor::CompassSensor() open data_fd");
+
+ if (data_fd) {
+ strcpy(input_sysfs_path, "/sys/class/input/");
+ strcat(input_sysfs_path, input_name);
+ strcat(input_sysfs_path, "/device/");
+ input_sysfs_path_len = strlen(input_sysfs_path);
+
+ //enable(0, 1);
+ }
+}
+
+CompassSensor::~CompassSensor() {
+
+ LOGD("CompassSensor::~CompassSensor()");
+ if (mEnabled) {
+ enable(0, 0);
+ }
+}
+
+
+
+int CompassSensor::enable(int32_t, int en) {
+
+
+ LOGD("CompassSensor::~enable(0, %d)", en);
+ int flags = en ? 1 : 0;
+ if (flags != mEnabled) {
+ int fd;
+ strcpy(&input_sysfs_path[input_sysfs_path_len], "enable");
+ LOGD("CompassSensor::~enable(0, %d) open %s",en, input_sysfs_path);
+ fd = open(input_sysfs_path, O_RDWR);
+ if (fd >= 0) {
+ LOGD("CompassSensor::~enable(0, %d) opened %s",en, input_sysfs_path);
+ char buf[2];
+ int err;
+ buf[1] = 0;
+ if (flags) {
+ buf[0] = '1';
+ } else {
+ buf[0] = '0';
+ }
+ err = write(fd, buf, sizeof(buf));
+ close(fd);
+ mEnabled = flags;
+ return 0;
+ }
+ return -1;
+ }
+ return 0;
+}
+
+
+bool CompassSensor::hasPendingEvents() const {
+ /* FIXME probably here should be returning mEnabled but instead
+ mHasPendingEvents. It does not work, so we cheat.*/
+ //LOGD("CompassSensor::~hasPendingEvents %d", mHasPendingEvent ? 1 : 0 );
+ return mHasPendingEvent;
+}
+
+
+int CompassSensor::setDelay(int32_t handle, int64_t ns)
+{
+ LOGD("CompassSensor::~setDelay(%d, %d)", handle, ns);
+ /* FIXME needs changes to the kernel driver.
+ We need to add a IOCTL that can set the samplingrate
+ the driver in ther kernel supports this allready only need
+ to add a IOCTL on both sides for that*/
+ return 0;
+}
+
+
+int CompassSensor::readEvents(sensors_event_t* data, int count)
+{
+ //LOGD("CompassSensor::~readEvents() %d", count);
+ if (count < 1)
+ return -EINVAL;
+
+ if (mHasPendingEvent) {
+ mHasPendingEvent = false;
+ mPendingEvent.timestamp = getTimestamp();
+ *data = mPendingEvent;
+ return mEnabled ? 1 : 0;
+ }
+
+ 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_REL) {
+ float value = event->value;
+ if (event->code == EVENT_TYPE_MAGV_X) {
+ mPendingEvent.magnetic.x = value * CONVERT_M_X;
+ } else if (event->code == EVENT_TYPE_MAGV_Y) {
+ mPendingEvent.magnetic.y = value * CONVERT_M_Y;
+ } else if (event->code == EVENT_TYPE_MAGV_Z) {
+ mPendingEvent.magnetic.z = value * CONVERT_M_Z;
+ }
+ } else if (type == EV_SYN) {
+ mPendingEvent.timestamp = timevalToNano(event->time);
+ if (mEnabled) {
+ *data++ = mPendingEvent;
+ count--;
+ numEventReceived++;
+ }
+ } else {
+ LOGE("CompassSensor: unknown event (type=%d, code=%d)",
+ type, event->code);
+ }
+ mInputReader.next();
+ }
+
+ //LOGD("CompassSensor::~readEvents() numEventReceived = %d", numEventReceived);
+ return numEventReceived++;
+
+}
diff --git a/libsensors/CompassSensor.h b/libsensors/CompassSensor.h
new file mode 100644
index 0000000..0270431
--- /dev/null
+++ b/libsensors/CompassSensor.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_COMPASS_SENSOR_H
+#define ANDROID_COMPASS_SENSOR_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include "sensors.h"
+#include "SensorBase.h"
+#include "InputEventReader.h"
+
+/*****************************************************************************/
+
+
+struct input_event;
+
+class CompassSensor : public SensorBase {
+ int mEnabled;
+ InputEventCircularReader mInputReader;
+ sensors_event_t mPendingEvent;
+ bool mHasPendingEvent;
+ char input_sysfs_path[PATH_MAX];
+ int input_sysfs_path_len;
+
+
+public:
+ CompassSensor();
+ virtual ~CompassSensor();
+ virtual int readEvents(sensors_event_t* data, int count);
+ virtual bool hasPendingEvents() const;
+ virtual int setDelay(int32_t handle, int64_t ns);
+ virtual int enable(int32_t handle, int enabled);
+};
+
+/*****************************************************************************/
+
+#endif // ANDROID_GYRO_SENSOR_H
diff --git a/libsensors/GyroSensor.cpp b/libsensors/GyroSensor.cpp
new file mode 100644
index 0000000..11df71e
--- /dev/null
+++ b/libsensors/GyroSensor.cpp
@@ -0,0 +1,181 @@
+/*
+ * 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 "GyroSensor.h"
+
+#define FETCH_FULL_EVENT_BEFORE_RETURN 1
+
+/*****************************************************************************/
+
+GyroSensor::GyroSensor()
+ : SensorBase(NULL, "gyro"),
+ mEnabled(0),
+ mInputReader(4),
+ mHasPendingEvent(false)
+{
+ mPendingEvent.version = sizeof(sensors_event_t);
+ mPendingEvent.sensor = ID_GY;
+ mPendingEvent.type = SENSOR_TYPE_GYROSCOPE;
+ memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
+
+ if (data_fd) {
+ strcpy(input_sysfs_path, "/sys/class/input/");
+ strcat(input_sysfs_path, input_name);
+ strcat(input_sysfs_path, "/device/");
+ input_sysfs_path_len = strlen(input_sysfs_path);
+ enable(0, 1);
+ }
+}
+
+GyroSensor::~GyroSensor() {
+ if (mEnabled) {
+ enable(0, 0);
+ }
+}
+
+int GyroSensor::setInitialState() {
+ struct input_absinfo absinfo_x;
+ struct input_absinfo absinfo_y;
+ struct input_absinfo absinfo_z;
+ float value;
+ if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_x) &&
+ !ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_y) &&
+ !ioctl(data_fd, EVIOCGABS(EVENT_TYPE_GYRO_X), &absinfo_z)) {
+ value = absinfo_x.value;
+ mPendingEvent.data[0] = value * CONVERT_GYRO_X;
+ value = absinfo_x.value;
+ mPendingEvent.data[1] = value * CONVERT_GYRO_Y;
+ value = absinfo_x.value;
+ mPendingEvent.data[2] = value * CONVERT_GYRO_Z;
+ mHasPendingEvent = true;
+ }
+ return 0;
+}
+
+int GyroSensor::enable(int32_t, int en) {
+ int flags = en ? 1 : 0;
+ if (flags != mEnabled) {
+ int fd;
+ strcpy(&input_sysfs_path[input_sysfs_path_len], "enable");
+ fd = open(input_sysfs_path, O_RDWR);
+ if (fd >= 0) {
+ char buf[2];
+ int err;
+ buf[1] = 0;
+ if (flags) {
+ buf[0] = '1';
+ } else {
+ buf[0] = '0';
+ }
+ err = write(fd, buf, sizeof(buf));
+ close(fd);
+ mEnabled = flags;
+ setInitialState();
+ return 0;
+ }
+ return -1;
+ }
+ return 0;
+}
+
+bool GyroSensor::hasPendingEvents() const {
+ return mHasPendingEvent;
+}
+
+int GyroSensor::setDelay(int32_t handle, int64_t delay_ns)
+{
+ int fd;
+ strcpy(&input_sysfs_path[input_sysfs_path_len], "poll_delay");
+ fd = open(input_sysfs_path, O_RDWR);
+ if (fd >= 0) {
+ char buf[80];
+ sprintf(buf, "%lld", delay_ns);
+ write(fd, buf, strlen(buf)+1);
+ close(fd);
+ return 0;
+ }
+ return -1;
+}
+
+int GyroSensor::readEvents(sensors_event_t* data, int count)
+{
+ if (count < 1)
+ return -EINVAL;
+
+ if (mHasPendingEvent) {
+ mHasPendingEvent = false;
+ mPendingEvent.timestamp = getTimestamp();
+ *data = mPendingEvent;
+ return mEnabled ? 1 : 0;
+ }
+
+ ssize_t n = mInputReader.fill(data_fd);
+ if (n < 0)
+ return n;
+
+ int numEventReceived = 0;
+ input_event const* event;
+
+#if FETCH_FULL_EVENT_BEFORE_RETURN
+again:
+#endif
+ while (count && mInputReader.readEvent(&event)) {
+ int type = event->type;
+ if (type == EV_REL) {
+ float value = event->value;
+ if (event->code == EVENT_TYPE_GYRO_X) {
+ mPendingEvent.data[0] = value * CONVERT_GYRO_X;
+ } else if (event->code == EVENT_TYPE_GYRO_Y) {
+ mPendingEvent.data[1] = value * CONVERT_GYRO_Y;
+ } else if (event->code == EVENT_TYPE_GYRO_Z) {
+ mPendingEvent.data[2] = value * CONVERT_GYRO_Z;
+ }
+ } else if (type == EV_SYN) {
+ mPendingEvent.timestamp = timevalToNano(event->time);
+ if (mEnabled) {
+ *data++ = mPendingEvent;
+ count--;
+ numEventReceived++;
+ }
+ } else {
+ LOGE("GyroSensor: unknown event (type=%d, code=%d)",
+ type, event->code);
+ }
+ mInputReader.next();
+ }
+
+#if FETCH_FULL_EVENT_BEFORE_RETURN
+ /* if we didn't read a complete event, see if we can fill and
+ try again instead of returning with nothing and redoing poll. */
+ if (numEventReceived == 0 && mEnabled == 1) {
+ n = mInputReader.fill(data_fd);
+ if (n)
+ goto again;
+ }
+#endif
+
+ return numEventReceived;
+}
+
diff --git a/libsensors/GyroSensor.h b/libsensors/GyroSensor.h
new file mode 100644
index 0000000..1b206bd
--- /dev/null
+++ b/libsensors/GyroSensor.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_GYRO_SENSOR_H
+#define ANDROID_GYRO_SENSOR_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include "sensors.h"
+#include "SensorBase.h"
+#include "InputEventReader.h"
+
+/*****************************************************************************/
+
+struct input_event;
+
+class GyroSensor : public SensorBase {
+ int mEnabled;
+ InputEventCircularReader mInputReader;
+ sensors_event_t mPendingEvent;
+ bool mHasPendingEvent;
+ char input_sysfs_path[PATH_MAX];
+ int input_sysfs_path_len;
+
+ int setInitialState();
+
+public:
+ GyroSensor();
+ virtual ~GyroSensor();
+ virtual int readEvents(sensors_event_t* data, int count);
+ virtual bool hasPendingEvents() const;
+ virtual int setDelay(int32_t handle, int64_t ns);
+ virtual int enable(int32_t handle, int enabled);
+};
+
+/*****************************************************************************/
+
+#endif // ANDROID_GYRO_SENSOR_H
diff --git a/libsensors/InputEventReader.cpp b/libsensors/InputEventReader.cpp
new file mode 100644
index 0000000..c6bac93
--- /dev/null
+++ b/libsensors/InputEventReader.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <errno.h>
+#include <unistd.h>
+#include <poll.h>
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <linux/input.h>
+
+#include <cutils/log.h>
+
+#include "InputEventReader.h"
+
+/*****************************************************************************/
+
+struct input_event;
+
+InputEventCircularReader::InputEventCircularReader(size_t numEvents)
+ : mBuffer(new input_event[numEvents * 2]),
+ mBufferEnd(mBuffer + numEvents),
+ mHead(mBuffer),
+ mCurr(mBuffer),
+ mFreeSpace(numEvents)
+{
+}
+
+InputEventCircularReader::~InputEventCircularReader()
+{
+ delete [] mBuffer;
+}
+
+ssize_t InputEventCircularReader::fill(int fd)
+{
+ size_t numEventsRead = 0;
+ if (mFreeSpace) {
+ const ssize_t nread = read(fd, mHead, mFreeSpace * sizeof(input_event));
+ if (nread<0 || nread % sizeof(input_event)) {
+ // we got a partial event!!
+ return nread<0 ? -errno : -EINVAL;
+ }
+
+ numEventsRead = nread / sizeof(input_event);
+ if (numEventsRead) {
+ mHead += numEventsRead;
+ mFreeSpace -= numEventsRead;
+ if (mHead > mBufferEnd) {
+ size_t s = mHead - mBufferEnd;
+ memcpy(mBuffer, mBufferEnd, s * sizeof(input_event));
+ mHead = mBuffer + s;
+ }
+ }
+ }
+
+ return numEventsRead;
+}
+
+ssize_t InputEventCircularReader::readEvent(input_event const** events)
+{
+ *events = mCurr;
+ ssize_t available = (mBufferEnd - mBuffer) - mFreeSpace;
+ return available ? 1 : 0;
+}
+
+void InputEventCircularReader::next()
+{
+ mCurr++;
+ mFreeSpace++;
+ if (mCurr >= mBufferEnd) {
+ mCurr = mBuffer;
+ }
+}
diff --git a/libsensors/InputEventReader.h b/libsensors/InputEventReader.h
new file mode 100644
index 0000000..fbf5121
--- /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..ea3e250
--- /dev/null
+++ b/libsensors/LightSensor.cpp
@@ -0,0 +1,180 @@
+/*
+ * 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 "LightSensor.h"
+
+/*****************************************************************************/
+
+/* The Crespo ADC sends 4 somewhat bogus events after enabling the sensor.
+ This becomes a problem if the phone is turned off in bright light
+ and turned back on in the dark.
+ To avoid this we ignore the first 4 events received after enabling the sensor.
+ */
+#define FIRST_GOOD_EVENT 5
+
+LightSensor::LightSensor()
+ : SensorBase(NULL, "light_sensor"),
+ mEnabled(0),
+ mEventsSinceEnable(0),
+ mInputReader(4),
+ mHasPendingEvent(false)
+{
+ mPendingEvent.version = sizeof(sensors_event_t);
+ mPendingEvent.sensor = ID_L;
+ mPendingEvent.type = SENSOR_TYPE_LIGHT;
+ memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
+
+ if (data_fd) {
+ strcpy(input_sysfs_path, "/sys/class/input/");
+ strcat(input_sysfs_path, input_name);
+ strcat(input_sysfs_path, "/device/");
+ input_sysfs_path_len = strlen(input_sysfs_path);
+ enable(0, 1);
+ }
+}
+
+LightSensor::~LightSensor() {
+ if (mEnabled) {
+ enable(0, 0);
+ }
+}
+
+int LightSensor::setDelay(int32_t handle, int64_t ns)
+{
+ int fd;
+ strcpy(&input_sysfs_path[input_sysfs_path_len], "poll_delay");
+ fd = open(input_sysfs_path, O_RDWR);
+ if (fd >= 0) {
+ char buf[80];
+ sprintf(buf, "%lld", ns);
+ write(fd, buf, strlen(buf)+1);
+ close(fd);
+ return 0;
+ }
+ return -1;
+}
+
+int LightSensor::enable(int32_t handle, int en)
+{
+ int flags = en ? 1 : 0;
+ mEventsSinceEnable = 0;
+ mPreviousLight = -1;
+ if (flags != mEnabled) {
+ int fd;
+ strcpy(&input_sysfs_path[input_sysfs_path_len], "enable");
+ fd = open(input_sysfs_path, O_RDWR);
+ if (fd >= 0) {
+ char buf[2];
+ int err;
+ buf[1] = 0;
+ if (flags) {
+ buf[0] = '1';
+ } else {
+ buf[0] = '0';
+ }
+ err = write(fd, buf, sizeof(buf));
+ close(fd);
+ mEnabled = flags;
+ return 0;
+ }
+ return -1;
+ }
+ return 0;
+}
+
+bool LightSensor::hasPendingEvents() const {
+ return mHasPendingEvent;
+}
+
+int LightSensor::readEvents(sensors_event_t* data, int count)
+{
+ if (count < 1)
+ return -EINVAL;
+
+ if (mHasPendingEvent) {
+ mHasPendingEvent = false;
+ mPendingEvent.timestamp = getTimestamp();
+ *data = mPendingEvent;
+ return mEnabled ? 1 : 0;
+ }
+
+ 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) {
+ mPendingEvent.light = indexToValue(event->value);
+ if (mEventsSinceEnable < FIRST_GOOD_EVENT)
+ mEventsSinceEnable++;
+ }
+ } else if (type == EV_SYN) {
+ mPendingEvent.timestamp = timevalToNano(event->time);
+ if (mEnabled && (mPendingEvent.light != mPreviousLight) &&
+ mEventsSinceEnable >= FIRST_GOOD_EVENT) {
+ *data++ = mPendingEvent;
+ count--;
+ numEventReceived++;
+ mPreviousLight = mPendingEvent.light;
+ }
+ } else {
+ LOGE("LightSensor: unknown event (type=%d, code=%d)",
+ type, event->code);
+ }
+ mInputReader.next();
+ }
+
+ return numEventReceived;
+}
+
+float LightSensor::indexToValue(size_t index) const
+{
+ /* Driver gives a rolling average adc value. We convert it lux levels. */
+ static const struct adcToLux {
+ size_t adc_value;
+ float lux_value;
+ } adcToLux[] = {
+ { 150, 10.0 }, /* from 0 - 150 adc, we map to 10.0 lux */
+ { 800, 160.0 }, /* from 151 - 800 adc, we map to 160.0 lux */
+ { 900, 225.0 }, /* from 801 - 900 adc, we map to 225.0 lux */
+ { 1000, 320.0 }, /* from 901 - 1000 adc, we map to 320.0 lux */
+ { 1200, 640.0 }, /* from 1001 - 1200 adc, we map to 640.0 lux */
+ { 1400, 1280.0 }, /* from 1201 - 1400 adc, we map to 1280.0 lux */
+ { 1600, 2600.0 }, /* from 1401 - 1600 adc, we map to 2600.0 lux */
+ { 4095, 10240.0 }, /* from 1601 - 4095 adc, we map to 10240.0 lux */
+ };
+ size_t i;
+ for (i = 0; i < ARRAY_SIZE(adcToLux); i++) {
+ if (index < adcToLux[i].adc_value) {
+ return adcToLux[i].lux_value;
+ }
+ }
+ return adcToLux[ARRAY_SIZE(adcToLux)-1].lux_value;
+}
diff --git a/libsensors/LightSensor.h b/libsensors/LightSensor.h
new file mode 100644
index 0000000..cc1a00d
--- /dev/null
+++ b/libsensors/LightSensor.h
@@ -0,0 +1,57 @@
+/*
+ * 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 "sensors.h"
+#include "SensorBase.h"
+#include "InputEventReader.h"
+
+/*****************************************************************************/
+
+struct input_event;
+
+class LightSensor : public SensorBase {
+ int mEnabled;
+ int mEventsSinceEnable;
+ InputEventCircularReader mInputReader;
+ sensors_event_t mPendingEvent;
+ bool mHasPendingEvent;
+ char input_sysfs_path[PATH_MAX];
+ int input_sysfs_path_len;
+
+ int setInitialState();
+ float mPreviousLight;
+ float indexToValue(size_t index) const;
+
+public:
+ LightSensor();
+ virtual ~LightSensor();
+ virtual int readEvents(sensors_event_t* data, int count);
+ virtual bool hasPendingEvents() const;
+ virtual int setDelay(int32_t handle, int64_t ns);
+ virtual int enable(int32_t handle, int enabled);
+};
+
+/*****************************************************************************/
+
+#endif // ANDROID_LIGHT_SENSOR_H
diff --git a/libsensors/OrientationSensor.cpp b/libsensors/OrientationSensor.cpp
new file mode 100644
index 0000000..3fb5d29
--- /dev/null
+++ b/libsensors/OrientationSensor.cpp
@@ -0,0 +1,163 @@
+/*
+ * 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 "OrientationSensor.h"
+
+
+/*****************************************************************************/
+OrientationSensor::OrientationSensor()
+ : SensorBase(NULL, "orientation_sensor"),
+ mEnabled(0),
+ mInputReader(4),
+ mHasPendingEvent(false)
+{
+ LOGD("OrientationSensor::OrientationSensor()");
+ mPendingEvent.version = sizeof(sensors_event_t);
+ mPendingEvent.sensor = ID_O;
+ mPendingEvent.type = SENSOR_TYPE_ORIENTATION;
+ memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
+
+ LOGD("OrientationSensor::OrientationSensor() open data_fd");
+
+ if (data_fd) {
+ strcpy(input_sysfs_path, "/sys/class/input/");
+ strcat(input_sysfs_path, input_name);
+ strcat(input_sysfs_path, "/device/");
+ input_sysfs_path_len = strlen(input_sysfs_path);
+
+ // enable(0, 1);
+ }
+}
+
+OrientationSensor::~OrientationSensor() {
+
+ LOGD("OrientationSensor::~OrientationSensor()");
+ if (mEnabled) {
+ enable(0, 0);
+ }
+}
+
+
+int OrientationSensor::enable(int32_t, int en) {
+
+
+ LOGD("OrientationSensor::~enable(0, %d)", en);
+ int flags = en ? 1 : 0;
+ if (flags != mEnabled) {
+ int fd;
+ strcpy(&input_sysfs_path[input_sysfs_path_len], "enable");
+ LOGD("OrientationSensor::~enable(0, %d) open %s",en, input_sysfs_path);
+ fd = open(input_sysfs_path, O_RDWR);
+ if (fd >= 0) {
+ LOGD("OrientationSensor::~enable(0, %d) opened %s",en, input_sysfs_path);
+ char buf[2];
+ int err;
+ buf[1] = 0;
+ if (flags) {
+ buf[0] = '1';
+ } else {
+ buf[0] = '0';
+ }
+ err = write(fd, buf, sizeof(buf));
+ close(fd);
+ mEnabled = flags;
+ //setInitialState();
+ return 0;
+ }
+ return -1;
+ }
+ return 0;
+}
+
+
+bool OrientationSensor::hasPendingEvents() const {
+ /* FIXME probably here should be returning mEnabled but instead
+ mHasPendingEvents. It does not work, so we cheat.*/
+ //LOGD("OrientationSensor::~hasPendingEvents %d", mHasPendingEvent ? 1 : 0 );
+ return mHasPendingEvent;
+}
+
+
+int OrientationSensor::setDelay(int32_t handle, int64_t ns)
+{
+ LOGD("OrientationSensor::~setDelay(%d, %d)", handle, ns);
+ /* FIXME needs changes to the kernel driver.
+ We need to add a IOCTL that can set the samplingrate
+ the driver in ther kernel supports this allready only need
+ to add a IOCTL on both sides for that*/
+ return 0;
+}
+
+
+int OrientationSensor::readEvents(sensors_event_t* data, int count)
+{
+ //LOGD("OrientationSensor::~readEvents() %d", count);
+ if (count < 1)
+ return -EINVAL;
+
+ if (mHasPendingEvent) {
+ mHasPendingEvent = false;
+ mPendingEvent.timestamp = getTimestamp();
+ *data = mPendingEvent;
+ return mEnabled ? 1 : 0;
+ }
+
+ 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_REL) {
+ float value = event->value;
+ if (event->code == EVENT_TYPE_YAW) {
+ mPendingEvent.orientation.azimuth = value * CONVERT_O_A;
+ } else if (event->code == EVENT_TYPE_PITCH) {
+ mPendingEvent.orientation.pitch = value * CONVERT_O_P;
+ } else if (event->code == EVENT_TYPE_ROLL) {
+ mPendingEvent.orientation.roll = value * CONVERT_O_R;
+ }
+ } else if (type == EV_SYN) {
+ mPendingEvent.timestamp = timevalToNano(event->time);
+ if (mEnabled) {
+ *data++ = mPendingEvent;
+ count--;
+ numEventReceived++;
+ }
+ } else {
+ LOGE("OrientationSensor: unknown event (type=%d, code=%d)",
+ type, event->code);
+ }
+ mInputReader.next();
+ }
+
+ //LOGD("OrientationSensor::~readEvents() numEventReceived = %d", numEventReceived);
+ return numEventReceived++;
+
+}
diff --git a/libsensors/OrientationSensor.h b/libsensors/OrientationSensor.h
new file mode 100644
index 0000000..cbb7064
--- /dev/null
+++ b/libsensors/OrientationSensor.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_ORIEN_SENSOR_H
+#define ANDROID_ORIEN_SENSOR_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include "sensors.h"
+#include "SensorBase.h"
+#include "InputEventReader.h"
+
+/*****************************************************************************/
+
+
+struct input_event;
+
+class OrientationSensor : public SensorBase {
+ int mEnabled;
+ InputEventCircularReader mInputReader;
+ sensors_event_t mPendingEvent;
+ bool mHasPendingEvent;
+ char input_sysfs_path[PATH_MAX];
+ int input_sysfs_path_len;
+
+
+public:
+ OrientationSensor();
+ virtual ~OrientationSensor();
+ virtual int readEvents(sensors_event_t* data, int count);
+ virtual bool hasPendingEvents() const;
+ virtual int setDelay(int32_t handle, int64_t ns);
+ virtual int enable(int32_t handle, int enabled);
+};
+
+/*****************************************************************************/
+
+#endif // ANDROID_GYRO_SENSOR_H
diff --git a/libsensors/ProximitySensor.cpp b/libsensors/ProximitySensor.cpp
new file mode 100644
index 0000000..f7151ee
--- /dev/null
+++ b/libsensors/ProximitySensor.cpp
@@ -0,0 +1,144 @@
+/*
+ * 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 "ProximitySensor.h"
+
+/*****************************************************************************/
+
+ProximitySensor::ProximitySensor()
+ : SensorBase(NULL, "proximity_sensor"),
+ mEnabled(0),
+ mInputReader(4),
+ mHasPendingEvent(false)
+{
+ mPendingEvent.version = sizeof(sensors_event_t);
+ mPendingEvent.sensor = ID_P;
+ mPendingEvent.type = SENSOR_TYPE_PROXIMITY;
+ memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
+
+ if (data_fd) {
+ strcpy(input_sysfs_path, "/sys/class/input/");
+ strcat(input_sysfs_path, input_name);
+ strcat(input_sysfs_path, "/device/");
+ input_sysfs_path_len = strlen(input_sysfs_path);
+ enable(0, 1);
+ }
+}
+
+ProximitySensor::~ProximitySensor() {
+ if (mEnabled) {
+ enable(0, 0);
+ }
+}
+
+int ProximitySensor::setInitialState() {
+ struct input_absinfo absinfo;
+ if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_PROXIMITY), &absinfo)) {
+ // make sure to report an event immediately
+ mHasPendingEvent = true;
+ mPendingEvent.distance = indexToValue(absinfo.value);
+ }
+ return 0;
+}
+
+int ProximitySensor::enable(int32_t, int en) {
+ int flags = en ? 1 : 0;
+ if (flags != mEnabled) {
+ int fd;
+ strcpy(&input_sysfs_path[input_sysfs_path_len], "enable");
+ fd = open(input_sysfs_path, O_RDWR);
+ if (fd >= 0) {
+ char buf[2];
+ buf[1] = 0;
+ if (flags) {
+ buf[0] = '1';
+ } else {
+ buf[0] = '0';
+ }
+ write(fd, buf, sizeof(buf));
+ close(fd);
+ mEnabled = flags;
+ setInitialState();
+ return 0;
+ }
+ return -1;
+ }
+ return 0;
+}
+
+bool ProximitySensor::hasPendingEvents() const {
+ return mHasPendingEvent;
+}
+
+int ProximitySensor::readEvents(sensors_event_t* data, int count)
+{
+ if (count < 1)
+ return -EINVAL;
+
+ if (mHasPendingEvent) {
+ mHasPendingEvent = false;
+ mPendingEvent.timestamp = getTimestamp();
+ *data = mPendingEvent;
+ return mEnabled ? 1 : 0;
+ }
+
+ 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) {
+ if (event->value != -1) {
+ // FIXME: not sure why we're getting -1 sometimes
+ mPendingEvent.distance = indexToValue(event->value);
+ }
+ }
+ } else if (type == EV_SYN) {
+ mPendingEvent.timestamp = timevalToNano(event->time);
+ if (mEnabled) {
+ *data++ = mPendingEvent;
+ count--;
+ numEventReceived++;
+ }
+ } else {
+ LOGE("ProximitySensor: unknown event (type=%d, code=%d)",
+ type, event->code);
+ }
+ mInputReader.next();
+ }
+
+ return numEventReceived;
+}
+
+float ProximitySensor::indexToValue(size_t index) const
+{
+ return index * PROXIMITY_THRESHOLD_GP2A;
+}
diff --git a/libsensors/ProximitySensor.h b/libsensors/ProximitySensor.h
new file mode 100644
index 0000000..e9f782f
--- /dev/null
+++ b/libsensors/ProximitySensor.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_PROXIMITY_SENSOR_H
+#define ANDROID_PROXIMITY_SENSOR_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include "sensors.h"
+#include "SensorBase.h"
+#include "InputEventReader.h"
+
+/*****************************************************************************/
+
+struct input_event;
+
+class ProximitySensor : public SensorBase {
+ int mEnabled;
+ InputEventCircularReader mInputReader;
+ sensors_event_t mPendingEvent;
+ bool mHasPendingEvent;
+ char input_sysfs_path[PATH_MAX];
+ int input_sysfs_path_len;
+
+ int setInitialState();
+ float indexToValue(size_t index) const;
+
+public:
+ ProximitySensor();
+ virtual ~ProximitySensor();
+ virtual int readEvents(sensors_event_t* data, int count);
+ virtual bool hasPendingEvents() const;
+ virtual int enable(int32_t handle, int enabled);
+};
+
+/*****************************************************************************/
+
+#endif // ANDROID_PROXIMITY_SENSOR_H
diff --git a/libsensors/SensorBase.cpp b/libsensors/SensorBase.cpp
new file mode 100644
index 0000000..2fe5c2d
--- /dev/null
+++ b/libsensors/SensorBase.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 <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)
+{
+ if (data_name) {
+ data_fd = openInput(data_name);
+ }
+}
+
+SensorBase::~SensorBase() {
+ if (data_fd >= 0) {
+ close(data_fd);
+ }
+ if (dev_fd >= 0) {
+ close(dev_fd);
+ }
+}
+
+int SensorBase::open_device() {
+ if (dev_fd<0 && dev_name) {
+ dev_fd = open(dev_name, O_RDONLY);
+ LOGE_IF(dev_fd<0, "Couldn't open %s (%s)", dev_name, strerror(errno));
+ }
+ return 0;
+}
+
+int SensorBase::close_device() {
+ if (dev_fd >= 0) {
+ close(dev_fd);
+ dev_fd = -1;
+ }
+ return 0;
+}
+
+int SensorBase::getFd() const {
+ if (!data_name) {
+ return dev_fd;
+ }
+ return data_fd;
+}
+
+int SensorBase::setDelay(int32_t handle, int64_t ns) {
+ return 0;
+}
+
+bool SensorBase::hasPendingEvents() const {
+ return false;
+}
+
+int64_t SensorBase::getTimestamp() {
+ struct timespec t;
+ t.tv_sec = t.tv_nsec = 0;
+ clock_gettime(CLOCK_MONOTONIC, &t);
+ return int64_t(t.tv_sec)*1000000000LL + t.tv_nsec;
+}
+
+int SensorBase::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)) {
+ strcpy(input_name, filename);
+ 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..6b4b555
--- /dev/null
+++ b/libsensors/SensorBase.h
@@ -0,0 +1,65 @@
+/*
+ * 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>
+
+
+/*****************************************************************************/
+
+struct sensors_event_t;
+
+class SensorBase {
+protected:
+ const char* dev_name;
+ const char* data_name;
+ char input_name[PATH_MAX];
+ int dev_fd;
+ int data_fd;
+
+ int openInput(const char* inputName);
+ static int64_t getTimestamp();
+
+
+ static int64_t timevalToNano(timeval const& t) {
+ return t.tv_sec*1000000000LL + t.tv_usec*1000;
+ }
+
+ int open_device();
+ int close_device();
+
+public:
+ SensorBase(
+ const char* dev_name,
+ const char* data_name);
+
+ virtual ~SensorBase();
+
+ virtual int readEvents(sensors_event_t* data, int count) = 0;
+ virtual bool hasPendingEvents() const;
+ virtual int getFd() const;
+ virtual int setDelay(int32_t handle, int64_t ns);
+ virtual int enable(int32_t handle, int enabled) = 0;
+};
+
+/*****************************************************************************/
+
+#endif // ANDROID_SENSOR_BASE_H
diff --git a/libsensors/Smb380Sensor.cpp b/libsensors/Smb380Sensor.cpp
new file mode 100644
index 0000000..3de4d9b
--- /dev/null
+++ b/libsensors/Smb380Sensor.cpp
@@ -0,0 +1,165 @@
+/*
+ * 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 "Smb380Sensor.h"
+
+
+/*****************************************************************************/
+Smb380Sensor::Smb380Sensor()
+ : SensorBase(NULL, "accelerometer_sensor"),
+ mEnabled(0),
+
+ mInputReader(4),
+ mHasPendingEvent(false)
+{
+ LOGD("Smb380Sensor::Smb380Sensor()");
+ mPendingEvent.version = sizeof(sensors_event_t);
+ mPendingEvent.sensor = ID_A;
+ mPendingEvent.type = SENSOR_TYPE_ACCELEROMETER;
+ memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
+
+ LOGD("Smb380Sensor::Smb380Sensor() open data_fd");
+
+ if (data_fd) {
+ strcpy(input_sysfs_path, "/sys/class/input/");
+ strcat(input_sysfs_path, input_name);
+ strcat(input_sysfs_path, "/device/");
+ input_sysfs_path_len = strlen(input_sysfs_path);
+
+ //enable(0, 1);
+ }
+}
+
+Smb380Sensor::~Smb380Sensor() {
+
+ LOGD("Smb380Sensor::~Smb380Sensor()");
+ if (mEnabled) {
+ enable(0, 0);
+ }
+}
+
+
+
+int Smb380Sensor::enable(int32_t, int en) {
+
+
+ LOGD("Smb380Sensor::~enable(0, %d)", en);
+ int flags = en ? 1 : 0;
+ if (flags != mEnabled) {
+ int fd;
+ strcpy(&input_sysfs_path[input_sysfs_path_len], "enable");
+ LOGD("Smb380Sensor::~enable(0, %d) open %s",en, input_sysfs_path);
+ fd = open(input_sysfs_path, O_RDWR);
+ if (fd >= 0) {
+ LOGD("Smb380Sensor::~enable(0, %d) opened %s",en, input_sysfs_path);
+ char buf[2];
+ int err;
+ buf[1] = 0;
+ if (flags) {
+ buf[0] = '1';
+ } else {
+ buf[0] = '0';
+ }
+ err = write(fd, buf, sizeof(buf));
+ close(fd);
+ mEnabled = flags;
+ //setInitialState();
+ return 0;
+ }
+ return -1;
+ }
+ return 0;
+}
+
+
+bool Smb380Sensor::hasPendingEvents() const {
+ /* FIXME probably here should be returning mEnabled but instead
+ mHasPendingEvents. It does not work, so we cheat.*/
+ //LOGD("Smb380Sensor::~hasPendingEvents %d", mHasPendingEvent ? 1 : 0 );
+ return mHasPendingEvent;
+}
+
+
+int Smb380Sensor::setDelay(int32_t handle, int64_t ns)
+{
+ LOGD("Smb380Sensor::~setDelay(%d, %d)", handle, ns);
+ /* FIXME needs changes to the kernel driver.
+ We need to add a IOCTL that can set the samplingrate
+ the driver in ther kernel supports this allready only need
+ to add a IOCTL on both sides for that*/
+ return 0;
+}
+
+
+int Smb380Sensor::readEvents(sensors_event_t* data, int count)
+{
+ //LOGD("Smb380Sensor::~readEvents() %d", count);
+ if (count < 1)
+ return -EINVAL;
+
+ if (mHasPendingEvent) {
+ mHasPendingEvent = false;
+ mPendingEvent.timestamp = getTimestamp();
+ *data = mPendingEvent;
+ return mEnabled ? 1 : 0;
+ }
+
+ 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_REL) {
+ float value = event->value;
+ if (event->code == EVENT_TYPE_ACCEL_X) {
+ mPendingEvent.acceleration.x = value * CONVERT_A_X;
+ } else if (event->code == EVENT_TYPE_ACCEL_Y) {
+ mPendingEvent.acceleration.y = value * CONVERT_A_Y;
+ } else if (event->code == EVENT_TYPE_ACCEL_Z) {
+ mPendingEvent.acceleration.z = value * CONVERT_A_Z;
+ }
+ } else if (type == EV_SYN) {
+ mPendingEvent.timestamp = timevalToNano(event->time);
+ if (mEnabled) {
+ *data++ = mPendingEvent;
+ count--;
+ numEventReceived++;
+ }
+ } else {
+ LOGE("Smb380Sensor: unknown event (type=%d, code=%d)",
+ type, event->code);
+ }
+ mInputReader.next();
+ }
+
+ //LOGD("Smb380Sensor::~readEvents() numEventReceived = %d", numEventReceived);
+ return numEventReceived++;
+
+}
diff --git a/libsensors/Smb380Sensor.h b/libsensors/Smb380Sensor.h
new file mode 100644
index 0000000..5e55e9b
--- /dev/null
+++ b/libsensors/Smb380Sensor.h
@@ -0,0 +1,69 @@
+/*
+ * 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_SMB380_SENSOR_H
+#define ANDROID_SMB380_SENSOR_H
+
+#include <stdint.h>
+#include <errno.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include "sensors.h"
+#include "SensorBase.h"
+#include "InputEventReader.h"
+
+/*****************************************************************************/
+
+
+struct smb380acc_t {
+ short x, /**< holds x-axis acceleration data sign extended. Range -512 to 511. */
+ y, /**< holds y-axis acceleration data sign extended. Range -512 to 511. */
+ z; /**< holds z-axis acceleration data sign extended. Range -512 to 511. */
+} ;
+
+/* smb ioctl command label */
+#define IOCTL_SMB_GET_ACC_VALUE 0
+#define DCM_IOC_MAGIC 's'
+#define IOC_SET_ACCELEROMETER _IO (DCM_IOC_MAGIC, 0x64)
+#define BMA150_CALIBRATION _IOWR(DCM_IOC_MAGIC,48,short)
+
+#define SMB_POWER_OFF 0
+#define SMB_POWER_ON 1
+
+struct input_event;
+
+class Smb380Sensor : public SensorBase {
+ int mEnabled;
+ InputEventCircularReader mInputReader;
+ sensors_event_t mPendingEvent;
+ bool mHasPendingEvent;
+ char input_sysfs_path[PATH_MAX];
+ int input_sysfs_path_len;
+
+
+public:
+ Smb380Sensor();
+ virtual ~Smb380Sensor();
+ virtual int readEvents(sensors_event_t* data, int count);
+ virtual bool hasPendingEvents() const;
+ virtual int setDelay(int32_t handle, int64_t ns);
+ virtual int enable(int32_t handle, int enabled);
+};
+
+/*****************************************************************************/
+
+#endif // ANDROID_GYRO_SENSOR_H
diff --git a/libsensors/sensors.cpp b/libsensors/sensors.cpp
new file mode 100644
index 0000000..2358a2e
--- /dev/null
+++ b/libsensors/sensors.cpp
@@ -0,0 +1,335 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "Sensors"
+
+#include <hardware/sensors.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <dirent.h>
+#include <math.h>
+#include <poll.h>
+#include <pthread.h>
+#include <stdlib.h>
+
+#include <linux/input.h>
+
+
+#include <utils/Atomic.h>
+#include <utils/Log.h>
+
+#include "sensors.h"
+
+#include "LightSensor.h"
+#include "ProximitySensor.h"
+//#include "BoschYamaha.h"
+#include "Smb380Sensor.h"
+#include "CompassSensor.h"
+#include "OrientationSensor.h"
+
+/*****************************************************************************/
+
+#define DELAY_OUT_TIME 0x7FFFFFFF
+
+#define LIGHT_SENSOR_POLLTIME 2000000000
+
+
+#define SENSORS_ACCELERATION (1<<ID_A)
+#define SENSORS_MAGNETIC_FIELD (1<<ID_M)
+#define SENSORS_ORIENTATION (1<<ID_O)
+#define SENSORS_LIGHT (1<<ID_L)
+#define SENSORS_PROXIMITY (1<<ID_P)
+#define SENSORS_GYROSCOPE (1<<ID_GY)
+
+#define SENSORS_ACCELERATION_HANDLE 0
+#define SENSORS_MAGNETIC_FIELD_HANDLE 1
+#define SENSORS_ORIENTATION_HANDLE 2
+#define SENSORS_LIGHT_HANDLE 3
+#define SENSORS_PROXIMITY_HANDLE 4
+#define SENSORS_GYROSCOPE_HANDLE 5
+
+#define AKM_FTRACE 0
+#define AKM_DEBUG 0
+#define AKM_DATA 0
+
+/*****************************************************************************/
+
+/* The SENSORS Module */
+static const struct sensor_t sSensorList[] = {
+
+ { "SMB380 3-axis Accelerometer",
+ "Bosch Sensortec",
+ 1, SENSORS_ACCELERATION_HANDLE,
+ SENSOR_TYPE_ACCELEROMETER, RANGE_A, RESOLUTION_A, 0.20f, 40000, { } },
+ { "MS3C 3-axis Magnetic field sensor",
+ "Yamaha ",
+ 1, SENSORS_MAGNETIC_FIELD_HANDLE,
+ SENSOR_TYPE_MAGNETIC_FIELD, 2000.0f, CONVERT_M, 6.8f, 30000, { } },
+ { "CM Hacked Orientation Sensor",
+ "CM Team",
+ 1, SENSORS_ORIENTATION_HANDLE,
+ SENSOR_TYPE_ORIENTATION, 360.0f, CONVERT_O, 7.8f, 30000, { } },
+ { "GP2A Light sensor",
+ "Sharp",
+ 1, SENSORS_LIGHT_HANDLE,
+ SENSOR_TYPE_LIGHT, 3000.0f, 1.0f, 0.75f, 0, { } },
+ { "GP2A Proximity sensor",
+ "Sharp",
+ 1, SENSORS_PROXIMITY_HANDLE,
+ SENSOR_TYPE_PROXIMITY, 5.0f, 5.0f, 0.75f, 0, { } },
+};
+
+
+static int open_sensors(const struct hw_module_t* module, const char* id,
+ struct hw_device_t** device);
+
+
+static int sensors__get_sensors_list(struct sensors_module_t* module,
+ struct sensor_t const** list)
+{
+ *list = sSensorList;
+ return ARRAY_SIZE(sSensorList);
+}
+
+static struct hw_module_methods_t sensors_module_methods = {
+ open: open_sensors
+};
+
+struct sensors_module_t HAL_MODULE_INFO_SYM = {
+ common: {
+ tag: HARDWARE_MODULE_TAG,
+ version_major: 1,
+ version_minor: 0,
+ id: SENSORS_HARDWARE_MODULE_ID,
+ name: "Samsung Sensor module",
+ author: "Samsung Electronic Company",
+ methods: &sensors_module_methods,
+ },
+ get_sensors_list: sensors__get_sensors_list,
+};
+
+struct sensors_poll_context_t {
+ struct sensors_poll_device_t device; // must be first
+
+ sensors_poll_context_t();
+ ~sensors_poll_context_t();
+ int activate(int handle, int enabled);
+ int setDelay(int handle, int64_t ns);
+ int pollEvents(sensors_event_t* data, int count);
+
+private:
+ enum {
+ light = 0,
+ proximity = 1,
+ bosch = 2,
+ yamaha = 3,
+ orientation = 4,
+ numSensorDrivers,
+ numFds,
+ };
+
+ static const size_t wake = numFds - 1;
+ static const char WAKE_MESSAGE = 'W';
+ struct pollfd mPollFds[numFds];
+ int mWritePipeFd;
+ SensorBase* mSensors[numSensorDrivers];
+
+ int handleToDriver(int handle) const {
+ switch (handle) {
+
+ case ID_A:
+ return bosch;
+ case ID_M:
+ return yamaha;
+ case ID_O:
+ return orientation;
+ case ID_P:
+ return proximity;
+ case ID_L:
+ return light;
+
+ }
+ return -EINVAL;
+ }
+};
+
+/*****************************************************************************/
+
+sensors_poll_context_t::sensors_poll_context_t()
+{
+ mSensors[light] = new LightSensor();
+ mPollFds[light].fd = mSensors[light]->getFd();
+ mPollFds[light].events = POLLIN;
+ mPollFds[light].revents = 0;
+
+ mSensors[proximity] = new ProximitySensor();
+ mPollFds[proximity].fd = mSensors[proximity]->getFd();
+ mPollFds[proximity].events = POLLIN;
+ mPollFds[proximity].revents = 0;
+
+ mSensors[bosch] = new Smb380Sensor();
+ mPollFds[bosch].fd = mSensors[bosch]->getFd();
+ mPollFds[bosch].events = POLLIN;
+ mPollFds[bosch].revents = 0;
+
+ mSensors[yamaha] = new CompassSensor();
+ mPollFds[yamaha].fd = mSensors[yamaha]->getFd();
+ mPollFds[yamaha].events = POLLIN;
+ mPollFds[yamaha].revents = 0;
+
+ mSensors[orientation] = new OrientationSensor();
+ mPollFds[orientation].fd = mSensors[orientation]->getFd();
+ mPollFds[orientation].events = POLLIN;
+ mPollFds[orientation].revents = 0;
+
+ int wakeFds[2];
+ int result = pipe(wakeFds);
+ LOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno));
+ fcntl(wakeFds[0], F_SETFL, O_NONBLOCK);
+ fcntl(wakeFds[1], F_SETFL, O_NONBLOCK);
+ mWritePipeFd = wakeFds[1];
+
+ mPollFds[wake].fd = wakeFds[0];
+ mPollFds[wake].events = POLLIN;
+ mPollFds[wake].revents = 0;
+}
+
+sensors_poll_context_t::~sensors_poll_context_t() {
+ for (int i=0 ; i<numSensorDrivers ; i++) {
+ delete mSensors[i];
+ }
+ close(mPollFds[wake].fd);
+ close(mWritePipeFd);
+}
+
+int sensors_poll_context_t::activate(int handle, int enabled) {
+ int index = handleToDriver(handle);
+ if (index < 0) return index;
+ int err = mSensors[index]->enable(handle, enabled);
+ if (enabled && !err) {
+ const char wakeMessage(WAKE_MESSAGE);
+ int result = write(mWritePipeFd, &wakeMessage, 1);
+ LOGE_IF(result<0, "error sending wake message (%s)", strerror(errno));
+ }
+ return err;
+}
+
+int sensors_poll_context_t::setDelay(int handle, int64_t ns) {
+
+ int index = handleToDriver(handle);
+ if (index < 0) return index;
+ return mSensors[index]->setDelay(handle, ns);
+}
+
+int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
+{
+ int nbEvents = 0;
+ int n = 0;
+
+ do {
+ // see if we have some leftover from the last poll()
+ for (int i=0 ; count && i<numSensorDrivers ; i++) {
+ SensorBase* const sensor(mSensors[i]);
+ if ((mPollFds[i].revents & POLLIN) || (sensor->hasPendingEvents())) {
+ int nb = sensor->readEvents(data, count);
+ if (nb < count) {
+ // no more data for this sensor
+ mPollFds[i].revents = 0;
+ }
+ count -= nb;
+ nbEvents += nb;
+ data += nb;
+ }
+ }
+
+ if (count) {
+ // we still have some room, so try to see if we can get
+ // some events immediately or just wait if we don't have
+ // anything to return
+ n = poll(mPollFds, numFds, nbEvents ? 0 : -1);
+ if (n<0) {
+ LOGE("poll() failed (%s)", strerror(errno));
+ return -errno;
+ }
+ if (mPollFds[wake].revents & POLLIN) {
+ char msg;
+ int result = read(mPollFds[wake].fd, &msg, 1);
+ LOGE_IF(result<0, "error reading from wake pipe (%s)", strerror(errno));
+ LOGE_IF(msg != WAKE_MESSAGE, "unknown message on wake queue (0x%02x)", int(msg));
+
+ mPollFds[wake].revents = 0;
+ }
+ }
+ // if we have events and space, go read them
+ } while (n && count);
+
+ return nbEvents;
+}
+
+/*****************************************************************************/
+
+static int poll__close(struct hw_device_t *dev)
+{
+ sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
+ if (ctx) {
+ delete ctx;
+ }
+ return 0;
+}
+
+static int poll__activate(struct sensors_poll_device_t *dev,
+ int handle, int enabled) {
+ sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
+ return ctx->activate(handle, enabled);
+}
+
+static int poll__setDelay(struct sensors_poll_device_t *dev,
+ int handle, int64_t ns) {
+ sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
+ return ctx->setDelay(handle, ns);
+}
+
+static int poll__poll(struct sensors_poll_device_t *dev,
+ sensors_event_t* data, int count) {
+ sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
+ return ctx->pollEvents(data, count);
+}
+
+/*****************************************************************************/
+
+/** Open a new instance of a sensor device using name */
+static int open_sensors(const struct hw_module_t* module, const char* id,
+ struct hw_device_t** device)
+{
+ int status = -EINVAL;
+ sensors_poll_context_t *dev = new sensors_poll_context_t();
+
+ memset(&dev->device, 0, sizeof(sensors_poll_device_t));
+
+ dev->device.common.tag = HARDWARE_DEVICE_TAG;
+ dev->device.common.version = 0;
+ dev->device.common.module = const_cast<hw_module_t*>(module);
+ dev->device.common.close = poll__close;
+ dev->device.activate = poll__activate;
+ dev->device.setDelay = poll__setDelay;
+ dev->device.poll = poll__poll;
+
+ *device = &dev->device.common;
+ status = 0;
+
+ return status;
+}
+
diff --git a/libsensors/sensors.h b/libsensors/sensors.h
new file mode 100644
index 0000000..4943fc1
--- /dev/null
+++ b/libsensors/sensors.h
@@ -0,0 +1,117 @@
+/*
+ * 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
+
+/*****************************************************************************/
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+#define ID_A (0)
+#define ID_M (1)
+#define ID_O (2)
+#define ID_L (3)
+#define ID_P (4)
+#define ID_GY (5)
+
+/*****************************************************************************/
+
+/*
+ * The SENSORS Module
+ */
+
+/* the GP2A is a binary proximity sensor that triggers around 5 cm on
+ * this hardware */
+#define PROXIMITY_THRESHOLD_GP2A 5.0f
+
+/*****************************************************************************/
+
+#define AKM_DEVICE_NAME "/dev/akm8973_aot"
+
+
+#define EVENT_TYPE_ACCEL_X ABS_X
+#define EVENT_TYPE_ACCEL_Y ABS_Y
+#define EVENT_TYPE_ACCEL_Z ABS_Z
+
+#define EVENT_TYPE_YAW REL_X
+#define EVENT_TYPE_PITCH REL_Y
+#define EVENT_TYPE_ROLL REL_Z
+#define EVENT_TYPE_ORIENT_STATUS REL_WHEEL
+
+/* For AK8973iB */
+#define EVENT_TYPE_MAGV_X ABS_X
+#define EVENT_TYPE_MAGV_Y ABS_Y
+#define EVENT_TYPE_MAGV_Z ABS_Z
+
+#define EVENT_TYPE_PROXIMITY ABS_DISTANCE
+#define EVENT_TYPE_LIGHT ABS_MISC
+
+#define EVENT_TYPE_GYRO_X REL_RY
+#define EVENT_TYPE_GYRO_Y REL_RX
+#define EVENT_TYPE_GYRO_Z REL_RZ
+
+
+// 720 LSG = 1G
+#define LSG (720.0f)
+#define NUMOFACCDATA 8
+
+// conversion of acceleration data to SI units (m/s^2)
+#define RANGE_A (2*GRAVITY_EARTH)
+#define RESOLUTION_A (RANGE_A/(512))
+#define CONVERT_A (RANGE_A/(512))
+#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/1000.0f)
+#define CONVERT_M_X (CONVERT_M)
+#define CONVERT_M_Y (CONVERT_M)
+#define CONVERT_M_Z (CONVERT_M)
+
+/* conversion of orientation data to degree units */
+#define CONVERT_O (1.0f/1000.0f)
+#define CONVERT_O_A (CONVERT_O)
+#define CONVERT_O_P (CONVERT_O)
+#define CONVERT_O_R (CONVERT_O)
+
+// conversion of gyro data to SI units (radian/sec)
+#define RANGE_GYRO (2000.0f*(float)M_PI/180.0f)
+#define CONVERT_GYRO ((70.0f / 1000.0f) * ((float)M_PI / 180.0f))
+#define CONVERT_GYRO_X (CONVERT_GYRO)
+#define CONVERT_GYRO_Y (-CONVERT_GYRO)
+#define CONVERT_GYRO_Z (CONVERT_GYRO)
+
+#define SENSOR_STATE_MASK (0x7FFF)
+
+/*****************************************************************************/
+
+__END_DECLS
+
+#endif // ANDROID_SENSORS_H