/* * STMicroelectronics Sensor Base Class * * Copyright 2013-2015 STMicroelectronics Inc. * Author: Denis Ciocca - * * Licensed under the Apache License, Version 2.0 (the "License"). */ #include #include #include #include #include #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); }