398 lines
12 KiB
C++
Executable File
398 lines
12 KiB
C++
Executable File
/*
|
|
* 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 <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 <cutils/atomic.h>
|
|
#include <math.h>
|
|
|
|
#include "nusensors.h"
|
|
#include "LightSensor.h"
|
|
#include "ProximitySensor.h"
|
|
#include "MmaSensor.h"
|
|
#include "AkmSensor.h"
|
|
#include "GyroSensor.h"
|
|
#include "PressureSensor.h"
|
|
#include "TemperatureSensor.h"
|
|
|
|
/*****************************************************************************/
|
|
|
|
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);
|
|
int flush(int handle);
|
|
bool getInitialized() { return mInitialized; };
|
|
|
|
private:
|
|
bool mInitialized;
|
|
|
|
enum {
|
|
light = 0,
|
|
proximity = 1,
|
|
mma = 2,
|
|
akm = 3,
|
|
gyro = 4,
|
|
pressure = 5,
|
|
temperature = 6,
|
|
numSensorDrivers,
|
|
numFds,
|
|
};
|
|
|
|
static const size_t flushPipe = numFds - 1;
|
|
struct pollfd mPollFds[numFds];
|
|
int mFlushWritePipeFd;
|
|
SensorBase* mSensors[numSensorDrivers];
|
|
|
|
int handleToDriver(int handle) const {
|
|
switch (handle) {
|
|
case ID_A:
|
|
return mma;
|
|
case ID_M:
|
|
return akm;
|
|
case ID_P:
|
|
return proximity;
|
|
case ID_L:
|
|
return light;
|
|
case ID_GY:
|
|
return gyro;
|
|
case ID_PR:
|
|
return pressure;
|
|
case ID_TMP:
|
|
return temperature;
|
|
}
|
|
return -EINVAL;
|
|
}
|
|
};
|
|
|
|
/*****************************************************************************/
|
|
|
|
sensors_poll_context_t::sensors_poll_context_t()
|
|
{
|
|
mInitialized = false;
|
|
/* Must clean this up early or else the destructor will make a mess */
|
|
memset(mSensors, 0, sizeof(mSensors));
|
|
|
|
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[mma] = new MmaSensor();
|
|
mPollFds[mma].fd = mSensors[mma]->getFd();
|
|
mPollFds[mma].events = POLLIN;
|
|
mPollFds[mma].revents = 0;
|
|
|
|
mSensors[akm] = new AkmSensor();
|
|
mPollFds[akm].fd = mSensors[akm]->getFd();
|
|
mPollFds[akm].events = POLLIN;
|
|
mPollFds[akm].revents = 0;
|
|
|
|
mSensors[gyro] = new GyroSensor();
|
|
mPollFds[gyro].fd = mSensors[gyro]->getFd();
|
|
mPollFds[gyro].events = POLLIN;
|
|
mPollFds[gyro].revents = 0;
|
|
|
|
mSensors[pressure] = new PressureSensor();
|
|
mPollFds[pressure].fd = mSensors[pressure]->getFd();
|
|
mPollFds[pressure].events = POLLIN;
|
|
mPollFds[pressure].revents = 0;
|
|
|
|
mSensors[temperature] = new TemperatureSensor();
|
|
mPollFds[temperature].fd = mSensors[temperature]->getFd();
|
|
mPollFds[temperature].events = POLLIN;
|
|
mPollFds[temperature].revents = 0;
|
|
|
|
int flushFds[2];
|
|
int result = pipe(flushFds);
|
|
LOGE_IF(result<0, "error creating flush pipe (%s)", strerror(errno));
|
|
result = fcntl(flushFds[0], F_SETFL, O_NONBLOCK);
|
|
LOGE_IF(result<0, "error setting flushFds[0] access mode (%s)", strerror(errno));
|
|
result = fcntl(flushFds[1], F_SETFL, O_NONBLOCK);
|
|
LOGE_IF(result<0, "error setting flushFds[1] access mode (%s)", strerror(errno));
|
|
mFlushWritePipeFd = flushFds[1];
|
|
|
|
mPollFds[flushPipe].fd = flushFds[0];
|
|
mPollFds[flushPipe].events = POLLIN;
|
|
mPollFds[flushPipe].revents = 0;
|
|
|
|
mInitialized = true;
|
|
}
|
|
|
|
sensors_poll_context_t::~sensors_poll_context_t() {
|
|
for (int i=0 ; i<numSensorDrivers ; i++) {
|
|
delete mSensors[i];
|
|
}
|
|
close(mPollFds[flushPipe].fd);
|
|
close(mFlushWritePipeFd);
|
|
mInitialized = false;
|
|
}
|
|
|
|
int sensors_poll_context_t::activate(int handle, int enabled) {
|
|
if (!mInitialized) return -EINVAL;
|
|
int index = handleToDriver(handle);
|
|
if (index < 0) return index;
|
|
return mSensors[index]->enable(handle, enabled);
|
|
}
|
|
|
|
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::flush(int handle)
|
|
{
|
|
int result;
|
|
sensors_event_t flush_event_data;
|
|
|
|
int index = handleToDriver(handle);
|
|
if (index < 0) return index;
|
|
|
|
result = mSensors[index]->isActivated(handle);
|
|
if (!result)
|
|
return -EINVAL;
|
|
|
|
flush_event_data.sensor = 0;
|
|
flush_event_data.timestamp = 0;
|
|
flush_event_data.meta_data.sensor = handle;
|
|
flush_event_data.meta_data.what = META_DATA_FLUSH_COMPLETE;
|
|
flush_event_data.type = SENSOR_TYPE_META_DATA;
|
|
flush_event_data.version = META_DATA_VERSION;
|
|
|
|
result = write(mFlushWritePipeFd, &flush_event_data, sizeof(sensors_event_t));
|
|
ALOGE_IF(result<0, "error sending flush event data (%s)", strerror(errno));
|
|
|
|
return (result >= 0 ? 0 : result);
|
|
}
|
|
|
|
static int64_t tm_min=0;
|
|
static int64_t tm_max=0;
|
|
static int64_t tm_sum=0;
|
|
static int64_t tm_last_print=0;
|
|
static int64_t tm_count=0;
|
|
|
|
static int debug_time = 0;
|
|
static int debug_lvl = 0;
|
|
|
|
#define NSEC_PER_SEC 1000000000
|
|
#include <cutils/properties.h>
|
|
|
|
static inline int64_t timespec_to_ns(const struct timespec *ts)
|
|
{
|
|
return ((int64_t) ts->tv_sec * NSEC_PER_SEC) + ts->tv_nsec;
|
|
}
|
|
|
|
static int64_t get_time_ns(void)
|
|
{
|
|
struct timespec ts;
|
|
clock_gettime(CLOCK_MONOTONIC, &ts);
|
|
return timespec_to_ns(&ts);
|
|
}
|
|
|
|
int sensors_poll_context_t::pollEvents(sensors_event_t* data, int count)
|
|
{
|
|
int nbEvents = 0;
|
|
int nb, polltime = -1;
|
|
|
|
// look for new events
|
|
nb = poll(mPollFds, numFds, polltime);
|
|
|
|
/* flush event data */
|
|
if ((count > 0) && (nb > 0)) {
|
|
if (mPollFds[flushPipe].revents & POLLIN) {
|
|
int n = read(mPollFds[flushPipe].fd, data, count * sizeof(sensors_event_t));
|
|
if (n < 0) {
|
|
LOGE("error reading from flush pipe (%s)", strerror(errno));
|
|
return 0;
|
|
}
|
|
nb = n / sizeof(sensors_event_t);
|
|
mPollFds[flushPipe].revents = 0;
|
|
count -= nb;
|
|
nbEvents += nb;
|
|
data += nb;
|
|
LOGI("report %d flush event\n", nbEvents);
|
|
return nbEvents;
|
|
}
|
|
}
|
|
|
|
if (nb > 0) {
|
|
for (int i=0 ; count && i < numSensorDrivers ; i++) {
|
|
SensorBase* const sensor(mSensors[i]);
|
|
if (mPollFds[i].revents & POLLIN) {
|
|
nb = 0;
|
|
nb = sensor->readEvents(data, count);
|
|
mPollFds[i].revents = 0;
|
|
|
|
//LOGI("count = %d, nbEvents = %d, nb = %d\n", count, nbEvents, nb);
|
|
if (nb > 0) {
|
|
if (debug_time) {
|
|
int64_t tm_cur = get_time_ns();
|
|
int64_t tm_delta = tm_cur - data->timestamp;
|
|
if (tm_min==0 && tm_max==0)
|
|
tm_min = tm_max = tm_delta;
|
|
else if (tm_delta < tm_min)
|
|
tm_min = tm_delta;
|
|
else if (tm_delta > tm_max)
|
|
tm_max = tm_delta;
|
|
tm_sum += tm_delta;
|
|
tm_count++;
|
|
//LOGI("tm_count = %d\n", tm_count);
|
|
if ((tm_cur-tm_last_print) > 1000000000) {
|
|
LOGD("ST HAL report rate[%4lld]: %8lld, %8lld, %8lld\n", (long long)tm_count, (long long)tm_min, (long long)(tm_sum/tm_count), (long long)tm_max);
|
|
tm_last_print = tm_cur;
|
|
tm_min = tm_max = tm_count = tm_sum = 0;
|
|
}
|
|
}
|
|
|
|
if (debug_lvl > 0) {
|
|
for (int j=0; j<nb; j++) {
|
|
if ((debug_lvl&1) && data[j].sensor==ID_GY) {
|
|
LOGD("GYRO: %+f %+f %+f - %lld", data[j].gyro.x, data[j].gyro.y, data[j].gyro.z, (long long)data[j].timestamp);
|
|
}
|
|
if ((debug_lvl&2) && data[j].sensor==ID_A) {
|
|
LOGD("ACCL: %+f %+f %+f - %lld", data[j].acceleration.x, data[j].acceleration.y, data[j].acceleration.z, (long long)data[j].timestamp);
|
|
}
|
|
if ((debug_lvl&4) && (data[j].sensor==ID_M)) {
|
|
LOGD("MAG: %+f %+f %+f - %lld", data[j].magnetic.x, data[j].magnetic.y, data[j].magnetic.z, (long long)data[j].timestamp);
|
|
}
|
|
}
|
|
}
|
|
|
|
count -= nb;
|
|
nbEvents += nb;
|
|
data += nb;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
LOGI("set active: handle = %d, enable = %d\n", handle, enabled);
|
|
|
|
char propbuf[PROPERTY_VALUE_MAX];
|
|
property_get("vendor.sensor.debug.level", propbuf, "0");
|
|
debug_lvl = atoi(propbuf);
|
|
|
|
memset(propbuf, 0, sizeof(propbuf));
|
|
property_get("vendor.sensor.debug.time", propbuf, "0");
|
|
debug_time = atoi(propbuf);
|
|
|
|
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;
|
|
|
|
LOGI("set delay: handle = %d, delay = %dns\n", handle, (int)ns);
|
|
|
|
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);
|
|
}
|
|
|
|
static int poll__batch(struct sensors_poll_device_1 *dev,
|
|
int handle, int flags, int64_t period_ns, int64_t timeout)
|
|
{
|
|
LOGI("set batch: handle = %d, period_ns = %dns, timeout = %dns\n", handle, (int)period_ns, (int)timeout);
|
|
|
|
sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
|
|
return ctx->setDelay(handle, period_ns);
|
|
}
|
|
|
|
static int poll__flush(struct sensors_poll_device_1 *dev,
|
|
int handle)
|
|
{
|
|
LOGI("set flush: handle = %d\n", handle);
|
|
sensors_poll_context_t *ctx = (sensors_poll_context_t *)dev;
|
|
return ctx->flush(handle);
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
|
|
int init_nusensors(hw_module_t const* module, hw_device_t** device)
|
|
{
|
|
LOGD("%s\n",SENSOR_VERSION_AND_TIME);
|
|
int status = -EINVAL;
|
|
|
|
sensors_poll_context_t *dev = new sensors_poll_context_t();
|
|
if (!dev->getInitialized()) {
|
|
LOGE("Failed to open the sensors");
|
|
return status;
|
|
}
|
|
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_3;
|
|
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;
|
|
|
|
/* Batch processing */
|
|
dev->device.batch = poll__batch;
|
|
dev->device.flush = poll__flush;
|
|
|
|
*device = &dev->device.common;
|
|
|
|
status = 0;
|
|
return status;
|
|
}
|