OSDN Git Service

Moping the floor: remove superfluous f type specifiers
[android-x86/hardware-intel-libsensors.git] / control.c
index a12735c..9d88047 100644 (file)
--- a/control.c
+++ b/control.c
 #include "transform.h"
 #include "calibration.h"
 #include "description.h"
+#include "filtering.h"
 
 /* Currently active sensors count, per device */
 static int poll_sensors_per_dev[MAX_DEVICES];  /* poll-mode sensors */
 static int trig_sensors_per_dev[MAX_DEVICES];  /* trigger, event based */
 
 static int device_fd[MAX_DEVICES];   /* fd on the /dev/iio:deviceX file */
+static int has_iio_ts[MAX_DEVICES];  /* ts channel available on this iio dev */
 
 static int poll_fd; /* epoll instance covering all enabled sensors */
 
@@ -104,7 +106,51 @@ static int setup_trigger (int s, const char* trigger_val)
 }
 
 
-void build_sensor_report_maps(int dev_num)
+static void enable_iio_timestamp (int dev_num, int known_channels)
+{
+       /* Check if we have a dedicated iio timestamp channel */
+
+       char spec_buf[MAX_TYPE_SPEC_LEN];
+       char sysfs_path[PATH_MAX];
+       int n;
+
+       sprintf(sysfs_path, CHANNEL_PATH "%s", dev_num, "in_timestamp_type");
+
+       n = sysfs_read_str(sysfs_path, spec_buf, sizeof(spec_buf));
+
+       if (n <= 0)
+               return;
+
+       if (strcmp(spec_buf, "le:s64/64>>0"))
+               return;
+
+       /* OK, type is int64_t as expected, in little endian representation */
+
+       sprintf(sysfs_path, CHANNEL_PATH"%s", dev_num, "in_timestamp_index");
+
+       if (sysfs_read_int(sysfs_path, &n))
+               return;
+
+       /* Check that the timestamp comes after the other fields we read */
+       if (n != known_channels)
+               return;
+
+       /* Try enabling that channel */
+       sprintf(sysfs_path, CHANNEL_PATH "%s", dev_num, "in_timestamp_en");
+
+       sysfs_write_int(sysfs_path, 1);
+
+       if (sysfs_read_int(sysfs_path, &n))
+               return;
+
+       if (n) {
+               ALOGI("Detected timestamp channel on iio device %d\n", dev_num);
+               has_iio_ts[dev_num] = 1;
+       }
+}
+
+
+void build_sensor_report_maps (int dev_num)
 {
        /*
         * Read sysfs files from a iio device's scan_element directory, and
@@ -239,6 +285,9 @@ void build_sensor_report_maps(int dev_num)
 
                offset += size;
         }
+
+       /* Enable the timestamp channel if there is one available */
+       enable_iio_timestamp(dev_num, known_channels);
 }
 
 
@@ -258,11 +307,11 @@ int adjust_counters (int s, int enabled)
                ALOGI("Enabling sensor %d (iio device %d: %s)\n",
                        s, dev_num, sensor_info[s].friendly_name);
 
-               sensor_info[s].enable_count++;
-
-               if (sensor_info[s].enable_count > 1)
+               if (sensor_info[s].enabled)
                        return 0; /* The sensor was, and remains, in use */
 
+               sensor_info[s].enabled = 1;
+
                switch (sensor_info[s].type) {
                        case SENSOR_TYPE_MAGNETIC_FIELD:
                                compass_read_data(&sensor_info[s]);
@@ -274,16 +323,13 @@ int adjust_counters (int s, int enabled)
                                break;
                }
        } else {
-               if (sensor_info[s].enable_count == 0)
-                       return -1; /* Spurious disable call */
+               if (sensor_info[s].enabled == 0)
+                       return 0; /* Spurious disable call */
 
                ALOGI("Disabling sensor %d (iio device %d: %s)\n", s, dev_num,
                      sensor_info[s].friendly_name);
 
-               sensor_info[s].enable_count--;
-
-               if (sensor_info[s].enable_count > 0)
-                       return 0; /* The sensor was, and remains, in use */
+               sensor_info[s].enabled = 0;
 
                /* Sensor disabled, lower report available flag */
                sensor_info[s].report_pending = 0;
@@ -299,7 +345,7 @@ int adjust_counters (int s, int enabled)
 
        /* If uncalibrated type and pair is already active don't adjust counters */
        if (sensor_info[s].type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED &&
-               sensor_info[sensor_info[s].pair_idx].enable_count != 0)
+               sensor_info[sensor_info[s].pair_idx].enabled != 0)
                        return 0;
 
        /* We changed the state of a sensor - adjust per iio device counters */
