From ed082860513438f8ce5a327161ba33f2e7ac2af4 Mon Sep 17 00:00:00 2001 From: Sungmin Choi Date: Mon, 10 Jun 2013 17:41:02 -0700 Subject: [PATCH] sensors: Use hammerhead's own sensor HAL Add light and proximity sensor based on invensense HAL Bug: 8968282 Change-Id: I9952ca39ec090b0ce3ec3425f366dc8c8fac4409 --- libsensors/Android.mk | 38 +++ libsensors/LightSensor.cpp | 165 +++++++++++++ libsensors/LightSensor.h | 57 +++++ libsensors/ProximitySensor.cpp | 147 +++++++++++ libsensors/ProximitySensor.h | 52 ++++ libsensors/sensors.cpp | 429 +++++++++++++++++++++++++++++++++ libsensors/sensors.h | 67 +++++ 7 files changed, 955 insertions(+) create mode 100644 libsensors/Android.mk create mode 100644 libsensors/LightSensor.cpp create mode 100644 libsensors/LightSensor.h create mode 100644 libsensors/ProximitySensor.cpp create mode 100644 libsensors/ProximitySensor.h create mode 100644 libsensors/sensors.cpp create mode 100644 libsensors/sensors.h diff --git a/libsensors/Android.mk b/libsensors/Android.mk new file mode 100644 index 0000000..7d922ae --- /dev/null +++ b/libsensors/Android.mk @@ -0,0 +1,38 @@ +# Copyright 2013 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) + +# HAL module implemenation stored in +# hw/..so +include $(CLEAR_VARS) + +LOCAL_MODULE := sensors.hammerhead + +LOCAL_PRELINK_MODULE := false +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw + +LOCAL_MODULE_TAGS := optional +LOCAL_CFLAGS := -DLOG_TAG=\"Sensors\" +LOCAL_CFLAGS += -DINVENSENSE_COMPASS_CAL +LOCAL_C_INCLUDES += hardware/invensense/65xx/libsensors_iio +LOCAL_SRC_FILES := \ + sensors.cpp \ + LightSensor.cpp \ + ProximitySensor.cpp + +LOCAL_SHARED_LIBRARIES := libinvensense_hal liblog libutils libdl + +include $(BUILD_SHARED_LIBRARY) diff --git a/libsensors/LightSensor.cpp b/libsensors/LightSensor.cpp new file mode 100644 index 0000000..db335da --- /dev/null +++ b/libsensors/LightSensor.cpp @@ -0,0 +1,165 @@ +/* + * Copyright 2013 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 +#include +#include +#include +#include +#include +#include +#include + +#include "sensors.h" +#include "LightSensor.h" + +#define ABS_LIGHT 0x29 + +LightSensor::LightSensor() + : SensorBase(NULL, LIGHT_DATA), + mEnabled(0), + mEventsSinceEnable(0), + mInputReader(4), + mHasPendingEvent(false) +{ + mPendingEvent.sensor = ID_L; + mPendingEvent.type = SENSOR_TYPE_LIGHT; + memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data)); +} + +LightSensor::~LightSensor() +{ +} + +int LightSensor::setInitialState() +{ + return 0; +} + +int LightSensor::setDelay(int32_t handle, int64_t ns) +{ + int fd; + char sysfs[PATH_MAX]; + + strcpy(sysfs, I2C); + strcat(sysfs, "als_poll_delay"); + + fd = open(sysfs, O_RDWR); + if (fd >= 0) { + char buf[16] = {0,}; + snprintf(buf, sizeof(buf), "%lld", ns); + write(fd, buf, sizeof(buf)); + close(fd); + return 0; + } + return -1; +} + +int LightSensor::enable(int32_t handle, int en) +{ + int newState = en ? 1 : 0; + int err = 0; + + if (newState != mEnabled) { + if (!mEnabled && dev_name != NULL) { + open_device(); + } + + char sysfs[PATH_MAX]; + + strcpy(sysfs, I2C); + strcat(sysfs, "enable_als_sensor"); + + ALOGI_IF(DEBUG, "enable.open(%s), en(%d)", sysfs, en); + + int fd = open(sysfs, O_RDWR); + if (fd < 0) { + ALOGE("couldn't open '%s' input device", sysfs); + err = -1; + } else { + char buf[2]; + + buf[0] = newState ? '1' : '0'; + buf[1] = '\0'; + + write(fd, buf, sizeof(buf)); + close(fd); + setInitialState(); + } + + mEnabled = newState; + + if (!mEnabled && dev_name != NULL) { + close_device(); + } + } + return err; +} + +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 == ABS_LIGHT) { + mPendingEvent.sensor = ID_L; + mPendingEvent.type = SENSOR_TYPE_LIGHT; + mPendingEvent.light = (float)event->value; + } + } else if (type == EV_SYN) { + mPendingEvent.timestamp = timevalToNano(event->time); + if (mEnabled && (mPendingEvent.light != mPreviousLight) ) { + *data++ = mPendingEvent; + count--; + numEventReceived++; + mPreviousLight = mPendingEvent.light; + } + } else { + ALOGE("LightSensor: unknown event (type=%d, code=%d)", + type, event->code); + } + mInputReader.next(); + } + + return numEventReceived; +} + +float LightSensor::indexToValue(size_t index) const +{ + return 0.0; +} diff --git a/libsensors/LightSensor.h b/libsensors/LightSensor.h new file mode 100644 index 0000000..2ba4533 --- /dev/null +++ b/libsensors/LightSensor.h @@ -0,0 +1,57 @@ +/* + * Copyright 2013 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 +#include +#include +#include + +#include "SensorBase.h" +#include "InputEventReader.h" +#include "sensors.h" + +/*****************************************************************************/ + +struct input_event; + +class LightSensor : public SensorBase { + int mEnabled; + int mEventsSinceEnable; + InputEventCircularReader mInputReader; + sensors_event_t mPendingEvent; + bool mHasPendingEvent; + char input_sysfs_path[PATH_MAX]; + int input_sysfs_path_len; + + int setInitialState(); + float mPreviousLight; + float indexToValue(size_t index) const; + +public: + LightSensor(); + virtual ~LightSensor(); + virtual int readEvents(sensors_event_t* data, int count); + virtual bool hasPendingEvents() const; + virtual int setDelay(int32_t handle, int64_t ns); + virtual int enable(int32_t handle, int enabled); +}; + +/*****************************************************************************/ + +#endif // ANDROID_LIGHT_SENSOR_H diff --git a/libsensors/ProximitySensor.cpp b/libsensors/ProximitySensor.cpp new file mode 100644 index 0000000..2273fb4 --- /dev/null +++ b/libsensors/ProximitySensor.cpp @@ -0,0 +1,147 @@ +/* + * Copyright 2013 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 +#include +#include +#include +#include +#include +#include + +#include + +#include "sensors.h" +#include "ProximitySensor.h" + +/*****************************************************************************/ + +ProximitySensor::ProximitySensor() + : SensorBase(NULL, PROXIMITY_DATA), + mEnabled(0), + mInputReader(4), + mHasPendingEvent(false) +{ + mPendingEvent.sensor = ID_PX; + mPendingEvent.type = SENSOR_TYPE_PROXIMITY; + memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data)); +} + +ProximitySensor::~ProximitySensor() +{ +} + +int ProximitySensor::setInitialState() +{ + return 0; +} + +int ProximitySensor::enable(int32_t, int en) +{ + int newState = en ? 1 : 0; + int err = 0; + + if (newState != mEnabled) { + if (!mEnabled && dev_name != NULL) { + open_device(); + } + + char sysfs[PATH_MAX]; + + strcpy(sysfs, I2C); + strcat(sysfs, "enable_ps_sensor"); + + ALOGI_IF(DEBUG, "enable.open(%s), en(%d)", sysfs, en); + + int fd = open(sysfs, O_RDWR); + if (fd < 0) { + ALOGE("couldn't open '%s' input device", sysfs); + err = -1; + } else { + char buf[2]; + + buf[0] = newState ? '1' : '0'; + buf[1] = '\0'; + + write(fd, buf, sizeof(buf)); + close(fd); + setInitialState(); + } + + mEnabled = newState; + + if (!mEnabled && dev_name != NULL) { + close_device(); + } + } + return err; +} + +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 == ABS_DISTANCE) { + mPendingEvent.sensor = ID_PX; + mPendingEvent.type = SENSOR_TYPE_PROXIMITY; + mPendingEvent.distance = (float) 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_CM; + return index; +} diff --git a/libsensors/ProximitySensor.h b/libsensors/ProximitySensor.h new file mode 100644 index 0000000..f2fd87b --- /dev/null +++ b/libsensors/ProximitySensor.h @@ -0,0 +1,52 @@ +/* + * Copyright 2013 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 +#include +#include +#include + +#include "SensorBase.h" +#include "InputEventReader.h" +#include "sensors.h" + +/*****************************************************************************/ + +struct input_event; + +class ProximitySensor : public SensorBase { + int mEnabled; + InputEventCircularReader mInputReader; + sensors_event_t mPendingEvent; + bool mHasPendingEvent; + + 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/sensors.cpp b/libsensors/sensors.cpp new file mode 100644 index 0000000..5e167b4 --- /dev/null +++ b/libsensors/sensors.cpp @@ -0,0 +1,429 @@ +/* + * Copyright 2013 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 +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include + +#include "sensors.h" +#include "MPLSensor.h" +#include "LightSensor.h" +#include "ProximitySensor.h" + +/*****************************************************************************/ +/* The SENSORS Module */ + +#ifdef ENABLE_DMP_SCREEN_AUTO_ROTATION +#define GLOBAL_SENSORS (MPLSensor::NumSensors + 1) +#else +#define GLOBAL_SENSORS MPLSensor::NumSensors +#endif + +#define LOCAL_SENSORS (2) + +#define SENSORS_LIGHT_HANDLE (ID_L) +#define SENSORS_PROXIMITY_HANDLE (ID_PX) + +static struct sensor_t sSensorList[GLOBAL_SENSORS + LOCAL_SENSORS] = { + { + .name = "Light Sensor", + .vendor = "Avago Technologies", + .version = 1, + .handle = SENSORS_LIGHT_HANDLE, + .type = SENSOR_TYPE_LIGHT, + .maxRange = 30000.0f, + .resolution = 1.0f, + .power = 0.5f, + .minDelay = 100000, + {} + }, + { + .name = "Proximity Sensor", + .vendor = "Avago Technologies", + .version = 1, + .handle = SENSORS_PROXIMITY_HANDLE, + .type = SENSOR_TYPE_PROXIMITY, + .maxRange = 5.0f, + .resolution = 1.0f, + .power = 0.5f, + .minDelay = 100000, + {} + }, +}; +static int sensors = (sizeof(sSensorList) / sizeof(sensor_t)); + +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 sensors; +} + +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: "LGE Sensor module", + author: "LG Electronics Inc.", + methods: &sensors_module_methods, + dso: NULL, + reserved: {0} + }, + get_sensors_list: sensors__get_sensors_list, +}; + +struct sensors_poll_context_t { + sensors_poll_device_1_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); + int batch(int handle, int flags, int64_t period_ns, int64_t timeout); + +private: + enum { + mpl = 0, + compass, + dmpOrient, + dmpSign, + dmpPed, + light, + proximity, + numSensorDrivers, // wake pipe goes here + numFds, + }; + + static const size_t wake = numFds - 1; + static const char WAKE_MESSAGE = 'W'; + struct pollfd mPollFds[numFds]; + int mWritePipeFd; + SensorBase *mSensor[numSensorDrivers]; + CompassSensor *mCompassSensor; + + int handleToDriver(int handle) const { + switch (handle) { + case ID_GY: + case ID_RG: + case ID_A: + case ID_M: + case ID_RM: + case ID_PS: + case ID_O: + case ID_RV: + case ID_GRV: + case ID_LA: + case ID_GR: + case ID_SM: + case ID_P: + case ID_SC: + case ID_GMRV: + case ID_SO: + return mpl; + case ID_L: + return light; + case ID_PX: + return proximity; + } + return -EINVAL; + } +}; + +/******************************************************************************/ + +sensors_poll_context_t::sensors_poll_context_t() { + /* TODO: Handle external pressure sensor */ + mCompassSensor = new CompassSensor(); + MPLSensor *mplSensor = new MPLSensor(mCompassSensor); + // Must clean this up early or else the destructor will make a mess. + memset(mSensor, 0, sizeof(mSensor)); + + // setup the callback object for handing mpl callbacks + setCallbackObject(mplSensor); + + // populate the sensor list + sensors = LOCAL_SENSORS + + mplSensor->populateSensorList(sSensorList + LOCAL_SENSORS, + sizeof(sSensorList[0]) * (ARRAY_SIZE(sSensorList) - LOCAL_SENSORS)); + + mSensor[mpl] = mplSensor; + mPollFds[mpl].fd = mSensor[mpl]->getFd(); + mPollFds[mpl].events = POLLIN; + mPollFds[mpl].revents = 0; + + mSensor[compass] = mplSensor; + mPollFds[compass].fd = mCompassSensor->getFd(); + mPollFds[compass].events = POLLIN; + mPollFds[compass].revents = 0; + + mSensor[dmpOrient] = mplSensor; + mPollFds[dmpOrient].fd = ((MPLSensor*) mSensor[dmpOrient])->getDmpOrientFd(); + mPollFds[dmpOrient].events = POLLPRI; + mPollFds[dmpOrient].revents = 0; + + mSensor[dmpSign] = mplSensor; + mPollFds[dmpSign].fd = ((MPLSensor*) mSensor[dmpSign])->getDmpSignificantMotionFd(); + mPollFds[dmpSign].events = POLLPRI; + mPollFds[dmpSign].revents = 0; + + mSensor[dmpPed] = mplSensor; + mPollFds[dmpPed].fd = ((MPLSensor*) mSensor[dmpPed])->getDmpPedometerFd(); + mPollFds[dmpPed].events = POLLPRI; + mPollFds[dmpPed].revents = 0; + + mSensor[light] = new LightSensor(); + mPollFds[light].fd = mSensor[light]->getFd(); + mPollFds[light].events = POLLIN; + mPollFds[light].revents = 0; + + mSensor[proximity] = new ProximitySensor(); + mPollFds[proximity].fd = mSensor[proximity]->getFd(); + mPollFds[proximity].events = POLLIN; + mPollFds[proximity].revents = 0; + + /* Timer based sensor initialization */ + 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; +} + +sensors_poll_context_t::~sensors_poll_context_t() { + for (int i=0 ; ienable(handle, enabled); + if (!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 mSensor[index]->setDelay(handle, ns); +} + +int sensors_poll_context_t::pollEvents(sensors_event_t *data, int count) +{ + int nbEvents = 0; + int n = 0; + int nb, polltime = -1; + + do { + for (int i = 0; count && i < numSensorDrivers; i++) { + SensorBase* const sensor(mSensor[i]); + if (mPollFds[i].revents & (POLLIN | POLLPRI)) { + nb = 0; + if (i == mpl) { + ((MPLSensor*) sensor)->buildMpuEvent(); + mPollFds[i].revents = 0; + nb = ((MPLSensor*) sensor)->readEvents(data, count); + if (nb > 0) { + count -= nb; + nbEvents += nb; + data += nb; + } + } else if (i == compass) { + ((MPLSensor*) sensor)->buildCompassEvent(); + mPollFds[i].revents = 0; + nb = ((MPLSensor*) sensor)->readEvents(data, count); + if (nb > 0) { + count -= nb; + nbEvents += nb; + data += nb; + } + } else if (i == dmpOrient) { + nb = ((MPLSensor*) sensor)->readDmpOrientEvents(data, count); + mPollFds[dmpOrient].revents= 0; + if (isDmpScreenAutoRotationEnabled() && nb > 0) { + count -= nb; + nbEvents += nb; + data += nb; + } + } else if (i == dmpSign) { + ALOGI("HAL: dmpSign interrupt"); + nb = ((MPLSensor*) sensor)->readDmpSignificantMotionEvents(data, count); + mPollFds[i].revents = 0; + count -= nb; + nbEvents += nb; + data += nb; + } else if (i == dmpPed) { + ALOGI("HAL: dmpPed interrupt"); + nb = ((MPLSensor*) sensor)->readDmpPedometerEvents(data, count, ID_P, SENSOR_TYPE_STEP_DETECTOR, 0); + mPollFds[i].revents = 0; + count -= nb; + nbEvents += nb; + data += nb; + } else { + // LightSensor and ProximitySensor + nb = sensor->readEvents(data, count); + if (nb < count) { + // no more data for this sensor + mPollFds[i].revents = 0; + } + count -= nb; + nbEvents += nb; + data += nb; + } + ALOGI_IF(0, "sensors_mpl:readEvents() - nb=%d, count=%d, nbEvents=%d, data->timestamp=%lld, data->data[0]=%f,", + nb, count, nbEvents, data->timestamp, data->data[0]); + } + } + + /* to see if any step counter events */ + if (((MPLSensor*) mSensor[mpl])->hasStepCountPendingEvents() == true) { + nb = 0; + nb = ((MPLSensor*) mSensor[mpl])->readDmpPedometerEvents(data, count, ID_SC, SENSOR_TYPE_STEP_COUNTER, 0); + ALOGI_IF(0, "sensors_mpl:readStepCount() - nb=%d, count=%d, nbEvents=%d, data->timestamp=%lld, data->data[0]=%f,", + nb, count, nbEvents, data->timestamp, data->data[0]); + if (nb > 0) { + count -= nb; + nbEvents += nb; + data += nb; + } + } + if (count) { + do { + n = poll(mPollFds, numFds, nbEvents ? 0 : polltime); + } while (n < 0 && errno == EINTR); + if (n < 0) { + ALOGE("poll() failed (%s)", strerror(errno)); + return -errno; + } + if (mPollFds[wake].revents & (POLLIN | POLLPRI)) { + 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; + } + } + } while (n && count); + + return nbEvents; +} + +int sensors_poll_context_t::batch(int handle, int flags, int64_t period_ns, int64_t timeout) +{ + int index = handleToDriver(handle); + if (index < 0) return index; + return mSensor[index]->batch(handle, flags, period_ns, timeout); +} +/******************************************************************************/ + +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; + int s= ctx->setDelay(handle, ns); + return s; +} + +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); +} + +static int poll__batch(struct sensors_poll_device_1 *dev, + int handle, int flags, int64_t period_ns, int64_t timeout) +{ + sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev; + return ctx->batch(handle, flags, period_ns, timeout); +} +/******************************************************************************/ + +/** 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_1)); + + dev->device.common.tag = HARDWARE_DEVICE_TAG; + dev->device.common.version = SENSORS_DEVICE_API_VERSION_1_0; + dev->device.common.module = const_cast(module); + dev->device.common.close = poll__close; + dev->device.activate = poll__activate; + dev->device.setDelay = poll__setDelay; + dev->device.poll = poll__poll; + + /* Batch processing */ + dev->device.batch = poll__batch; + + *device = &dev->device.common; + status = 0; + + return status; +} diff --git a/libsensors/sensors.h b/libsensors/sensors.h new file mode 100644 index 0000000..6ea70e6 --- /dev/null +++ b/libsensors/sensors.h @@ -0,0 +1,67 @@ +/* + * Copyright 2013 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 +#include +#include +#include + +#include + +#include +#include + +__BEGIN_DECLS + +/*****************************************************************************/ + +#define I2C "/sys/bus/i2c/devices/3-0039/" +#define PROXIMITY_DATA "Avago proximity sensor" +#define LIGHT_DATA "Avago light sensor" +#define INPUT_EVENT_DEBUG (0) +#define DEBUG (0) + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) +#endif + +enum { + ID_GY = 0, + ID_RG, + ID_A, + ID_M, + ID_RM, + ID_PS, + ID_O, + ID_RV, + ID_GRV, + ID_LA, + ID_GR, + ID_SM, + ID_P, + ID_SC, + ID_GMRV, + ID_SO, + ID_L = 0x100, + ID_PX +}; + +__END_DECLS + +#endif // ANDROID_SENSORS_H