OSDN Git Service

Don't let the timestamp get too far behind
[android-x86/hardware-intel-libsensors.git] / control.c
index a7fe20c..9565f46 100644 (file)
--- a/control.c
+++ b/control.c
@@ -28,6 +28,8 @@ static int poll_fd; /* epoll instance covering all enabled sensors */
 
 static int active_poll_sensors; /* Number of enabled poll-mode sensors */
 
+int64_t ts_delta; /* delta between SystemClock.getNanos and our timestamp */
+
 /* We use pthread condition variables to get worker threads out of sleep */
 static pthread_condattr_t thread_cond_attr     [MAX_SENSORS];
 static pthread_cond_t     thread_release_cond  [MAX_SENSORS];
@@ -250,20 +252,18 @@ int adjust_counters (int s, int enabled)
         */
 
        int dev_num = sensor_info[s].dev_num;
-       int catalog_index = sensor_info[s].catalog_index;
-       int sensor_type = sensor_catalog[catalog_index].type;
 
        /* Refcount per sensor, in terms of enable count */
        if (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 */
 
-               switch (sensor_type) {
+               sensor_info[s].enabled = 1;
+
+               switch (sensor_info[s].type) {
                        case SENSOR_TYPE_MAGNETIC_FIELD:
                                compass_read_data(&sensor_info[s]);
                                break;
@@ -274,28 +274,29 @@ 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;
 
-               if (sensor_type == SENSOR_TYPE_MAGNETIC_FIELD)
+               if (sensor_info[s].type == SENSOR_TYPE_MAGNETIC_FIELD)
                        compass_store_data(&sensor_info[s]);
+
+               if(sensor_info[s].type == SENSOR_TYPE_GYROSCOPE ||
+                       sensor_info[s].type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED)
+                       gyro_store_data(&sensor_info[s]);
        }
 
 
        /* If uncalibrated type and pair is already active don't adjust counters */
-       if (sensor_type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED &&
-               sensor_info[sensor_info[s].pair_idx].enable_count != 0)
+       if (sensor_info[s].type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED &&
+               sensor_info[sensor_info[s].pair_idx].enabled != 0)
                        return 0;
 
        /* We changed the state of a sensor - adjust per iio device counters */
@@ -325,10 +326,7 @@ int adjust_counters (int s, int enabled)
 
 static int get_field_count (int s)
 {
-       int catalog_index = sensor_info[s].catalog_index;
-       int sensor_type   = sensor_catalog[catalog_index].type;
-
-       switch (sensor_type) {
+       switch (sensor_info[s].type) {
                case SENSOR_TYPE_ACCELEROMETER:         /* m/s^2        */
                case SENSOR_TYPE_MAGNETIC_FIELD:        /* micro-tesla  */
                case SENSOR_TYPE_ORIENTATION:           /* degrees      */
@@ -354,7 +352,6 @@ static int get_field_count (int s)
 }
 
 
-
 static void* acquisition_routine (void* param)
 {
        /*
@@ -400,7 +397,7 @@ static void* acquisition_routine (void* param)
        pthread_mutex_lock(&thread_release_mutex[s]);
 
        /* Pinpoint the moment we start sampling */
-       timestamp = get_timestamp();
+       timestamp = get_timestamp_monotonic();
 
        /* Check and honor termination requests */
        while (sensor_info[s].thread_data_fd[1] != -1) {
@@ -468,7 +465,7 @@ static void start_acquisition_thread (int s)
 
        /* Create condition variable and mutex for quick thread release */
        ret = pthread_condattr_init(&thread_cond_attr[s]);
-       ret = pthread_condattr_setclock(&thread_cond_attr[s], POLLING_CLOCK);
+       ret = pthread_condattr_setclock(&thread_cond_attr[s], CLOCK_MONOTONIC);
        ret = pthread_cond_init(&thread_release_cond[s], &thread_cond_attr[s]);
        ret = pthread_mutex_init(&thread_release_mutex[s], NULL);
 
@@ -533,6 +530,8 @@ int sensor_activate(int s, int enabled)
 
        /* Prepare the report timestamp field for the first event, see set_report_ts method */
        sensor_info[s].report_ts = 0;
+       ts_delta = load_timestamp_sys_clock() - get_timestamp_monotonic();
+
 
        /* If we want to activate gyro calibrated and gyro uncalibrated is activated
         * Deactivate gyro uncalibrated - Uncalibrated releases handler
@@ -544,8 +543,8 @@ int sensor_activate(int s, int enabled)
         * Deactivate gyro calibrated   - Calibrated releases handler
         * Reactivate gyro uncalibrated - Uncalibrated has handler */
 
-       if (sensor_catalog[sensor_info[s].catalog_index].type == SENSOR_TYPE_GYROSCOPE &&
-               sensor_info[s].pair_idx && sensor_info[sensor_info[s].pair_idx].enable_count != 0) {
+       if (sensor_info[s].type == SENSOR_TYPE_GYROSCOPE &&
+               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);
@@ -559,6 +558,8 @@ int sensor_activate(int s, int enabled)
        if (ret <= 0)
                return ret;
 
+       sensor_info[s].event_count = 0;
+       sensor_info[s].meta_data_pending = 0;
 
        if (!is_poll_sensor) {
 
@@ -665,9 +666,8 @@ static int is_fast_accelerometer (int s)
         * to request fairly high event rates. Favor continuous triggers if the
         * sensor is an accelerometer and uses a sampling rate of at least 25.
         */
-       int catalog_index = sensor_info[s].catalog_index;
 
-       if (sensor_catalog[catalog_index].type != SENSOR_TYPE_ACCELEROMETER)
+       if (sensor_info[s].type != SENSOR_TYPE_ACCELEROMETER)
                return 0;
 
        if (sensor_info[s].sampling_rate < 25)
@@ -708,11 +708,12 @@ 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 ||
-                    is_fast_accelerometer(s))
+                    is_fast_accelerometer(s) ||
+                    (sensor_info[s].quirks & QUIRK_FORCE_CONTINUOUS))
                    )
                        return; /* Nope */
 
@@ -720,9 +721,8 @@ 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].quirks & QUIRK_CONTINUOUS_DRIVER) &&
                    sensor_info[s].selected_trigger !=
                        sensor_info[s].motion_trigger_name)
                                candidate[candidate_count++] = s;
@@ -742,9 +742,17 @@ static void enable_motion_trigger (int dev_num)
        enable_buffer(dev_num, 1);
 }
 
+/* CTS acceptable thresholds:
+ *     EventGapVerification.java: (th <= 1.8)
+ *     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;
+       int catalog_index = sensor_info[s].catalog_index;
+       int is_accel      = (sensor_catalog[catalog_index].type == SENSOR_TYPE_ACCELEROMETER);
 
        /*
        *  A bit of a hack to please a bunch of cts tests. They
@@ -757,14 +765,17 @@ void set_report_ts(int s, int64_t ts)
                REPORTING_MODE(sensor_desc[s].flags) == SENSOR_FLAG_CONTINUOUS_MODE)
        {
                period = (int64_t) (1000000000LL / sensor_info[s].sampling_rate);
-               maxTs = sensor_info[s].report_ts + period;
+               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)
+static int integrate_device_report (int dev_num)
 {
        int len;
        int s,c;
@@ -773,7 +784,6 @@ static int integrate_device_report(int dev_num)
        unsigned char *target;
        unsigned char *source;
        int size;
-       int64_t ts;
 
        /* There's an incoming report on the specified iio device char dev fd */
 
@@ -787,7 +797,7 @@ static int integrate_device_report(int dev_num)
                return -1;
        }
 
