OSDN Git Service

Fix type of recently introduced semi arbitrated sampling rate
[android-x86/hardware-intel-libsensors.git] / control.c
index bc28a20..b8fdeab 100644 (file)
--- a/control.c
+++ b/control.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2014 Intel Corporation.
+ * Copyright (C) 2014-2015 Intel Corporation.
  */
 
 #include <stdlib.h>
@@ -9,9 +9,11 @@
 #include <time.h>
 #include <math.h>
 #include <sys/epoll.h>
+#include <sys/ioctl.h>
 #include <sys/socket.h>
 #include <utils/Log.h>
 #include <hardware/sensors.h>
+#include <linux/ioctl.h>
 #include "control.h"
 #include "enumeration.h"
 #include "utils.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 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 events_fd[MAX_DEVICES];                     /* fd on the /sys/bus/iio/devices/iio:deviceX/events/<event_name> file */
 static int has_iio_ts[MAX_DEVICES];                    /* ts channel available on this iio dev         */
 static int expected_dev_report_size[MAX_DEVICES];      /* expected iio scan len                        */
 static int poll_fd;                                    /* epoll instance covering all enabled sensors  */
 
-static int active_poll_sensors; /* Number of enabled poll-mode sensors */
+static int active_poll_sensors;                                /* Number of enabled poll-mode sensors          */
 
 /* We use pthread condition variables to get worker threads out of sleep */
 static pthread_condattr_t thread_cond_attr     [MAX_SENSORS];
@@ -37,15 +40,15 @@ static pthread_cond_t     thread_release_cond       [MAX_SENSORS];
 static pthread_mutex_t    thread_release_mutex [MAX_SENSORS];
 
 /*
- * We associate tags to each of our poll set entries. These tags have the
- * following values:
+ * We associate tags to each of our poll set entries. These tags have the following values:
  * - a iio device number if the fd is a iio character device fd
  * - THREAD_REPORT_TAG_BASE + sensor handle if the fd is the receiving end of a pipe used by a sysfs data acquisition thread
  */
-#define THREAD_REPORT_TAG_BASE 0x00010000
+#define THREAD_REPORT_TAG_BASE         1000
 
-#define ENABLE_BUFFER_RETRIES 10
-#define ENABLE_BUFFER_RETRY_DELAY_MS 10
+/* If buffer enable fails, we may want to retry a few times before giving up */
+#define ENABLE_BUFFER_RETRIES          3
+#define ENABLE_BUFFER_RETRY_DELAY_MS   10
 
 
 inline int is_enabled (int s)
@@ -84,35 +87,25 @@ static int check_state_change (int s, int enabled, int from_virtual)
 }
 
 
-static int enable_buffer(int dev_num, int enabled)
+static int enable_buffer (int dev_num, int enabled)
 {
        char sysfs_path[PATH_MAX];
-       int ret, retries, millisec;
-       struct timespec req = {0};
-
-       retries = ENABLE_BUFFER_RETRIES;
-       millisec = ENABLE_BUFFER_RETRY_DELAY_MS;
-       req.tv_sec = 0;
-       req.tv_nsec = millisec * 1000000L;
+       int retries = ENABLE_BUFFER_RETRIES;
 
        sprintf(sysfs_path, ENABLE_PATH, dev_num);
 
-       while (retries--) {
+       while (retries) {
                /* Low level, non-multiplexed, enable/disable routine */
-               ret = sysfs_write_int(sysfs_path, enabled);
-               if (ret > 0)
-                       break;
-
-               ALOGE("Failed enabling buffer, retrying");
-               nanosleep(&req, (struct timespec *)NULL);
-       }
+               if (sysfs_write_int(sysfs_path, enabled) > 0)
+                       return 0;
 
-       if (ret < 0) {
-               ALOGE("Could not enable buffer\n");
-               return -EIO;
+               ALOGE("Failed enabling buffer on dev%d, retrying", dev_num);
+               usleep(ENABLE_BUFFER_RETRY_DELAY_MS*1000);
+               retries--;
        }
 
-       return 0;
+       ALOGE("Could not enable buffer\n");
+       return -EIO;
 }
 
 
@@ -138,6 +131,21 @@ static int setup_trigger (int s, const char* trigger_val)
        return ret;
 }
 
