blob: bfee207079e3e6bb03176ff8335a4e303baa05c6 [file] [log] [blame]
/*
* STMicroelectronics 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 <signal.h>
#include <time.h>
#include "SensorBase.h"
int64_t get_monotonic_time(void)
{
int err;
struct timespec tm;
err = clock_gettime(CLOCK_BOOTTIME, &tm);
if (err < 0) {
ALOGE("get_monotonic_time failed, err=%d", err);
return err;
}
ALOGD("get_monotonic_time %ld, %ld", tm.tv_sec, tm.tv_nsec);
return (int64_t) tm.tv_sec * 1000000000 + (int64_t) tm.tv_nsec;
}
SensorBase::SensorBase(const char *name, int handle, int type, int pipe_data_fd)
{
int i;
if (strlen(name) + 1 > SENSOR_BASE_ANDROID_NAME_MAX) {
memcpy(android_name, name, SENSOR_BASE_ANDROID_NAME_MAX - 1);
android_name[SENSOR_BASE_ANDROID_NAME_MAX - 1] = '\0';
} else
memcpy(android_name, name, strlen(name) + 1);
memset(&sensor_t_data, 0, sizeof(sensor_t));
memset(&sensor_event, 0, sizeof(sensors_event_t));
memset(type_dependencies, 0, SENSOR_BASE_MAX_DEPENDENCY * sizeof(int));
memset(sensors_pollrates, 0, ST_HAL_IIO_MAX_DEVICES * sizeof(int64_t));
memset(last_timestap_pushed, 0, ST_HAL_IIO_MAX_DEVICES * sizeof(int64_t));
for (i = 0; i < ST_HAL_IIO_MAX_DEVICES; i++)
sensors_timeout[i] = INT64_MAX;
sensor_event.version = sizeof(sensors_event_t);
sensor_event.sensor = handle;
sensor_event.type = type;
sensor_t_data.name = android_name;
sensor_t_data.handle = handle;
sensor_t_data.type = type;
sensor_t_data.vendor = "STMicroelectronics";
sensor_t_data.version = 1;
real_pollrate = 0;
dependencies_num = 0;
last_data_timestamp = 0;
enabled_sensors_mask = 0;
sensors_to_trigger_num = 0;
type_sensor_need_trigger = -ENODEV;
sensors_to_push_data_num = 0;
num_data_axis = SENSOR_BASE_3AXIS;
android_pipe_fd = pipe_data_fd;
pthread_mutex_init(&mutext.trigger_mutex, NULL);
pthread_cond_init(&mutext.trigger_data_cond, NULL);
valid_class = true;
}
SensorBase::~SensorBase()
{
int i;
for (i = 0; i < (int)dependencies_num; i++)
DeAllocateBufferForDependencyData(i);
}
bool SensorBase::IsValidClass()
{
return valid_class;
}
int SensorBase::GetHandle()
{
return sensor_t_data.handle;
}
int SensorBase::GetType()
{
return sensor_t_data.type;
}
int SensorBase::GetMaxFifoLenght()
{
return sensor_t_data.fifoMaxEventCount;
}
void SensorBase::SetBitEnableMask(int handle)
{
enabled_sensors_mask |= (1ULL << handle);
}
void SensorBase::ResetBitEnableMask(int handle)
{
enabled_sensors_mask &= ~(1ULL << handle);
}
char* SensorBase::GetName()
{
return (char *)sensor_t_data.name;
}
int SensorBase::Enable(int handle, bool enable)
{
int err, i = 0;
#if (CONFIG_ST_HAL_DEBUG_LEVEL >= ST_HAL_DEBUG_INFO)
bool old_status = GetStatus();
#endif /* CONFIG_ST_HAL_DEBUG_LEVEL */
if ((enable && !GetStatus()) || (!enable && !GetStatusExcludeHandle(handle))) {
for (i = 0; i < (int)dependencies_num; i++) {
err = dependencies[i]->Enable(sensor_event.sensor, enable);
if (err < 0)
goto restore_enable_dependencies;
}
}
if (enable)
SetBitEnableMask(handle);
else {
err = SetDelay(handle, 0, INT64_MAX);
if (err < 0)
goto restore_enable_dependencies;
ResetBitEnableMask(handle);
}
#if (CONFIG_ST_HAL_DEBUG_LEVEL >= ST_HAL_DEBUG_INFO)
if (((old_status && !GetStatus()) || (!old_status && GetStatus())) && (sensor_t_data.type < SENSOR_TYPE_ST_CUSTOM_NO_SENSOR)) {
if (GetStatus())
ALOGI("\"%s\": power-on (sensor type: %d).", sensor_t_data.name, sensor_t_data.type);
else
ALOGI("\"%s\": power-off (sensor type: %d).", sensor_t_data.name, sensor_t_data.type);
}
#endif /* CONFIG_ST_HAL_DEBUG_LEVEL */
return 0;
restore_enable_dependencies:
for (i--; i >= 0; i--)
dependencies[i]->Enable(sensor_event.sensor, !enable);
return err;
}
bool SensorBase::GetStatusExcludeHandle(int handle)
{
return (enabled_sensors_mask & ~(1ULL << handle)) > 0 ? true : false;
}
bool SensorBase::GetStatusOfHandle(int handle)
{
return (enabled_sensors_mask & (1ULL << handle)) > 0 ? true : false;
}
bool SensorBase::GetStatus()
{
return enabled_sensors_mask > 0 ? true : false;
}
int SensorBase::SetDelay(int handle, int64_t period_ns, int64_t timeout)
{
int err, i;
int64_t restore_min_timeout, restore_min_period_ms;
restore_min_timeout = sensors_timeout[handle];
restore_min_period_ms = sensors_pollrates[handle];
sensors_pollrates[handle] = period_ns;
sensors_timeout[handle] = timeout;
for (i = 0; i < (int)dependencies_num; i++) {
err = dependencies[i]->SetDelay(sensor_event.sensor, GetMinPeriod(), GetMinTimeout());
if (err < 0)
goto restore_delay_dependencies;
}
#if (CONFIG_ST_HAL_DEBUG_LEVEL >= ST_HAL_DEBUG_INFO)
if ((handle == sensor_t_data.handle) && (period_ns > 0))
ALOGI("\"%s\": changed pollrate to %.2f Hz, timeout %lld ms (sensor type: %d).",
sensor_t_data.name, NS_TO_FREQUENCY((float)(uint64_t)period_ns),
(uint64_t)NS_TO_MS((uint64_t)timeout), sensor_t_data.type);
#endif /* CONFIG_ST_HAL_DEBUG_LEVEL */
return 0;
restore_delay_dependencies:
sensors_pollrates[handle] = restore_min_period_ms;
sensors_timeout[handle] = restore_min_timeout;
for (i--; i >= 0; i--)
dependencies[i]->SetDelay(sensor_event.sensor, GetMinPeriod(), GetMinTimeout());
return err;
}
int64_t SensorBase::GetDelay()
{
return sensors_pollrates[sensor_event.sensor];
}
int64_t SensorBase::GetRealPollrate()
{
return real_pollrate;
}
void SensorBase::GetDepenciesTypeList(int type[SENSOR_BASE_MAX_DEPENDENCY])
{
memcpy(type, type_dependencies, SENSOR_BASE_MAX_DEPENDENCY * sizeof(int));
}
trigger_mutex* SensorBase::GetMutexForTrigger()
{
return &mutext;
}
int SensorBase::GetSensorNeedTriggerType()
{
return type_sensor_need_trigger;
}
int SensorBase::AddSensorDependency(SensorBase *p)
{
int err;
uint32_t sensor_wake_flag;
struct sensor_t dependecy_data;
if (dependencies_num >= SENSOR_BASE_MAX_DEPENDENCY) {
ALOGE("%s: Failed to add dependency, too many dependencies.", android_name);
return -ENOMEM;
}
err = AllocateBufferForDependencyData(dependencies_num, p->GetMaxFifoLenght());
if (err < 0)
return err;
err = p->AddSensorToDataPush(this);
if (err < 0) {
DeAllocateBufferForDependencyData(dependencies_num);
return err;
}
p->FillSensor_tData(&dependecy_data);
sensor_t_data.power += dependecy_data.power;
sensor_wake_flag = (dependecy_data.flags & SENSOR_FLAG_WAKE_UP);
if (dependencies_num == 0)
sensor_t_data.flags |= sensor_wake_flag;
else {
if (!sensor_wake_flag)
sensor_t_data.flags &= ~sensor_wake_flag;
}
handle_remapping[p->GetHandle()] = dependencies_num;
dependencies[dependencies_num] = p;
dependencies_num++;
return 0;
}
void SensorBase::RemoveSensorDependency(SensorBase *p)
{
int i;
for (i = 0; i < (int)dependencies_num; i++) {
if (p == dependencies[i])
break;
}
if (i == (int)dependencies_num)
return;
DeAllocateBufferForDependencyData(i);
p->RemoveSensorToDataPush(this);
for (; i < (int)dependencies_num - 1; i++)
dependencies[i] = dependencies[i + 1];
dependencies_num--;
}
int SensorBase::AllocateBufferForDependencyData(int dependency_id, unsigned int max_fifo_len)
{
circular_buffer_data[dependency_id] = new CircularBuffer(max_fifo_len < 2 ? 2 : max_fifo_len);
if (!circular_buffer_data[dependency_id])
return -ENOMEM;
return 0;
}
void SensorBase::DeAllocateBufferForDependencyData(int dependency_id)
{
delete circular_buffer_data[dependency_id];
}
int SensorBase::AddSensorToDataPush(SensorBase *t)
{
int err;
if (sensors_to_push_data_num >= SENSOR_BASE_MAX_DEPENDENCY) {
ALOGE("%s: Failed to add dependency data, too many sensors to push data.", android_name);
return -ENOMEM;
}
sensors_to_push_data_type[sensors_to_push_data_num] = t->GetType();
sensors_to_push_data[sensors_to_push_data_num] = t;
sensors_to_push_data_num++;
return 0;
}
void SensorBase::RemoveSensorToDataPush(SensorBase *t)
{
int i;
for (i = 0; i < (int)sensors_to_push_data_num; i++) {
if (t == sensors_to_push_data[i])
break;
}
if (i == (int)sensors_to_push_data_num)
return;
for (; i < (int)sensors_to_push_data_num - 1; i++)
sensors_to_push_data[i] = sensors_to_push_data[i + 1];
sensors_to_push_data_num--;
}
int SensorBase::AddSensorToTrigger(SensorBase *t)
{
int err;
if (sensors_to_trigger_num >= SENSOR_BASE_MAX_DEPENDENCY) {
ALOGE("%s: Failed to add dependency, too many sensors to trigger.", android_name);
return -ENOMEM;
}
sensors_to_trigger[sensors_to_trigger_num] = t;
sensors_to_trigger_num++;
return 0;
}
bool SensorBase::FillSensor_tData(struct sensor_t *data)
{
memcpy(data, &sensor_t_data, sizeof(struct sensor_t));
if (sensor_t_data.type >= SENSOR_TYPE_ST_CUSTOM_NO_SENSOR)
return false;
return true;
}
int SensorBase::WritePipeWithPoll(sensors_event_t *event_data, int size, int timeout)
{
int err;
struct pollfd poll_fd;
poll_fd.fd = android_pipe_fd;
poll_fd.events = POLLOUT;
err = poll(&poll_fd, (unsigned long)1, timeout);
if (err < 0) {
ALOGE("%s: error happened when polling pipe, errno: %d.", android_name, errno);
return err;
}
if (err == 0) {
ALOGE("%s: polling pipe timeout, timeout = %d.", android_name, timeout);
return err;
}
if (poll_fd.revents&POLLOUT) {
err = write(android_pipe_fd, event_data, size);
if (err <= 0) {
ALOGE("%s: Failed to write to pipe, timeout: %d, errno: %d.",
android_name, timeout, errno);
return err;
}
} else {
ALOGE("%s: polling was breaked by unexpected event: %d", android_name, poll_fd.revents);
return -EAGAIN;
}
return err;
}
int SensorBase::FlushData(bool)
{
int err = 0, retry = 3;
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 = 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 flush event data to pipe, err=%d.", android_name, err);
else
ALOGD("SensorBase::FlushData completed.");
return err;
}
void SensorBase::WriteDataToPipe()
{
int err;
if (!GetStatusOfHandle(sensor_t_data.handle))
return;
if (sensor_event.timestamp > last_data_timestamp) {
err = WritePipeWithPoll(&sensor_event, sizeof(sensor_event),
POLL_TIMEOUT_DATA_EVENT);
if (err <= 0) {
ALOGE("%s: Failed to write sensor data to pipe.", android_name);
return;
}
last_data_timestamp = sensor_event.timestamp;
}
}
void SensorBase::ProcessData(SensorBaseData *data)
{
int i;
trigger_mutex *dep_mutex;
for (i = 0; i < (int)sensors_to_push_data_num; i++) {
if (sensors_to_push_data[i]->GetStatus())
sensors_to_push_data[i]->ReceiveDataFromDependency(sensor_t_data.handle, data);
}
for (i = 0; i < (int)sensors_to_trigger_num; i++) {
if (sensors_to_trigger[i]->GetStatus()) {
dep_mutex = sensors_to_trigger[i]->GetMutexForTrigger();
pthread_mutex_lock(&dep_mutex->trigger_mutex);
pthread_cond_signal(&dep_mutex->trigger_data_cond);
pthread_mutex_unlock(&dep_mutex->trigger_mutex);
}
}
}
void SensorBase::ProcessEvent(struct iio_event_data __attribute__((unused))*event_data)
{
return;
}
void SensorBase::TriggerEventReceived()
{
return;
}
void SensorBase::ReceiveDataFromDependency(int handle, SensorBaseData *data)
{
if (data->timestamp >= last_timestap_pushed[handle]) {
circular_buffer_data[handle_remapping[handle]]->writeElement(data);
last_timestap_pushed[handle] = data->timestamp;
}
return;
}
int SensorBase::GetLatestValidDataFromDependency(int dependency_id, SensorBaseData *data)
{
return circular_buffer_data[dependency_id]->readElement(data);
}
int64_t SensorBase::GetMinTimeout()
{
int i;
int64_t min = INT64_MAX;
for (i = 0; i < ST_HAL_IIO_MAX_DEVICES; i++) {
if (sensors_timeout[i] < min)
min = sensors_timeout[i];
}
return min;
}
int64_t SensorBase::GetMinPeriod()
{
int i;
int64_t min = INT64_MAX;
for (i = 0; i < ST_HAL_IIO_MAX_DEVICES; i++) {
if ((sensors_pollrates[i] < min) && (sensors_pollrates[i] > 0))
min = sensors_pollrates[i];
}
return min;
}
void *SensorBase::ThreadWork(void *context)
{
SensorBase *mypointer = (SensorBase *)context;
mypointer->ThreadTask();
return mypointer;
}
void SensorBase::ThreadTask()
{
pthread_exit(NULL);
}