diff options
author | Arve Hjønnevåg <arve@android.com> | 2011-06-14 20:47:06 -0700 |
---|---|---|
committer | Arve Hjønnevåg <arve@android.com> | 2011-06-16 20:29:17 -0700 |
commit | 3f066439dbf291506e1c2b845fa1e16e263ae605 (patch) | |
tree | 42f643d344ec66c1f08fbe940119dfc11c6192dd /libsensors | |
parent | 80950b610cecdc902ac6ff11f5a8de07549be62c (diff) | |
download | device_samsung_tuna-3f066439dbf291506e1c2b845fa1e16e263ae605.zip device_samsung_tuna-3f066439dbf291506e1c2b845fa1e16e263ae605.tar.gz device_samsung_tuna-3f066439dbf291506e1c2b845fa1e16e263ae605.tar.bz2 |
Add sensors hal
Only the sensors from the invensense library are inclueded fro now.
Change-Id: I997d38eb722e2e5c0b44168db8c70282fab407a6
Diffstat (limited to 'libsensors')
-rw-r--r-- | libsensors/Android.mk | 39 | ||||
-rw-r--r-- | libsensors/sensors.cpp | 370 |
2 files changed, 409 insertions, 0 deletions
diff --git a/libsensors/Android.mk b/libsensors/Android.mk new file mode 100644 index 0000000..6eb9556 --- /dev/null +++ b/libsensors/Android.mk @@ -0,0 +1,39 @@ +# 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 stored in +# hw/<SENSORS_HARDWARE_MODULE_ID>.<ro.product.board>.so +include $(CLEAR_VARS) + +LOCAL_MODULE := sensors.tuna + +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw + +LOCAL_MODULE_TAGS := optional + +LOCAL_CFLAGS := -DLOG_TAG=\"Sensors\" +LOCAL_C_INCLUDES += vendor/invensense/libsensors +LOCAL_SRC_FILES := \ + sensors.cpp + +LOCAL_SHARED_LIBRARIES := libinvensense_hal libcutils libutils libdl + +include $(BUILD_SHARED_LIBRARY) + +endif # !TARGET_SIMULATOR diff --git a/libsensors/sensors.cpp b/libsensors/sensors.cpp new file mode 100644 index 0000000..44697bf --- /dev/null +++ b/libsensors/sensors.cpp @@ -0,0 +1,370 @@ + +/* + * Copyright (C) 2011 Invensense, Inc. + * + * 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. + */ +/**********Removed the gesture related code from this file for Google code check modified by Meenakshi Ramamoorthi on May 31st **********/ + +#define LOG_NDEBUG 0 +#define LOG_TAG "Sensors" +#define FUNC_LOG LOGV("%s", __PRETTY_FUNCTION__) + +#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 "MPLSensor.h" + +/*****************************************************************************/ + +#define DELAY_OUT_TIME 0x7FFFFFFF + +#define LIGHT_SENSOR_POLLTIME 2000000000 + +#define SENSORS_ROTATION_VECTOR (1<<ID_RV) +#define SENSORS_LINEAR_ACCEL (1<<ID_LA) +#define SENSORS_GRAVITY (1<<ID_GR) +#define SENSORS_GYROSCOPE (1<<ID_GY) +#define SENSORS_ACCELERATION (1<<ID_A) +#define SENSORS_MAGNETIC_FIELD (1<<ID_M) +#define SENSORS_ORIENTATION (1<<ID_O) + +#define SENSORS_ROTATION_VECTOR_HANDLE (ID_RV) +#define SENSORS_LINEAR_ACCEL_HANDLE (ID_LA) +#define SENSORS_GRAVITY_HANDLE (ID_GR) +#define SENSORS_GYROSCOPE_HANDLE (ID_GY) +#define SENSORS_ACCELERATION_HANDLE (ID_A) +#define SENSORS_MAGNETIC_FIELD_HANDLE (ID_M) +#define SENSORS_ORIENTATION_HANDLE (ID_O) + + +#define AKM_FTRACE 0 +#define AKM_DEBUG 0 +#define AKM_DATA 0 + +/*****************************************************************************/ + +/* The SENSORS Module */ +static const struct sensor_t sSensorList[] = { + { "MPL rotation vector", + "Invensense", + 1, SENSORS_ROTATION_VECTOR_HANDLE, + SENSOR_TYPE_ROTATION_VECTOR, 10240.0f, 1.0f, 0.5f, 20000,{ } }, + { "MPL linear accel", + "Invensense", + 1, SENSORS_LINEAR_ACCEL_HANDLE, + SENSOR_TYPE_LINEAR_ACCELERATION, 10240.0f, 1.0f, 0.5f, 20000,{ } }, + { "MPL gravity", + "Invensense", + 1, SENSORS_GRAVITY_HANDLE, + SENSOR_TYPE_GRAVITY, 10240.0f, 1.0f, 0.5f, 20000,{ } }, + { "MPL Gyro", + "Invensense", + 1, SENSORS_GYROSCOPE_HANDLE, + SENSOR_TYPE_GYROSCOPE, 10240.0f, 1.0f, 0.5f, 20000,{ } }, + { "MPL accel", + "Invensense", + 1, SENSORS_ACCELERATION_HANDLE, + SENSOR_TYPE_ACCELEROMETER, 10240.0f, 1.0f, 0.5f, 20000,{ } }, + { "MPL magnetic field", + "Invensense", + 1, SENSORS_MAGNETIC_FIELD_HANDLE, + SENSOR_TYPE_MAGNETIC_FIELD, 10240.0f, 1.0f, 0.5f, 20000,{ } }, + { "MPL Orientation (android deprecated format)", + "Invensense", + 1, SENSORS_ORIENTATION_HANDLE, + SENSOR_TYPE_ORIENTATION, 360.0f, 1.0f, 9.7f, 20000,{ } }, + + +}; + + +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: "Invensense module", + author: "Invensense Inc.", + 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 { + mpl = 0, //all mpl entries must be consecutive and in this order + mpl_accel, + mpl_timer, + numSensorDrivers, // wake pipe goes here + mpl_power, //special handle for MPL pm interaction + numFds, + }; + + static const size_t wake = numFds - 2; + static const char WAKE_MESSAGE = 'W'; + struct pollfd mPollFds[numFds]; + int mWritePipeFd; + SensorBase* mSensors[numSensorDrivers]; + + int handleToDriver(int handle) const { + switch (handle) { + case ID_RV: + case ID_LA: + case ID_GR: + case ID_GY: + case ID_A: + case ID_M: + case ID_O: + return mpl; + } + return -EINVAL; + } +}; + +/*****************************************************************************/ + +sensors_poll_context_t::sensors_poll_context_t() +{ + FUNC_LOG; + MPLSensor* p_mplsen = new MPLSensor(); + setCallbackObject(p_mplsen); //setup the callback object for handing mpl callbacks + + mSensors[mpl] = p_mplsen; + mPollFds[mpl].fd = mSensors[mpl]->getFd(); + mPollFds[mpl].events = POLLIN; + mPollFds[mpl].revents = 0; + + mSensors[mpl_accel] = mSensors[mpl]; + mPollFds[mpl_accel].fd = ((MPLSensor*)mSensors[mpl])->getAccelFd(); + mPollFds[mpl_accel].events = POLLIN; + mPollFds[mpl_accel].revents = 0; + + mSensors[mpl_timer] = mSensors[mpl]; + mPollFds[mpl_timer].fd = ((MPLSensor*)mSensors[mpl])->getTimerFd(); + mPollFds[mpl_timer].events = POLLIN; + mPollFds[mpl_timer].revents = 0; + + int wakeFds[2]; + int result = pipe(wakeFds); + LOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno)); + fcntl(wakeFds[0], F_SETFL, O_NONBLOCK); + fcntl(wakeFds[1], F_SETFL, O_NONBLOCK); + mWritePipeFd = wakeFds[1]; + + mPollFds[wake].fd = wakeFds[0]; + mPollFds[wake].events = POLLIN; + mPollFds[wake].revents = 0; + + //setup MPL pm interaction handle + mPollFds[mpl_power].fd = ((MPLSensor*)mSensors[mpl])->getPowerFd(); + mPollFds[mpl_power].events = POLLIN; + mPollFds[mpl_power].revents = 0; +} + +sensors_poll_context_t::~sensors_poll_context_t() +{ + FUNC_LOG; + 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) +{ + FUNC_LOG; + int index = handleToDriver(handle); + if (index < 0) return index; + int err = mSensors[index]->enable(handle, enabled); + if (!err) { + const char wakeMessage(WAKE_MESSAGE); + int result = write(mWritePipeFd, &wakeMessage, 1); + LOGE_IF(result<0, "error sending wake message (%s)", strerror(errno)); + } + return err; +} + +int sensors_poll_context_t::setDelay(int handle, int64_t ns) +{ + FUNC_LOG; + 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) +{ + //FUNC_LOG; + int nbEvents = 0; + int n = 0; + int polltime = -1; + + 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; + + //special handling for the mpl, which has multiple handles + if(i==mpl) { + i+=2; //skip accel and timer + mPollFds[mpl_accel].revents = 0; + mPollFds[mpl_timer].revents = 0; + } + if(i==mpl_accel) { + i+=1; //skip timer + mPollFds[mpl_timer].revents = 0; + } + } + } + + 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 + int i; + + n = poll(mPollFds, numFds, nbEvents ? 0 : polltime); + if (n<0) { + LOGE("poll() failed (%s)", strerror(errno)); + return -errno; + } + if (mPollFds[wake].revents & POLLIN) { + char msg; + int result = read(mPollFds[wake].fd, &msg, 1); + LOGE_IF(result<0, "error reading from wake pipe (%s)", strerror(errno)); + LOGE_IF(msg != WAKE_MESSAGE, "unknown message on wake queue (0x%02x)", int(msg)); + mPollFds[wake].revents = 0; + } + if(mPollFds[mpl_power].revents & POLLIN) { + ((MPLSensor*)mSensors[mpl])->handlePowerEvent(); + mPollFds[mpl_power].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) +{ + FUNC_LOG; + 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) +{ + FUNC_LOG; + 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) +{ + FUNC_LOG; + 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) +{ + //FUNC_LOG; + 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) +{ + FUNC_LOG; + 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; +} + + |