diff options
-rw-r--r-- | libsensors/AccelSensor.cpp | 176 | ||||
-rw-r--r-- | libsensors/AccelSensor.h | 69 | ||||
-rw-r--r-- | libsensors/Android.mk | 47 | ||||
-rw-r--r-- | libsensors/CompassSensor.cpp | 190 | ||||
-rw-r--r-- | libsensors/CompassSensor.h | 54 | ||||
-rw-r--r-- | libsensors/InputEventReader.cpp | 88 | ||||
-rw-r--r-- | libsensors/InputEventReader.h | 47 | ||||
-rw-r--r-- | libsensors/LightSensor.cpp | 145 | ||||
-rw-r--r-- | libsensors/LightSensor.h | 54 | ||||
-rw-r--r-- | libsensors/OrientationSensor.cpp | 184 | ||||
-rw-r--r-- | libsensors/OrientationSensor.h | 54 | ||||
-rw-r--r-- | libsensors/ProximitySensor.cpp | 144 | ||||
-rw-r--r-- | libsensors/ProximitySensor.h | 54 | ||||
-rw-r--r-- | libsensors/SensorBase.cpp | 128 | ||||
-rw-r--r-- | libsensors/SensorBase.h | 65 | ||||
-rw-r--r-- | libsensors/sensors.cpp | 374 | ||||
-rw-r--r-- | libsensors/sensors.h | 119 | ||||
-rw-r--r-- | n5110.mk | 4 |
18 files changed, 1996 insertions, 0 deletions
diff --git a/libsensors/AccelSensor.cpp b/libsensors/AccelSensor.cpp new file mode 100644 index 0000000..3ab5e2e --- /dev/null +++ b/libsensors/AccelSensor.cpp @@ -0,0 +1,176 @@ +/* + * 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 "AccelSensor.h" + + +/*****************************************************************************/ +AccelSensor::AccelSensor() + : SensorBase(NULL, "accelerometer"), + mEnabled(0), + + mInputReader(4), + mHasPendingEvent(false) +{ + // ALOGD("AccelSensor::AccelSensor()"); + mPendingEvent.version = sizeof(sensors_event_t); + mPendingEvent.sensor = ID_A; + mPendingEvent.type = SENSOR_TYPE_ACCELEROMETER; + memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data)); + + // ALOGD("AccelSensor::AccelSensor() 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); + } + // ALOGE("AccelSensor: sysfs: %s",input_sysfs_path); +} + +AccelSensor::~AccelSensor() { + + // ALOGD("AccelSensor::~AccelSensor()"); + if (mEnabled) { + enable(0, 0); + } +} + + + +int AccelSensor::enable(int32_t, int en) { + + + // ALOGD("AccelSensor::~enable(0, %d)", en); + int flags = en ? 1 : 0; + if (flags != mEnabled) { + int fd; + strcpy(&input_sysfs_path[input_sysfs_path_len], "enable"); + // ALOGD("AccelSensor::~enable(0, %d) open %s",en, input_sysfs_path); + fd = open(input_sysfs_path, O_RDWR); + if (fd >= 0) { + // ALOGD("AccelSensor::~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 AccelSensor::hasPendingEvents() const { + /* FIXME probably here should be returning mEnabled but instead + mHasPendingEvents. It does not work, so we cheat.*/ + //ALOGD("AccelSensor::~hasPendingEvents %d", mHasPendingEvent ? 1 : 0 ); + return mHasPendingEvent; +} + + +int AccelSensor::setDelay(int32_t handle, int64_t ns) +{ + // ALOGD("AccelSensor::~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 AccelSensor::readEvents(sensors_event_t* data, int count) +{ + //ALOGD("AccelSensor::~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_ABS) { + 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("AccelSensor: unknown event (type=%d, code=%d)", + type, event->code); + } + mInputReader.next(); + } + return numEventReceived++; + +} diff --git a/libsensors/AccelSensor.h b/libsensors/AccelSensor.h new file mode 100644 index 0000000..e87c3ec --- /dev/null +++ b/libsensors/AccelSensor.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_SMB380_SENSOR_H +#define ANDROID_SMB380_SENSOR_H + +#include <stdint.h> +#include <errno.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +#include "sensors.h" +#include "SensorBase.h" +#include "InputEventReader.h" + +/*****************************************************************************/ + + +struct smb380acc_t { + short x, /**< holds x-axis acceleration data sign extended. Range -512 to 511. */ + y, /**< holds y-axis acceleration data sign extended. Range -512 to 511. */ + z; /**< holds z-axis acceleration data sign extended. Range -512 to 511. */ +} ; + +/* smb ioctl command label */ +#define IOCTL_SMB_GET_ACC_VALUE 0 +#define DCM_IOC_MAGIC 's' +#define IOC_SET_ACCELEROMETER _IO (DCM_IOC_MAGIC, 0x64) +#define BMA150_CALIBRATION _IOWR(DCM_IOC_MAGIC,48,short) + +#define SMB_POWER_OFF 0 +#define SMB_POWER_ON 1 + +struct input_event; + +class AccelSensor : public SensorBase { + int mEnabled; + InputEventCircularReader mInputReader; + sensors_event_t mPendingEvent; + bool mHasPendingEvent; + char input_sysfs_path[PATH_MAX]; + int input_sysfs_path_len; + + +public: + AccelSensor(); + virtual ~AccelSensor(); + 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/Android.mk b/libsensors/Android.mk new file mode 100644 index 0000000..1542efe --- /dev/null +++ b/libsensors/Android.mk @@ -0,0 +1,47 @@ +# Copyright (C) 2008 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +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.$(TARGET_BOOTLOADER_BOARD_NAME) + +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw + +LOCAL_MODULE_TAGS := optional + +LOCAL_CFLAGS := -DLOG_TAG=\"Sensors\" + +LOCAL_SRC_FILES := \ + sensors.cpp \ + SensorBase.cpp \ + LightSensor.cpp \ + ProximitySensor.cpp \ + AccelSensor.cpp \ + CompassSensor.cpp \ + OrientationSensor.cpp \ + InputEventReader.cpp + +LOCAL_SHARED_LIBRARIES := liblog libcutils libdl +LOCAL_PRELINK_MODULE := false + +include $(BUILD_SHARED_LIBRARY) + +endif + diff --git a/libsensors/CompassSensor.cpp b/libsensors/CompassSensor.cpp new file mode 100644 index 0000000..39daa81 --- /dev/null +++ b/libsensors/CompassSensor.cpp @@ -0,0 +1,190 @@ +/* + * 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, "geomagnetic"), + //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); + } + + // ALOGE("MagneticSensor: sysfs: %s",input_sysfs_path); +} + +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_ABS) { + float value = event->value; + if (event->code == EVENT_TYPE_MAGV_X) { + mPendingEvent.magnetic.x = (float)value / 1000.0f; + } else if (event->code == EVENT_TYPE_MAGV_Y) { + mPendingEvent.magnetic.y = (float)value / 1000.0f; + } else if (event->code == EVENT_TYPE_MAGV_Z) { + mPendingEvent.magnetic.z = (float)value / 1000.0f; + } + } 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 new file mode 100644 index 0000000..9b34f9d --- /dev/null +++ b/libsensors/CompassSensor.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_COMPASS_SENSOR_H +#define ANDROID_COMPASS_SENSOR_H + +#include <stdint.h> +#include <errno.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +#include "sensors.h" +#include "SensorBase.h" +#include "InputEventReader.h" + +/*****************************************************************************/ + + +struct input_event; + +class CompassSensor : public SensorBase { + int mEnabled; + InputEventCircularReader mInputReader; + sensors_event_t mPendingEvent; + bool mHasPendingEvent; + char input_sysfs_path[PATH_MAX]; + int input_sysfs_path_len; + + +public: + CompassSensor(); + virtual ~CompassSensor(); + virtual int readEvents(sensors_event_t* data, int count); + virtual bool hasPendingEvents() const; + virtual int setDelay(int32_t handle, int64_t ns); + virtual int enable(int32_t handle, int enabled); +}; + +/*****************************************************************************/ + +#endif // ANDROID_GYRO_SENSOR_H diff --git a/libsensors/InputEventReader.cpp b/libsensors/InputEventReader.cpp new file mode 100644 index 0000000..1014f29 --- /dev/null +++ b/libsensors/InputEventReader.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <stdint.h> +#include <errno.h> +#include <unistd.h> +#include <poll.h> + +#include <sys/cdefs.h> +#include <sys/types.h> + +#include <linux/input.h> + +#include <cutils/log.h> + +#include "InputEventReader.h" + +/*****************************************************************************/ + +struct input_event; + +InputEventCircularReader::InputEventCircularReader(size_t numEvents) + : mBuffer(new input_event[numEvents * 2]), + mBufferEnd(mBuffer + numEvents), + mHead(mBuffer), + mCurr(mBuffer), + mFreeSpace(numEvents) +{ +} + +InputEventCircularReader::~InputEventCircularReader() +{ + delete [] mBuffer; +} + +ssize_t InputEventCircularReader::fill(int fd) +{ + size_t numEventsRead = 0; + if (mFreeSpace) { + const ssize_t nread = read(fd, mHead, mFreeSpace * sizeof(input_event)); + if (nread<0 || nread % sizeof(input_event)) { + // we got a partial event!! + return nread<0 ? -errno : -EINVAL; + } + + numEventsRead = nread / sizeof(input_event); + if (numEventsRead) { + mHead += numEventsRead; + mFreeSpace -= numEventsRead; + if (mHead > mBufferEnd) { + size_t s = mHead - mBufferEnd; + memcpy(mBuffer, mBufferEnd, s * sizeof(input_event)); + mHead = mBuffer + s; + } + } + } + + return numEventsRead; +} + +ssize_t InputEventCircularReader::readEvent(input_event const** events) +{ + *events = mCurr; + ssize_t available = (mBufferEnd - mBuffer) - mFreeSpace; + return available ? 1 : 0; +} + +void InputEventCircularReader::next() +{ + mCurr++; + mFreeSpace++; + if (mCurr >= mBufferEnd) { + mCurr = mBuffer; + } +} diff --git a/libsensors/InputEventReader.h b/libsensors/InputEventReader.h new file mode 100644 index 0000000..180aade --- /dev/null +++ b/libsensors/InputEventReader.h @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_INPUT_EVENT_READER_H +#define ANDROID_INPUT_EVENT_READER_H + +#include <stdint.h> +#include <errno.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +/*****************************************************************************/ + +struct input_event; + +class InputEventCircularReader +{ + struct input_event* const mBuffer; + struct input_event* const mBufferEnd; + struct input_event* mHead; + struct input_event* mCurr; + ssize_t mFreeSpace; + +public: + InputEventCircularReader(size_t numEvents); + ~InputEventCircularReader(); + ssize_t fill(int fd); + ssize_t readEvent(input_event const** events); + void next(); +}; + +/*****************************************************************************/ + +#endif // ANDROID_INPUT_EVENT_READER_H diff --git a/libsensors/LightSensor.cpp b/libsensors/LightSensor.cpp new file mode 100644 index 0000000..e931e2e --- /dev/null +++ b/libsensors/LightSensor.cpp @@ -0,0 +1,145 @@ +/* + * 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, "light_sensor"), + 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); + } + // ALOGE("LightSensor: sysfs: %s",input_sysfs_path); +} + +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_REL) { + // 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 = event->value; + } 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 new file mode 100644 index 0000000..79e0ccf --- /dev/null +++ b/libsensors/LightSensor.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_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 new file mode 100644 index 0000000..0ca6085 --- /dev/null +++ b/libsensors/OrientationSensor.cpp @@ -0,0 +1,184 @@ +/* + * 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"), + 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); + //ALOGE("OrientationSensor: sysfs: %s",input_sysfs_path); + } +} + +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_ABS) { + float value = event->value; + //ALOGD("OrientationSensor: event->code = %i",event->code); + 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 new file mode 100644 index 0000000..7add75b --- /dev/null +++ b/libsensors/OrientationSensor.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_ORIEN_SENSOR_H +#define ANDROID_ORIEN_SENSOR_H + +#include <stdint.h> +#include <errno.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +#include "sensors.h" +#include "SensorBase.h" +#include "InputEventReader.h" + +/*****************************************************************************/ + + +struct input_event; + +class OrientationSensor : public SensorBase { + int mEnabled; + InputEventCircularReader mInputReader; + sensors_event_t mPendingEvent; + bool mHasPendingEvent; + char input_sysfs_path[PATH_MAX]; + int input_sysfs_path_len; + + +public: + OrientationSensor(); + virtual ~OrientationSensor(); + virtual int readEvents(sensors_event_t* data, int count); + virtual bool hasPendingEvents() const; + virtual int setDelay(int32_t handle, int64_t ns); + virtual int enable(int32_t handle, int enabled); +}; + +/*****************************************************************************/ + +#endif // ANDROID_GYRO_SENSOR_H diff --git a/libsensors/ProximitySensor.cpp b/libsensors/ProximitySensor.cpp new file mode 100644 index 0000000..2f3604c --- /dev/null +++ b/libsensors/ProximitySensor.cpp @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <fcntl.h> +#include <errno.h> +#include <math.h> +#include <poll.h> +#include <unistd.h> +#include <dirent.h> +#include <sys/select.h> + +#include <cutils/log.h> + +#include "ProximitySensor.h" + +/*****************************************************************************/ + +ProximitySensor::ProximitySensor() + : SensorBase(NULL, "proximity_sensor"), + mEnabled(0), + mInputReader(4), + mHasPendingEvent(false) +{ + mPendingEvent.version = sizeof(sensors_event_t); + mPendingEvent.sensor = ID_P; + mPendingEvent.type = SENSOR_TYPE_PROXIMITY; + memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data)); + + if (data_fd) { + strcpy(input_sysfs_path, "/sys/class/input/"); + strcat(input_sysfs_path, input_name); + strcat(input_sysfs_path, "/device/"); + input_sysfs_path_len = strlen(input_sysfs_path); + enable(0, 1); + } +} + +ProximitySensor::~ProximitySensor() { + if (mEnabled) { + enable(0, 0); + } +} + +int ProximitySensor::setInitialState() { + struct input_absinfo absinfo; + if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_PROXIMITY), &absinfo)) { + // make sure to report an event immediately + mHasPendingEvent = true; + mPendingEvent.distance = indexToValue(absinfo.value); + } + return 0; +} + +int ProximitySensor::enable(int32_t, int en) { + int flags = en ? 1 : 0; + if (flags != mEnabled) { + int fd; + strcpy(&input_sysfs_path[input_sysfs_path_len], "enable"); + fd = open(input_sysfs_path, O_RDWR); + if (fd >= 0) { + char buf[2]; + buf[1] = 0; + if (flags) { + buf[0] = '1'; + } else { + buf[0] = '0'; + } + write(fd, buf, sizeof(buf)); + close(fd); + mEnabled = flags; + setInitialState(); + return 0; + } + return -1; + } + return 0; +} + +bool ProximitySensor::hasPendingEvents() const { + return mHasPendingEvent; +} + +int ProximitySensor::readEvents(sensors_event_t* data, int count) +{ + if (count < 1) + return -EINVAL; + + if (mHasPendingEvent) { + mHasPendingEvent = false; + mPendingEvent.timestamp = getTimestamp(); + *data = mPendingEvent; + return mEnabled ? 1 : 0; + } + + ssize_t n = mInputReader.fill(data_fd); + if (n < 0) + return n; + + int numEventReceived = 0; + input_event const* event; + + while (count && mInputReader.readEvent(&event)) { + int type = event->type; + if (type == EV_ABS) { + if (event->code == EVENT_TYPE_PROXIMITY) { + if (event->value != -1) { + // FIXME: not sure why we're getting -1 sometimes + mPendingEvent.distance = indexToValue(event->value); + } + } + } else if (type == EV_SYN) { + mPendingEvent.timestamp = timevalToNano(event->time); + if (mEnabled) { + *data++ = mPendingEvent; + count--; + numEventReceived++; + } + } else { + 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 new file mode 100644 index 0000000..08ea49c --- /dev/null +++ b/libsensors/ProximitySensor.h @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_PROXIMITY_SENSOR_H +#define ANDROID_PROXIMITY_SENSOR_H + +#include <stdint.h> +#include <errno.h> +#include <sys/cdefs.h> +#include <sys/types.h> + +#include "sensors.h" +#include "SensorBase.h" +#include "InputEventReader.h" + +/*****************************************************************************/ + +struct input_event; + +class ProximitySensor : public SensorBase { + int mEnabled; + InputEventCircularReader mInputReader; + sensors_event_t mPendingEvent; + bool mHasPendingEvent; + char input_sysfs_path[PATH_MAX]; + int input_sysfs_path_len; + + int setInitialState(); + float indexToValue(size_t index) const; + +public: + ProximitySensor(); + virtual ~ProximitySensor(); + virtual int readEvents(sensors_event_t* data, int count); + virtual bool hasPendingEvents() const; + virtual int enable(int32_t handle, int enabled); +}; + +/*****************************************************************************/ + +#endif // ANDROID_PROXIMITY_SENSOR_H diff --git a/libsensors/SensorBase.cpp b/libsensors/SensorBase.cpp new file mode 100644 index 0000000..79b1ee2 --- /dev/null +++ b/libsensors/SensorBase.cpp @@ -0,0 +1,128 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <fcntl.h> +#include <errno.h> +#include <math.h> +#include <poll.h> +#include <unistd.h> +#include <dirent.h> +#include <sys/select.h> + +#include <cutils/log.h> + +#include <linux/input.h> + +#include "SensorBase.h" + +/*****************************************************************************/ + +SensorBase::SensorBase( + const char* dev_name, + const char* data_name) + : dev_name(dev_name), data_name(data_name), + dev_fd(-1), data_fd(-1) +{ + if (data_name) { + data_fd = openInput(data_name); + } +} + +SensorBase::~SensorBase() { + if (data_fd >= 0) { + close(data_fd); + } + if (dev_fd >= 0) { + close(dev_fd); + } +} + +int SensorBase::open_device() { + if (dev_fd<0 && dev_name) { + dev_fd = open(dev_name, O_RDONLY); + 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 new file mode 100644 index 0000000..bb4d055 --- /dev/null +++ b/libsensors/SensorBase.h @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_SENSOR_BASE_H +#define ANDROID_SENSOR_BASE_H + +#include <stdint.h> +#include <errno.h> +#include <sys/cdefs.h> +#include <sys/types.h> + + +/*****************************************************************************/ + +struct sensors_event_t; + +class SensorBase { +protected: + const char* dev_name; + const char* data_name; + char input_name[PATH_MAX]; + int dev_fd; + int data_fd; + + int openInput(const char* inputName); + static int64_t getTimestamp(); + + + static int64_t timevalToNano(timeval const& t) { + return t.tv_sec*1000000000LL + t.tv_usec*1000; + } + + int open_device(); + int close_device(); + +public: + SensorBase( + const char* dev_name, + const char* data_name); + + virtual ~SensorBase(); + + virtual int readEvents(sensors_event_t* data, int count) = 0; + virtual bool hasPendingEvents() const; + virtual int getFd() const; + virtual int setDelay(int32_t handle, int64_t ns); + virtual int enable(int32_t handle, int enabled) = 0; +}; + +/*****************************************************************************/ + +#endif // ANDROID_SENSOR_BASE_H diff --git a/libsensors/sensors.cpp b/libsensors/sensors.cpp new file mode 100644 index 0000000..a0194ef --- /dev/null +++ b/libsensors/sensors.cpp @@ -0,0 +1,374 @@ +/* + * 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 "AccelSensor.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[] = { + + { "LIS3DH Acceleration Sensor", + "STMicroelectronics", + 1, SENSORS_ACCELERATION_HANDLE, + SENSOR_TYPE_ACCELEROMETER, RANGE_A, RESOLUTION_A, 0.20f, 10000, { } }, + { "MS-3R (YAS532) Magnetic Sensor", + "Yamaha Corporation", + 1, SENSORS_MAGNETIC_FIELD_HANDLE, + SENSOR_TYPE_MAGNETIC_FIELD, 2000.0f, 0.06f, 6.8f, 10000, { } }, + { "MS-x Orientation Sensor", + "Yamaha Corporation", + 1, SENSORS_ORIENTATION_HANDLE, + SENSOR_TYPE_ORIENTATION, 360.0f, CONVERT_O, 7.8f, 10000, { } }, + { "AL3201 Light Sensor", + "LITEON", + 1, SENSORS_LIGHT_HANDLE, + SENSOR_TYPE_LIGHT, 10240.0f, 1.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 AccelSensor(); + 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 new file mode 100644 index 0000000..406754a --- /dev/null +++ b/libsensors/sensors.h @@ -0,0 +1,119 @@ +/* + * 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 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 REL_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 NUMOFACCDATA 8 + +// conversion of acceleration data to SI units (m/s^2) +/* Accel BMA250 */ +#define EVENT_TYPE_ACCEL_X ABS_X +#define EVENT_TYPE_ACCEL_Y ABS_Y +#define EVENT_TYPE_ACCEL_Z ABS_Z +#define LSG (1000.0f) + +// conversion of acceleration data to SI units (m/s^2) +#define RANGE_A (4*GRAVITY_EARTH) +#define RESOLUTION_A (GRAVITY_EARTH / LSG) +#define CONVERT_A (GRAVITY_EARTH / LSG) +#define CONVERT_A_X (CONVERT_A) +#define CONVERT_A_Y (CONVERT_A) +#define CONVERT_A_Z (CONVERT_A) + +// conversion of magnetic data to uT units +#define CONVERT_M (1.0f/1000.0.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 @@ -52,6 +52,10 @@ PRODUCT_COPY_FILES += \ PRODUCT_PACKAGES += \ camera.smdk4x12 +# Sensors +PRODUCT_PACKAGES += \ + sensors.smdk4x12 + # RIL PRODUCT_PROPERTY_OVERRIDES += \ mobiledata.interfaces=wlan0 |