From cb410ba6658ed29c7ad59cc789ac95d95e912e0a Mon Sep 17 00:00:00 2001 From: Marty Fouts Date: Mon, 27 Jun 2011 22:40:40 -0700 Subject: tuna: sensors: add light, proximity, pressure sensors NOTE: - light sensor ADC values need to be calibrated. Change-Id: Iba75dc62a922bbcd0d1e273566f9089c4da450fb Signed-off-by: Marty Fouts --- libsensors/Android.mk | 6 +- libsensors/LightSensor.cpp | 68 +++++++++++++++ libsensors/LightSensor.h | 44 ++++++++++ libsensors/PressureSensor.cpp | 45 ++++++++++ libsensors/PressureSensor.h | 43 ++++++++++ libsensors/ProximitySensor.cpp | 70 +++++++++++++++ libsensors/ProximitySensor.h | 51 +++++++++++ libsensors/SamsungSensorBase.cpp | 179 +++++++++++++++++++++++++++++++++++++++ libsensors/SamsungSensorBase.h | 59 +++++++++++++ libsensors/sensors.cpp | 49 ++++++++++- libsensors/sensors.h | 3 + 11 files changed, 613 insertions(+), 4 deletions(-) create mode 100644 libsensors/LightSensor.cpp create mode 100644 libsensors/LightSensor.h create mode 100644 libsensors/PressureSensor.cpp create mode 100644 libsensors/PressureSensor.h create mode 100644 libsensors/ProximitySensor.cpp create mode 100644 libsensors/ProximitySensor.h create mode 100644 libsensors/SamsungSensorBase.cpp create mode 100644 libsensors/SamsungSensorBase.h (limited to 'libsensors') diff --git a/libsensors/Android.mk b/libsensors/Android.mk index 5fe88f4..d936b2f 100644 --- a/libsensors/Android.mk +++ b/libsensors/Android.mk @@ -31,7 +31,11 @@ LOCAL_CFLAGS := -DLOG_TAG=\"Sensors\" LOCAL_C_INCLUDES += vendor/invensense/libsensors LOCAL_SRC_FILES := \ sensors.cpp \ - InputEventReader.cpp + InputEventReader.cpp \ + LightSensor.cpp \ + ProximitySensor.cpp \ + PressureSensor.cpp \ + SamsungSensorBase.cpp LOCAL_SHARED_LIBRARIES := libinvensense_hal libcutils libutils libdl diff --git a/libsensors/LightSensor.cpp b/libsensors/LightSensor.cpp new file mode 100644 index 0000000..067654f --- /dev/null +++ b/libsensors/LightSensor.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2011 Samsung + * + * 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 "LightSensor.h" + +LightSensor::LightSensor() + : SamsungSensorBase(NULL, "lightsensor-level", ABS_MISC) +{ + mPendingEvent.sensor = ID_L; + mPendingEvent.type = SENSOR_TYPE_LIGHT; + mPreviousLight = -1; +} + +bool LightSensor::handleEvent(input_event const *event) { + mPendingEvent.light = indexToValue(event->value); + if (mPendingEvent.light != mPreviousLight) { + mPreviousLight = mPendingEvent.light; + return true; + } + return false; +} + +float LightSensor::indexToValue(size_t index) const { + /* Driver gives a rolling average adc value. We convert it lux levels. */ + static const struct adcToLux { + size_t adc_value; + float lux_value; + } adcToLux[] = { + { 150, 10.0 }, /* from 0 - 150 adc, we map to 10.0 lux */ + { 800, 160.0 }, /* from 151 - 800 adc, we map to 160.0 lux */ + { 900, 225.0 }, /* from 801 - 900 adc, we map to 225.0 lux */ + { 1000, 320.0 }, /* from 901 - 1000 adc, we map to 320.0 lux */ + { 1200, 640.0 }, /* from 1001 - 1200 adc, we map to 640.0 lux */ + { 1400, 1280.0 }, /* from 1201 - 1400 adc, we map to 1280.0 lux */ + { 1600, 2600.0 }, /* from 1401 - 1600 adc, we map to 2600.0 lux */ + { 4095, 10240.0 }, /* from 1601 - 4095 adc, we map to 10240.0 lux */ + }; + size_t i; + for (i = 0; i < ARRAY_SIZE(adcToLux); i++) { + if (index < adcToLux[i].adc_value) { + return adcToLux[i].lux_value; + } + } + return adcToLux[ARRAY_SIZE(adcToLux)-1].lux_value; +} diff --git a/libsensors/LightSensor.h b/libsensors/LightSensor.h new file mode 100644 index 0000000..ed639f4 --- /dev/null +++ b/libsensors/LightSensor.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2011 Samsung + * + * 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 "sensors.h" +#include "SamsungSensorBase.h" +#include "InputEventReader.h" + +/*****************************************************************************/ + +struct input_event; + +class LightSensor:public SamsungSensorBase { + + float mPreviousLight; + virtual bool handleEvent(input_event const * event); + float indexToValue(size_t index) const; +public: + LightSensor(); +}; + +/*****************************************************************************/ + +#endif /* ANDROID_LIGHT_SENSOR_H */ diff --git a/libsensors/PressureSensor.cpp b/libsensors/PressureSensor.cpp new file mode 100644 index 0000000..dc34b95 --- /dev/null +++ b/libsensors/PressureSensor.cpp @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2011 Samsung + * + * 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 "PressureSensor.h" + +/* + * The BMP driver gives pascal values. + * It needs to be changed into hectoPascal + */ +#define PRESSURE_HECTO (1.0f/100.0f) + +PressureSensor::PressureSensor() + : SamsungSensorBase(NULL, "barometer", ABS_PRESSURE) +{ + mPendingEvent.sensor = ID_PR; + mPendingEvent.type = SENSOR_TYPE_PRESSURE; +} + +bool PressureSensor::handleEvent(input_event const *event) { + mPendingEvent.pressure = event->value * PRESSURE_HECTO; + return true; +} diff --git a/libsensors/PressureSensor.h b/libsensors/PressureSensor.h new file mode 100644 index 0000000..183bfd3 --- /dev/null +++ b/libsensors/PressureSensor.h @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2011 Samsung + * + * 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_PRESSURE_SENSOR_H +#define ANDROID_PRESSURE_SENSOR_H + +#include +#include +#include +#include + +#include "sensors.h" +#include "SamsungSensorBase.h" +#include "InputEventReader.h" + +/*****************************************************************************/ + +struct input_event; + +class PressureSensor:public SamsungSensorBase { + virtual bool handleEvent(input_event const * event); + +public: + PressureSensor(); +}; + +/*****************************************************************************/ + +#endif /* ANDROID_PRESSURE_SENSOR_H */ + diff --git a/libsensors/ProximitySensor.cpp b/libsensors/ProximitySensor.cpp new file mode 100644 index 0000000..4e1ec9d --- /dev/null +++ b/libsensors/ProximitySensor.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2011 Samsung + * + * 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 "ProximitySensor.h" + +/*****************************************************************************/ + +ProximitySensor::ProximitySensor() + : SamsungSensorBase(NULL, "proximity", ABS_DISTANCE) +{ + mPendingEvent.sensor = ID_P; + mPendingEvent.type = SENSOR_TYPE_PROXIMITY; +} + +int ProximitySensor::setDelay(int32_t handle, int64_t ns) +{ + return -1; +} + +float ProximitySensor::indexToValue(size_t index) const +{ + return index * PROXIMITY_THRESHOLD_GP2A; +} + +bool ProximitySensor::hasPendingEvents() const { + return mHasPendingEvent; +} + +int ProximitySensor::handleEnable(int en) { + if (!en) + return 0; + + struct input_absinfo absinfo; + if (!ioctl(data_fd, EVIOCGABS(ABS_DISTANCE), &absinfo)) { + mHasPendingEvent = true; + mPendingEvent.distance = indexToValue(absinfo.value); + return 0; + } else { + return -1; + } +} + +bool ProximitySensor::handleEvent(input_event const *event) { + mPendingEvent.distance = indexToValue(event->value); + return true; +} diff --git a/libsensors/ProximitySensor.h b/libsensors/ProximitySensor.h new file mode 100644 index 0000000..36b79d1 --- /dev/null +++ b/libsensors/ProximitySensor.h @@ -0,0 +1,51 @@ +/* + * Copyright (C) 2011 Samsung + * + * 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 "sensors.h" +#include "SamsungSensorBase.h" +#include "InputEventReader.h" + +/* the GP2A is a binary proximity sensor that triggers around 5 cm on + * this hardware */ +#define PROXIMITY_THRESHOLD_GP2A 5.0f + +/*****************************************************************************/ + +struct input_event; + +class ProximitySensor:public SamsungSensorBase { + + virtual int handleEnable(int en); + virtual bool handleEvent(input_event const * event); + + float indexToValue(size_t index) const; +public: + ProximitySensor(); + virtual int setDelay(int32_t handle, int64_t ns); + virtual bool hasPendingEvents() const; +}; + +/*****************************************************************************/ + +#endif /* ANDROID_PROXIMITY_SENSOR_H */ diff --git a/libsensors/SamsungSensorBase.cpp b/libsensors/SamsungSensorBase.cpp new file mode 100644 index 0000000..ab8f9d6 --- /dev/null +++ b/libsensors/SamsungSensorBase.cpp @@ -0,0 +1,179 @@ +/* + * Copyright (C) 2011 Samsung + * + * 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 "SamsungSensorBase.h" + +char *SamsungSensorBase::makeSysfsName(const char *input_name, + const char *file_name) { + char *name; + int length = strlen("/sys/class/input/") + + strlen(input_name) + + strlen("/device/") + + strlen(file_name); + + name = new char[length + 1]; + if (name) { + strcpy(name, "/sys/class/input/"); + strcat(name, input_name); + strcat(name, "/device/"); + strcat(name, file_name); + } + + return name; +} + +bool SamsungSensorBase::handleEvent(input_event const * event) { + return true; +} + +int SamsungSensorBase::handleEnable(int en) { + return 0; +} + +SamsungSensorBase::SamsungSensorBase(const char *dev_name, + const char *data_name, + int sensor_code) + : SensorBase(dev_name, data_name), + mEnabled(true), + mHasPendingEvent(false), + mInputReader(4), + mSensorCode(sensor_code), + mLock(PTHREAD_MUTEX_INITIALIZER) +{ + mPendingEvent.version = sizeof(sensors_event_t); + memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data)); + if (!data_fd) + return; + mInputSysfsEnable = makeSysfsName(input_name, "enable"); + if (!mInputSysfsEnable) { + LOGE("%s: unable to allocate mem for %s:enable", __func__, + data_name); + return; + } + mInputSysfsPollDelay = makeSysfsName(input_name, "poll_delay"); + if (!mInputSysfsPollDelay) { + LOGE("%s: unable to allocate mem for %s:poll_delay", __func__, + data_name); + return; + } + + int flags = fcntl(data_fd, F_GETFL, 0); + fcntl(data_fd, F_SETFL, flags | O_NONBLOCK); + + enable(0, 0); +} + +SamsungSensorBase::~SamsungSensorBase() { + if (mEnabled) { + enable(0, 0); + } + delete[] mInputSysfsEnable; + delete[] mInputSysfsPollDelay; +} + +int SamsungSensorBase::enable(int32_t handle, int en) +{ + int err = 0; + pthread_mutex_lock(&mLock); + if (en != mEnabled) { + int fd; + fd = open(mInputSysfsEnable, O_RDWR); + if (fd >= 0) { + err = write(fd, en ? "1" : "0", 2); + close(fd); + if (err < 0) { + goto cleanup; + } + mEnabled = en; + err = handleEnable(en); + } else { + err = -1; + } + } +cleanup: + pthread_mutex_unlock(&mLock); + return err; +} + +int SamsungSensorBase::setDelay(int32_t handle, int64_t ns) +{ + int fd; + int result = 0; + char buf[21]; + pthread_mutex_lock(&mLock); + fd = open(mInputSysfsPollDelay, O_RDWR); + if (fd < 0) { + result = -1; + goto done; + } + sprintf(buf, "%lld", ns); + write(fd, buf, strlen(buf)+1); + close(fd); +done: + pthread_mutex_unlock(&mLock); + return result; +} + +int SamsungSensorBase::readEvents(sensors_event_t* data, int count) +{ + if (count < 1) + return -EINVAL; + + pthread_mutex_lock(&mLock); + int numEventReceived = 0; + + if (!mEnabled) + goto done; + + if (mHasPendingEvent) { + mHasPendingEvent = false; + mPendingEvent.timestamp = getTimestamp(); + *data = mPendingEvent; + numEventReceived++; + goto done; + } + + input_event const* event; + while (count && mInputReader.readEvent(data_fd, &event)) { + if (event->type == EV_ABS) { + if (event->code == mSensorCode) { + if (handleEvent(event)) { + mPendingEvent.timestamp = timevalToNano(event->time); + *data++ = mPendingEvent; + count--; + numEventReceived++; + } + } + } + mInputReader.next(); + } + +done: + pthread_mutex_unlock(&mLock); + return numEventReceived; + +} diff --git a/libsensors/SamsungSensorBase.h b/libsensors/SamsungSensorBase.h new file mode 100644 index 0000000..c989c71 --- /dev/null +++ b/libsensors/SamsungSensorBase.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2011 Samsung + * + * 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 SAMSUNG_SENSORBASE_H +#define SAMSUNG_SENSORBASE_H + +#include +#include +#include +#include + +#include "sensors.h" +#include "SensorBase.h" +#include "SamsungSensorBase.h" +#include "InputEventReader.h" + +/*****************************************************************************/ + +class SamsungSensorBase:public SensorBase { +protected: + bool mEnabled; + bool mHasPendingEvent; + InputEventCircularReader mInputReader; + sensors_event_t mPendingEvent; + char *mInputSysfsEnable; + char *mInputSysfsPollDelay; + int mSensorCode; + pthread_mutex_t mLock; + + char *makeSysfsName(const char *input_name, + const char *input_file); + + virtual int handleEnable(int en); + virtual bool handleEvent(input_event const * event); + +public: + SamsungSensorBase(const char* dev_name, + const char* data_name, + int sensor_code); + + virtual ~SamsungSensorBase(); + virtual int enable(int32_t handle, int en); + virtual int setDelay(int32_t handle, int64_t ns); + virtual int readEvents(sensors_event_t *data, int count); +}; +#endif /* SAMSUNG_SENSORBASE_H */ diff --git a/libsensors/sensors.cpp b/libsensors/sensors.cpp index f9dd0ef..ab2c571 100644 --- a/libsensors/sensors.cpp +++ b/libsensors/sensors.cpp @@ -35,6 +35,10 @@ #include "sensors.h" #include "MPLSensor.h" +#include "LightSensor.h" +#include "ProximitySensor.h" +#include "PressureSensor.h" + /*****************************************************************************/ @@ -49,6 +53,9 @@ #define SENSORS_ACCELERATION (1<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[pressure] = new PressureSensor(); + mPollFds[pressure].fd = mSensors[pressure]->getFd(); + mPollFds[pressure].events = POLLIN; + mPollFds[pressure].revents = 0; + int wakeFds[2]; int result = pipe(wakeFds); LOGE_IF(result<0, "error creating wake pipe (%s)", strerror(errno)); diff --git a/libsensors/sensors.h b/libsensors/sensors.h index 4628865..49610ca 100644 --- a/libsensors/sensors.h +++ b/libsensors/sensors.h @@ -45,6 +45,9 @@ __BEGIN_DECLS #define ID_A (ID_GY + 1) #define ID_M (ID_A + 1) #define ID_O (ID_M + 1) +#define ID_L (ID_O + 1) +#define ID_P (ID_L + 1) +#define ID_PR (ID_P + 1) /*****************************************************************************/ -- cgit v1.1