blob: 83da79f2f99c17b224d58944901e6594d861c367 [file] [log] [blame]
/*
* STMicroelectronics SW Sensor Base Class
*
* Copyright 2013-2015 STMicroelectronics Inc.
* Author: Denis Ciocca - <denis.ciocca@st.com>
*
* Licensed under the Apache License, Version 2.0 (the "License").
*/
#include <fcntl.h>
#include <assert.h>
#include <string.h>
#include "SWSensorBase.h"
SWSensorBase::SWSensorBase(const char *name, int handle, int sensor_type, int pipe_data_fd,
bool use_dependency_resolution, bool use_dependency_range, bool use_dependency_delay,
bool use_dependency_name) : SensorBase(name, handle, sensor_type, pipe_data_fd)
{
dependency_resolution = use_dependency_resolution;
dependency_range = use_dependency_range;
dependency_delay = use_dependency_delay;
dependency_name = use_dependency_name;
return;
}
SWSensorBase::~SWSensorBase()
{
return;
}
int SWSensorBase::AddSensorDependency(SensorBase *p)
{
struct sensor_t dependecy_data;
if (sensor_t_data.fifoMaxEventCount == 0)
sensor_t_data.fifoMaxEventCount = p->GetMaxFifoLenght();
else {
if (p->GetMaxFifoLenght() < (int)sensor_t_data.fifoMaxEventCount)
sensor_t_data.fifoMaxEventCount = p->GetMaxFifoLenght();
}
p->FillSensor_tData(&dependecy_data);
if (dependency_resolution)
sensor_t_data.resolution = dependecy_data.resolution;
if (dependency_range)
sensor_t_data.maxRange = dependecy_data.maxRange;
if (dependency_delay) {
if (sensor_t_data.minDelay == 0)
sensor_t_data.minDelay = dependecy_data.minDelay;
else {
if (dependecy_data.minDelay > sensor_t_data.minDelay)
sensor_t_data.minDelay = dependecy_data.minDelay;
}
if (sensor_t_data.maxDelay == 0)
sensor_t_data.maxDelay = dependecy_data.maxDelay;
else {
if (dependecy_data.maxDelay < sensor_t_data.maxDelay)
sensor_t_data.maxDelay = dependecy_data.maxDelay;
}
}
if (dependency_name) {
memcpy((char *)sensor_t_data.name, dependecy_data.name, strlen(dependecy_data.name) + 1);
}
return SensorBase::AddSensorDependency(p);
}
int SWSensorBase::FlushData(bool /*need_report_event*/)
{
int err = -1, i;
bool report_event_at_once = false;
if (GetStatus() && (GetMinTimeout() > 0)) {
int64_t flush_timestamp = get_monotonic_time();
if (flush_timestamp <= real_pollrate) {
ALOGE("HWSensorBase get flush base timestamp failed");
return err;
}
ALOGD("sw flush timestamp %lld", flush_timestamp);
if (flush_timestamp > (last_data_timestamp + real_pollrate * 11 / 10)) {
flush_timestamp -= real_pollrate;
(SensorBase::timestamp).push_back(flush_timestamp);
} else
report_event_at_once = true;
for (i = 0; i < (int)dependencies_num; i++) {
err = dependencies[i]->FlushData(false);
if (err < 0)
return -EINVAL;
}
if (report_event_at_once)
SensorBase::FlushData(false);
return 0;
} else
return -EINVAL;
}
void SWSensorBase::ThreadTask()
{
while (true) {
pthread_mutex_lock(&mutext.trigger_mutex);
pthread_cond_wait(&mutext.trigger_data_cond, &mutext.trigger_mutex);
TriggerEventReceived();
pthread_mutex_unlock(&mutext.trigger_mutex);
}
}
SWSensorBaseWithPollrate::SWSensorBaseWithPollrate(const char *name, int handle, int sensor_type, int pipe_data_fd,
bool use_dependency_resolution, bool use_dependency_range, bool use_dependency_delay,
bool use_dependency_name) : SWSensorBase(name, handle, sensor_type, pipe_data_fd,
use_dependency_resolution, use_dependency_range, use_dependency_delay, use_dependency_name)
{
}
SWSensorBaseWithPollrate::~SWSensorBaseWithPollrate()
{
}
int SWSensorBaseWithPollrate::SetDelay(int handle, int64_t period_ns, int64_t timeout)
{
int i, err;
int64_t temp_real_pollrate = 0;
err = SWSensorBase::SetDelay(handle, period_ns, timeout);
if (err < 0)
return err;
for (i = 0; i < (int)dependencies_num; i++) {
if (temp_real_pollrate < GetMinPeriod())
temp_real_pollrate = GetMinPeriod();
}
return 0;
}
void SWSensorBaseWithPollrate::WriteDataToPipe()
{
int err, retry = 3;
std::vector<int64_t>::iterator it;
if (!GetStatusOfHandle(sensor_t_data.handle))
return;
if (!(SensorBase::timestamp.empty())) {
int64_t last_timestamp = 0;
for (it = SensorBase::timestamp.begin(); it != SensorBase::timestamp.end(); ) {
/* If two flush event come within 1 odr, there may not have data in hw fifo,
* so report corresponding flush complete events here.
*/
if ((sensor_event.timestamp >= *it) ||
(last_timestamp != 0 && (*it - last_timestamp < real_pollrate * 11 / 10))) {
sensors_event_t flush_event_data;
flush_event_data.sensor = 0;
flush_event_data.timestamp = 0;
flush_event_data.meta_data.sensor = sensor_t_data.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;
while (retry) {
err = SensorBase::WritePipeWithPoll(&flush_event_data, sizeof(sensor_event),
POLL_TIMEOUT_FLUSH_EVENT);
if (err > 0)
break;
retry--;
ALOGI("%s: Retry writing flush event data to pipe, retry_cnt: %d.", android_name, 3-retry);
}
if (retry == 0)
ALOGE("%s: Failed to write SW flush_complete, err=%d", android_name, err);
else
ALOGD("SW flush_complete sent");
last_timestamp = *it;
it = SensorBase::timestamp.erase(it);
} else
break;
}
}
if (sensor_event.timestamp >= (last_data_timestamp + real_pollrate * 9 / 10)) {
err = SensorBase::WritePipeWithPoll(&sensor_event, sizeof(sensor_event), POLL_TIMEOUT_DATA_EVENT);
if (err <= 0) {
ALOGE("%s: Failed to write sensor data - err=%d.", android_name, err);
return;
}
last_data_timestamp = sensor_event.timestamp;
}
}