improvement to sensor hal
Change-Id: I72a73535e052b1867c1968a15ae255382e323e27
diff --git a/libsensors/AkmSensor.cpp b/libsensors/AkmSensor.cpp
index 6f30744..ef49c31 100644
--- a/libsensors/AkmSensor.cpp
+++ b/libsensors/AkmSensor.cpp
@@ -32,10 +32,9 @@
AkmSensor::AkmSensor()
: SensorBase(AKM_DEVICE_NAME, "compass"),
- mEnabled(0),
- mInputReader(32),
- mPendingMask(0),
- mLastEventIndex(0)
+ mEnabled(0),
+ mPendingMask(0),
+ mInputReader(32)
{
memset(mPendingEvents, 0, sizeof(mPendingEvents));
@@ -60,7 +59,7 @@
// read the actual value of all sensors if they're enabled already
struct input_absinfo absinfo;
- short flags;
+ short flags = 0;
if (!ioctl(dev_fd, ECS_IOCTL_APP_GET_AFLAG, &flags)) {
if (flags) {
mEnabled |= 1<<Accelerometer;
@@ -124,10 +123,10 @@
if (uint32_t(what) >= numSensors)
return -EINVAL;
- int flags = en ? 1 : 0;
+ int newState = en ? 1 : 0;
int err = 0;
- if ((uint32_t(flags)<<what) != (mEnabled & (1<<what))) {
+ if ((uint32_t(newState)<<what) != (mEnabled & (1<<what))) {
int cmd;
switch (what) {
case Accelerometer: cmd = ECS_IOCTL_APP_SET_AFLAG; break;
@@ -135,6 +134,7 @@
case Orientation: cmd = ECS_IOCTL_APP_SET_MFLAG; break;
case Temperature: cmd = ECS_IOCTL_APP_SET_TFLAG; break;
}
+ short flags = newState;
err = ioctl(dev_fd, cmd, &flags);
err = err<0 ? -errno : 0;
LOGE_IF(err, "ECS_IOCTL_APP_SET_XXX failed (%s)", strerror(-err));
@@ -186,9 +186,11 @@
if (mPendingMask & (1<<j)) {
mPendingMask &= ~(1<<j);
mPendingEvents[j].timestamp = time;
- *data++ = mPendingEvents[j];
- count--;
- numEventReceived++;
+ if (mEnabled & (1<<j)) {
+ *data++ = mPendingEvents[j];
+ count--;
+ numEventReceived++;
+ }
}
}
if (!mPendingMask) {
@@ -232,15 +234,15 @@
case EVENT_TYPE_YAW:
mPendingMask |= 1<<Orientation;
- mPendingEvents[Orientation].orientation.azimuth = value;
+ mPendingEvents[Orientation].orientation.azimuth = value * CONVERT_O_Y;
break;
case EVENT_TYPE_PITCH:
mPendingMask |= 1<<Orientation;
- mPendingEvents[Orientation].orientation.pitch = value;
+ mPendingEvents[Orientation].orientation.pitch = value * CONVERT_O_P;
break;
case EVENT_TYPE_ROLL:
mPendingMask |= 1<<Orientation;
- mPendingEvents[Orientation].orientation.roll = -value;
+ mPendingEvents[Orientation].orientation.roll = value * CONVERT_O_R;
break;
case EVENT_TYPE_ORIENT_STATUS:
mPendingMask |= 1<<Orientation;
diff --git a/libsensors/AkmSensor.h b/libsensors/AkmSensor.h
index b1833c4..adaa854 100644
--- a/libsensors/AkmSensor.h
+++ b/libsensors/AkmSensor.h
@@ -51,10 +51,9 @@
private:
uint32_t mEnabled;
- InputEventCircularReader mInputReader;
uint32_t mPendingMask;
+ InputEventCircularReader mInputReader;
sensors_event_t mPendingEvents[numSensors];
- int mLastEventIndex;
};
diff --git a/libsensors/InputEventReader.cpp b/libsensors/InputEventReader.cpp
index b69a1ef..1014f29 100644
--- a/libsensors/InputEventReader.cpp
+++ b/libsensors/InputEventReader.cpp
@@ -17,6 +17,7 @@
#include <stdint.h>
#include <errno.h>
#include <unistd.h>
+#include <poll.h>
#include <sys/cdefs.h>
#include <sys/types.h>
diff --git a/libsensors/LightSensor.cpp b/libsensors/LightSensor.cpp
index 86d1e0b..6d8ba1d 100644
--- a/libsensors/LightSensor.cpp
+++ b/libsensors/LightSensor.cpp
@@ -32,22 +32,19 @@
LightSensor::LightSensor()
: SensorBase(LS_DEVICE_NAME, "lightsensor-level"),
- mHasInitialValue(0),
mEnabled(0),
- mInputReader(4)
+ mInputReader(4),
+ mHasPendingEvent(false)
{
mPendingEvent.version = sizeof(sensors_event_t);
mPendingEvent.sensor = ID_L;
mPendingEvent.type = SENSOR_TYPE_LIGHT;
- mPendingEvent.reserved0 = 0;
- mPendingEvent.reserved1[0] = 0;
- mPendingEvent.reserved1[1] = 0;
- mPendingEvent.reserved1[2] = 0;
- mPendingEvent.reserved1[3] = 0;
+ memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
int flags = 0;
if (!ioctl(dev_fd, LIGHTSENSOR_IOCTL_GET_ENABLED, &flags)) {
if (flags) {
+ mEnabled = 1;
setInitialState();
}
}
@@ -60,7 +57,7 @@
struct input_absinfo absinfo;
if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_LIGHT), &absinfo)) {
mPendingEvent.light = indexToValue(absinfo.value);
- mHasInitialValue = 1;
+ mHasPendingEvent = true;
}
return 0;
}
@@ -82,23 +79,23 @@
return err;
}
+bool LightSensor::hasPendingEvents() const {
+ return mHasPendingEvent;
+}
+
int LightSensor::readEvents(sensors_event_t* data, int count)
{
if (count < 1)
return -EINVAL;
- if (mHasInitialValue) {
- struct timespec t;
- t.tv_sec = t.tv_nsec = 0;
- clock_gettime(CLOCK_MONOTONIC, &t);
- mHasInitialValue = 0;
- mPendingEvent.timestamp = int64_t(t.tv_sec)*1000000000LL + t.tv_nsec;
+ if (mHasPendingEvent) {
+ mHasPendingEvent = false;
+ mPendingEvent.timestamp = getTimestamp();
*data = mPendingEvent;
- return 1;
+ return mEnabled ? 1 : 0;
}
ssize_t n = mInputReader.fill(data_fd);
-
if (n < 0)
return n;
@@ -116,9 +113,11 @@
}
} else if (type == EV_SYN) {
mPendingEvent.timestamp = timevalToNano(event->time);
- *data++ = mPendingEvent;
- count--;
- numEventReceived++;
+ if (mEnabled) {
+ *data++ = mPendingEvent;
+ count--;
+ numEventReceived++;
+ }
}
mInputReader.next();
}
diff --git a/libsensors/LightSensor.h b/libsensors/LightSensor.h
index 16e7f30..b417853 100644
--- a/libsensors/LightSensor.h
+++ b/libsensors/LightSensor.h
@@ -31,20 +31,21 @@
struct input_event;
class LightSensor : public SensorBase {
- int mHasInitialValue;
int mEnabled;
InputEventCircularReader mInputReader;
sensors_event_t mPendingEvent;
+ bool mHasPendingEvent;
- int setInitialState();
float indexToValue(size_t index) const;
+ int setInitialState();
public:
- LightSensor();
- ~LightSensor();
+ LightSensor();
+ virtual ~LightSensor();
+ virtual int readEvents(sensors_event_t* data, int count);
+ virtual bool hasPendingEvents() const;
int enable(int enabled);
- int readEvents(sensors_event_t* data, int count);
};
/*****************************************************************************/
diff --git a/libsensors/ProximitySensor.cpp b/libsensors/ProximitySensor.cpp
index 89a6de4..2499915 100644
--- a/libsensors/ProximitySensor.cpp
+++ b/libsensors/ProximitySensor.cpp
@@ -32,21 +32,18 @@
ProximitySensor::ProximitySensor()
: SensorBase(CM_DEVICE_NAME, "proximity"),
- mHasInitialValue(0),
mEnabled(0),
- mInputReader(4)
+ mInputReader(4),
+ mHasPendingEvent(false)
{
mPendingEvent.version = sizeof(sensors_event_t);
mPendingEvent.sensor = ID_P;
mPendingEvent.type = SENSOR_TYPE_PROXIMITY;
- mPendingEvent.reserved0 = 0;
- mPendingEvent.reserved1[0] = 0;
- mPendingEvent.reserved1[1] = 0;
- mPendingEvent.reserved1[2] = 0;
- mPendingEvent.reserved1[3] = 0;
+ memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));
int flags = 0;
if (!ioctl(dev_fd, CAPELLA_CM3602_IOCTL_GET_ENABLED, &flags)) {
+ mEnabled = 1;
if (flags) {
setInitialState();
}
@@ -59,21 +56,23 @@
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);
- mHasInitialValue = 1;
}
return 0;
}
int ProximitySensor::enable(int en) {
- int flags = en ? 1 : 0;
+ int newState = en ? 1 : 0;
int err = 0;
- if (flags != mEnabled) {
+ if (newState != mEnabled) {
+ int flags = newState;
err = ioctl(dev_fd, CAPELLA_CM3602_IOCTL_ENABLE, &flags);
err = err<0 ? -errno : 0;
LOGE_IF(err, "CAPELLA_CM3602_IOCTL_ENABLE failed (%s)", strerror(-err));
if (!err) {
- mEnabled = en ? 1 : 0;
+ mEnabled = newState;
if (en) {
setInitialState();
}
@@ -82,19 +81,20 @@
return err;
}
+bool ProximitySensor::hasPendingEvents() const {
+ return mHasPendingEvent;
+}
+
int ProximitySensor::readEvents(sensors_event_t* data, int count)
{
if (count < 1)
return -EINVAL;
- if (mHasInitialValue) {
- struct timespec t;
- t.tv_sec = t.tv_nsec = 0;
- clock_gettime(CLOCK_MONOTONIC, &t);
- mHasInitialValue = 0;
- mPendingEvent.timestamp = int64_t(t.tv_sec)*1000000000LL + t.tv_nsec;
+ if (mHasPendingEvent) {
+ mHasPendingEvent = false;
+ mPendingEvent.timestamp = getTimestamp();
*data = mPendingEvent;
- return 1;
+ return mEnabled ? 1 : 0;
}
ssize_t n = mInputReader.fill(data_fd);
@@ -112,9 +112,11 @@
}
} else if (type == EV_SYN) {
mPendingEvent.timestamp = timevalToNano(event->time);
- *data++ = mPendingEvent;
- count--;
- numEventReceived++;
+ if (mEnabled) {
+ *data++ = mPendingEvent;
+ count--;
+ numEventReceived++;
+ }
}
mInputReader.next();
}
diff --git a/libsensors/ProximitySensor.h b/libsensors/ProximitySensor.h
index 5dcabf5..d9d74a9 100644
--- a/libsensors/ProximitySensor.h
+++ b/libsensors/ProximitySensor.h
@@ -31,20 +31,21 @@
struct input_event;
class ProximitySensor : public SensorBase {
- int mHasInitialValue;
int mEnabled;
InputEventCircularReader mInputReader;
sensors_event_t mPendingEvent;
+ bool mHasPendingEvent;
int setInitialState();
float indexToValue(size_t index) const;
public:
- ProximitySensor();
- ~ProximitySensor();
+ ProximitySensor();
+ virtual ~ProximitySensor();
+ virtual int readEvents(sensors_event_t* data, int count);
+ virtual bool hasPendingEvents() const;
int enable(int enabled);
- int readEvents(sensors_event_t* data, int count);
};
/*****************************************************************************/
diff --git a/libsensors/SensorBase.cpp b/libsensors/SensorBase.cpp
index 8df1f8c..55dae06 100644
--- a/libsensors/SensorBase.cpp
+++ b/libsensors/SensorBase.cpp
@@ -38,8 +38,10 @@
{
data_fd = openInput(data_name);
- dev_fd = open(dev_name, O_RDONLY);
- LOGE_IF(dev_fd<0, "Couldn't open %s (%s)", dev_name, strerror(errno));
+ if (dev_name) {
+ dev_fd = open(dev_name, O_RDONLY);
+ LOGE_IF(dev_fd<0, "Couldn't open %s (%s)", dev_name, strerror(errno));
+ }
}
SensorBase::~SensorBase() {
@@ -60,6 +62,17 @@
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";
diff --git a/libsensors/SensorBase.h b/libsensors/SensorBase.h
index 9bdb522..c0c4d15 100644
--- a/libsensors/SensorBase.h
+++ b/libsensors/SensorBase.h
@@ -25,6 +25,8 @@
/*****************************************************************************/
+struct sensors_event_t;
+
class SensorBase {
protected:
const char* dev_name;
@@ -33,20 +35,24 @@
int data_fd;
static 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;
}
- ~SensorBase();
-
public:
- SensorBase(
- const char* dev_name,
- const char* data_name);
+ SensorBase(
+ const char* dev_name,
+ const char* data_name);
- int getFd() const;
- int setDelay(int64_t ns);
+ virtual ~SensorBase();
+
+ virtual int readEvents(sensors_event_t* data, int count) = 0;
+ virtual bool hasPendingEvents() const;
+ virtual int getFd() const;
+ virtual int setDelay(int64_t ns);
};
/*****************************************************************************/
diff --git a/libsensors/nusensors.cpp b/libsensors/nusensors.cpp
index 0dc1d83..f94ad85 100644
--- a/libsensors/nusensors.cpp
+++ b/libsensors/nusensors.cpp
@@ -22,7 +22,6 @@
#include <poll.h>
#include <pthread.h>
-#include <sys/select.h>
#include <linux/input.h>
@@ -46,88 +45,116 @@
int pollEvents(sensors_event_t* data, int count);
private:
- struct pollfd mPollFds[3];
- LightSensor mLightSensor;
- ProximitySensor mProximitySensor;
- AkmSensor mAkmSensor;
+ enum {
+ light = 0,
+ proximity = 1,
+ akm = 2,
+ numSensorDrivers,
+ numFds,
+ };
+
+ static const size_t wake = numFds - 1;
+ static const char WAKE_MESSAGE = 'W';
+ struct pollfd mPollFds[numFds];
+ int mWritePipeFd;
+ SensorBase* mSensors[numSensorDrivers];
+
+ int handleToDriver(int handle) const {
+ switch (handle) {
+ case ID_A:
+ case ID_M:
+ case ID_O:
+ case ID_T:
+ return akm;
+ case ID_P:
+ return proximity;
+ case ID_L:
+ return light;
+ }
+ return -EINVAL;
+ }
};
/*****************************************************************************/
sensors_poll_context_t::sensors_poll_context_t()
{
- mPollFds[0].fd = mLightSensor.getFd();
- mPollFds[0].events = POLLIN;
- mPollFds[0].revents = 0;
+ mSensors[light] = new LightSensor();
+ mPollFds[light].fd = mSensors[light]->getFd();
+ mPollFds[light].events = POLLIN;
+ mPollFds[light].revents = 0;
- mPollFds[1].fd = mProximitySensor.getFd();
- mPollFds[1].events = POLLIN;
- mPollFds[1].revents = 0;
+ mSensors[proximity] = new ProximitySensor();
+ mPollFds[proximity].fd = mSensors[proximity]->getFd();
+ mPollFds[proximity].events = POLLIN;
+ mPollFds[proximity].revents = 0;
- mPollFds[2].fd = mAkmSensor.getFd();
- mPollFds[2].events = POLLIN;
- mPollFds[2].revents = 0;
+ mSensors[akm] = new AkmSensor();
+ mPollFds[akm].fd = mSensors[akm]->getFd();
+ mPollFds[akm].events = POLLIN;
+ mPollFds[akm].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;
}
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 = -EINVAL;
- int idx = -1;
switch (handle) {
case ID_A:
- err = mAkmSensor.enable(AkmSensor::Accelerometer, enabled);
- idx = 2;
+ err = static_cast<AkmSensor*>(
+ mSensors[akm])->enable(AkmSensor::Accelerometer, enabled);
break;
case ID_M:
- err = mAkmSensor.enable(AkmSensor::MagneticField, enabled);
- idx = 2;
+ err = static_cast<AkmSensor*>(
+ mSensors[akm])->enable(AkmSensor::MagneticField, enabled);
break;
case ID_O:
- err = mAkmSensor.enable(AkmSensor::Orientation, enabled);
- idx = 2;
+ err = static_cast<AkmSensor*>(
+ mSensors[akm])->enable(AkmSensor::Orientation, enabled);
break;
case ID_T:
- err = mAkmSensor.enable(AkmSensor::Temperature, enabled);
- idx = 2;
+ err = static_cast<AkmSensor*>(
+ mSensors[akm])->enable(AkmSensor::Temperature, enabled);
break;
case ID_P:
- err = mProximitySensor.enable(enabled);
- idx = 1;
+ err = static_cast<ProximitySensor*>(
+ mSensors[proximity])->enable(enabled);
break;
case ID_L:
- err = mLightSensor.enable(enabled);
- idx = 0;
+ err = static_cast<LightSensor*>(
+ mSensors[light])->enable(enabled);
break;
}
-
- if (!err && enabled && idx>=0) {
- // pretend there is an event, so we return "something" asap.
- mPollFds[idx].revents = POLLIN;
+ if (enabled && !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) {
- switch (handle) {
- case ID_A:
- case ID_M:
- case ID_O:
- case ID_T:
- mAkmSensor.setDelay(ns);
- break;
- case ID_P:
- mProximitySensor.setDelay(ns);
- break;
- case ID_L:
- mLightSensor.setDelay(ns);
- break;
- default:
- return -EINVAL;
- }
- return 0;
+
+ int index = handleToDriver(handle);
+ if (index < 0) return index;
+ return mSensors[index]->setDelay(ns);
}
int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
@@ -137,17 +164,10 @@
do {
// see if we have some leftover from the last poll()
- for (int i=0 ; count && i<3 ; i++) {
- if (mPollFds[i].revents & POLLIN) {
- int nb = 0;
- if (i == 0) {
- nb = mLightSensor.readEvents(data, count);
- } else if (i == 1) {
- nb = mProximitySensor.readEvents(data, count);
- } else if (i == 2) {
- nb = mAkmSensor.readEvents(data, count);
- }
-
+ 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;
@@ -160,13 +180,20 @@
if (count) {
// we still have some room, so try to see if we can get
- // some events immediately or just wait we we don't have
+ // some events immediately or just wait if we don't have
// anything to return
- n = poll(mPollFds, 3, nbEvents ? 0 : -1);
+ n = poll(mPollFds, numFds, nbEvents ? 0 : -1);
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 we have events and space, go read them
} while (n && count);
diff --git a/libsensors/nusensors.h b/libsensors/nusensors.h
index 1023cf1..60e819a 100644
--- a/libsensors/nusensors.h
+++ b/libsensors/nusensors.h
@@ -60,9 +60,6 @@
#define CM_DEVICE_NAME "/dev/cm3602"
#define LS_DEVICE_NAME "/dev/lightsensor"
-
-// sensor IDs must be a power of two and
-// must match values in SensorManager.java
#define EVENT_TYPE_ACCEL_X ABS_X
#define EVENT_TYPE_ACCEL_Y ABS_Z
#define EVENT_TYPE_ACCEL_Z ABS_Y
@@ -98,6 +95,11 @@
#define CONVERT_M_Y (-CONVERT_M)
#define CONVERT_M_Z (CONVERT_M)
+#define CONVERT_O (1.0f)
+#define CONVERT_O_Y (CONVERT_M)
+#define CONVERT_O_P (CONVERT_M)
+#define CONVERT_O_R (-CONVERT_M)
+
#define SENSOR_STATE_MASK (0x7FFF)
/*****************************************************************************/