summaryrefslogtreecommitdiff
path: root/libsensors_iio/src/HWSensorBase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'libsensors_iio/src/HWSensorBase.cpp')
-rw-r--r--libsensors_iio/src/HWSensorBase.cpp101
1 files changed, 92 insertions, 9 deletions
diff --git a/libsensors_iio/src/HWSensorBase.cpp b/libsensors_iio/src/HWSensorBase.cpp
index 1b487c5..c3c941e 100644
--- a/libsensors_iio/src/HWSensorBase.cpp
+++ b/libsensors_iio/src/HWSensorBase.cpp
@@ -313,11 +313,51 @@ restore_status_enable:
return err;
}
-int HWSensorBase::FlushData(int base)
+int HWSensorBase::FlushData(bool need_report_event)
{
- int err;
+ bool report_at_once = false;
+ int err = -1;
+ int32_t type = SensorBase::sensor_t_data.type;
+#ifdef __LP64__
+ uint64_t flags;
+#else
+ uint32_t flags;
+#endif
+
+ flags = SensorBase::sensor_t_data.flags;
+ ALOGD("HWSensorBase::FlushData type=%d, flags=%lld", type, flags);
+
+ /* No flush events for One-shot sensors */
+ if (SENSOR_FLAG_ONE_SHOT_MODE == (flags & REPORTING_MODE_MASK))
+ return -EINVAL;
if (GetStatus()) {
+ /* Sensors used fifo would report flush complete event after data in fifo reported,
+ * so we store the flush timestamp here. When we write fifo data to pipe,
+ * we compare them. If the fifo data wrote done, then write the flush complete event.
+ * One exception: if the flush call come after a fifo parse, there would no data
+ * in the fifo. If we still sent flush complete event like before, that should wait for
+ * another fifo parse, that would be a very long time (unit seconds). In this case,
+ * we would sent the flush complete event here.
+ */
+ if (need_report_event && ((type == SENSOR_TYPE_ACCELEROMETER) ||
+ (type == SENSOR_TYPE_GYROSCOPE))) {
+ int64_t flush_timestamp = get_monotonic_time();
+ if (flush_timestamp <= real_pollrate) {
+ ALOGE("HWSensorBase get flush base timestamp failed");
+ return err;
+ }
+ ALOGD("hw flush timestamp %lld", flush_timestamp);
+ /* Scale the real_pollrate by 11/10 because LSM6DS3 ODR has +/-10% skew */
+ if (flush_timestamp <= (last_data_timestamp + real_pollrate * 11 / 10))
+ report_at_once = true;
+ else {
+ flush_timestamp -= real_pollrate * 11 /10;
+ (SensorBase::timestamp).push_back(flush_timestamp);
+ }
+ }
+
+ /* Sensors used fifo would trigger read fifo here */
if (current_fifo_len > HW_SENSOR_BASE_DEFAULT_IIO_BUFFER_LEN) {
err = write_sysfs_int((char *)FILENAME_FLUSH, common_data.iio_sysfs_path, 1);
if (err < 0) {
@@ -326,13 +366,20 @@ int HWSensorBase::FlushData(int base)
return -EINVAL;
}
}
+
+ /* Sensors which not use fifo would sent a flush complete event here.
+ * Sensors used fifo would sent a flush complete event here too if the fifo
+ * is empty now.
+ */
+ if (need_report_event && (report_at_once || ((type != SENSOR_TYPE_ACCELEROMETER) &&
+ (type != SENSOR_TYPE_GYROSCOPE))))
+ return SensorBase::FlushData(true);
+ else
+ return 0;
+
} else
return -EINVAL;
- if (base)
- return SensorBase::FlushData(0);
- else
- return 0;
}
void HWSensorBase::ThreadTask()
@@ -461,17 +508,53 @@ int HWSensorBaseWithPollrate::SetDelay(int handle, int64_t period_ns, int64_t ti
void HWSensorBaseWithPollrate::WriteDataToPipe()
{
int err;
+ std::vector<int64_t>::iterator it;
if (!GetStatusOfHandle(sensor_t_data.handle))
return;
- if (sensor_event.timestamp >= (last_data_timestamp + real_pollrate)) {
+ 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;
+
+ err = write(android_pipe_fd, &flush_event_data, sizeof(sensor_event));
+
+ if (err < 0) {
+ ALOGE("%s: Writing flush_complete event failed, errno=%d", android_name, errno);
+ return;
+ }
+
+ last_timestamp = *it;
+ it = SensorBase::timestamp.erase(it);
+ ALOGD("write hw flush complete event to pipe succeed.");
+ } else
+ break;
+ }
+ }
+
+ /* Scale the real_pollrate by 9/10 because LSM6DS3 ODR has +/-10% skew */
+ if (sensor_event.timestamp >= (last_data_timestamp + real_pollrate * 9 / 10)) {
err = write(android_pipe_fd, &sensor_event, sizeof(sensor_event));
if (err < 0) {
- ALOGE("%s: Failed to write sensor data to pipe.", android_name);
+ ALOGE("%s: Write sensor data failed, errno=%d", android_name, errno);
return;
}
last_data_timestamp = sensor_event.timestamp;
- }
+ } else
+ ALOGE("%s: Dropping event type=%d because ts %lld < %lld (%lld + %lld * 9 / 10)", android_name,
+ (last_data_timestamp + real_pollrate * 9 / 10), last_data_timestamp, real_pollrate);
}