@@ -372,7 +418,7 @@ static void* acquisition_routine (void* param)
        int c;
        int ret;
        struct timespec target_time;
-       int64_t timestamp, period;
+       int64_t timestamp, period, start, stop;
 
        if (s < 0 || s >= sensor_count) {
                ALOGE("Invalid sensor handle!\n");
@@ -389,7 +435,7 @@ static void* acquisition_routine (void* param)
        }
 
        num_fields = get_field_count(s);
-       sample_size = num_fields * sizeof(float);
+       sample_size = sizeof(int64_t) + num_fields * sizeof(float);
 
        /*
         * Each condition variable is associated to a mutex that has to be
@@ -404,7 +450,7 @@ static void* acquisition_routine (void* param)
 
        /* Check and honor termination requests */
        while (sensor_info[s].thread_data_fd[1] != -1) {
-
+               start = get_timestamp();
                /* Read values through sysfs */
                for (c=0; c<num_fields; c++) {
                        data.data[c] = acquire_immediate_value(s, c);
@@ -412,13 +458,16 @@ static void* acquisition_routine (void* param)
                        if (sensor_info[s].thread_data_fd[1] == -1)
                                goto exit;
                }
+               stop = get_timestamp();
+               data.timestamp = start/2 + stop/2;
 
                /* If the sample looks good */
                if (sensor_info[s].ops.finalize(s, &data)) {
 
                        /* Pipe it for transmission to poll loop */
                        ret = write(    sensor_info[s].thread_data_fd[1],
-                                       data.data, sample_size);
+                                       &data.timestamp, sample_size);
+
                        if (ret != sample_size)
                                ALOGE("S%d acquisition thread: tried to write %d, ret: %d\n",
                                        s, sample_size, ret);
@@ -547,7 +596,7 @@ int sensor_activate(int s, int enabled)
         * Reactivate gyro uncalibrated - Uncalibrated has handler */
 
        if (sensor_info[s].type == SENSOR_TYPE_GYROSCOPE &&
-               sensor_info[s].pair_idx && sensor_info[sensor_info[s].pair_idx].enable_count != 0) {
+               sensor_info[s].pair_idx && sensor_info[sensor_info[s].pair_idx].enabled != 0) {
 
                                sensor_activate(sensor_info[s].pair_idx, 0);
                                ret = sensor_activate(s, enabled);
@@ -564,6 +613,10 @@ int sensor_activate(int s, int enabled)
        sensor_info[s].event_count = 0;
        sensor_info[s].meta_data_pending = 0;
 
+       if (enabled && (sensor_info[s].quirks & QUIRK_NOISY))
+               /* Initialize filtering data if required */
+               setup_noise_filtering(s);
+
        if (!is_poll_sensor) {
 
                /* Stop sampling */
@@ -603,16 +656,8 @@ int sensor_activate(int s, int enabled)
                                device_fd[dev_num] = -1;
                        }
 
-               /* If we recorded a trail of samples for filtering, delete it */
-               if (sensor_info[s].history) {
-                       free(sensor_info[s].history);
-                       sensor_info[s].history = NULL;
-                       sensor_info[s].history_size = 0;
-                       if (sensor_info[s].history_sum) {
-                               free(sensor_info[s].history_sum);
-                               sensor_info[s].history_sum = NULL;
-                       }
-               }
+               /* Release any filtering data we may have accumulated */
+               release_noise_filtering_data(s);
 
                return 0;
        }
@@ -711,7 +756,7 @@ static void enable_motion_trigger (int dev_num)
 
        for (s=0; s<MAX_SENSORS; s++)
                if (sensor_info[s].dev_num == dev_num &&
-                   sensor_info[s].enable_count &&
+                   sensor_info[s].enabled &&
                    sensor_info[s].num_channels &&
                    (!sensor_info[s].motion_trigger_name[0] ||
                     !sensor_info[s].report_initialized ||
@@ -724,7 +769,7 @@ static void enable_motion_trigger (int dev_num)
 
        for (s=0; s<MAX_SENSORS; s++)
                if (sensor_info[s].dev_num == dev_num &&
-                   sensor_info[s].enable_count &&
+                   sensor_info[s].enabled &&
                    sensor_info[s].num_channels &&
                    sensor_info[s].selected_trigger !=
                        sensor_info[s].motion_trigger_name)
@@ -750,6 +795,7 @@ static void enable_motion_trigger (int dev_num)
  *     FrequencyVerification.java: (0.9)*(expected freq) => (th <= 1.1111)
  */
 #define THRESHOLD 1.10
+#define MAX_DELAY 500000000 /* 500 ms */
 void set_report_ts(int s, int64_t ts)
 {
        int64_t maxTs, period;
@@ -768,12 +814,16 @@ void set_report_ts(int s, int64_t ts)
        {
                period = (int64_t) (1000000000LL / sensor_info[s].sampling_rate);
                maxTs = sensor_info[s].report_ts + (is_accel ? 1 : THRESHOLD) * period;
+               /* If we're too far behind get back on track */
+               if (ts - maxTs >= MAX_DELAY)
+                       maxTs = ts;
                sensor_info[s].report_ts = (ts < maxTs ? ts : maxTs);
        } else {
                sensor_info[s].report_ts = ts;
        }
 }
 
+
 static int integrate_device_report (int dev_num)
 {
        int len;
@@ -783,6 +833,8 @@ static int integrate_device_report (int dev_num)
        unsigned char *target;
        unsigned char *source;
        int size;
+       int64_t ts = 0;
+       int ts_offset = 0;      /* Offset of iio timestamp, if provided */
 
        /* There's an incoming report on the specified iio device char dev fd */
 
@@ -796,8 +848,6 @@ static int integrate_device_report (int dev_num)
                return -1;
        }
 
-
-
        len = read(device_fd[dev_num], buf, MAX_SENSOR_REPORT_SIZE);
 
        if (len == -1) {
@@ -812,7 +862,7 @@ static int integrate_device_report (int dev_num)
 
        for (s=0; s<MAX_SENSORS; s++)
                if (sensor_info[s].dev_num == dev_num &&
-                   sensor_info[s].enable_count) {
+                   sensor_info[s].enabled) {
 
                        sr_offset = 0;
 
@@ -834,14 +884,38 @@ static int integrate_device_report (int dev_num)
                        ALOGV("Sensor %d report available (%d bytes)\n", s,
                              sr_offset);
 
-                       set_report_ts(s, get_timestamp());
                        sensor_info[s].report_pending = DATA_TRIGGER;
                        sensor_info[s].report_initialized = 1;
+                       set_report_ts(s, get_timestamp());
+
+                       ts_offset += sr_offset;
                }
 
        /* Tentatively switch to an any-motion trigger if conditions are met */
        enable_motion_trigger(dev_num);
 
+       /* If no iio timestamp channel was detected for this device, bail out */
+       if (!has_iio_ts[dev_num])
+               return 0;
+
+       /* Align on a 64 bits boundary */
+       ts_offset = (ts_offset + 7)/8*8;
+
+       /* If we read an amount of data consistent with timestamp presence */
+       if (len == ts_offset + (int) sizeof(int64_t))
+               ts = *(int64_t*) (buf + ts_offset);
+
+       if (ts == 0) {
+               ALOGV("Unreliable timestamp channel on iio dev %d\n", dev_num);
+               return 0;
+       }
+
+       ALOGV("Driver timestamp on iio device %d: ts=%lld\n", dev_num, ts);
+
+       for (s=0; s<MAX_SENSORS; s++)
+               if (sensor_info[s].dev_num == dev_num && sensor_info[s].enabled)
+                       set_report_ts(s, ts);
+
        return 0;
 }
 
@@ -861,7 +935,7 @@ static int propagate_sensor_report (int s, struct sensors_event_t  *data)
 
        /* Only return uncalibrated event if also gyro active */
        if (sensor_info[s].type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED &&
-               sensor_info[sensor_info[s].pair_idx].enable_count != 0)
+               sensor_info[sensor_info[s].pair_idx].enabled != 0)
                        return 0;
 
        memset(data, 0, sizeof(sensors_event_t));
@@ -919,7 +993,7 @@ static void synthetize_duplicate_samples (void)
        for (s=0; s<sensor_count; s++) {
 
                /* Ignore disabled sensors */
-               if (!sensor_info[s].enable_count)
+               if (!sensor_info[s].enabled)
                        continue;
 
                /* If the sensor is continuously firing, leave it alone */
@@ -958,15 +1032,21 @@ static void integrate_thread_report (uint32_t tag)
        int s = tag - THREAD_REPORT_TAG_BASE;
        int len;
        int expected_len;
+       int64_t timestamp;
+       unsigned char current_sample[MAX_SENSOR_REPORT_SIZE];
 
-       expected_len = get_field_count(s) * sizeof(float);
+       expected_len = sizeof(int64_t) + get_field_count(s) * sizeof(float);
 
        len = read(sensor_info[s].thread_data_fd[0],
-                  sensor_info[s].report_buffer,
+                  current_sample,
                   expected_len);
 
+       memcpy(&timestamp, current_sample, sizeof(int64_t));
+       memcpy(sensor_info[s].report_buffer, sizeof(int64_t) + current_sample,
+                       expected_len - sizeof(int64_t));
+
        if (len == expected_len) {
-               set_report_ts(s, get_timestamp());
+               set_report_ts(s, timestamp);
                sensor_info[s].report_pending = DATA_SYSFS;
        }
 }
@@ -992,7 +1072,7 @@ static int get_poll_wait_timeout (void)
         * duplicate events. Check deadline for the nearest upcoming event.
         */
        for (s=0; s<sensor_count; s++)
-               if (sensor_info[s].enable_count &&
+               if (sensor_info[s].enabled &&
                    sensor_info[s].selected_trigger ==
                    sensor_info[s].motion_trigger_name &&
                    sensor_info[s].sampling_rate) {
@@ -1049,7 +1129,7 @@ return_available_sensor_reports:
 
                        /* Duplicate only if both cal & uncal are active */
                        if (sensor_info[s].type == SENSOR_TYPE_GYROSCOPE &&
-                                       sensor_info[s].pair_idx && sensor_info[sensor_info[s].pair_idx].enable_count != 0) {
+                                       sensor_info[s].pair_idx && sensor_info[sensor_info[s].pair_idx].enabled != 0) {
                                        struct gyro_cal* gyro_data = (struct gyro_cal*) sensor_info[s].cal_data;
 
                                        memcpy(&data[returned_events + event_count], &data[returned_events],
@@ -1167,9 +1247,9 @@ int sensor_set_delay(int s, int64_t ns)
        int per_device_sampling_rate;
        int32_t min_delay_us = sensor_desc[s].minDelay;
        max_delay_t max_delay_us = sensor_desc[s].maxDelay;
-       float min_supported_rate = max_delay_us ? (1000000.0f / max_delay_us) : 1;
+       float min_supported_rate = max_delay_us ? (1000000.0 / max_delay_us) : 1;
        float max_supported_rate = 
-               (min_delay_us && min_delay_us != -1) ? (1000000.0f / min_delay_us) : 0;
+               (min_delay_us && min_delay_us != -1) ? (1000000.0 / min_delay_us) : 0;
        char freqs_buf[100];
        char* cursor;
        int n;
@@ -1233,7 +1313,7 @@ int sensor_set_delay(int s, int64_t ns)
                for (n=0; n<sensor_count; n++)
                        if (n != s && sensor_info[n].dev_num == dev_num &&
                            sensor_info[n].num_channels &&
-                           sensor_info[n].enable_count &&
+                           sensor_info[n].enabled &&
                            sensor_info[n].sampling_rate > new_sampling_rate)
                                new_sampling_rate= sensor_info[n].sampling_rate;
 
@@ -1307,7 +1387,7 @@ int sensor_flush (int s)
 {
        /* If one shot or not enabled return -EINVAL */
        if (sensor_desc[s].flags & SENSOR_FLAG_ONE_SHOT_MODE ||
-               sensor_info[s].enable_count == 0)
+               sensor_info[s].enabled == 0)
                return -EINVAL;
 
        sensor_info[s].meta_data_pending++;