-       ts = get_timestamp();
+
 
        len = read(device_fd[dev_num], buf, MAX_SENSOR_REPORT_SIZE);
 
@@ -803,7 +813,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;
 
@@ -825,8 +835,8 @@ static int integrate_device_report(int dev_num)
                        ALOGV("Sensor %d report available (%d bytes)\n", s,
                              sr_offset);
 
-                       set_report_ts(s, ts);
-                       sensor_info[s].report_pending = 1;
+                       set_report_ts(s, get_timestamp());
+                       sensor_info[s].report_pending = DATA_TRIGGER;
                        sensor_info[s].report_initialized = 1;
                }
 
@@ -837,12 +847,10 @@ static int integrate_device_report(int dev_num)
 }
 
 
-static int propagate_sensor_report(int s, struct sensors_event_t  *data)
+static int propagate_sensor_report (int s, struct sensors_event_t  *data)
 {
        /* There's a sensor report pending for this sensor ; transmit it */
 
-       int catalog_index = sensor_info[s].catalog_index;
-       int sensor_type   = sensor_catalog[catalog_index].type;
        int num_fields    = get_field_count(s);
        int c;
        unsigned char* current_sample;
@@ -853,18 +861,18 @@ static int propagate_sensor_report(int s, struct sensors_event_t  *data)
 
 
        /* Only return uncalibrated event if also gyro active */
-       if (sensor_type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED &&
-               sensor_info[sensor_info[s].pair_idx].enable_count != 0)
+       if (sensor_info[s].type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED &&
+               sensor_info[sensor_info[s].pair_idx].enabled != 0)
                        return 0;
 
        memset(data, 0, sizeof(sensors_event_t));
 
        data->version   = sizeof(sensors_event_t);
        data->sensor    = s;
-       data->type      = sensor_type;
+       data->type      = sensor_info[s].type;
        data->timestamp = sensor_info[s].report_ts;
 
-       ALOGV("Sample on sensor %d (type %d):\n", s, sensor_type);
+       ALOGV("Sample on sensor %d (type %d):\n", s, sensor_info[s].type);
 
        current_sample = sensor_info[s].report_buffer;
 
@@ -912,12 +920,12 @@ 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 */
-               if (    sensor_info[s].selected_trigger !=
-                       sensor_info[s].motion_trigger_name)
+               if (sensor_info[s].selected_trigger !=
+                   sensor_info[s].motion_trigger_name)
                        continue;
 
                /* If we haven't seen a sample, there's nothing to duplicate */
@@ -940,7 +948,7 @@ static void synthetize_duplicate_samples (void)
                if (target_ts <= current_ts) {
                        /* Mark the sensor for event generation */
                        set_report_ts(s, current_ts);
-                       sensor_info[s].report_pending = 1;
+                       sensor_info[s].report_pending = DATA_DUPLICATE;
                }
        }
 }
