diff options
40 files changed, 3910 insertions, 2820 deletions
diff --git a/device_base.mk b/device_base.mk index 21f63d6..7cd0463 100644 --- a/device_base.mk +++ b/device_base.mk @@ -88,6 +88,8 @@ PRODUCT_COPY_FILES += \ PRODUCT_PACKAGES += \ lights.aries \ sensors.aries \ + geomagneticd \ + orientationd \ power.s5pc110 \ hwcomposer.s5pc110 \ camera.aries \ diff --git a/init.aries.rc b/init.aries.rc index e9da574..fd29cc7 100644 --- a/init.aries.rc +++ b/init.aries.rc @@ -173,13 +173,12 @@ on property:ril.bt_macaddr=* # oneshot # keycodes 114 115 116 -service orientationd /system/vendor/bin/orientationd +service orientationd /system/bin/orientationd class late_start user compass group system input - disabled -service geomagneticd /system/vendor/bin/geomagneticd +service geomagneticd /system/bin/geomagneticd class late_start user compass group system input diff --git a/libsensors/Android.mk b/libsensors/Android.mk deleted file mode 100644 index 8add1e7..0000000 --- a/libsensors/Android.mk +++ /dev/null @@ -1,54 +0,0 @@ -# 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. - -ifneq ($(TARGET_PROVIDES_LIBSENSORS),true) - -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 - -endif diff --git a/libsensors/BoschYamaha.cpp b/libsensors/BoschYamaha.cpp deleted file mode 100644 index 5836d19..0000000 --- a/libsensors/BoschYamaha.cpp +++ /dev/null @@ -1,500 +0,0 @@ -/* - * 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 - ALOGD("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"); - ALOGD("BoschYamaha::~enable Compass(0, %d) open %s",en, input_sysfs_path); - fd = open(input_sysfs_path, O_RDWR); - if (fd >= 0) { - ALOGD("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 - ALOGD("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"); - ALOGD("BoschYamaha::~enable Accel(0, %d) open %s",en, input_accel_sysfs_path); - fd = open(input_accel_sysfs_path, O_RDWR); - if (fd >= 0) { - ALOGD("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() { - - //ALOGD("hasPendingEvents was called"); - if(accelEnabled || compassEnabled){ - //ALOGD("hasPendingEvents will return true"); - return true; - } - else { - //ALOGD("hasPendingEvents will return false"); - return false; - } -} - - - -int BoschYamaha::readEvents(sensors_event_t* data, int count) -{ - if (count < 1) - return -EINVAL; - - - int numEventReceived = 0; - - //ALOGD("Sensor: Read events was called with count: %d", count); - - if(compassEnabled) - { - //ALOGD("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) { - //ALOGD("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 { - ALOGE("BoschYamaha: unknown event (type=%d, code=%d)", type, event->code); - - } - mInputReaderMagnetic.next(); - } - } - - //ALOGD("Sensor: Compass read quited, count: %d", count); - - - if(accelEnabled) - { - //ALOGD("Sensor: Accel is enabled, going to take care of it, count: %d", count); - - ssize_t n = mInputReaderAccel.fill(data_fd); - //ALOGD("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) { - //ALOGD("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) { - //ALOGD("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 { - ALOGE("BoschYamaha: unknown event (type=%d, code=%d)", type, event->code); - - } - mInputReaderAccel.next(); - } - } - - //ALOGD("Sensor: Accel read quited, count: %d, acceldata Ready: %d, compassData Ready = %d", count, accelDataReady, compassDataReady); - - if( (accelDataReady == 1) && (compassDataReady == 1)){ - //ALOGD("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); - } - - //ALOGD("BoschYamaha: azimuth is %d", (int)(euler[0])); - //ALOGD("BoschYamaha: pitch is %d", (int)(euler[1])); - //ALOGD("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 deleted file mode 100644 index c4b4988..0000000 --- a/libsensors/BoschYamaha.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * 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 deleted file mode 100644 index 6f63751..0000000 --- a/libsensors/CompassSensor.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/* - * 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) -{ - ALOGD("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)); - - ALOGD("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() { - - ALOGD("CompassSensor::~CompassSensor()"); - if (mEnabled) { - enable(0, 0); - } -} - - - -int CompassSensor::enable(int32_t, int en) { - - - ALOGD("CompassSensor::~enable(0, %d)", en); - int flags = en ? 1 : 0; - if (flags != mEnabled) { - int fd; - strcpy(&input_sysfs_path[input_sysfs_path_len], "enable"); - ALOGD("CompassSensor::~enable(0, %d) open %s",en, input_sysfs_path); - fd = open(input_sysfs_path, O_RDWR); - if (fd >= 0) { - ALOGD("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.*/ - //ALOGD("CompassSensor::~hasPendingEvents %d", mHasPendingEvent ? 1 : 0 ); - return mHasPendingEvent; -} - - -int CompassSensor::setDelay(int32_t handle, int64_t ns) -{ - int fd; - int val; - - // Kernel driver only support specific values - if (ns < 20000000L) { - val = 1; - } else if (ns < 60000000L) { - val = 20; - } else if (ns < 200000000L) { - val = 60; - } else if (ns < 1000000000L) { - val = 200; - } else { - val = 1000; - } - - ALOGD("CompassSensor::~setDelay(%d, %lld) val = %d", handle, ns, val); - - strcpy(&input_sysfs_path[input_sysfs_path_len], "delay"); - fd = open(input_sysfs_path, O_RDWR); - if (fd >= 0) { - char buf[80]; - sprintf(buf, "%d", val); - write(fd, buf, strlen(buf)+1); - close(fd); - return 0; - } - return -1; -} - - -int CompassSensor::readEvents(sensors_event_t* data, int count) -{ - //ALOGD("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 { - ALOGE("CompassSensor: unknown event (type=%d, code=%d)", - type, event->code); - } - mInputReader.next(); - } - - //ALOGD("CompassSensor::~readEvents() numEventReceived = %d", numEventReceived); - return numEventReceived++; - -} diff --git a/libsensors/CompassSensor.h b/libsensors/CompassSensor.h deleted file mode 100644 index 9b34f9d..0000000 --- a/libsensors/CompassSensor.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 deleted file mode 100644 index 03e5fce..0000000 --- a/libsensors/GyroSensor.cpp +++ /dev/null @@ -1,181 +0,0 @@ -/* - * 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 { - ALOGE("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 deleted file mode 100644 index e5a9241..0000000 --- a/libsensors/GyroSensor.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 deleted file mode 100644 index 1014f29..0000000 --- a/libsensors/InputEventReader.cpp +++ /dev/null @@ -1,88 +0,0 @@ -/* - * 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 deleted file mode 100644 index 180aade..0000000 --- a/libsensors/InputEventReader.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * 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 deleted file mode 100644 index fe0b8b3..0000000 --- a/libsensors/LightSensor.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* - * 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" - -/*****************************************************************************/ - -LightSensor::LightSensor() - : SensorBase(NULL, "lightsensor-level"), - mEnabled(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; - 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) { - // Convert adc value to lux assuming: - // I = 10 * log(Ev) uA - // R = 47kOhm - // Max adc value 4095 = 3.3V - // 1/4 of light reaches sensor - mPendingEvent.light = powf(10, event->value * (330.0f / 4095.0f / 47.0f)) * 4; - } - } else if (type == EV_SYN) { - mPendingEvent.timestamp = timevalToNano(event->time); - if (mEnabled) { - *data++ = mPendingEvent; - count--; - numEventReceived++; - } - } else { - ALOGE("LightSensor: unknown event (type=%d, code=%d)", - type, event->code); - } - mInputReader.next(); - } - - return numEventReceived; -} diff --git a/libsensors/LightSensor.h b/libsensors/LightSensor.h deleted file mode 100644 index 79e0ccf..0000000 --- a/libsensors/LightSensor.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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; - InputEventCircularReader mInputReader; - sensors_event_t mPendingEvent; - bool mHasPendingEvent; - char input_sysfs_path[PATH_MAX]; - int input_sysfs_path_len; - - int setInitialState(); - -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 deleted file mode 100644 index e39edd7..0000000 --- a/libsensors/OrientationSensor.cpp +++ /dev/null @@ -1,182 +0,0 @@ -/* - * 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/properties.h> -#include <cutils/log.h> - - -#include "OrientationSensor.h" - - -/*****************************************************************************/ -OrientationSensor::OrientationSensor() - : SensorBase(NULL, "orientation_sensor"), - mEnabled(0), - mInputReader(4), - mHasPendingEvent(false) -{ - ALOGD("OrientationSensor::OrientationSensor()"); - mPendingEvent.version = sizeof(sensors_event_t); - mPendingEvent.sensor = ID_O; - mPendingEvent.type = SENSOR_TYPE_ORIENTATION; - memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data)); - - ALOGD("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() { - - ALOGD("OrientationSensor::~OrientationSensor()"); - if (mEnabled) { - enable(0, 0); - } -} - - -int OrientationSensor::enable(int32_t, int en) { - - - ALOGD("OrientationSensor::~enable(0, %d)", en); - int flags = en ? 1 : 0; - if (flags != mEnabled) { - int fd; - strcpy(&input_sysfs_path[input_sysfs_path_len], "enable"); - ALOGD("OrientationSensor::~enable(0, %d) open %s",en, input_sysfs_path); - fd = open(input_sysfs_path, O_RDWR); - if (fd >= 0) { - ALOGD("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(); - - /* Since the migration to 3.0 kernel, orientationd doesn't poll - * the enabled state properly, so start it when it's enabled and - * stop it when we're done using it. - */ - property_set(mEnabled ? "ctl.start" : "ctl.stop", "orientationd"); - 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.*/ - //ALOGD("OrientationSensor::~hasPendingEvents %d", mHasPendingEvent ? 1 : 0 ); - return mHasPendingEvent; -} - - -int OrientationSensor::setDelay(int32_t handle, int64_t ns) -{ - ALOGD("OrientationSensor::~setDelay(%d, %lld)", handle, ns); - - int fd; - - if (ns < 10000000) { - ns = 10000000; // Minimum on stock - } - - strcpy(&input_sysfs_path[input_sysfs_path_len], "delay"); - fd = open(input_sysfs_path, O_RDWR); - if (fd >= 0) { - char buf[80]; - sprintf(buf, "%lld", ns / 10000000 * 10); // Some flooring to match stock value - write(fd, buf, strlen(buf)+1); - close(fd); - return 0; - } - return -1; -} - - -int OrientationSensor::readEvents(sensors_event_t* data, int count) -{ - //ALOGD("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 { - ALOGE("OrientationSensor: unknown event (type=%d, code=%d)", - type, event->code); - } - mInputReader.next(); - } - - //ALOGD("OrientationSensor::~readEvents() numEventReceived = %d", numEventReceived); - return numEventReceived++; - -} diff --git a/libsensors/OrientationSensor.h b/libsensors/OrientationSensor.h deleted file mode 100644 index 7add75b..0000000 --- a/libsensors/OrientationSensor.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 deleted file mode 100644 index 77a7f3c..0000000 --- a/libsensors/ProximitySensor.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * 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"), - 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 { - ALOGE("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 deleted file mode 100644 index 08ea49c..0000000 --- a/libsensors/ProximitySensor.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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 deleted file mode 100644 index 79b1ee2..0000000 --- a/libsensors/SensorBase.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* - * 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); - ALOGE_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); - ALOGE_IF(fd<0, "couldn't find '%s' input device", inputName); - return fd; -} diff --git a/libsensors/SensorBase.h b/libsensors/SensorBase.h deleted file mode 100644 index bb4d055..0000000 --- a/libsensors/SensorBase.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * 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 deleted file mode 100644 index e8aedee..0000000 --- a/libsensors/Smb380Sensor.cpp +++ /dev/null @@ -1,177 +0,0 @@ -/* - * 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) -{ - ALOGD("Smb380Sensor::Smb380Sensor()"); - mPendingEvent.version = sizeof(sensors_event_t); - mPendingEvent.sensor = ID_A; - mPendingEvent.type = SENSOR_TYPE_ACCELEROMETER; - memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data)); - - ALOGD("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() { - - ALOGD("Smb380Sensor::~Smb380Sensor()"); - if (mEnabled) { - enable(0, 0); - } -} - - - -int Smb380Sensor::enable(int32_t, int en) { - - - ALOGD("Smb380Sensor::~enable(0, %d)", en); - int flags = en ? 1 : 0; - if (flags != mEnabled) { - int fd; - strcpy(&input_sysfs_path[input_sysfs_path_len], "enable"); - ALOGD("Smb380Sensor::~enable(0, %d) open %s",en, input_sysfs_path); - fd = open(input_sysfs_path, O_RDWR); - if (fd >= 0) { - ALOGD("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.*/ - //ALOGD("Smb380Sensor::~hasPendingEvents %d", mHasPendingEvent ? 1 : 0 ); - return mHasPendingEvent; -} - - -int Smb380Sensor::setDelay(int32_t handle, int64_t ns) -{ - ALOGD("Smb380Sensor::~setDelay(%d, %lld)", handle, ns); - - int fd; - - if (ns < 10000000) { - ns = 10000000; // Minimum on stock - } - - strcpy(&input_sysfs_path[input_sysfs_path_len], "delay"); - fd = open(input_sysfs_path, O_RDWR); - if (fd >= 0) { - char buf[80]; - sprintf(buf, "%lld", ns / 10000000 * 10); // Some flooring to match stock value - write(fd, buf, strlen(buf)+1); - close(fd); - return 0; - } - return -1; -} - - -int Smb380Sensor::readEvents(sensors_event_t* data, int count) -{ - //ALOGD("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 { - ALOGE("Smb380Sensor: unknown event (type=%d, code=%d)", - type, event->code); - } - mInputReader.next(); - } - - //ALOGD("Smb380Sensor::~readEvents() numEventReceived = %d", numEventReceived); - return numEventReceived++; - -} diff --git a/libsensors/Smb380Sensor.h b/libsensors/Smb380Sensor.h deleted file mode 100644 index 1277ab4..0000000 --- a/libsensors/Smb380Sensor.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * 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 deleted file mode 100644 index 848bfe1..0000000 --- a/libsensors/sensors.cpp +++ /dev/null @@ -1,378 +0,0 @@ -/* - * 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, 10000, { } }, - { "MS3C 3-axis Magnetic field sensor", - "Yamaha ", - 1, SENSORS_MAGNETIC_FIELD_HANDLE, - SENSOR_TYPE_MAGNETIC_FIELD, 2000.0f, CONVERT_M, 6.8f, 10000, { } }, - { "CM Hacked Orientation Sensor", - "CM Team", - 1, SENSORS_ORIENTATION_HANDLE, - SENSOR_TYPE_ORIENTATION, 360.0f, CONVERT_O, 7.8f, 10000, { } }, - { "GP2A Light sensor", - "Sharp", - 1, SENSORS_LIGHT_HANDLE, - SENSOR_TYPE_LIGHT, 10240.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]; - - // For keeping track of usage (only count from system) - bool mAccelActive; - bool mMagnetActive; - bool mOrientationActive; - - int real_activate(int handle, int enabled); - - 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); - ALOGE_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; - - mAccelActive = false; - mMagnetActive = false; - mOrientationActive = false; -} - -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 err; - - // Orientation requires accelerometer and magnetic sensor - if (handle == ID_O) { - mOrientationActive = enabled ? true : false; - if (!mAccelActive) { - err = real_activate(ID_A, enabled); - if (err) return err; - } - if (!mMagnetActive) { - err = real_activate(ID_M, enabled); - if (err) return err; - } - } - // Keep track of magnetic and accelerometer use from system - else if (handle == ID_A) { - mAccelActive = enabled ? true : false; - // No need to enable or disable if orientation sensor is active as that will handle it - if (mOrientationActive) return 0; - } - else if (handle == ID_M) { - mMagnetActive = enabled ? true : false; - // No need to enable or disable if orientation sensor is active as that will handle it - if (mOrientationActive) return 0; - } - - return real_activate(handle, enabled); -} - -int sensors_poll_context_t::real_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); - ALOGE_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 - do { - n = poll(mPollFds, numFds, nbEvents ? 0 : -1); - } while (n < 0 && errno == EINTR); - if (n<0) { - ALOGE("poll() failed (%s)", strerror(errno)); - return -errno; - } - if (mPollFds[wake].revents & POLLIN) { - char msg; - int result = read(mPollFds[wake].fd, &msg, 1); - ALOGE_IF(result<0, "error reading from wake pipe (%s)", strerror(errno)); - ALOGE_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 deleted file mode 100644 index 2b7e138..0000000 --- a/libsensors/sensors.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * 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 diff --git a/sensors/Android.mk b/sensors/Android.mk new file mode 100644 index 0000000..72bccb8 --- /dev/null +++ b/sensors/Android.mk @@ -0,0 +1,74 @@ +# Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +LOCAL_PATH := $(call my-dir) +ARIES_SENSORS_PATH := $(LOCAL_PATH) + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + aries_sensors.c \ + input.c \ + smb380.c \ + gp2a_light.c \ + gp2a_proximity.c \ + yas529.c \ + yas_orientation.c + +LOCAL_C_INCLUDES := \ + $(LOCAL_PATH) + +LOCAL_SHARED_LIBRARIES := libutils libcutils liblog libhardware +LOCAL_PRELINK_MODULE := false + +LOCAL_MODULE := sensors.aries +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw +LOCAL_MODULE_TAGS := optional + +include $(BUILD_SHARED_LIBRARY) + +LOCAL_PATH := $(ARIES_SENSORS_PATH)/geomagneticd + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + geomagneticd.c \ + input.c + +LOCAL_SHARED_LIBRARIES := libutils libcutils liblog +LOCAL_PRELINK_MODULE := false + +LOCAL_MODULE := geomagneticd +LOCAL_MODULE_TAGS := optional + +include $(BUILD_EXECUTABLE) + +LOCAL_PATH := $(ARIES_SENSORS_PATH)/orientationd + +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + orientationd.c \ + input.c \ + smb380.c \ + yas529.c + +LOCAL_SHARED_LIBRARIES := libutils libcutils liblog +LOCAL_PRELINK_MODULE := false + +LOCAL_MODULE := orientationd +LOCAL_MODULE_TAGS := optional + +include $(BUILD_EXECUTABLE) diff --git a/sensors/aries_sensors.c b/sensors/aries_sensors.c new file mode 100644 index 0000000..ef28b5f --- /dev/null +++ b/sensors/aries_sensors.c @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <unistd.h> +#include <stdint.h> +#include <fcntl.h> +#include <errno.h> +#include <poll.h> +#include <sys/select.h> +#include <hardware/sensors.h> +#include <hardware/hardware.h> + +#define LOG_TAG "aries_sensors" +#include <utils/Log.h> + +#include "aries_sensors.h" + +/* + * Sensors list + */ + +struct sensor_t aries_sensors[] = { + { "SMB380 Acceleration Sensor", "Bosch", 1, SENSOR_TYPE_ACCELEROMETER, + SENSOR_TYPE_ACCELEROMETER, 2 * GRAVITY_EARTH, GRAVITY_EARTH / 256.0f, 0.20f, 10000, {}, }, + { "YAS529 Magnetic Sensor", "Yamaha", 1, SENSOR_TYPE_MAGNETIC_FIELD, + SENSOR_TYPE_MAGNETIC_FIELD, 2000.0f, 1.0f / 1000, 6.8f, 10000, {}, }, + { "YAS Orientation Sensor", "Yamaha", 1, SENSOR_TYPE_ORIENTATION, + SENSOR_TYPE_ORIENTATION, 360.0f, 0.1f, 0.0f, 10000, {}, }, + { "GP2A Light Sensor", "Sharp", 1, SENSOR_TYPE_LIGHT, + SENSOR_TYPE_LIGHT, 10240.0f, 1.0f, 0.75f, 0, {}, }, + { "GP2A Proximity Sensor", "Sharp", 1, SENSOR_TYPE_PROXIMITY, + SENSOR_TYPE_PROXIMITY, 5.0f, 5.0f, 0.75f, 0, {}, }, +}; + +int aries_sensors_count = sizeof(aries_sensors) / sizeof(struct sensor_t); + +struct aries_sensors_handlers *aries_sensors_handlers[] = { + &smb380, + &yas529, + &yas_orientation, + &gp2a_light, + &gp2a_proximity, +}; + +int aries_sensors_handlers_count = sizeof(aries_sensors_handlers) / + sizeof(struct aries_sensors_handlers *); + +/* + * Aries Sensors + */ + +int aries_sensors_activate(struct sensors_poll_device_t *dev, int handle, + int enabled) +{ + struct aries_sensors_device *device; + int i; + + ALOGD("%s(%p, %d, %d)", __func__, dev, handle, enabled); + + if (dev == NULL) + return -EINVAL; + + device = (struct aries_sensors_device *) dev; + + if (device->handlers == NULL || device->handlers_count <= 0) + return -EINVAL; + + for (i = 0; i < device->handlers_count; i++) { + if (device->handlers[i] == NULL) + continue; + + if (device->handlers[i]->handle == handle) { + if (enabled && device->handlers[i]->activate != NULL) { + device->handlers[i]->needed |= ARIES_SENSORS_NEEDED_API; + if (device->handlers[i]->needed == ARIES_SENSORS_NEEDED_API) + return device->handlers[i]->activate(device->handlers[i]); + else + return 0; + } else if (!enabled && device->handlers[i]->deactivate != NULL) { + device->handlers[i]->needed &= ~ARIES_SENSORS_NEEDED_API; + if (device->handlers[i]->needed == 0) + return device->handlers[i]->deactivate(device->handlers[i]); + else + return 0; + } + } + } + + return -1; +} + +int aries_sensors_set_delay(struct sensors_poll_device_t *dev, int handle, + int64_t ns) +{ + struct aries_sensors_device *device; + int i; + + ALOGD("%s(%p, %d, %ld)", __func__, dev, handle, (long int) ns); + + if (dev == NULL) + return -EINVAL; + + device = (struct aries_sensors_device *) dev; + + if (device->handlers == NULL || device->handlers_count <= 0) + return -EINVAL; + + for (i = 0; i < device->handlers_count; i++) { + if (device->handlers[i] == NULL) + continue; + + if (device->handlers[i]->handle == handle && device->handlers[i]->set_delay != NULL) + return device->handlers[i]->set_delay(device->handlers[i], (long int) ns); + } + + return 0; +} + +int aries_sensors_poll(struct sensors_poll_device_t *dev, + struct sensors_event_t* data, int count) +{ + struct aries_sensors_device *device; + int i, j; + int c, n; + int poll_rc, rc; + +// ALOGD("%s(%p, %p, %d)", __func__, dev, data, count); + + if (dev == NULL) + return -EINVAL; + + device = (struct aries_sensors_device *) dev; + + if (device->handlers == NULL || device->handlers_count <= 0 || + device->poll_fds == NULL || device->poll_fds_count <= 0) + return -EINVAL; + + n = 0; + + do { + poll_rc = poll(device->poll_fds, device->poll_fds_count, n > 0 ? 0 : -1); + if (poll_rc < 0) + return -1; + + for (i = 0; i < device->poll_fds_count; i++) { + if (!(device->poll_fds[i].revents & POLLIN)) + continue; + + for (j = 0; j < device->handlers_count; j++) { + if (device->handlers[j] == NULL || device->handlers[j]->poll_fd != device->poll_fds[i].fd || device->handlers[j]->get_data == NULL) + continue; + + rc = device->handlers[j]->get_data(device->handlers[j], &data[n]); + if (rc < 0) { + device->poll_fds[i].revents = 0; + poll_rc = -1; + } else { + n++; + count--; + } + } + } + } while ((poll_rc > 0 || n < 1) && count > 0); + + return n; +} + +/* + * Interface + */ + +int aries_sensors_close(hw_device_t *device) +{ + struct aries_sensors_device *aries_sensors_device; + int i; + + ALOGD("%s(%p)", __func__, device); + + if (device == NULL) + return -EINVAL; + + aries_sensors_device = (struct aries_sensors_device *) device; + + if (aries_sensors_device->poll_fds != NULL) + free(aries_sensors_device->poll_fds); + + for (i = 0; i < aries_sensors_device->handlers_count; i++) { + if (aries_sensors_device->handlers[i] == NULL || aries_sensors_device->handlers[i]->deinit == NULL) + continue; + + aries_sensors_device->handlers[i]->deinit(aries_sensors_device->handlers[i]); + } + + free(device); + + return 0; +} + +int aries_sensors_open(const struct hw_module_t* module, const char *id, + struct hw_device_t** device) +{ + struct aries_sensors_device *aries_sensors_device; + int p, i; + + ALOGD("%s(%p, %s, %p)", __func__, module, id, device); + + if (module == NULL || device == NULL) + return -EINVAL; + + aries_sensors_device = (struct aries_sensors_device *) + calloc(1, sizeof(struct aries_sensors_device)); + aries_sensors_device->device.common.tag = HARDWARE_DEVICE_TAG; + aries_sensors_device->device.common.version = 0; + aries_sensors_device->device.common.module = (struct hw_module_t *) module; + aries_sensors_device->device.common.close = aries_sensors_close; + aries_sensors_device->device.activate = aries_sensors_activate; + aries_sensors_device->device.setDelay = aries_sensors_set_delay; + aries_sensors_device->device.poll = aries_sensors_poll; + aries_sensors_device->handlers = aries_sensors_handlers; + aries_sensors_device->handlers_count = aries_sensors_handlers_count; + aries_sensors_device->poll_fds = (struct pollfd *) + calloc(1, aries_sensors_handlers_count * sizeof(struct pollfd)); + + p = 0; + for (i = 0; i < aries_sensors_handlers_count; i++) { + if (aries_sensors_handlers[i] == NULL || aries_sensors_handlers[i]->init == NULL) + continue; + + aries_sensors_handlers[i]->init(aries_sensors_handlers[i], aries_sensors_device); + if (aries_sensors_handlers[i]->poll_fd >= 0) { + aries_sensors_device->poll_fds[p].fd = aries_sensors_handlers[i]->poll_fd; + aries_sensors_device->poll_fds[p].events = POLLIN; + p++; + } + } + + aries_sensors_device->poll_fds_count = p; + + *device = &(aries_sensors_device->device.common); + + return 0; +} + +int aries_sensors_get_sensors_list(struct sensors_module_t* module, + const struct sensor_t **sensors_p) +{ + ALOGD("%s(%p, %p)", __func__, module, sensors_p); + + if (sensors_p == NULL) + return -EINVAL; + + *sensors_p = aries_sensors; + return aries_sensors_count; +} + +struct hw_module_methods_t aries_sensors_module_methods = { + .open = aries_sensors_open, +}; + +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 = "Aries Sensors", + .author = "Paul Kocialkowski", + .methods = &aries_sensors_module_methods, + }, + .get_sensors_list = aries_sensors_get_sensors_list, +}; diff --git a/sensors/aries_sensors.h b/sensors/aries_sensors.h new file mode 100644 index 0000000..c9d8df8 --- /dev/null +++ b/sensors/aries_sensors.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> +#include <poll.h> +#include <linux/input.h> + +#include <hardware/sensors.h> +#include <hardware/hardware.h> + +#ifndef _ARIES_SENSORS_H_ +#define _ARIES_SENSORS_H_ + +#define ARIES_SENSORS_NEEDED_API (1 << 0) +#define ARIES_SENSORS_NEEDED_ORIENTATION (1 << 1) + +struct aries_sensors_device; + +struct aries_sensors_handlers { + char *name; + int handle; + + int (*init)(struct aries_sensors_handlers *handlers, + struct aries_sensors_device *device); + int (*deinit)(struct aries_sensors_handlers *handlers); + int (*activate)(struct aries_sensors_handlers *handlers); + int (*deactivate)(struct aries_sensors_handlers *handlers); + int (*set_delay)(struct aries_sensors_handlers *handlers, + long int delay); + int (*get_data)(struct aries_sensors_handlers *handlers, + struct sensors_event_t *event); + + int activated; + int needed; + int poll_fd; + + void *data; +}; + +struct aries_sensors_device { + struct sensors_poll_device_t device; + + struct aries_sensors_handlers **handlers; + int handlers_count; + + struct pollfd *poll_fds; + int poll_fds_count; +}; + +extern struct aries_sensors_handlers *aries_sensors_handlers[]; +extern int aries_sensors_handlers_count; + +int aries_sensors_activate(struct sensors_poll_device_t *dev, int handle, + int enabled); +int aries_sensors_set_delay(struct sensors_poll_device_t *dev, int handle, + int64_t ns); +int aries_sensors_poll(struct sensors_poll_device_t *dev, + struct sensors_event_t* data, int count); + +/* + * Input + */ + +void input_event_set(struct input_event *event, int type, int code, int value); +long int timestamp(struct timeval *time); +long int input_timestamp(struct input_event *event); +int uinput_rel_create(const char *name); +void uinput_destroy(int uinput_fd); +int input_open(char *name); +int sysfs_path_prefix(char *name, char *path_prefix); +int sysfs_value_read(char *path); +int sysfs_value_write(char *path, int value); +int sysfs_string_read(char *path, char *buffer, size_t length); +int sysfs_string_write(char *path, char *buffer, size_t length); + +/* + * Sensors + */ + +int orientation_fill(struct aries_sensors_handlers *handlers, + sensors_vec_t *acceleration, sensors_vec_t *magnetic); + +extern struct aries_sensors_handlers smb380; +extern struct aries_sensors_handlers yas529; +extern struct aries_sensors_handlers yas_orientation; +extern struct aries_sensors_handlers gp2a_light; +extern struct aries_sensors_handlers gp2a_proximity; + +#endif diff --git a/sensors/geomagneticd/geomagneticd.c b/sensors/geomagneticd/geomagneticd.c new file mode 100644 index 0000000..87ad16a --- /dev/null +++ b/sensors/geomagneticd/geomagneticd.c @@ -0,0 +1,521 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <poll.h> +#include <linux/input.h> + +#include <hardware/sensors.h> +#include <hardware/hardware.h> + +#define LOG_TAG "geomagneticd" +#include <utils/Log.h> + +#include "geomagneticd.h" + +// This geomagnetic daemon is in charge of finding the correct calibration +// offsets to apply to the YAS529 magnetic field sensor. +// This is done by finding raw data extrema (minimum and maximum) for each axis +// and calculating the offset so that these values are -45uT and 45uT. + +/* + * Config + */ + +int geomagneticd_config_read(struct geomagneticd_data *data) +{ + char buffer[100] = { 0 }; + int config_fd = -1; + int rc; + + if (data == NULL) + return -EINVAL; + + config_fd = open(GEOMAGNETICD_CONFIG_PATH, O_RDONLY); + if (config_fd < 0) { + ALOGE("%s: Unable to open config", __func__); + goto error; + } + + rc = read(config_fd, buffer, sizeof(buffer)); + if (rc <= 0) { + ALOGE("%s: Unable to read config", __func__); + goto error; + } + + rc = sscanf(buffer, "%d,%d,%d,%d,%d,%d,%d", + &data->hard_offsets[0], &data->hard_offsets[1], &data->hard_offsets[2], + &data->calib_offsets[0], &data->calib_offsets[1], &data->calib_offsets[2], + &data->accuracy); + if (rc != 7) { + ALOGE("%s: Unable to parse config", __func__); + goto error; + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (config_fd >= 0) + close(config_fd); + + return rc; +} + +int geomagneticd_config_write(struct geomagneticd_data *data) +{ + char buffer[100] = { 0 }; + int config_fd = -1; + int rc; + + if (data == NULL) + return -EINVAL; + + config_fd = open(GEOMAGNETICD_CONFIG_BACKUP_PATH, O_WRONLY | O_TRUNC | O_CREAT, 0644); + if (config_fd < 0) { + ALOGE("%s: Unable to open config", __func__); + goto error; + } + + sprintf(buffer, "%d,%d,%d,%d,%d,%d,%d", + data->hard_offsets[0], data->hard_offsets[1], data->hard_offsets[2], + data->calib_offsets[0], data->calib_offsets[1], data->calib_offsets[2], + data->accuracy); + + rc = write(config_fd, buffer, strlen(buffer) + 1); + if (rc < (int) strlen(buffer) + 1) { + ALOGE("%s: Unable to write config", __func__); + goto error; + } + + rename(GEOMAGNETICD_CONFIG_BACKUP_PATH, GEOMAGNETICD_CONFIG_PATH); + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (config_fd >= 0) + close(config_fd); + + return rc; +} + +/* + * Offsets + */ + +int geomagneticd_offsets_read(struct geomagneticd_data *data) +{ + char buffer[100] = { 0 }; + int offsets_fd = -1; + int rc; + + if (data == NULL) + return -EINVAL; + + offsets_fd = open(data->path_offsets, O_RDONLY); + if (offsets_fd < 0) { + ALOGE("%s: Unable to open offsets", __func__); + goto error; + } + + rc = read(offsets_fd, buffer, sizeof(buffer)); + if (rc <= 0) { + ALOGE("%s: Unable to read offsets", __func__); + goto error; + } + + rc = sscanf(buffer, "%d %d %d %d %d %d %d", + &data->hard_offsets[0], &data->hard_offsets[1], &data->hard_offsets[2], + &data->calib_offsets[0], &data->calib_offsets[1], &data->calib_offsets[2], + &data->accuracy); + if (rc != 7) { + ALOGE("%s: Unable to parse offsets", __func__); + goto error; + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (offsets_fd >= 0) + close(offsets_fd); + + return rc; +} + +int geomagneticd_offsets_write(struct geomagneticd_data *data) +{ + char buffer[100] = { 0 }; + int offsets_fd = -1; + int rc; + + if (data == NULL) + return -EINVAL; + + offsets_fd = open(data->path_offsets, O_WRONLY); + if (offsets_fd < 0) { + ALOGE("%s: Unable to open offsets", __func__); + goto error; + } + + sprintf(buffer, "%d %d %d %d %d %d %d\n", + data->hard_offsets[0], data->hard_offsets[1], data->hard_offsets[2], + data->calib_offsets[0], data->calib_offsets[1], data->calib_offsets[2], + data->accuracy); + + rc = write(offsets_fd, buffer, strlen(buffer) + 1); + if (rc < (int) strlen(buffer) + 1) { + ALOGE("%s: Unable to write offsets", __func__); + goto error; + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (offsets_fd >= 0) + close(offsets_fd); + + return rc; +} + +int geomagneticd_offsets_init(struct geomagneticd_data *data) +{ + int count; + int i; + + if (data == NULL) + return -EINVAL; + + count = sizeof(data->hard_offsets) / sizeof(int); + + // 0xff is an invalid value for hard offsets + for (i = 0; i < count; i++) + data->hard_offsets[i] = 0xff; + + count = sizeof(data->calib_offsets) / sizeof(int); + + // 0x0x7fffffff is an invalid value for calib offsets + for (i = 0; i < count; i++) + data->calib_offsets[i] = 0x7fffffff; + + return 0; +} + +int geomagneticd_offsets_check(struct geomagneticd_data *data) +{ + int count; + int i; + + if (data == NULL) + return -EINVAL; + + count = sizeof(data->hard_offsets) / sizeof(int); + + // 0xff is an invalid value for hard offsets + for (i = 0; i < count; i++) + if (data->hard_offsets[i] == 0xff) + return 0; + + count = sizeof(data->calib_offsets) / sizeof(int); + + // 0x0x7fffffff is an invalid value for calib offsets + for (i = 0; i < count; i++) + if (data->calib_offsets[i] == 0x7fffffff) + return 0; + + return 1; +} + +/* + * Geomagneticd + */ + +int geomagneticd_magnetic_extrema_init(struct geomagneticd_data *data) +{ + int count; + int i; + + if (data == NULL) + return -EINVAL; + + count = sizeof(data->calib_offsets) / sizeof(int); + + // Approximate the previous extrema from the calib offsets + for (i = 0; i < count; i++) { + data->magnetic_extrema[0][i] = -(data->calib_offsets[i] + 45) + 5; + data->magnetic_extrema[1][i] = (data->calib_offsets[i] + 45) - 5; + } + + return 0; +} + +int geomagneticd_magnetic_extrema(struct geomagneticd_data *data, int index, + int value) +{ + if (data == NULL || index < 0 || index >= 3) + return -EINVAL; + + if (value == 0) + return 0; + + // Update the extrema from the current value if needed + if (value < data->magnetic_extrema[0][index] || data->magnetic_extrema[0][index] == 0) + data->magnetic_extrema[0][index] = value; + if (value > data->magnetic_extrema[1][index] || data->magnetic_extrema[1][index] == 0) + data->magnetic_extrema[1][index] = value; + + return 0; +} + +int geomagneticd_calib_offsets(struct geomagneticd_data *data) +{ + int calib_offsets[3]; + int offsets[2]; + int update; + int count; + int rc; + int i; + + if (data == NULL) + return -EINVAL; + + // Calculating the offset is only meaningful when enough values were + // obtained. There is no need to calculate it too often either. + if (data->count % 10 != 0) + return 0; + + update = 0; + + count = sizeof(data->calib_offsets) / sizeof(int); + + // Calculate the calib offset for each axis to have values in [-45;45] uT + for (i = 0; i < count; i++) { + offsets[0] = data->magnetic_extrema[0][i] + 45; + offsets[1] = data->magnetic_extrema[1][i] - 45; + calib_offsets[i] = (offsets[0] + offsets[1]) / 2; + + if (calib_offsets[i] != data->calib_offsets[i]) { + data->calib_offsets[i] = calib_offsets[i]; + update = 1; + } + } + + if (update) { + data->accuracy = 1; + + rc = geomagneticd_offsets_write(data); + if (rc < 0) { + ALOGE("%s: Unable to write offsets", __func__); + return -1; + } + + rc = geomagneticd_config_write(data); + if (rc < 0) { + ALOGE("%s: Unable to write config", __func__); + return -1; + } + } + + return 0; +} + +int geomagneticd_poll(struct geomagneticd_data *data) +{ + struct input_event input_event; + struct pollfd poll_fd; + int rc; + + if (data == NULL) + return -EINVAL; + + if (data->input_fd < 0) + return -1; + + memset(&poll_fd, 0, sizeof(poll_fd)); + poll_fd.fd = data->input_fd; + poll_fd.events = POLLIN; + + while (1) { + rc = poll(&poll_fd, 1, -1); + if (rc < 0) { + ALOGE("%s: poll failure", __func__); + goto error; + } + + if (!(poll_fd.revents & POLLIN)) + continue; + + poll_fd.revents = 0; + + rc = read(data->input_fd, &input_event, sizeof(input_event)); + if (rc < (int) sizeof(input_event)) { + ALOGE("%s: Unable to read input event", __func__); + continue; + } + + // Update the extrema from the current value + if(input_event.type == EV_REL) { + switch (input_event.code) { + case REL_X: + geomagneticd_magnetic_extrema(data, 0, input_event.value); + break; + case REL_Y: + geomagneticd_magnetic_extrema(data, 1, input_event.value); + break; + case REL_Z: + geomagneticd_magnetic_extrema(data, 2, input_event.value); + break; + } + } + + if (input_event.type == EV_SYN) { + // Sometimes, the hard offsets cannot be read at startup + // so we need to do it now + if (!geomagneticd_offsets_check(data)) { + rc = geomagneticd_offsets_read(data); + if (rc < 0) { + ALOGE("%s: Unable to read offsets", __func__); + continue; + } + + // Most likely, the calib offset will be invalid + if (geomagneticd_offsets_check(data)) { + data->accuracy = 1; + geomagneticd_magnetic_extrema_init(data); + } + + rc = geomagneticd_config_write(data); + if (rc < 0) { + ALOGE("%s: Unable to write config", __func__); + continue; + } + } + + data->count++; + + rc = geomagneticd_calib_offsets(data); + if (rc < 0) { + ALOGE("%s: Unable to calib offsets", __func__); + continue; + } + } + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + return rc; +} + +int main(int argc, char *argv[]) +{ + struct geomagneticd_data *geomagneticd_data = NULL; + char path[PATH_MAX] = { 0 }; + int input_fd = -1; + int rc; + + geomagneticd_data = (struct geomagneticd_data *) + calloc(1, sizeof(struct geomagneticd_data)); + + input_fd = input_open("raw_magnetic_sensor"); + if (input_fd < 0) { + ALOGE("%s: Unable to open input", __func__); + goto error; + } + + rc = sysfs_path_prefix("raw_magnetic_sensor", (char *) &path); + if (rc < 0 || path[0] == '\0') { + ALOGE("%s: Unable to open sysfs", __func__); + goto error; + } + + snprintf(geomagneticd_data->path_offsets, PATH_MAX, "%s/offsets", path); + + geomagneticd_data->input_fd = input_fd; + + geomagneticd_offsets_init(geomagneticd_data); + + // Attempt to read the offsets from the config + rc = geomagneticd_config_read(geomagneticd_data); + if (rc < 0 || !geomagneticd_offsets_check(geomagneticd_data)) { + // Read the offsets from the driver + rc = geomagneticd_offsets_read(geomagneticd_data); + if (rc < 0) { + ALOGE("%s: Unable to read offsets", __func__); + goto error; + } + + // Most likely, the calib offset will be invalid and the hard + // offset may be invalid as well + if (geomagneticd_offsets_check(geomagneticd_data)) { + geomagneticd_data->accuracy = 1; + geomagneticd_magnetic_extrema_init(geomagneticd_data); + } + } else { + // Get the magnetic extrema from the config's offsets + geomagneticd_magnetic_extrema_init(geomagneticd_data); + + rc = geomagneticd_offsets_write(geomagneticd_data); + if (rc < 0) { + ALOGE("%s: Unable to write offsets", __func__); + goto error; + } + } + + rc = geomagneticd_poll(geomagneticd_data); + if (rc < 0) + goto error; + + rc = 0; + goto complete; + +error: + while (1) + sleep(3600); + + rc = 1; + +complete: + if (input_fd >= 0) + close(input_fd); + + if (geomagneticd_data != NULL) + free(geomagneticd_data); + + return rc; +} diff --git a/sensors/geomagneticd/geomagneticd.h b/sensors/geomagneticd/geomagneticd.h new file mode 100644 index 0000000..b196c0d --- /dev/null +++ b/sensors/geomagneticd/geomagneticd.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> +#include <poll.h> +#include <linux/input.h> + +#include <hardware/sensors.h> +#include <hardware/hardware.h> + +#ifndef _GEOMAGNETICD_H_ +#define _GEOMAGNETICD_H_ + +#define GEOMAGNETICD_CONFIG_PATH "/data/system/yas529.cfg" +#define GEOMAGNETICD_CONFIG_BACKUP_PATH "/data/system/yas529-backup.cfg" + +struct geomagneticd_data { + int magnetic_extrema[2][3]; + int hard_offsets[3]; + int calib_offsets[3]; + int accuracy; + + int input_fd; + char path_offsets[PATH_MAX]; + + int count; +}; + +/* + * Input + */ + +void input_event_set(struct input_event *event, int type, int code, int value); +long int timestamp(struct timeval *time); +long int input_timestamp(struct input_event *event); +int uinput_rel_create(const char *name); +void uinput_destroy(int uinput_fd); +int input_open(char *name); +int sysfs_path_prefix(char *name, char *path_prefix); +int sysfs_value_read(char *path); +int sysfs_value_write(char *path, int value); +int sysfs_string_read(char *path, char *buffer, size_t length); +int sysfs_string_write(char *path, char *buffer, size_t length); + +#endif diff --git a/sensors/geomagneticd/input.c b/sensors/geomagneticd/input.c new file mode 100644 index 0000000..7e9ca4a --- /dev/null +++ b/sensors/geomagneticd/input.c @@ -0,0 +1,335 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <unistd.h> +#include <stdint.h> +#include <fcntl.h> +#include <errno.h> +#include <dirent.h> +#include <linux/ioctl.h> +#include <linux/input.h> +#include <linux/uinput.h> + +#define LOG_TAG "geomagneticd" +#include <utils/Log.h> + +#include "geomagneticd.h" + +void input_event_set(struct input_event *event, int type, int code, int value) +{ + if (event == NULL) + return; + + memset(event, 0, sizeof(struct input_event)); + + event->type = type, + event->code = code; + event->value = value; + + gettimeofday(&event->time, NULL); +} + +long int timestamp(struct timeval *time) +{ + if (time == NULL) + return -1; + + return time->tv_sec * 1000000000LL + time->tv_usec * 1000; +} + +long int input_timestamp(struct input_event *event) +{ + if (event == NULL) + return -1; + + return timestamp(&event->time); +} + +int uinput_rel_create(const char *name) +{ + struct uinput_user_dev uinput_dev; + int uinput_fd; + int rc; + + if (name == NULL) + return -1; + + uinput_fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); + if (uinput_fd < 0) { + ALOGE("%s: Unable to open uinput device", __func__); + goto error; + } + + memset(&uinput_dev, 0, sizeof(uinput_dev)); + + strncpy(uinput_dev.name, name, sizeof(uinput_dev.name)); + uinput_dev.id.bustype = BUS_I2C; + uinput_dev.id.vendor = 0; + uinput_dev.id.product = 0; + uinput_dev.id.version = 0; + + rc = 0; + rc |= ioctl(uinput_fd, UI_SET_EVBIT, EV_REL); + rc |= ioctl(uinput_fd, UI_SET_RELBIT, REL_X); + rc |= ioctl(uinput_fd, UI_SET_RELBIT, REL_Y); + rc |= ioctl(uinput_fd, UI_SET_RELBIT, REL_Z); + rc |= ioctl(uinput_fd, UI_SET_EVBIT, EV_SYN); + + if (rc < 0) { + ALOGE("%s: Unable to set uinput bits", __func__); + goto error; + } + + rc = write(uinput_fd, &uinput_dev, sizeof(uinput_dev)); + if (rc < 0) { + ALOGE("%s: Unable to write uinput device", __func__); + goto error; + } + + rc = ioctl(uinput_fd, UI_DEV_CREATE); + if (rc < 0) { + ALOGE("%s: Unable to create uinput device", __func__); + goto error; + } + + usleep(3000); + + return uinput_fd; + +error: + if (uinput_fd >= 0) + close(uinput_fd); + + return -1; +} + +void uinput_destroy(int uinput_fd) +{ + if (uinput_fd < 0) + return; + + ioctl(uinput_fd, UI_DEV_DESTROY); +} + +int input_open(char *name) +{ + DIR *d; + struct dirent *di; + + char input_name[80] = { 0 }; + char path[PATH_MAX]; + char *c; + int fd; + int rc; + + if (name == NULL) + return -EINVAL; + + d = opendir("/dev/input"); + if (d == NULL) + return -1; + + while ((di = readdir(d))) { + if (di == NULL || strcmp(di->d_name, ".") == 0 || strcmp(di->d_name, "..") == 0) + continue; + + snprintf(path, PATH_MAX, "/dev/input/%s", di->d_name); + fd = open(path, O_RDWR | O_NONBLOCK); + if (fd < 0) + continue; + + rc = ioctl(fd, EVIOCGNAME(sizeof(input_name) - 1), &input_name); + if (rc < 0) + continue; + + c = strstr((char *) &input_name, "\n"); + if (c != NULL) + *c = '\0'; + + if (strcmp(input_name, name) == 0) + return fd; + else + close(fd); + } + + return -1; +} + +int sysfs_path_prefix(char *name, char *path_prefix) +{ + DIR *d; + struct dirent *di; + + char input_name[80] = { 0 }; + char path[PATH_MAX]; + char *c; + int fd; + + if (name == NULL || path_prefix == NULL) + return -EINVAL; + + d = opendir("/sys/class/input"); + if (d == NULL) + return -1; + + while ((di = readdir(d))) { + if (di == NULL || strcmp(di->d_name, ".") == 0 || strcmp(di->d_name, "..") == 0) + continue; + + snprintf(path, PATH_MAX, "/sys/class/input/%s/name", di->d_name); + + fd = open(path, O_RDONLY); + if (fd < 0) + continue; + + read(fd, &input_name, sizeof(input_name)); + close(fd); + + c = strstr((char *) &input_name, "\n"); + if (c != NULL) + *c = '\0'; + + if (strcmp(input_name, name) == 0) { + snprintf(path_prefix, PATH_MAX, "/sys/class/input/%s", di->d_name); + return 0; + } + } + + return -1; +} + +int sysfs_value_read(char *path) +{ + char buffer[100]; + int value; + int fd = -1; + int rc; + + if (path == NULL) + return -1; + + fd = open(path, O_RDONLY); + if (fd < 0) + goto error; + + rc = read(fd, &buffer, sizeof(buffer)); + if (rc <= 0) + goto error; + + value = atoi(buffer); + goto complete; + +error: + value = -1; + +complete: + if (fd >= 0) + close(fd); + + return value; +} + +int sysfs_value_write(char *path, int value) +{ + char buffer[100]; + int fd = -1; + int rc; + + if (path == NULL) + return -1; + + fd = open(path, O_WRONLY); + if (fd < 0) + goto error; + + snprintf((char *) &buffer, sizeof(buffer), "%d\n", value); + + rc = write(fd, buffer, strlen(buffer)); + if (rc < (int) strlen(buffer)) + goto error; + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (fd >= 0) + close(fd); + + return rc; +} + +int sysfs_string_read(char *path, char *buffer, size_t length) +{ + int fd = -1; + int rc; + + if (path == NULL || buffer == NULL || length == 0) + return -1; + + fd = open(path, O_RDONLY); + if (fd < 0) + goto error; + + rc = read(fd, buffer, length); + if (rc <= 0) + goto error; + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (fd >= 0) + close(fd); + + return rc; +} + +int sysfs_string_write(char *path, char *buffer, size_t length) +{ + int fd = -1; + int rc; + + if (path == NULL || buffer == NULL || length == 0) + return -1; + + fd = open(path, O_WRONLY); + if (fd < 0) + goto error; + + rc = write(fd, buffer, length); + if (rc <= 0) + goto error; + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (fd >= 0) + close(fd); + + return rc; +} diff --git a/sensors/gp2a_light.c b/sensors/gp2a_light.c new file mode 100644 index 0000000..a76d8e9 --- /dev/null +++ b/sensors/gp2a_light.c @@ -0,0 +1,239 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <unistd.h> +#include <stdint.h> +#include <fcntl.h> +#include <errno.h> +#include <math.h> +#include <sys/types.h> +#include <linux/ioctl.h> +#include <linux/input.h> + +#include <hardware/sensors.h> +#include <hardware/hardware.h> + +#define LOG_TAG "aries_sensors" +#include <utils/Log.h> + +#include "aries_sensors.h" + +struct gp2a_light_data { + char path_enable[PATH_MAX]; + char path_delay[PATH_MAX]; +}; + +int gp2a_light_init(struct aries_sensors_handlers *handlers, + struct aries_sensors_device *device) +{ + struct gp2a_light_data *data = NULL; + char path[PATH_MAX] = { 0 }; + int input_fd = -1; + int rc; + + ALOGD("%s(%p, %p)", __func__, handlers, device); + + if (handlers == NULL) + return -EINVAL; + + data = (struct gp2a_light_data *) calloc(1, sizeof(struct gp2a_light_data)); + + input_fd = input_open("lightsensor-level"); + if (input_fd < 0) { + ALOGE("%s: Unable to open input", __func__); + goto error; + } + + rc = sysfs_path_prefix("lightsensor-level", (char *) &path); + if (rc < 0 || path[0] == '\0') { + ALOGE("%s: Unable to open sysfs", __func__); + goto error; + } + + snprintf(data->path_enable, PATH_MAX, "%s/enable", path); + snprintf(data->path_delay, PATH_MAX, "%s/poll_delay", path); + + handlers->poll_fd = input_fd; + handlers->data = (void *) data; + + return 0; + +error: + if (data != NULL) + free(data); + + if (input_fd >= 0) + close(input_fd); + + handlers->poll_fd = -1; + handlers->data = NULL; + + return -1; +} + +int gp2a_light_deinit(struct aries_sensors_handlers *handlers) +{ + ALOGD("%s(%p)", __func__, handlers); + + if (handlers == NULL) + return -EINVAL; + + if (handlers->poll_fd >= 0) + close(handlers->poll_fd); + handlers->poll_fd = -1; + + if (handlers->data != NULL) + free(handlers->data); + handlers->data = NULL; + + return 0; +} + +int gp2a_light_activate(struct aries_sensors_handlers *handlers) +{ + struct gp2a_light_data *data; + int rc; + + ALOGD("%s(%p)", __func__, handlers); + + if (handlers == NULL || handlers->data == NULL) + return -EINVAL; + + data = (struct gp2a_light_data *) handlers->data; + + rc = sysfs_value_write(data->path_enable, 1); + if (rc < 0) { + ALOGE("%s: Unable to write sysfs value", __func__); + return -1; + } + + handlers->activated = 1; + + return 0; +} + +int gp2a_light_deactivate(struct aries_sensors_handlers *handlers) +{ + struct gp2a_light_data *data; + int rc; + + ALOGD("%s(%p)", __func__, handlers); + + if (handlers == NULL || handlers->data == NULL) + return -EINVAL; + + data = (struct gp2a_light_data *) handlers->data; + + rc = sysfs_value_write(data->path_enable, 0); + if (rc < 0) { + ALOGE("%s: Unable to write sysfs value", __func__); + return -1; + } + + handlers->activated = 1; + + return 0; +} + +int gp2a_light_set_delay(struct aries_sensors_handlers *handlers, long int delay) +{ + struct gp2a_light_data *data; + int rc; + + ALOGD("%s(%p, %ld)", __func__, handlers, delay); + + if (handlers == NULL || handlers->data == NULL) + return -EINVAL; + + data = (struct gp2a_light_data *) handlers->data; + + rc = sysfs_value_write(data->path_delay, (int) delay); + if (rc < 0) { + ALOGE("%s: Unable to write sysfs value", __func__); + return -1; + } + + return 0; +} + +float gp2a_light_convert(int value) +{ + // Converting the raw value to lux units is done with: + // I = 10 * log(light) uA + // U = raw * 3300 / 4095 (max ADC value is 3.3V for 4095 LSB) + // R = 47kOhm + // => light = 10 ^ (I / 10) = 10 ^ (U / R / 10) + // => light = 10 ^ (raw * 330 / 4095 / 47) + // Only 1/4 of light reaches the sensor: + // => light = 4 * (10 ^ (raw * 330 / 4095 / 47)) + + return powf(10, value * (330.0f / 4095.0f / 47.0f)) * 4; +} + +int gp2a_light_get_data(struct aries_sensors_handlers *handlers, + struct sensors_event_t *event) +{ + struct input_event input_event; + int input_fd; + int rc; + +// ALOGD("%s(%p, %p)", __func__, handlers, event); + + if (handlers == NULL || event == NULL) + return -EINVAL; + + input_fd = handlers->poll_fd; + if (input_fd < 0) + return -EINVAL; + + memset(event, 0, sizeof(struct sensors_event_t)); + event->version = sizeof(struct sensors_event_t); + event->sensor = handlers->handle; + event->type = handlers->handle; + + do { + rc = read(input_fd, &input_event, sizeof(input_event)); + if (rc < (int) sizeof(input_event)) + break; + + if (input_event.type == EV_ABS) { + if (input_event.code == ABS_MISC) + event->light = gp2a_light_convert(input_event.value); + } else if (input_event.type == EV_SYN) { + if (input_event.code == SYN_REPORT) + event->timestamp = input_timestamp(&input_event); + } + } while (input_event.type != EV_SYN); + + return 0; +} + +struct aries_sensors_handlers gp2a_light = { + .name = "GP2A Light", + .handle = SENSOR_TYPE_LIGHT, + .init = gp2a_light_init, + .deinit = gp2a_light_deinit, + .activate = gp2a_light_activate, + .deactivate = gp2a_light_deactivate, + .set_delay = gp2a_light_set_delay, + .get_data = gp2a_light_get_data, + .activated = 0, + .needed = 0, + .poll_fd = -1, + .data = NULL, +}; diff --git a/sensors/gp2a_proximity.c b/sensors/gp2a_proximity.c new file mode 100644 index 0000000..3122891 --- /dev/null +++ b/sensors/gp2a_proximity.c @@ -0,0 +1,213 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <unistd.h> +#include <stdint.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/types.h> +#include <linux/ioctl.h> +#include <linux/input.h> + +#include <hardware/sensors.h> +#include <hardware/hardware.h> + +#define LOG_TAG "aries_sensors" +#include <utils/Log.h> + +#include "aries_sensors.h" + +struct gp2a_proximity_data { + char path_enable[PATH_MAX]; +}; + +int gp2a_proximity_init(struct aries_sensors_handlers *handlers, + struct aries_sensors_device *device) +{ + struct gp2a_proximity_data *data = NULL; + char path[PATH_MAX] = { 0 }; + int input_fd = -1; + int rc; + + ALOGD("%s(%p, %p)", __func__, handlers, device); + + if (handlers == NULL) + return -EINVAL; + + data = (struct gp2a_proximity_data *) calloc(1, sizeof(struct gp2a_proximity_data)); + + input_fd = input_open("proximity"); + if (input_fd < 0) { + ALOGE("%s: Unable to open input", __func__); + goto error; + } + + rc = sysfs_path_prefix("proximity", (char *) &path); + if (rc < 0 || path[0] == '\0') { + ALOGE("%s: Unable to open sysfs", __func__); + goto error; + } + + snprintf(data->path_enable, PATH_MAX, "%s/enable", path); + + handlers->poll_fd = input_fd; + handlers->data = (void *) data; + + return 0; + +error: + if (data != NULL) + free(data); + + if (input_fd >= 0) + close(input_fd); + + handlers->poll_fd = -1; + handlers->data = NULL; + + return -1; +} + +int gp2a_proximity_deinit(struct aries_sensors_handlers *handlers) +{ + ALOGD("%s(%p)", __func__, handlers); + + if (handlers == NULL) + return -EINVAL; + + if (handlers->poll_fd >= 0) + close(handlers->poll_fd); + handlers->poll_fd = -1; + + if (handlers->data != NULL) + free(handlers->data); + handlers->data = NULL; + + return 0; +} + +int gp2a_proximity_activate(struct aries_sensors_handlers *handlers) +{ + struct gp2a_proximity_data *data; + int rc; + + ALOGD("%s(%p)", __func__, handlers); + + if (handlers == NULL || handlers->data == NULL) + return -EINVAL; + + data = (struct gp2a_proximity_data *) handlers->data; + + rc = sysfs_value_write(data->path_enable, 1); + if (rc < 0) { + ALOGE("%s: Unable to write sysfs value", __func__); + return -1; + } + + handlers->activated = 1; + + return 0; +} + +int gp2a_proximity_deactivate(struct aries_sensors_handlers *handlers) +{ + struct gp2a_proximity_data *data; + int rc; + + ALOGD("%s(%p)", __func__, handlers); + + if (handlers == NULL || handlers->data == NULL) + return -EINVAL; + + data = (struct gp2a_proximity_data *) handlers->data; + + rc = sysfs_value_write(data->path_enable, 0); + if (rc < 0) { + ALOGE("%s: Unable to write sysfs value", __func__); + return -1; + } + + handlers->activated = 1; + + return 0; +} + +int gp2a_proximity_set_delay(struct aries_sensors_handlers *handlers, long int delay) +{ + ALOGD("%s(%p, %ld)", __func__, handlers, delay); + + return 0; +} + +float gp2a_proximity_convert(int value) +{ + return (float) value * 5.0f; +} + +int gp2a_proximity_get_data(struct aries_sensors_handlers *handlers, + struct sensors_event_t *event) +{ + struct input_event input_event; + int input_fd; + int rc; + +// ALOGD("%s(%p, %p)", __func__, handlers, event); + + if (handlers == NULL || event == NULL) + return -EINVAL; + + input_fd = handlers->poll_fd; + if (input_fd < 0) + return -EINVAL; + + memset(event, 0, sizeof(struct sensors_event_t)); + event->version = sizeof(struct sensors_event_t); + event->sensor = handlers->handle; + event->type = handlers->handle; + + do { + rc = read(input_fd, &input_event, sizeof(input_event)); + if (rc < (int) sizeof(input_event)) + break; + + if (input_event.type == EV_ABS) { + if (input_event.code == ABS_DISTANCE) + event->distance = gp2a_proximity_convert(input_event.value); + } else if (input_event.type == EV_SYN) { + if (input_event.code == SYN_REPORT) + event->timestamp = input_timestamp(&input_event); + } + } while (input_event.type != EV_SYN); + + return 0; +} + +struct aries_sensors_handlers gp2a_proximity = { + .name = "GP2A Proximity", + .handle = SENSOR_TYPE_PROXIMITY, + .init = gp2a_proximity_init, + .deinit = gp2a_proximity_deinit, + .activate = gp2a_proximity_activate, + .deactivate = gp2a_proximity_deactivate, + .set_delay = gp2a_proximity_set_delay, + .get_data = gp2a_proximity_get_data, + .activated = 0, + .needed = 0, + .poll_fd = -1, + .data = NULL, +}; diff --git a/sensors/input.c b/sensors/input.c new file mode 100644 index 0000000..db28d7f --- /dev/null +++ b/sensors/input.c @@ -0,0 +1,335 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <unistd.h> +#include <stdint.h> +#include <fcntl.h> +#include <errno.h> +#include <dirent.h> +#include <linux/ioctl.h> +#include <linux/input.h> +#include <linux/uinput.h> + +#define LOG_TAG "aries_sensors" +#include <utils/Log.h> + +#include "aries_sensors.h" + +void input_event_set(struct input_event *event, int type, int code, int value) +{ + if (event == NULL) + return; + + memset(event, 0, sizeof(struct input_event)); + + event->type = type, + event->code = code; + event->value = value; + + gettimeofday(&event->time, NULL); +} + +long int timestamp(struct timeval *time) +{ + if (time == NULL) + return -1; + + return time->tv_sec * 1000000000LL + time->tv_usec * 1000; +} + +long int input_timestamp(struct input_event *event) +{ + if (event == NULL) + return -1; + + return timestamp(&event->time); +} + +int uinput_rel_create(const char *name) +{ + struct uinput_user_dev uinput_dev; + int uinput_fd; + int rc; + + if (name == NULL) + return -1; + + uinput_fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); + if (uinput_fd < 0) { + ALOGE("%s: Unable to open uinput device", __func__); + goto error; + } + + memset(&uinput_dev, 0, sizeof(uinput_dev)); + + strncpy(uinput_dev.name, name, sizeof(uinput_dev.name)); + uinput_dev.id.bustype = BUS_I2C; + uinput_dev.id.vendor = 0; + uinput_dev.id.product = 0; + uinput_dev.id.version = 0; + + rc = 0; + rc |= ioctl(uinput_fd, UI_SET_EVBIT, EV_REL); + rc |= ioctl(uinput_fd, UI_SET_RELBIT, REL_X); + rc |= ioctl(uinput_fd, UI_SET_RELBIT, REL_Y); + rc |= ioctl(uinput_fd, UI_SET_RELBIT, REL_Z); + rc |= ioctl(uinput_fd, UI_SET_EVBIT, EV_SYN); + + if (rc < 0) { + ALOGE("%s: Unable to set uinput bits", __func__); + goto error; + } + + rc = write(uinput_fd, &uinput_dev, sizeof(uinput_dev)); + if (rc < 0) { + ALOGE("%s: Unable to write uinput device", __func__); + goto error; + } + + rc = ioctl(uinput_fd, UI_DEV_CREATE); + if (rc < 0) { + ALOGE("%s: Unable to create uinput device", __func__); + goto error; + } + + usleep(3000); + + return uinput_fd; + +error: + if (uinput_fd >= 0) + close(uinput_fd); + + return -1; +} + +void uinput_destroy(int uinput_fd) +{ + if (uinput_fd < 0) + return; + + ioctl(uinput_fd, UI_DEV_DESTROY); +} + +int input_open(char *name) +{ + DIR *d; + struct dirent *di; + + char input_name[80] = { 0 }; + char path[PATH_MAX]; + char *c; + int fd; + int rc; + + if (name == NULL) + return -EINVAL; + + d = opendir("/dev/input"); + if (d == NULL) + return -1; + + while ((di = readdir(d))) { + if (di == NULL || strcmp(di->d_name, ".") == 0 || strcmp(di->d_name, "..") == 0) + continue; + + snprintf(path, PATH_MAX, "/dev/input/%s", di->d_name); + fd = open(path, O_RDONLY | O_NONBLOCK); + if (fd < 0) + continue; + + rc = ioctl(fd, EVIOCGNAME(sizeof(input_name) - 1), &input_name); + if (rc < 0) + continue; + + c = strstr((char *) &input_name, "\n"); + if (c != NULL) + *c = '\0'; + + if (strcmp(input_name, name) == 0) + return fd; + else + close(fd); + } + + return -1; +} + +int sysfs_path_prefix(char *name, char *path_prefix) +{ + DIR *d; + struct dirent *di; + + char input_name[80] = { 0 }; + char path[PATH_MAX]; + char *c; + int fd; + + if (name == NULL || path_prefix == NULL) + return -EINVAL; + + d = opendir("/sys/class/input"); + if (d == NULL) + return -1; + + while ((di = readdir(d))) { + if (di == NULL || strcmp(di->d_name, ".") == 0 || strcmp(di->d_name, "..") == 0) + continue; + + snprintf(path, PATH_MAX, "/sys/class/input/%s/name", di->d_name); + + fd = open(path, O_RDONLY); + if (fd < 0) + continue; + + read(fd, &input_name, sizeof(input_name)); + close(fd); + + c = strstr((char *) &input_name, "\n"); + if (c != NULL) + *c = '\0'; + + if (strcmp(input_name, name) == 0) { + snprintf(path_prefix, PATH_MAX, "/sys/class/input/%s", di->d_name); + return 0; + } + } + + return -1; +} + +int sysfs_value_read(char *path) +{ + char buffer[100]; + int value; + int fd = -1; + int rc; + + if (path == NULL) + return -1; + + fd = open(path, O_RDONLY); + if (fd < 0) + goto error; + + rc = read(fd, &buffer, sizeof(buffer)); + if (rc <= 0) + goto error; + + value = atoi(buffer); + goto complete; + +error: + value = -1; + +complete: + if (fd >= 0) + close(fd); + + return value; +} + +int sysfs_value_write(char *path, int value) +{ + char buffer[100]; + int fd = -1; + int rc; + + if (path == NULL) + return -1; + + fd = open(path, O_WRONLY); + if (fd < 0) + goto error; + + snprintf((char *) &buffer, sizeof(buffer), "%d\n", value); + + rc = write(fd, buffer, strlen(buffer)); + if (rc < (int) strlen(buffer)) + goto error; + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (fd >= 0) + close(fd); + + return rc; +} + +int sysfs_string_read(char *path, char *buffer, size_t length) +{ + int fd = -1; + int rc; + + if (path == NULL || buffer == NULL || length == 0) + return -1; + + fd = open(path, O_RDONLY); + if (fd < 0) + goto error; + + rc = read(fd, buffer, length); + if (rc <= 0) + goto error; + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (fd >= 0) + close(fd); + + return rc; +} + +int sysfs_string_write(char *path, char *buffer, size_t length) +{ + int fd = -1; + int rc; + + if (path == NULL || buffer == NULL || length == 0) + return -1; + + fd = open(path, O_WRONLY); + if (fd < 0) + goto error; + + rc = write(fd, buffer, length); + if (rc <= 0) + goto error; + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (fd >= 0) + close(fd); + + return rc; +} diff --git a/sensors/orientationd/input.c b/sensors/orientationd/input.c new file mode 100644 index 0000000..1afa2b8 --- /dev/null +++ b/sensors/orientationd/input.c @@ -0,0 +1,335 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <unistd.h> +#include <stdint.h> +#include <fcntl.h> +#include <errno.h> +#include <dirent.h> +#include <linux/ioctl.h> +#include <linux/input.h> +#include <linux/uinput.h> + +#define LOG_TAG "orientationd" +#include <utils/Log.h> + +#include "orientationd.h" + +void input_event_set(struct input_event *event, int type, int code, int value) +{ + if (event == NULL) + return; + + memset(event, 0, sizeof(struct input_event)); + + event->type = type, + event->code = code; + event->value = value; + + gettimeofday(&event->time, NULL); +} + +long int timestamp(struct timeval *time) +{ + if (time == NULL) + return -1; + + return time->tv_sec * 1000000000LL + time->tv_usec * 1000; +} + +long int input_timestamp(struct input_event *event) +{ + if (event == NULL) + return -1; + + return timestamp(&event->time); +} + +int uinput_rel_create(const char *name) +{ + struct uinput_user_dev uinput_dev; + int uinput_fd; + int rc; + + if (name == NULL) + return -1; + + uinput_fd = open("/dev/uinput", O_WRONLY | O_NONBLOCK); + if (uinput_fd < 0) { + ALOGE("%s: Unable to open uinput device", __func__); + goto error; + } + + memset(&uinput_dev, 0, sizeof(uinput_dev)); + + strncpy(uinput_dev.name, name, sizeof(uinput_dev.name)); + uinput_dev.id.bustype = BUS_I2C; + uinput_dev.id.vendor = 0; + uinput_dev.id.product = 0; + uinput_dev.id.version = 0; + + rc = 0; + rc |= ioctl(uinput_fd, UI_SET_EVBIT, EV_REL); + rc |= ioctl(uinput_fd, UI_SET_RELBIT, REL_X); + rc |= ioctl(uinput_fd, UI_SET_RELBIT, REL_Y); + rc |= ioctl(uinput_fd, UI_SET_RELBIT, REL_Z); + rc |= ioctl(uinput_fd, UI_SET_EVBIT, EV_SYN); + + if (rc < 0) { + ALOGE("%s: Unable to set uinput bits", __func__); + goto error; + } + + rc = write(uinput_fd, &uinput_dev, sizeof(uinput_dev)); + if (rc < 0) { + ALOGE("%s: Unable to write uinput device", __func__); + goto error; + } + + rc = ioctl(uinput_fd, UI_DEV_CREATE); + if (rc < 0) { + ALOGE("%s: Unable to create uinput device", __func__); + goto error; + } + + usleep(3000); + + return uinput_fd; + +error: + if (uinput_fd >= 0) + close(uinput_fd); + + return -1; +} + +void uinput_destroy(int uinput_fd) +{ + if (uinput_fd < 0) + return; + + ioctl(uinput_fd, UI_DEV_DESTROY); +} + +int input_open(char *name) +{ + DIR *d; + struct dirent *di; + + char input_name[80] = { 0 }; + char path[PATH_MAX]; + char *c; + int fd; + int rc; + + if (name == NULL) + return -EINVAL; + + d = opendir("/dev/input"); + if (d == NULL) + return -1; + + while ((di = readdir(d))) { + if (di == NULL || strcmp(di->d_name, ".") == 0 || strcmp(di->d_name, "..") == 0) + continue; + + snprintf(path, PATH_MAX, "/dev/input/%s", di->d_name); + fd = open(path, O_RDWR | O_NONBLOCK); + if (fd < 0) + continue; + + rc = ioctl(fd, EVIOCGNAME(sizeof(input_name) - 1), &input_name); + if (rc < 0) + continue; + + c = strstr((char *) &input_name, "\n"); + if (c != NULL) + *c = '\0'; + + if (strcmp(input_name, name) == 0) + return fd; + else + close(fd); + } + + return -1; +} + +int sysfs_path_prefix(char *name, char *path_prefix) +{ + DIR *d; + struct dirent *di; + + char input_name[80] = { 0 }; + char path[PATH_MAX]; + char *c; + int fd; + + if (name == NULL || path_prefix == NULL) + return -EINVAL; + + d = opendir("/sys/class/input"); + if (d == NULL) + return -1; + + while ((di = readdir(d))) { + if (di == NULL || strcmp(di->d_name, ".") == 0 || strcmp(di->d_name, "..") == 0) + continue; + + snprintf(path, PATH_MAX, "/sys/class/input/%s/name", di->d_name); + + fd = open(path, O_RDONLY); + if (fd < 0) + continue; + + read(fd, &input_name, sizeof(input_name)); + close(fd); + + c = strstr((char *) &input_name, "\n"); + if (c != NULL) + *c = '\0'; + + if (strcmp(input_name, name) == 0) { + snprintf(path_prefix, PATH_MAX, "/sys/class/input/%s", di->d_name); + return 0; + } + } + + return -1; +} + +int sysfs_value_read(char *path) +{ + char buffer[100]; + int value; + int fd = -1; + int rc; + + if (path == NULL) + return -1; + + fd = open(path, O_RDONLY); + if (fd < 0) + goto error; + + rc = read(fd, &buffer, sizeof(buffer)); + if (rc <= 0) + goto error; + + value = atoi(buffer); + goto complete; + +error: + value = -1; + +complete: + if (fd >= 0) + close(fd); + + return value; +} + +int sysfs_value_write(char *path, int value) +{ + char buffer[100]; + int fd = -1; + int rc; + + if (path == NULL) + return -1; + + fd = open(path, O_WRONLY); + if (fd < 0) + goto error; + + snprintf((char *) &buffer, sizeof(buffer), "%d\n", value); + + rc = write(fd, buffer, strlen(buffer)); + if (rc < (int) strlen(buffer)) + goto error; + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (fd >= 0) + close(fd); + + return rc; +} + +int sysfs_string_read(char *path, char *buffer, size_t length) +{ + int fd = -1; + int rc; + + if (path == NULL || buffer == NULL || length == 0) + return -1; + + fd = open(path, O_RDONLY); + if (fd < 0) + goto error; + + rc = read(fd, buffer, length); + if (rc <= 0) + goto error; + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (fd >= 0) + close(fd); + + return rc; +} + +int sysfs_string_write(char *path, char *buffer, size_t length) +{ + int fd = -1; + int rc; + + if (path == NULL || buffer == NULL || length == 0) + return -1; + + fd = open(path, O_WRONLY); + if (fd < 0) + goto error; + + rc = write(fd, buffer, length); + if (rc <= 0) + goto error; + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (fd >= 0) + close(fd); + + return rc; +} diff --git a/sensors/orientationd/orientationd.c b/sensors/orientationd/orientationd.c new file mode 100644 index 0000000..e63e7c2 --- /dev/null +++ b/sensors/orientationd/orientationd.c @@ -0,0 +1,327 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#include <errno.h> +#include <poll.h> +#include <math.h> +#include <linux/input.h> + +#include <hardware/sensors.h> +#include <hardware/hardware.h> + +#define LOG_TAG "orientationd" +#include <utils/Log.h> + +#include "orientationd.h" + +struct orientationd_handlers *orientationd_handlers[] = { + &smb380, + &yas529, +}; + +int orientationd_handlers_count = sizeof(orientationd_handlers) / + sizeof(struct orientationd_handlers *); + +static float rad2deg(float v) +{ + return (v * 180.0f / 3.1415926535f); +} + +static float vector_scalar(sensors_vec_t *v, sensors_vec_t *d) +{ + return v->x * d->x + v->y * d->y + v->z * d->z; +} + +static float vector_length(sensors_vec_t *v) +{ + return sqrtf(vector_scalar(v, v)); +} + +int orientation_calculate(struct orientationd_data *data) +{ + sensors_vec_t *a, *m, *o; + float azimuth, pitch, roll; + float la, sinp, cosp, sinr, cosr, x, y; + + if (data == NULL) + return -EINVAL; + + a = &data->acceleration; + m = &data->magnetic; + o = &data->orientation; + + la = vector_length(a); + pitch = asinf(-(a->y) / la); + roll = asinf((a->x) / la); + + sinp = sinf(pitch); + cosp = cosf(pitch); + sinr = sinf(roll); + cosr = cosf(roll); + + y = -(m->x) * cosr + m->z * sinr; + x = m->x * sinp * sinr + m->y * cosp + m->z * sinp * cosr; + azimuth = atan2f(y, x); + + o->azimuth = rad2deg(azimuth); + o->pitch = rad2deg(pitch); + o->roll = rad2deg(roll); + + if (o->azimuth < 0) + o->azimuth += 360.0f; + + return 0; +} + +void *orientationd_thread(void *thread_data) +{ + struct orientationd_data *data; + struct input_event event; + struct timeval time; + long int before, after; + int diff; + int input_fd; + int rc; + + if (thread_data == NULL) + return NULL; + + data = (struct orientationd_data *) thread_data; + + input_fd = data->input_fd; + if (input_fd < 0) + return NULL; + + while (data->thread_continue) { + pthread_mutex_lock(&data->mutex); + if (!data->thread_continue) + break; + + while (data->activated) { + gettimeofday(&time, NULL); + before = timestamp(&time); + + rc = orientation_calculate(data); + if (rc < 0) { + ALOGE("%s: Unable to calculate orientation", __func__); + goto next; + } + + input_event_set(&event, EV_REL, REL_X, (int) (data->orientation.azimuth * 1000)); + write(input_fd, &event, sizeof(event)); + input_event_set(&event, EV_REL, REL_Y, (int) (data->orientation.pitch * 1000)); + write(input_fd, &event, sizeof(event)); + input_event_set(&event, EV_REL, REL_Z, (int) (data->orientation.roll * 1000)); + write(input_fd, &event, sizeof(event)); + input_event_set(&event, EV_SYN, 0, 0); + write(input_fd, &event, sizeof(event)); + +next: + gettimeofday(&time, NULL); + after = timestamp(&time); + + diff = (int) (data->delay * 1000000 - (after - before)) / 1000; + if (diff <= 0) + continue; + + usleep(diff); + } + } + return NULL; +} + +int orientation_get_data(struct orientationd_data *data) +{ + struct input_event input_event; + int input_fd; + int activated; + unsigned int delay; + int rc; + + if (data == NULL) + return -EINVAL; + + input_fd = data->input_fd; + if (input_fd < 0) + return -1; + + do { + rc = read(input_fd, &input_event, sizeof(input_event)); + if (rc < (int) sizeof(input_event)) + break; + + if (input_event.type == EV_REL) { + switch (input_event.code) { + case REL_RZ: + data->activated = input_event.value & (1 << 16) ? 1 : 0; + data->delay = input_event.value & ~(1 << 16); + + pthread_mutex_unlock(&data->mutex); + break; + default: + continue; + } + } + } while (input_event.type != EV_SYN); + + return 0; +} + +int orientationd_poll(struct orientationd_data *data) +{ + int count; + int i, j; + int rc; + + if (data == NULL) + return -EINVAL; + + ALOGD("Starting orientationd poll"); + + while (1) { + if (data->activated) + count = data->poll_fds_count; + else + count = 1; + + rc = poll(data->poll_fds, count, -1); + if (rc < 0) { + ALOGE("%s: poll failure", __func__); + goto error; + } + + for (i = 0; i < count; i++) { + if (data->poll_fds[i].revents & POLLIN) { + data->poll_fds[i].revents = 0; + + if (data->poll_fds[i].fd == data->input_fd) { + orientation_get_data(data); + continue; + } + + for (j = 0; j < data->handlers_count; j++) + if (data->handlers[j] != NULL && data->handlers[j]->poll_fd == data->poll_fds[i].fd && data->handlers[j]->get_data != NULL) + data->handlers[j]->get_data(data->handlers[j], data); + } + } + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + return rc; +} + +int main(int argc, char *argv[]) +{ + struct orientationd_data *orientationd_data = NULL; + pthread_attr_t thread_attr; + int input_fd = -1; + int poll_fd; + int p, i; + int rc; + + orientationd_data = (struct orientationd_data *) + calloc(1, sizeof(struct orientationd_data)); + orientationd_data->handlers = orientationd_handlers; + orientationd_data->handlers_count = orientationd_handlers_count; + orientationd_data->activated = 0; + orientationd_data->poll_fds = (struct pollfd *) + calloc(1, (orientationd_handlers_count + 1) * sizeof(struct pollfd)); + + p = 0; + + input_fd = input_open("orientation_sensor"); + if (input_fd < 0) { + ALOGE("%s: Unable to open input", __func__); + goto error; + } + + orientationd_data->input_fd = input_fd; + + orientationd_data->poll_fds[p].fd = input_fd; + orientationd_data->poll_fds[p].events = POLLIN; + p++; + + for (i = 0; i < orientationd_handlers_count; i++) { + if (orientationd_handlers[i] == NULL || orientationd_handlers[i]->input_name == NULL) + continue; + + poll_fd = input_open(orientationd_handlers[i]->input_name); + if (poll_fd < 0) { + ALOGE("%s: Unable to open input %s", __func__, orientationd_handlers[i]->input_name); + continue; + } + + orientationd_handlers[i]->poll_fd = poll_fd; + orientationd_data->poll_fds[p].fd = poll_fd; + orientationd_data->poll_fds[p].events = POLLIN; + p++; + } + + orientationd_data->poll_fds_count = p; + + orientationd_data->thread_continue = 1; + + pthread_mutex_init(&orientationd_data->mutex, NULL); + pthread_mutex_lock(&orientationd_data->mutex); + + pthread_attr_init(&thread_attr); + pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED); + + rc = pthread_create(&orientationd_data->thread, &thread_attr, orientationd_thread, (void *) orientationd_data); + if (rc < 0) { + ALOGE("%s: Unable to create orientationd thread", __func__); + goto error; + } + + rc = orientationd_poll(orientationd_data); + if (rc < 0) + goto error; + + rc = 0; + goto complete; + +error: + while (1) + sleep(3600); + + rc = 1; + +complete: + if (input_fd >= 0) + close(input_fd); + + if (orientationd_data != NULL) { + orientationd_data->thread_continue = 0; + pthread_mutex_destroy(&orientationd_data->mutex); + + if (orientationd_data->poll_fds != NULL) + free(orientationd_data->poll_fds); + + free(orientationd_data); + } + + return rc; +} diff --git a/sensors/orientationd/orientationd.h b/sensors/orientationd/orientationd.h new file mode 100644 index 0000000..887e698 --- /dev/null +++ b/sensors/orientationd/orientationd.h @@ -0,0 +1,86 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdint.h> +#include <poll.h> +#include <linux/input.h> + +#include <hardware/sensors.h> +#include <hardware/hardware.h> + +#ifndef _ORIENTATIOND_H_ +#define _ORIENTATIOND_H_ + +struct orientationd_data; + +struct orientationd_handlers { + char *input_name; + int handle; + int poll_fd; + + int (*get_data)(struct orientationd_handlers *handlers, + struct orientationd_data *data); +}; + +struct orientationd_data { + struct orientationd_handlers **handlers; + int handlers_count; + + struct pollfd *poll_fds; + int poll_fds_count; + + sensors_vec_t orientation; + sensors_vec_t acceleration; + sensors_vec_t magnetic; + + unsigned int delay; + int input_fd; + + int activated; + + pthread_t thread; + pthread_mutex_t mutex; + int thread_continue; +}; + +extern struct orientationd_handlers *orientationd_handlers[]; +extern int orientationd_handlers_count; + +/* + * Input + */ + +void input_event_set(struct input_event *event, int type, int code, int value); +long int timestamp(struct timeval *time); +long int input_timestamp(struct input_event *event); +int uinput_rel_create(const char *name); +void uinput_destroy(int uinput_fd); +int input_open(char *name); +int sysfs_path_prefix(char *name, char *path_prefix); +int sysfs_value_read(char *path); +int sysfs_value_write(char *path, int value); +int sysfs_string_read(char *path, char *buffer, size_t length); +int sysfs_string_write(char *path, char *buffer, size_t length); + +/* + * Sensors + */ + +extern struct orientationd_handlers smb380; +extern struct orientationd_handlers yas529; + +#endif diff --git a/sensors/orientationd/smb380.c b/sensors/orientationd/smb380.c new file mode 100644 index 0000000..4566d94 --- /dev/null +++ b/sensors/orientationd/smb380.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <unistd.h> +#include <stdint.h> +#include <fcntl.h> +#include <errno.h> +#include <math.h> +#include <sys/types.h> +#include <linux/ioctl.h> +#include <linux/input.h> + +#include <hardware/sensors.h> +#include <hardware/hardware.h> + +#define LOG_TAG "orientationd" +#include <utils/Log.h> + +#include "orientationd.h" + +float smb380_convert(int value) +{ + return value * (GRAVITY_EARTH / 256.0f); +} + +int smb380_get_data(struct orientationd_handlers *handlers, + struct orientationd_data *data) +{ + struct input_event input_event; + int input_fd; + int rc; + + if (handlers == NULL || data == NULL) + return -EINVAL; + + input_fd = handlers->poll_fd; + if (input_fd < 0) + return -1; + + do { + rc = read(input_fd, &input_event, sizeof(input_event)); + if (rc < (int) sizeof(input_event)) + break; + + if (input_event.type == EV_REL) { + switch (input_event.code) { + case REL_X: + data->acceleration.x = smb380_convert(input_event.value); + break; + case REL_Y: + data->acceleration.y = smb380_convert(input_event.value); + break; + case REL_Z: + data->acceleration.z = smb380_convert(input_event.value); + break; + default: + continue; + } + } + } while (input_event.type != EV_SYN); + + return 0; +} + +struct orientationd_handlers smb380 = { + .input_name = "accelerometer_sensor", + .handle = SENSOR_TYPE_ACCELEROMETER, + .poll_fd = -1, + .get_data = smb380_get_data, +}; diff --git a/sensors/orientationd/yas529.c b/sensors/orientationd/yas529.c new file mode 100644 index 0000000..50b304d --- /dev/null +++ b/sensors/orientationd/yas529.c @@ -0,0 +1,85 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <unistd.h> +#include <stdint.h> +#include <fcntl.h> +#include <errno.h> +#include <math.h> +#include <sys/types.h> +#include <linux/ioctl.h> +#include <linux/input.h> + +#include <hardware/sensors.h> +#include <hardware/hardware.h> + +#define LOG_TAG "orientationd" +#include <utils/Log.h> + +#include "orientationd.h" + +float yas529_convert(int value) +{ + return value / 1000.0f; +} + +int yas529_get_data(struct orientationd_handlers *handlers, + struct orientationd_data *data) +{ + struct input_event input_event; + int input_fd; + int rc; + + if (handlers == NULL || data == NULL) + return -EINVAL; + + input_fd = handlers->poll_fd; + if (input_fd < 0) + return -1; + + do { + rc = read(input_fd, &input_event, sizeof(input_event)); + if (rc < (int) sizeof(input_event)) + break; + + if (input_event.type == EV_REL) { + switch (input_event.code) { + case REL_X: + data->magnetic.x = yas529_convert(input_event.value); + break; + case REL_Y: + data->magnetic.y = yas529_convert(input_event.value); + break; + case REL_Z: + data->magnetic.z = yas529_convert(input_event.value); + break; + default: + continue; + } + } + } while (input_event.type != EV_SYN); + + return 0; +} + +struct orientationd_handlers yas529 = { + .input_name = "magnetic_sensor", + .handle = SENSOR_TYPE_MAGNETIC_FIELD, + .poll_fd = -1, + .get_data = yas529_get_data, +}; diff --git a/sensors/smb380.c b/sensors/smb380.c new file mode 100644 index 0000000..57d8837 --- /dev/null +++ b/sensors/smb380.c @@ -0,0 +1,260 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <unistd.h> +#include <stdint.h> +#include <fcntl.h> +#include <errno.h> +#include <math.h> +#include <sys/types.h> +#include <linux/ioctl.h> +#include <linux/input.h> + +#include <hardware/sensors.h> +#include <hardware/hardware.h> + +#define LOG_TAG "aries_sensors" +#include <utils/Log.h> + +#include "aries_sensors.h" + +struct smb380_data { + char path_enable[PATH_MAX]; + char path_delay[PATH_MAX]; + + sensors_vec_t acceleration; +}; + +int smb380_init(struct aries_sensors_handlers *handlers, + struct aries_sensors_device *device) +{ + struct smb380_data *data = NULL; + char path[PATH_MAX] = { 0 }; + int input_fd = -1; + int rc; + + ALOGD("%s(%p, %p)", __func__, handlers, device); + + if (handlers == NULL) + return -EINVAL; + + data = (struct smb380_data *) calloc(1, sizeof(struct smb380_data)); + + input_fd = input_open("accelerometer_sensor"); + if (input_fd < 0) { + ALOGE("%s: Unable to open input", __func__); + goto error; + } + + rc = sysfs_path_prefix("accelerometer_sensor", (char *) &path); + if (rc < 0 || path[0] == '\0') { + ALOGE("%s: Unable to open sysfs", __func__); + goto error; + } + + snprintf(data->path_enable, PATH_MAX, "%s/enable", path); + snprintf(data->path_delay, PATH_MAX, "%s/delay", path); + + handlers->poll_fd = input_fd; + handlers->data = (void *) data; + + return 0; + +error: + if (data != NULL) + free(data); + + if (input_fd >= 0) + close(input_fd); + + handlers->poll_fd = -1; + handlers->data = NULL; + + return -1; +} + +int smb380_deinit(struct aries_sensors_handlers *handlers) +{ + ALOGD("%s(%p)", __func__, handlers); + + if (handlers == NULL) + return -EINVAL; + + if (handlers->poll_fd >= 0) + close(handlers->poll_fd); + handlers->poll_fd = -1; + + if (handlers->data != NULL) + free(handlers->data); + handlers->data = NULL; + + return 0; +} + +int smb380_activate(struct aries_sensors_handlers *handlers) +{ + struct smb380_data *data; + int rc; + + ALOGD("%s(%p)", __func__, handlers); + + if (handlers == NULL || handlers->data == NULL) + return -EINVAL; + + data = (struct smb380_data *) handlers->data; + + rc = sysfs_value_write(data->path_enable, 1); + if (rc < 0) { + ALOGE("%s: Unable to write sysfs value", __func__); + return -1; + } + + handlers->activated = 1; + + return 0; +} + +int smb380_deactivate(struct aries_sensors_handlers *handlers) +{ + struct smb380_data *data; + int rc; + + ALOGD("%s(%p)", __func__, handlers); + + if (handlers == NULL || handlers->data == NULL) + return -EINVAL; + + data = (struct smb380_data *) handlers->data; + + rc = sysfs_value_write(data->path_enable, 0); + if (rc < 0) { + ALOGE("%s: Unable to write sysfs value", __func__); + return -1; + } + + handlers->activated = 1; + + return 0; +} + +int smb380_set_delay(struct aries_sensors_handlers *handlers, long int delay) +{ + struct smb380_data *data; + int d; + int rc; + + ALOGD("%s(%p, %ld)", __func__, handlers, delay); + + if (handlers == NULL || handlers->data == NULL) + return -EINVAL; + + data = (struct smb380_data *) handlers->data; + + if (delay < 10000000) + d = 10; + else + d = delay / 1000000; + + rc = sysfs_value_write(data->path_delay, d); + if (rc < 0) { + ALOGE("%s: Unable to write sysfs value", __func__); + return -1; + } + + return 0; +} + +float smb380_convert(int value) +{ + return value * (GRAVITY_EARTH / 256.0f); +} + +int smb380_get_data(struct aries_sensors_handlers *handlers, + struct sensors_event_t *event) +{ + struct smb380_data *data; + struct input_event input_event; + int input_fd; + int rc; + +// ALOGD("%s(%p, %p)", __func__, handlers, event); + + if (handlers == NULL || handlers->data == NULL || event == NULL) + return -EINVAL; + + data = (struct smb380_data *) handlers->data; + + input_fd = handlers->poll_fd; + if (input_fd < 0) + return -EINVAL; + + memset(event, 0, sizeof(struct sensors_event_t)); + event->version = sizeof(struct sensors_event_t); + event->sensor = handlers->handle; + event->type = handlers->handle; + + event->acceleration.x = data->acceleration.x; + event->acceleration.y = data->acceleration.y; + event->acceleration.z = data->acceleration.z; + + do { + rc = read(input_fd, &input_event, sizeof(input_event)); + if (rc < (int) sizeof(input_event)) + break; + + if (input_event.type == EV_REL) { + switch (input_event.code) { + case REL_X: + event->acceleration.x = smb380_convert(input_event.value); + break; + case REL_Y: + event->acceleration.y = smb380_convert(input_event.value); + break; + case REL_Z: + event->acceleration.z = smb380_convert(input_event.value); + break; + default: + continue; + } + } else if (input_event.type == EV_SYN) { + if (input_event.code == SYN_REPORT) + event->timestamp = input_timestamp(&input_event); + } + } while (input_event.type != EV_SYN); + + data->acceleration.x = event->acceleration.x; + data->acceleration.y = event->acceleration.y; + data->acceleration.z = event->acceleration.z; + + return 0; +} + +struct aries_sensors_handlers smb380 = { + .name = "SMB380", + .handle = SENSOR_TYPE_ACCELEROMETER, + .init = smb380_init, + .deinit = smb380_deinit, + .activate = smb380_activate, + .deactivate = smb380_deactivate, + .set_delay = smb380_set_delay, + .get_data = smb380_get_data, + .activated = 0, + .needed = 0, + .poll_fd = -1, + .data = NULL, +}; diff --git a/sensors/yas529.c b/sensors/yas529.c new file mode 100644 index 0000000..e6917aa --- /dev/null +++ b/sensors/yas529.c @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <unistd.h> +#include <stdint.h> +#include <fcntl.h> +#include <errno.h> +#include <math.h> +#include <sys/types.h> +#include <linux/ioctl.h> +#include <linux/input.h> + +#include <hardware/sensors.h> +#include <hardware/hardware.h> + +#define LOG_TAG "aries_sensors" +#include <utils/Log.h> + +#include "aries_sensors.h" + +struct yas529_data { + char path_enable[PATH_MAX]; + char path_delay[PATH_MAX]; + + sensors_vec_t magnetic; +}; + +int yas529_init(struct aries_sensors_handlers *handlers, + struct aries_sensors_device *device) +{ + struct yas529_data *data = NULL; + char path[PATH_MAX] = { 0 }; + int input_fd = -1; + int rc; + + ALOGD("%s(%p, %p)", __func__, handlers, device); + + if (handlers == NULL) + return -EINVAL; + + data = (struct yas529_data *) calloc(1, sizeof(struct yas529_data)); + + input_fd = input_open("magnetic_sensor"); + if (input_fd < 0) { + ALOGE("%s: Unable to open input", __func__); + goto error; + } + + rc = sysfs_path_prefix("magnetic_sensor", (char *) &path); + if (rc < 0 || path[0] == '\0') { + ALOGE("%s: Unable to open sysfs", __func__); + goto error; + } + + snprintf(data->path_enable, PATH_MAX, "%s/enable", path); + snprintf(data->path_delay, PATH_MAX, "%s/delay", path); + + handlers->poll_fd = input_fd; + handlers->data = (void *) data; + + return 0; + +error: + if (data != NULL) + free(data); + + if (input_fd >= 0) + close(input_fd); + + handlers->poll_fd = -1; + handlers->data = NULL; + + return -1; +} + +int yas529_deinit(struct aries_sensors_handlers *handlers) +{ + ALOGD("%s(%p)", __func__, handlers); + + if (handlers == NULL) + return -EINVAL; + + if (handlers->poll_fd >= 0) + close(handlers->poll_fd); + handlers->poll_fd = -1; + + if (handlers->data != NULL) + free(handlers->data); + handlers->data = NULL; + + return 0; +} + +int yas529_activate(struct aries_sensors_handlers *handlers) +{ + struct yas529_data *data; + int rc; + + ALOGD("%s(%p)", __func__, handlers); + + if (handlers == NULL || handlers->data == NULL) + return -EINVAL; + + data = (struct yas529_data *) handlers->data; + + rc = sysfs_value_write(data->path_enable, 1); + if (rc < 0) { + ALOGE("%s: Unable to write sysfs value", __func__); + return -1; + } + + handlers->activated = 1; + + return 0; +} + +int yas529_deactivate(struct aries_sensors_handlers *handlers) +{ + struct yas529_data *data; + int rc; + + ALOGD("%s(%p)", __func__, handlers); + + if (handlers == NULL || handlers->data == NULL) + return -EINVAL; + + data = (struct yas529_data *) handlers->data; + + rc = sysfs_value_write(data->path_enable, 0); + if (rc < 0) { + ALOGE("%s: Unable to write sysfs value", __func__); + return -1; + } + + handlers->activated = 1; + + return 0; +} + +int yas529_set_delay(struct aries_sensors_handlers *handlers, long int delay) +{ + struct yas529_data *data; + int d; + int rc; + + ALOGD("%s(%p, %ld)", __func__, handlers, delay); + + if (handlers == NULL || handlers->data == NULL) + return -EINVAL; + + data = (struct yas529_data *) handlers->data; + + if (delay < 20000000) + d = 1; + else if (delay < 60000000) + d = 20; + else if (delay < 200000000) + d = 60; + else if (delay < 1000000000) + d = 200; + else + d = 1000; + + rc = sysfs_value_write(data->path_delay, d); + if (rc < 0) { + ALOGE("%s: Unable to write sysfs value", __func__); + return -1; + } + + return 0; +} + +float yas529_convert(int value) +{ + return value / 1000.0f; +} + +int yas529_get_data(struct aries_sensors_handlers *handlers, + struct sensors_event_t *event) +{ + struct yas529_data *data; + struct input_event input_event; + int input_fd; + int rc; + +// ALOGD("%s(%p, %p)", __func__, handlers, event); + + if (handlers == NULL || handlers->data == NULL || event == NULL) + return -EINVAL; + + data = (struct yas529_data *) handlers->data; + + input_fd = handlers->poll_fd; + if (input_fd < 0) + return -EINVAL; + + memset(event, 0, sizeof(struct sensors_event_t)); + event->version = sizeof(struct sensors_event_t); + event->sensor = handlers->handle; + event->type = handlers->handle; + + event->magnetic.x = data->magnetic.x; + event->magnetic.y = data->magnetic.y; + event->magnetic.z = data->magnetic.z; + + do { + rc = read(input_fd, &input_event, sizeof(input_event)); + if (rc < (int) sizeof(input_event)) + break; + + if (input_event.type == EV_REL) { + switch (input_event.code) { + case REL_X: + event->magnetic.x = yas529_convert(input_event.value); + break; + case REL_Y: + event->magnetic.y = yas529_convert(input_event.value); + break; + case REL_Z: + event->magnetic.z = yas529_convert(input_event.value); + break; + default: + continue; + } + } else if (input_event.type == EV_SYN) { + if (input_event.code == SYN_REPORT) + event->timestamp = input_timestamp(&input_event); + } + } while (input_event.type != EV_SYN); + + data->magnetic.x = event->magnetic.x; + data->magnetic.y = event->magnetic.y; + data->magnetic.z = event->magnetic.z; + + return 0; +} + +struct aries_sensors_handlers yas529 = { + .name = "YAS529", + .handle = SENSOR_TYPE_MAGNETIC_FIELD, + .init = yas529_init, + .deinit = yas529_deinit, + .activate = yas529_activate, + .deactivate = yas529_deactivate, + .set_delay = yas529_set_delay, + .get_data = yas529_get_data, + .activated = 0, + .needed = 0, + .poll_fd = -1, + .data = NULL, +}; diff --git a/sensors/yas_orientation.c b/sensors/yas_orientation.c new file mode 100644 index 0000000..d1a6e8a --- /dev/null +++ b/sensors/yas_orientation.c @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr> + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <unistd.h> +#include <stdint.h> +#include <fcntl.h> +#include <errno.h> +#include <math.h> +#include <sys/types.h> +#include <linux/ioctl.h> +#include <linux/input.h> + +#include <hardware/sensors.h> +#include <hardware/hardware.h> + +#define LOG_TAG "aries_sensors" +#include <utils/Log.h> + +#include "aries_sensors.h" + +struct yas_orientation_data { + struct aries_sensors_handlers *acceleration_sensor; + struct aries_sensors_handlers *magnetic_sensor; + + char path_enable[PATH_MAX]; + char path_delay[PATH_MAX]; +}; + +int yas_orientation_init(struct aries_sensors_handlers *handlers, + struct aries_sensors_device *device) +{ + struct yas_orientation_data *data = NULL; + char path[PATH_MAX] = { 0 }; + int input_fd = -1; + int rc; + int i; + + ALOGD("%s(%p, %p)", __func__, handlers, device); + + if (handlers == NULL) + return -EINVAL; + + data = (struct yas_orientation_data *) calloc(1, sizeof(struct yas_orientation_data)); + + for (i = 0; i < device->handlers_count; i++) { + if (device->handlers[i] == NULL) + continue; + + if (device->handlers[i]->handle == SENSOR_TYPE_ACCELEROMETER) + data->acceleration_sensor = device->handlers[i]; + else if (device->handlers[i]->handle == SENSOR_TYPE_MAGNETIC_FIELD) + data->magnetic_sensor = device->handlers[i]; + } + + if (data->acceleration_sensor == NULL || data->magnetic_sensor == NULL) { + ALOGE("%s: Missing sensors for orientation", __func__); + goto error; + } + + input_fd = input_open("orientation_sensor"); + if (input_fd < 0) { + ALOGE("%s: Unable to open input", __func__); + goto error; + } + + rc = sysfs_path_prefix("orientation_sensor", (char *) &path); + if (rc < 0 || path[0] == '\0') { + ALOGE("%s: Unable to open sysfs", __func__); + goto error; + } + + snprintf(data->path_enable, PATH_MAX, "%s/enable", path); + snprintf(data->path_delay, PATH_MAX, "%s/delay", path); + + handlers->poll_fd = input_fd; + handlers->data = (void *) data; + + return 0; + +error: + if (data != NULL) + free(data); + + if (input_fd >= 0) + close(input_fd); + + handlers->poll_fd = -1; + handlers->data = NULL; + + return -1; +} + +int yas_orientation_deinit(struct aries_sensors_handlers *handlers) +{ + ALOGD("%s(%p)", __func__, handlers); + + if (handlers == NULL) + return -EINVAL; + + if (handlers->poll_fd >= 0) + close(handlers->poll_fd); + handlers->poll_fd = -1; + + if (handlers->data != NULL) + free(handlers->data); + handlers->data = NULL; + + return 0; +} + +int yas_orientation_activate(struct aries_sensors_handlers *handlers) +{ + struct yas_orientation_data *data; + int rc; + + ALOGD("%s(%p)", __func__, handlers); + + if (handlers == NULL || handlers->data == NULL) + return -EINVAL; + + data = (struct yas_orientation_data *) handlers->data; + + if (data->acceleration_sensor == NULL || data->magnetic_sensor == NULL) + return -1; + + data->acceleration_sensor->needed |= ARIES_SENSORS_NEEDED_ORIENTATION; + if (data->acceleration_sensor->needed == ARIES_SENSORS_NEEDED_ORIENTATION) + data->acceleration_sensor->activate(data->acceleration_sensor); + + data->magnetic_sensor->needed |= ARIES_SENSORS_NEEDED_ORIENTATION; + if (data->magnetic_sensor->needed == ARIES_SENSORS_NEEDED_ORIENTATION) + data->magnetic_sensor->activate(data->magnetic_sensor); + + rc = sysfs_value_write(data->path_enable, 1); + if (rc < 0) { + ALOGE("%s: Unable to write sysfs value", __func__); + return -1; + } + + handlers->activated = 1; + + return 0; +} + +int yas_orientation_deactivate(struct aries_sensors_handlers *handlers) +{ + struct yas_orientation_data *data; + int rc; + + ALOGD("%s(%p)", __func__, handlers); + + if (handlers == NULL || handlers->data == NULL) + return -EINVAL; + + data = (struct yas_orientation_data *) handlers->data; + + if (data->acceleration_sensor == NULL || data->magnetic_sensor == NULL) + return -1; + + data->acceleration_sensor->needed &= ~(ARIES_SENSORS_NEEDED_ORIENTATION); + if (data->acceleration_sensor->needed == 0) + data->acceleration_sensor->deactivate(data->acceleration_sensor); + + data->magnetic_sensor->needed &= ~(ARIES_SENSORS_NEEDED_ORIENTATION); + if (data->magnetic_sensor->needed == 0) + data->magnetic_sensor->deactivate(data->magnetic_sensor); + + rc = sysfs_value_write(data->path_enable, 0); + if (rc < 0) { + ALOGE("%s: Unable to write sysfs value", __func__); + return -1; + } + + handlers->activated = 1; + + return 0; +} + +int yas_orientation_set_delay(struct aries_sensors_handlers *handlers, long int delay) +{ + struct yas_orientation_data *data; + int d; + int rc; + + ALOGD("%s(%p, %ld)", __func__, handlers, delay); + + if (handlers == NULL || handlers->data == NULL) + return -EINVAL; + + data = (struct yas_orientation_data *) handlers->data; + + if (data->acceleration_sensor == NULL || data->magnetic_sensor == NULL) + return -1; + + if (data->acceleration_sensor->needed == ARIES_SENSORS_NEEDED_ORIENTATION) + data->acceleration_sensor->set_delay(data->acceleration_sensor, delay); + + if (data->magnetic_sensor->needed == ARIES_SENSORS_NEEDED_ORIENTATION) + data->magnetic_sensor->set_delay(data->magnetic_sensor, delay); + + if (delay < 10000000) + d = 10; + else + d = delay / 1000000; + + rc = sysfs_value_write(data->path_delay, d); + if (rc < 0) { + ALOGE("%s: Unable to write sysfs value", __func__); + return -1; + } + + return 0; +} + +float yas_orientation_convert(int value) +{ + return value / 1000.0f; +} + +int yas_orientation_get_data(struct aries_sensors_handlers *handlers, + struct sensors_event_t *event) +{ + struct input_event input_event; + int input_fd; + int rc; + +// ALOGD("%s(%p, %p)", __func__, handlers, event); + + if (handlers == NULL || event == NULL) + return -EINVAL; + + input_fd = handlers->poll_fd; + if (input_fd < 0) + return -EINVAL; + + memset(event, 0, sizeof(struct sensors_event_t)); + event->version = sizeof(struct sensors_event_t); + event->sensor = handlers->handle; + event->type = handlers->handle; + + do { + rc = read(input_fd, &input_event, sizeof(input_event)); + if (rc < (int) sizeof(input_event)) + break; + + if (input_event.type == EV_REL) { + switch (input_event.code) { + case REL_X: + event->orientation.azimuth = yas_orientation_convert(input_event.value); + break; + case REL_Y: + event->orientation.pitch = yas_orientation_convert(input_event.value); + break; + case REL_Z: + event->orientation.roll = yas_orientation_convert(input_event.value); + break; + default: + continue; + } + } else if (input_event.type == EV_SYN) { + if (input_event.code == SYN_REPORT) + event->timestamp = input_timestamp(&input_event); + } + } while (input_event.type != EV_SYN); + + return 0; +} + +struct aries_sensors_handlers yas_orientation = { + .name = "YAS Orientation", + .handle = SENSOR_TYPE_ORIENTATION, + .init = yas_orientation_init, + .deinit = yas_orientation_deinit, + .activate = yas_orientation_activate, + .deactivate = yas_orientation_deactivate, + .set_delay = yas_orientation_set_delay, + .get_data = yas_orientation_get_data, + .activated = 0, + .needed = 0, + .poll_fd = -1, + .data = NULL, +}; |