+static int enable_event(int dev_num, const char *name, int enabled)
+{
+       char sysfs_path[PATH_MAX];
+
+       sprintf(sysfs_path, EVENTS_PATH "%s", dev_num, name);
+       return sysfs_write_int(sysfs_path, enabled);
+}
+
+static int enable_sensor(int dev_num, const char *tag, int enabled)
+{
+       char sysfs_path[PATH_MAX];
+
+       sprintf(sysfs_path, SENSOR_ENABLE_PATH, dev_num, tag);
+       return sysfs_write_int(sysfs_path, enabled);
+}
 
 static void enable_iio_timestamp (int dev_num, int known_channels)
 {
@@ -183,8 +191,7 @@ static void enable_iio_timestamp (int dev_num, int known_channels)
 }
 
 
-static int decode_type_spec (const char type_buf[MAX_TYPE_SPEC_LEN],
-                            datum_info_t *type_info)
+static int decode_type_spec (const char type_buf[MAX_TYPE_SPEC_LEN], datum_info_t *type_info)
 {
        /* Return size in bytes for this type specification, or -1 in error */
        char sign;
@@ -196,8 +203,8 @@ static int decode_type_spec (const char type_buf[MAX_TYPE_SPEC_LEN],
 
        tokens = sscanf(type_buf, "%ce:%c%u/%u>>%u", &endianness, &sign, &realbits, &storagebits, &shift);
 
-       if     (tokens != 5 || (endianness != 'b' && endianness != 'l') || (sign != 'u' && sign != 's') ||
-               realbits > storagebits || (storagebits != 16 && storagebits != 32 && storagebits != 64)) {
+       if (tokens != 5 || (endianness != 'b' && endianness != 'l') || (sign != 'u' && sign != 's') ||
+           realbits > storagebits || (storagebits != 16 && storagebits != 32 && storagebits != 64)) {
                        ALOGE("Invalid iio channel type spec: %s\n", type_buf);
                        return -1;
        }
@@ -354,6 +361,7 @@ int adjust_counters (int s, int enabled, int from_virtual)
         * Adjust counters based on sensor enable action. Return values are:
         *  0 if the operation was completed and we're all set
         *  1 if we toggled the state of the sensor and there's work left
+        * -1 in case of an error
         */
 
        int dev_num = sensor[s].dev_num;
@@ -388,30 +396,36 @@ int adjust_counters (int s, int enabled, int from_virtual)
 
        /* We changed the state of a sensor: adjust device ref counts */
 
-       if (!sensor[s].is_polling) {
-
-                       if (enabled)
-                               trig_sensors_per_dev[dev_num]++;
-                       else
-                               trig_sensors_per_dev[dev_num]--;
+       switch(sensor[s].mode) {
+       case MODE_TRIGGER:
+               if (enabled)
+                       trig_sensors_per_dev[dev_num]++;
+               else
+                       trig_sensors_per_dev[dev_num]--;
 
+               return 1;
+       case MODE_POLL:
+               if (enabled) {
+                       active_poll_sensors++;
+                       poll_sensors_per_dev[dev_num]++;
                        return 1;
-       }
-
-       if (enabled) {
-               active_poll_sensors++;
-               poll_sensors_per_dev[dev_num]++;
+               } else {
+                       active_poll_sensors--;
+                       poll_sensors_per_dev[dev_num]--;
+                       return 1;
+               }
+       case MODE_EVENT:
                return 1;
+       default:
+               /* Invalid sensor mode */
+               return -1;
        }
-
-       active_poll_sensors--;
-       poll_sensors_per_dev[dev_num]--;
-       return 1;
 }
 
 
-static int get_field_count (int s)
+static int get_field_count (int s, size_t *field_size)
 {
+       *field_size = sizeof(float);
        switch (sensor[s].type) {
                case SENSOR_TYPE_ACCELEROMETER:         /* m/s^2        */
                case SENSOR_TYPE_MAGNETIC_FIELD:        /* micro-tesla  */
@@ -426,17 +440,53 @@ static int get_field_count (int s)
                case SENSOR_TYPE_PROXIMITY:             /* centimeters  */
                case SENSOR_TYPE_PRESSURE:              /* hecto-pascal */
                case SENSOR_TYPE_RELATIVE_HUMIDITY:     /* percent */
+               case SENSOR_TYPE_STEP_DETECTOR:         /* event: always 1 */
                        return 1;
 
                case SENSOR_TYPE_ROTATION_VECTOR:
                        return 4;
 
+               case SENSOR_TYPE_STEP_COUNTER:          /* number of steps */
+                       *field_size = sizeof(uint64_t);
+                       return 1;
                default:
                        ALOGE("Unknown sensor type!\n");
                        return 0;                       /* Drop sample */
        }
 }
 
+/*
+ *  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;
+
+       /*
+       *  A bit of a hack to please a bunch of cts tests. They
+       *  expect the timestamp to be exacly according to the set-up
+       *  frequency but if we're simply getting the timestamp at hal level
+       *  this may not be the case. Perhaps we'll get rid of this when
+       *  we'll be reading the timestamp from the iio channel for all sensors
+       */
+       if (sensor[s].report_ts && sensor[s].sampling_rate &&
+               REPORTING_MODE(sensor_desc[s].flags) == SENSOR_FLAG_CONTINUOUS_MODE)
+       {
+               period = (int64_t) (1000000000.0 / sensor[s].sampling_rate);
+               maxTs = sensor[s].report_ts + THRESHOLD * period;
+               /* If we're too far behind get back on track */
+               if (ts - maxTs >= MAX_DELAY)
+                       maxTs = ts;
+               sensor[s].report_ts = (ts < maxTs ? ts : maxTs);
+       } else {
+               sensor[s].report_ts = ts;
+       }
+}
 
 static void* acquisition_routine (void* param)
 {
@@ -447,27 +497,32 @@ static void* acquisition_routine (void* param)
         */
 
        int s = (int) (size_t) param;
-       int num_fields, sample_size;
+       int num_fields;
        sensors_event_t data = {0};
        int c;
        int ret;
        struct timespec target_time;
        int64_t timestamp, period, start, stop;
+       size_t field_size;
 
        if (s < 0 || s >= sensor_count) {
                ALOGE("Invalid sensor handle!\n");
                return NULL;
        }
 
-       ALOGI("Entering data acquisition thread S%d (%s), rate:%g\n", s, sensor[s].friendly_name, sensor[s].sampling_rate);
+       ALOGI("Entering S%d (%s) data acquisition thread: rate:%g\n", s, sensor[s].friendly_name, sensor[s].sampling_rate);
 
        if (sensor[s].sampling_rate <= 0) {
                ALOGE("Invalid rate in acquisition routine for sensor %d: %g\n", s, sensor[s].sampling_rate);
                return NULL;
        }
 
-       num_fields = get_field_count(s);
-       sample_size = sizeof(int64_t) + num_fields * sizeof(float);
+       /* Initialize data fields that will be shared by all sensor reports */
+       data.version    = sizeof(sensors_event_t);
+       data.sensor     = s;
+       data.type       = sensor[s].type;
+
+       num_fields = get_field_count(s, &field_size);
 
        /*
         * Each condition variable is associated to a mutex that has to be locked by the thread that's waiting on it. We use these condition
@@ -481,24 +536,29 @@ static void* acquisition_routine (void* param)
        /* Check and honor termination requests */
        while (sensor[s].thread_data_fd[1] != -1) {
                start = get_timestamp_boot();
+
                /* Read values through sysfs */
                for (c=0; c<num_fields; c++) {
-                       data.data[c] = acquire_immediate_value(s, c);
+                       if (field_size == sizeof(uint64_t))
+                               data.u64.data[c] = acquire_immediate_uint64_value(s, c);
+                       else
+                               data.data[c] = acquire_immediate_float_value(s, c);
+
                        /* Check and honor termination requests */
                        if (sensor[s].thread_data_fd[1] == -1)
                                goto exit;
                }
                stop = get_timestamp_boot();
-               data.timestamp = start/2 + stop/2;
-
+               set_report_ts(s, start/2 + stop/2);
+               data.timestamp = sensor[s].report_ts;
                /* If the sample looks good */
                if (sensor[s].ops.finalize(s, &data)) {
 
                        /* Pipe it for transmission to poll loop */
-                       ret = write(sensor[s].thread_data_fd[1], &data.timestamp, sample_size);
+                       ret = write(sensor[s].thread_data_fd[1], &data, sizeof(sensors_event_t));
 
-                       if (ret != sample_size)
-                               ALOGE("S%d write failure: wrote %d, got %d\n", s, sample_size, ret);
+                       if (ret != sizeof(sensors_event_t))
+                               ALOGE("S%d write failure: wrote %d, got %d\n", s, sizeof(sensors_event_t), ret);
                }
 
                /* Check and honor termination requests */
@@ -515,8 +575,7 @@ static void* acquisition_routine (void* param)
                timestamp += period;
                set_timestamp(&target_time, timestamp);
 
-               /* Wait until the sampling time elapses, or a rate change is signaled, or a thread exit is requested.
-                */
+               /* Wait until the sampling time elapses, or a rate change is signaled, or a thread exit is requested */
                ret = pthread_cond_timedwait(&thread_release_cond[s], &thread_release_mutex[s], &target_time);
        }
 
@@ -553,9 +612,13 @@ static void start_acquisition_thread (int s)
 
        /* Add incoming side of pipe to our poll set, with a suitable tag */
        ret = epoll_ctl(poll_fd, EPOLL_CTL_ADD, incoming_data_fd , &ev);
+       if (ret == -1) {
+               ALOGE("Failed adding %d to poll set (%s)\n",
+                       incoming_data_fd, strerror(errno));
+       }
 
        /* Create and start worker thread */
-       ret = pthread_create(   &sensor[s].acquisition_thread, NULL, acquisition_routine, (void*) (size_t) s);
+       ret = pthread_create(&sensor[s].acquisition_thread, NULL, acquisition_routine, (void*) (size_t) s);
 }
 
 
@@ -593,10 +656,8 @@ static void stop_acquisition_thread (int s)
 static int is_fast_accelerometer (int s)
 {
        /*
-        * Some games don't react well to accelerometers using any-motion
-        * triggers. Even very low thresholds seem to trip them, and they tend
-        * to request fairly high event rates. Favor continuous triggers if the
-        * sensor is an accelerometer and uses a sampling rate of at least 25.
+        * Some games don't react well to accelerometers using any-motion triggers. Even very low thresholds seem to trip them, and they tend to
+        * request fairly high event rates. Favor continuous triggers if the sensor is an accelerometer and uses a sampling rate of at least 25.
         */
 
        if (sensor[s].type != SENSOR_TYPE_ACCELEROMETER)
@@ -701,7 +762,7 @@ static int sensor_set_rate (int s, float requested_rate)
                return 0;
 
        /* If we're dealing with a poll-mode sensor */
-       if (sensor[s].is_polling) {
+       if (sensor[s].mode == MODE_POLL) {
                if (is_enabled(s))
                        pthread_cond_signal(&thread_release_cond[s]); /* Wake up thread so the new sampling rate gets used */
                return 0;
@@ -732,7 +793,7 @@ static int sensor_set_rate (int s, float requested_rate)
 
        sprintf(avail_sysfs_path, DEVICE_AVAIL_FREQ_PATH, dev_num);
 
-       if (sysfs_read_str(avail_sysfs_path, freqs_buf, sizeof(freqs_buf)) > 0){
+       if (sysfs_read_str(avail_sysfs_path, freqs_buf, sizeof(freqs_buf)) > 0) {
                cursor = freqs_buf;
 
                /* Decode allowed sampling rates string, ex: "10 20 50 100" */
@@ -750,9 +811,8 @@ static int sensor_set_rate (int s, float requested_rate)
                        }
 
                        /*
-                        * If we reached a higher value than the desired rate, adjust selected rate so it matches the first higher
-                        * available one and stop parsing - this makes the assumption that rates are sorted by increasing value
-                        * in the allowed frequencies string.
+                        * If we reached a higher value than the desired rate, adjust selected rate so it matches the first higher available one and
+                        * stop parsing - this makes the assumption that rates are sorted by increasing value in the allowed frequencies string.
                         */
                        if (sr > arb_sampling_rate) {
                                arb_sampling_rate = sr;
@@ -774,14 +834,17 @@ static int sensor_set_rate (int s, float requested_rate)
                arb_sampling_rate = sensor[s].max_supported_rate;
        }
 
+       /* Record the rate that was agreed upon with the sensor taken in isolation ; this avoid uncontrolled ripple effects between colocated sensor rates */
+       sensor[s].semi_arbitrated_rate = arb_sampling_rate;
 
        /* Coordinate with others active sensors on the same device, if any */
        if (per_device_sampling_rate)
                for (n=0; n<sensor_count; n++)
-                       if (n != s && sensor[n].dev_num == dev_num && sensor[n].num_channels && is_enabled(n) && sensor[n].sampling_rate > arb_sampling_rate) {
+                       if (n != s && sensor[n].dev_num == dev_num && sensor[n].num_channels && is_enabled(n) &&
+                               sensor[n].semi_arbitrated_rate > arb_sampling_rate) {
                                ALOGV("Sampling rate shared between %s and %s, using %g instead of %g\n", sensor[s].friendly_name, sensor[n].friendly_name,
-                                                                                                         sensor[n].sampling_rate, arb_sampling_rate);
-                               arb_sampling_rate = sensor[n].sampling_rate;
+                                                                                                         sensor[n].semi_arbitrated_rate, arb_sampling_rate);
+                               arb_sampling_rate = sensor[n].semi_arbitrated_rate;
                        }
 
        sensor[s].sampling_rate = arb_sampling_rate;
@@ -796,8 +859,7 @@ static int sensor_set_rate (int s, float requested_rate)
        if (arb_sampling_rate == cur_sampling_rate)
                return 0;
 
-       ALOGI("Sensor %d (%s) sampling rate set to %g\n",
-             s, sensor[s].friendly_name, arb_sampling_rate);
+       ALOGI("Sensor %d (%s) sampling rate set to %g\n", s, sensor[s].friendly_name, arb_sampling_rate);
 
        if (trig_sensors_per_dev[dev_num])
                enable_buffer(dev_num, 0);
@@ -822,7 +884,7 @@ static void reapply_sampling_rates (int s)
         * that ended up being used after arbitration.
         */
 
-       int i, j, base, user;
+       int i, j, base;
 
        if (sensor[s].is_virtual) {
                /* Take care of downwards dependencies */
@@ -879,9 +941,11 @@ int sensor_activate (int s, int enabled, int from_virtual)
 {
        char device_name[PATH_MAX];
        struct epoll_event ev = {0};
-       int dev_fd;
-       int ret;
+       int dev_fd, event_fd;
+       int ret, c, d;
        int dev_num = sensor[s].dev_num;
+       size_t field_size;
+       int catalog_index = sensor[s].catalog_index;
 
        if (sensor[s].is_virtual)
                return sensor_activate_virtual(s, enabled, from_virtual);
@@ -898,10 +962,10 @@ int sensor_activate (int s, int enabled, int from_virtual)
        sensor[s].event_count = 0;
        sensor[s].meta_data_pending = 0;
 
-       if (enabled && (sensor[s].quirks & QUIRK_NOISY))
+       if (enabled)
                setup_noise_filtering(s);       /* Initialize filtering data if required */
 
-       if (!sensor[s].is_polling) {
+       if (sensor[s].mode == MODE_TRIGGER) {
 
                /* Stop sampling */
                enable_buffer(dev_num, 0);
@@ -914,6 +978,10 @@ int sensor_activate (int s, int enabled, int from_virtual)
                        setup_trigger(s, sensor[s].init_trigger_name);
                        enable_buffer(dev_num, 1);
                }
+       } else if (sensor[s].mode == MODE_POLL) {
+               if (sensor[s].needs_enable) {
+                       enable_sensor(dev_num, sensor_catalog[catalog_index].tag, enabled);
+               }
        }
 
        /*
@@ -923,7 +991,7 @@ int sensor_activate (int s, int enabled, int from_virtual)
        dev_fd = device_fd[dev_num];
 
        if (!enabled) {
-               if (sensor[s].is_polling)
+               if (sensor[s].mode == MODE_POLL)
                        stop_acquisition_thread(s);
 
                if (dev_fd != -1 && !poll_sensors_per_dev[dev_num] && !trig_sensors_per_dev[dev_num]) {
@@ -934,6 +1002,20 @@ int sensor_activate (int s, int enabled, int from_virtual)
                                device_fd[dev_num] = -1;
                }
 
+               if (sensor[s].mode == MODE_EVENT) {
+                       event_fd = events_fd[dev_num];
+
+                       for (c = 0; c < sensor_catalog[catalog_index].num_channels; c++) {
+                               for (d = 0; d < sensor_catalog[catalog_index].channel[c].num_events; d++)
+                                       enable_event(dev_num, sensor_catalog[catalog_index].channel[c].event[d].ev_en_path, enabled);
+                       }
+
+                       epoll_ctl(poll_fd, EPOLL_CTL_DEL, event_fd, NULL);
+                       close(event_fd);
+                       events_fd[dev_num] = -1;
+
+               }
+
                /* Release any filtering data we may have accumulated */
                release_noise_filtering_data(s);
 
@@ -957,7 +1039,7 @@ int sensor_activate (int s, int enabled, int from_virtual)
 
                ALOGV("Opened %s: fd=%d\n", device_name, dev_fd);
 
-               if (!sensor[s].is_polling) {
+               if (sensor[s].mode == MODE_TRIGGER) {
 
                        /* Add this iio device fd to the set of watched fds */
                        ev.events = EPOLLIN;
@@ -971,13 +1053,47 @@ int sensor_activate (int s, int enabled, int from_virtual)
                        }
 
                        /* Note: poll-mode fds are not readable */
+               } else if (sensor[s].mode == MODE_EVENT) {
+                       event_fd = events_fd[dev_num];
+
+                       ret = ioctl(dev_fd, IIO_GET_EVENT_FD_IOCTL, &event_fd);
+                       if (ret == -1 || event_fd == -1) {
+                               ALOGE("Failed to retrieve event_fd from %d (%s)\n", dev_fd, strerror(errno));
+                               return -1;
+                       }
+                       events_fd[dev_num] = event_fd;
+                       ALOGV("Opened fd=%d to receive events\n", event_fd);
+
+                       /* Add this event fd to the set of watched fds */
+                       ev.events = EPOLLIN;
+                       ev.data.u32 = dev_num;
+
+                       ret = epoll_ctl(poll_fd, EPOLL_CTL_ADD, event_fd, &ev);
+                       if (ret == -1) {
+                               ALOGE("Failed adding %d to poll set (%s)\n", event_fd, strerror(errno));
+                               return -1;
+                       }
+                       for (c = 0; c < sensor_catalog[catalog_index].num_channels; c++) {
+                               int d;
+                               for (d = 0; d < sensor_catalog[catalog_index].channel[c].num_events; d++)
+                                       enable_event(dev_num, sensor_catalog[catalog_index].channel[c].event[d].ev_en_path, enabled);
+                       }
+
+                       if (!poll_sensors_per_dev[dev_num] && !trig_sensors_per_dev[dev_num]) {
+                               close(dev_fd);
+                               device_fd[dev_num] = -1;
+                       }
                }
        }
 
        /* Ensure that on-change sensors send at least one event after enable */
-       sensor[s].prev_val = -1;
+       get_field_count(s, &field_size);
+       if (field_size == sizeof(uint64_t))
+               sensor[s].prev_val.data64 = -1;
+       else
+               sensor[s].prev_val.data = -1;
 
-       if (sensor[s].is_polling)
+       if (sensor[s].mode == MODE_POLL)
                start_acquisition_thread(s);
 
        /* Reevaluate sampling rates of linked sensors */
@@ -1037,53 +1153,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;
-
-       /*
-       *  A bit of a hack to please a bunch of cts tests. They
-       *  expect the timestamp to be exacly according to the set-up
-       *  frequency but if we're simply getting the timestamp at hal level
-       *  this may not be the case. Perhaps we'll get rid of this when
-       *  we'll be reading the timestamp from the iio channel for all sensors
-       */
-       if (sensor[s].report_ts && sensor[s].sampling_rate &&
-               REPORTING_MODE(sensor_desc[s].flags) == SENSOR_FLAG_CONTINUOUS_MODE)
-       {
-               period = (int64_t) (1000000000.0 / sensor[s].sampling_rate);
-               maxTs = sensor[s].report_ts + THRESHOLD * period;
-               /* If we're too far behind get back on track */
-               if (ts - maxTs >= MAX_DELAY)
-                       maxTs = ts;
-               sensor[s].report_ts = (ts < maxTs ? ts : maxTs);
-       } else {
-               sensor[s].report_ts = ts;
-       }
-}
-
-
 static void stamp_reports (int dev_num, int64_t ts)
 {
        int s;
 
        for (s=0; s<MAX_SENSORS; s++)
-                       if (sensor[s].dev_num == dev_num &&
-                               is_enabled(s))
-                                       set_report_ts(s, ts);
+               if (sensor[s].dev_num == dev_num && is_enabled(s) && sensor[s].mode != MODE_POLL)
+                       set_report_ts(s, ts);
 }
 
 
-static int integrate_device_report (int dev_num)
+static int integrate_device_report_from_dev(int dev_num, int fd)
 {
        int len;
        int s,c;
@@ -1097,18 +1177,12 @@ static int integrate_device_report (int dev_num)
        int64_t boot_to_rt_delta;
 
        /* There's an incoming report on the specified iio device char dev fd */
-
-       if (dev_num < 0 || dev_num >= MAX_DEVICES) {
-               ALOGE("Event reported on unexpected iio device %d\n", dev_num);
-               return -1;
-       }
-
-       if (device_fd[dev_num] == -1) {
+       if (fd == -1) {
                ALOGE("Ignoring stale report on iio device %d\n", dev_num);
                return -1;
        }
 
-       len = read(device_fd[dev_num], buf, expected_dev_report_size[dev_num]);
+       len = read(fd, buf, expected_dev_report_size[dev_num]);
 
        if (len == -1) {
                ALOGE("Could not read report from iio device %d (%s)\n", dev_num, strerror(errno));
@@ -1163,7 +1237,7 @@ static int integrate_device_report (int dev_num)
                }
 
        /* Align on a 64 bits boundary */
-       ts_offset = (ts_offset + 7)/8*8;
+       ts_offset = expected_dev_report_size[dev_num] - sizeof(int64_t);
 
        /* If we read an amount of data consistent with timestamp presence */
        if (len == expected_dev_report_size[dev_num])
@@ -1184,6 +1258,63 @@ static int integrate_device_report (int dev_num)
        return 0;
 }
 
+static int integrate_device_report_from_event(int dev_num, int fd)
+{
+       int len, s;
+       int64_t ts;
+       struct iio_event_data event;
+
+       /* There's an incoming report on the specified iio device char dev fd */
+       if (fd == -1) {
+               ALOGE("Ignoring stale report on event fd %d of device %d\n",
+                       fd, dev_num);
+               return -1;
+       }
+
+       len = read(fd, &event, sizeof(event));
+
+       if (len == -1) {
+               ALOGE("Could not read event from fd %d of device %d (%s)\n",
+                       fd, dev_num, strerror(errno));
+               return -1;
+       }
+
+       ts = event.timestamp;
+
+       ALOGV("Read event %lld from fd %d of iio device %d\n", event.id, fd, dev_num);
+
+       /* Map device report to sensor reports */
+       for (s = 0; s < MAX_SENSORS; s++)
+               if (sensor[s].dev_num == dev_num &&
+                   is_enabled(s)) {
+                       sensor[s].report_ts = ts;
+                       sensor[s].report_pending = 1;
+                       sensor[s].report_initialized = 1;
+                       ALOGV("Sensor %d report available (1 byte)\n", s);
+               }
+       return 0;
+}
+
+static int integrate_device_report(int dev_num)
+{
+       int ret = 0;
+
+       if (dev_num < 0 || dev_num >= MAX_DEVICES) {
+               ALOGE("Event reported on unexpected iio device %d\n", dev_num);
+               return -1;
+       }
+
+       if (events_fd[dev_num] != -1) {
+               ret = integrate_device_report_from_event(dev_num, events_fd[dev_num]);
+               if (ret < 0)
+                       return ret;
+       }
+
+       if (device_fd[dev_num] != -1)
+               ret = integrate_device_report_from_dev(dev_num, device_fd[dev_num]);
+
+       return ret;
+}
 
 static int propagate_vsensor_report (int s, sensors_event_t *data)
 {
@@ -1201,14 +1332,29 @@ static int propagate_sensor_report (int s, sensors_event_t *data)
 {
        /* There's a sensor report pending for this sensor ; transmit it */
 
-       int num_fields    = get_field_count(s);
+       size_t field_size;
+       int num_fields    = get_field_count(s, &field_size);
        int c;
        unsigned char* current_sample;
+       int ret;
 
        /* If there's nothing to return... we're done */
        if (!num_fields)
                return 0;
 
+       ALOGV("Sample on sensor %d (type %d):\n", s, sensor[s].type);
+
+       if (sensor[s].mode == MODE_POLL) {
+               /* We received a good sample but we're not directly enabled so we'll drop */
+               if (!sensor[s].directly_enabled)
+                       return 0;
+               /* Use the data provided by the acquisition thread */
+               ALOGV("Reporting data from worker thread for S%d\n", s);
+               memcpy(data, &sensor[s].sample, sizeof(sensors_event_t));
+               data->timestamp = sensor[s].report_ts;
+               return 1;
+       }
+
        memset(data, 0, sizeof(sensors_event_t));
 
        data->version   = sizeof(sensors_event_t);
@@ -1216,19 +1362,19 @@ static int propagate_sensor_report (int s, sensors_event_t *data)
        data->type      = sensor[s].type;
        data->timestamp = sensor[s].report_ts;
 
-       ALOGV("Sample on sensor %d (type %d):\n", s, sensor[s].type);
-
-       current_sample = sensor[s].report_buffer;
-
-       /* If this is a poll sensor */
-       if (sensor[s].is_polling) {
-               /* Use the data provided by the acquisition thread */
-               ALOGV("Reporting data from worker thread for S%d\n", s);
-               memcpy(data->data, current_sample, num_fields * sizeof(float));
+       if (sensor[s].mode == MODE_EVENT) {
+               ALOGV("Reporting event\n");
+               /* Android requires events to return 1.0 */
+               data->data[0] = 1.0;
+               data->data[1] = 0.0;
+               data->data[2] = 0.0;
                return 1;
        }
 
        /* Convert the data into the expected Android-level format */
+
+       current_sample = sensor[s].report_buffer;
+
        for (c=0; c<num_fields; c++) {
 
                data->data[c] = sensor[s].ops.transform (s, c, current_sample);
@@ -1237,17 +1383,23 @@ static int propagate_sensor_report (int s, sensors_event_t *data)
                current_sample += sensor[s].channel[c].size;
        }
 
+       ret = sensor[s].ops.finalize(s, data);
+
+       /* We will drop samples if the sensor is not directly enabled */
+       if (!sensor[s].directly_enabled)
+               return 0;
+
        /* The finalize routine, in addition to its late sample processing duty, has the final say on whether or not the sample gets sent to Android */
-       return sensor[s].ops.finalize(s, data);
+       return ret;
 }
 
 
 static void synthetize_duplicate_samples (void)
 {
        /*
-        * Some sensor types (ex: gyroscope) are defined as continuously firing by Android, despite the fact that we can be dealing with iio drivers
-        * that only report events for new samples. For these we generate reports periodically, duplicating the last data we got from the
-        * driver. This is not necessary for polling sensors.
+        * Some sensor types (ex: gyroscope) are defined as continuously firing by Android, despite the fact that
+        * we can be dealing with iio drivers that only report events for new samples. For these we generate reports
+        * periodically, duplicating the last data we got from the driver. This is not necessary for polling sensors.
         */
 
        int s;
@@ -1295,23 +1447,11 @@ 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 = sizeof(int64_t) + get_field_count(s) * sizeof(float);
 
-       len = read(sensor[s].thread_data_fd[0],
-                  current_sample,
-                  expected_len);
+       len = read(sensor[s].thread_data_fd[0], &sensor[s].sample, sizeof(sensors_event_t));
 
-       memcpy(&timestamp, current_sample, sizeof(int64_t));
-       memcpy(sensor[s].report_buffer, sizeof(int64_t) + current_sample, expected_len - sizeof(int64_t));
-
-       if (len == expected_len) {
-               set_report_ts(s, timestamp);
+       if (len == sizeof(sensors_event_t))
                sensor[s].report_pending = DATA_SYSFS;
-       }
 }
 
 
@@ -1361,7 +1501,6 @@ int sensor_poll (sensors_event_t* data, int count)
        struct epoll_event ev[MAX_DEVICES];
        int returned_events;
        int event_count;
-       int uncal_start;
 
        /* Get one or more events from our collection of sensors */
 return_available_sensor_reports:
@@ -1370,8 +1509,10 @@ return_available_sensor_reports:
        synthetize_duplicate_samples();
 
        returned_events = 0;
+
        /* Check our sensor collection for available reports */
        for (s=0; s<sensor_count && returned_events < count; s++) {
+
                if (sensor[s].report_pending) {
                        event_count = 0;
 
@@ -1487,8 +1628,10 @@ int allocate_control_data (void)
 {
        int i;
 
-       for (i=0; i<MAX_DEVICES; i++)
+       for (i=0; i<MAX_DEVICES; i++) {
                device_fd[i] = -1;
+               events_fd[i] = -1;
+       }
 
        poll_fd = epoll_create(MAX_DEVICES);