@@ -960,7 +968,7 @@ static void integrate_thread_report (uint32_t tag)
 
        if (len == expected_len) {
                set_report_ts(s, get_timestamp());
-               sensor_info[s].report_pending = 1;
+               sensor_info[s].report_pending = DATA_SYSFS;
        }
 }
 
@@ -979,13 +987,13 @@ static int get_poll_wait_timeout (void)
        int64_t period;
 
        /*
-        * Check if have have to deal with "terse" drivers that only send events
-        * when there is motion, despite the fact that the associated Android
-        * sensor type is continuous rather than on-change. In that case we have
-        * to duplicate events. Check deadline for the nearest upcoming event.
+        * Check if we're dealing with a driver that only send events when
+        * there is motion, despite the fact that the associated Android sensor
+        * type is continuous rather than on-change. In that case we have to
+        * 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) {
@@ -1033,15 +1041,16 @@ return_available_sensor_reports:
        for (s=0; s<sensor_count && returned_events < count; s++) {
                if (sensor_info[s].report_pending) {
                        event_count = 0;
-                       /* Lower flag */
-                       sensor_info[s].report_pending = 0;
 
                        /* Report this event if it looks OK */
                        event_count = propagate_sensor_report(s, &data[returned_events]);
 
+                       /* Lower flag */
+                       sensor_info[s].report_pending = 0;
+
                        /* Duplicate only if both cal & uncal are active */
-                       if (sensor_catalog[sensor_info[s].catalog_index].type == SENSOR_TYPE_GYROSCOPE &&
-                                       sensor_info[s].pair_idx && sensor_info[sensor_info[s].pair_idx].enable_count != 0) {
+                       if (sensor_info[s].type == SENSOR_TYPE_GYROSCOPE &&
+                                       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],
@@ -1123,6 +1132,25 @@ await_event:
 }
 
 
+static void tentative_switch_trigger (int s)
+{
+       /*
+        * Under certain situations it may be beneficial to use an alternate
+        * trigger:
+        *
+        * - for applications using the accelerometer with high sampling rates,
+        *   prefer the continuous trigger over the any-motion one, to avoid
+        *   jumps related to motion thresholds
+        */
+
+       if (is_fast_accelerometer(s) &&
+               !(sensor_info[s].quirks & QUIRK_TERSE_DRIVER) &&
+                       sensor_info[s].selected_trigger ==
+                               sensor_info[s].motion_trigger_name)
+               setup_trigger(s, sensor_info[s].init_trigger_name);
+}
+
+
 int sensor_set_delay(int s, int64_t ns)
 {
        /* Set the rate at which a specific sensor should report events */
@@ -1206,7 +1234,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;
 
@@ -1251,13 +1279,11 @@ int sensor_set_delay(int s, int64_t ns)
                }
        }
 
-
        if (max_supported_rate &&
                new_sampling_rate > max_supported_rate) {
                new_sampling_rate = max_supported_rate;
        }
 
-
        /* If the desired rate is already active we're all set */
        if (new_sampling_rate == cur_sampling_rate)
                return 0;
@@ -1269,10 +1295,8 @@ int sensor_set_delay(int s, int64_t ns)
 
        sysfs_write_float(sysfs_path, new_sampling_rate);
 
-       /* Switch back to continuous sampling for accelerometer based games */
-       if (is_fast_accelerometer(s) && sensor_info[s].selected_trigger !=
-                                       sensor_info[s].init_trigger_name)
-               setup_trigger(s, sensor_info[s].init_trigger_name);
+       /* Check if it makes sense to use an alternate trigger */
+       tentative_switch_trigger(s);
 
        if (trig_sensors_per_dev[dev_num])
                enable_buffer(dev_num, 1);
@@ -1284,7 +1308,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++;