OSDN Git Service

Better support for virtual sensors
authorAdriana Reus <adriana.reus@intel.com>
Tue, 9 Dec 2014 07:07:08 +0000 (09:07 +0200)
committerReus, Adriana <adriana.reus@intel.com>
Fri, 12 Dec 2014 16:23:43 +0000 (16:23 +0000)
Re-work for the gyro uncalibrated implementation. Instead from reading from the device directly it is now built on top of the 'real' sensor.
The re-work is more general and can be used to construct virtual sensors on top of real ones more easily.

Change-Id: Ife169e860674f3ceec1d22dbb4ac9db278d6762d
Signed-off-by: Adriana Reus <adriana.reus@intel.com>
common.h
control.c
control.h
description.c
entry.c
enumeration.c
enumeration.h
filtering.c
gyro-calibration.c
transform.c

index f07d364..812c264 100644 (file)
--- a/common.h
+++ b/common.h
@@ -33,6 +33,8 @@
 
 #define MAX_NAME_SIZE          32
 
+#define MAX_REAL_DEP 3 /* Max number of base sensors a sensor can depend on */
+
 #define ARRAY_SIZE(x) sizeof(x)/sizeof(x[0])
 #define REPORTING_MODE(x)      ((x) & 0x06)
 
@@ -64,6 +66,7 @@ struct sensor_catalog_entry_t
        const char *tag; /* Prefix such as "accel", "gyro", "temp"... */
        const int type;  /* Sensor type ; ex: SENSOR_TYPE_ACCELEROMETER */
        const int num_channels; /* Expected iio channels for this sensor */
+       const int is_virtual;  /* Is the sensor virtual or not */
        struct channel_descriptor_t channel[MAX_CHANNELS];
 };
 
@@ -133,10 +136,10 @@ struct sensor_info_t
        float scale;    /*default: 1. when set to 0, use channel specific value*/
        float illumincalib;     /* to set the calibration for the ALS */
 
-       float sampling_rate;    /* requested events / second */
+       float requested_rate;   /* requested events / second */
+       float sampling_rate;    /* setup events / second */
 
        int dev_num;    /* Associated iio dev num, ex: 3 for /dev/iio:device3 */
-       int enabled;
 
        int catalog_index;/* Associated entry within the sensor_catalog array */
        int type;         /* Sensor type, such as SENSOR_TYPE_GYROSCOPE       */
@@ -203,13 +206,32 @@ struct sensor_info_t
        int thread_data_fd[2];
        pthread_t acquisition_thread;
 
-       /* For cal-uncal sensor pairs - index to the pair sensor in sensor_info */
-       int pair_idx;
+       /* How many base sensors is the sensor depending on */
+       int base_count;
+       int base_idx[MAX_REAL_DEP];
 
        uint32_t quirks; /* Bit mask expressing the need for special tweaks */
 
        /* Note: we may have to explicitely serialize access to some fields */
 
+       int is_virtual;
+       /*
+       * Dependency count - for a real sensor how many active virtual sensors are
+       * depending on it
+       */
+       uint32_t ref_count;
+
+       /*
+        * Flag showing if a sensor was enabled directly by Android
+        */
+       uint32_t directly_enabled;
+
+       /*
+        * Current sample for a virtual sensor - when a report is ready we'll
+        * keep the data here until it's finally processed. Can be modified for
+        * more than one at a later time.
+        */
+       struct sensors_event_t sample;
 
        /*
         * If the QUIRK_FIELD_ORDERING bit is set in quirks, the contents of
index 75f2824..28b6dc6 100644 (file)
--- a/control.c
+++ b/control.c
@@ -47,6 +47,51 @@ static pthread_mutex_t    thread_release_mutex       [MAX_SENSORS];
 #define ENABLE_BUFFER_RETRIES 10
 #define ENABLE_BUFFER_RETRY_DELAY_MS 10
 
+inline int is_enabled(int s)
+{
+       return (sensor_info[s].directly_enabled || sensor_info[s].ref_count);
+}
+
+static int check_state_change(int s, int enabled, int from_virtual)
+{
+       if(enabled) {
+               if (sensor_info[s].directly_enabled)
+                       return 0;
+
+               /* If we were enabled by Android no sample drops */
+               if (!from_virtual)
+                       sensor_info[s].directly_enabled = 1;
+
+               /*
+               * If we got here it means we were not previously directly enabled - we may
+               * or may not be now, whatever the case if we already had references we
+               * were already in use
+               */
+               if (sensor_info[s].ref_count)
+                       return 0;
+
+               return 1;
+
+       }
+       /* Spurious disable call */
+       if (!is_enabled(s))
+               return 0;
+
+       /* We're requesting disable for a virtual sensor but the base is still active */
+       if (from_virtual && sensor_info[s].directly_enabled)
+               return 0;
+
+       /* If it's disable, and it's from Android, and we still have ref counts */
+       if (!from_virtual && sensor_info[s].ref_count) {
+               sensor_info[s].directly_enabled = 0;
+               return 0;
+       }
+
+       /*If perhaps we are from virtual but we're disabling it*/
+       sensor_info[s].directly_enabled = 0;
+
+       return 1;
+}
 static int enable_buffer(int dev_num, int enabled)
 {
        char sysfs_path[PATH_MAX];
@@ -303,7 +348,7 @@ void build_sensor_report_maps (int dev_num)
 }
 
 
-int adjust_counters (int s, int enabled)
+int adjust_counters (int s, int enabled, int from_virtual)
 {
        /*
         * Adjust counters based on sensor enable action. Return values are:
@@ -314,54 +359,37 @@ int adjust_counters (int s, int enabled)
 
        int dev_num = sensor_info[s].dev_num;
 
-       /* Refcount per sensor, in terms of enable count */
+       if (!check_state_change(s, enabled, from_virtual))
+               return 0;
+
        if (enabled) {
                ALOGI("Enabling sensor %d (iio device %d: %s)\n",
                        s, dev_num, sensor_info[s].friendly_name);
 
-               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]);
                                break;
 
                        case SENSOR_TYPE_GYROSCOPE:
-                       case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
                                gyro_cal_init(&sensor_info[s]);
                                break;
                }
        } else {
-               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].enabled = 0;
-
                /* Sensor disabled, lower report available flag */
                sensor_info[s].report_pending = 0;
 
                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)
+               if(sensor_info[s].type == SENSOR_TYPE_GYROSCOPE)
                        gyro_store_data(&sensor_info[s]);
        }
 
-
-       /* 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].enabled != 0)
-                       return 0;
-
        /* We changed the state of a sensor - adjust per iio device counters */
-
        /* If this is a regular event-driven sensor */
        if (sensor_info[s].num_channels) {
 
@@ -582,8 +610,253 @@ static void stop_acquisition_thread (int s)
        pthread_mutex_destroy(&thread_release_mutex[s]);
 }
 
+static void sensor_activate_virtual(int s, int enabled, int from_virtual)
+{
+       int i, base;
+
+       sensor_info[s].event_count = 0;
+       sensor_info[s].meta_data_pending = 0;
 
-int sensor_activate(int s, int enabled)
+       if (!check_state_change(s, enabled, from_virtual))
+               return;
+       if (enabled) {
+               /* Enable all the base sensors for this virtual one */
+               for (i = 0; i < sensor_info[s].base_count; i++) {
+                       base = sensor_info[s].base_idx[i];
+                       sensor_activate(base, enabled, 1);
+                       sensor_info[base].ref_count++;
+               }
+               return;
+       }
+
+       /* Sensor disabled, lower report available flag */
+       sensor_info[s].report_pending = 0;
+
+       for (i = 0; i < sensor_info[s].base_count; i++) {
+               base = sensor_info[s].base_idx[i];
+               sensor_activate(base, enabled, 1);
+               sensor_info[base].ref_count--;
+       }
+
+}
+
+
+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.
+        */
+
+       if (sensor_info[s].type != SENSOR_TYPE_ACCELEROMETER)
+               return 0;
+
+       if (sensor_info[s].sampling_rate < 25)
+               return 0;
+
+       return 1;
+}
+
+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);
+}
+
+static int setup_delay_sysfs(int s, float new_sampling_rate)
+{
+       /* Set the rate at which a specific sensor should report events */
+
+       /* See Android sensors.h for indication on sensor trigger modes */
+
+       char sysfs_path[PATH_MAX];
+       char avail_sysfs_path[PATH_MAX];
+       float cur_sampling_rate; /* Currently used sampling rate              */
+       int dev_num             =       sensor_info[s].dev_num;
+       int i                   =       sensor_info[s].catalog_index;
+       const char *prefix      =       sensor_catalog[i].tag;
+       int per_sensor_sampling_rate;
+       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.0 / max_delay_us) : 1;
+       float max_supported_rate =
+               (min_delay_us && min_delay_us != -1) ? (1000000.0 / min_delay_us) : 0;
+       char freqs_buf[100];
+       char* cursor;
+       int n;
+       float sr;
+
+       if (new_sampling_rate < min_supported_rate)
+               new_sampling_rate = min_supported_rate;
+
+       if (max_supported_rate &&
+               new_sampling_rate > max_supported_rate) {
+               new_sampling_rate = max_supported_rate;
+       }
+
+       sensor_info[s].sampling_rate = new_sampling_rate;
+
+       /* If we're dealing with a poll-mode sensor */
+       if (!sensor_info[s].num_channels) {
+               /* Interrupt current sleep so the new sampling gets used */
+               pthread_cond_signal(&thread_release_cond[s]);
+               return 0;
+       }
+
+       sprintf(sysfs_path, SENSOR_SAMPLING_PATH, dev_num, prefix);
+
+       if (sysfs_read_float(sysfs_path, &cur_sampling_rate) != -1) {
+               per_sensor_sampling_rate = 1;
+               per_device_sampling_rate = 0;
+       } else {
+               per_sensor_sampling_rate = 0;
+
+               sprintf(sysfs_path, DEVICE_SAMPLING_PATH, dev_num);
+
+               if (sysfs_read_float(sysfs_path, &cur_sampling_rate) != -1)
+                       per_device_sampling_rate = 1;
+               else
+                       per_device_sampling_rate = 0;
+       }
+
+       if (!per_sensor_sampling_rate && !per_device_sampling_rate) {
+               ALOGE("No way to adjust sampling rate on sensor %d\n", s);
+               return -ENOSYS;
+       }
+
+       /* 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_info[n].dev_num == dev_num &&
+                           sensor_info[n].num_channels &&
+                           is_enabled(s) &&
+                           sensor_info[n].sampling_rate > new_sampling_rate)
+                               new_sampling_rate= sensor_info[n].sampling_rate;
+
+       /* Check if we have contraints on allowed sampling rates */
+
+       sprintf(avail_sysfs_path, DEVICE_AVAIL_FREQ_PATH, dev_num);
+
+       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" */
+
+               /* While we're not at the end of the string */
+               while (*cursor && cursor[0]) {
+
+                       /* Decode a single value */
+                       sr = strtod(cursor, NULL);
+
+                       /* If this matches the selected rate, we're happy */
+                       if (new_sampling_rate == sr)
+                               break;
+
+                       /*
+                        * 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 > new_sampling_rate) {
+                               new_sampling_rate = sr;
+                               break;
+                       }
+
+                       /* Skip digits */
+                       while (cursor[0] && !isspace(cursor[0]))
+                               cursor++;
+
+                       /* Skip spaces */
+                       while (cursor[0] && isspace(cursor[0]))
+                                       cursor++;
+               }
+       }
+
+       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;
+
+       ALOGI("Sensor %d sampling rate set to %g\n", s, new_sampling_rate);
+
+       if (trig_sensors_per_dev[dev_num])
+               enable_buffer(dev_num, 0);
+
+       sysfs_write_float(sysfs_path, new_sampling_rate);
+
+       /* 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);
+
+       return 0;
+}
+/*
+ * We go through all the virtual sensors of the base - and the base itself
+ * in order to recompute the maximum requested delay of the group and setup the base
+ * at that specific delay.
+ */
+static int arbitrate_bases (int s)
+{
+       int i, vidx;
+
+       float arbitrated_rate = 0;
+
+       if (sensor_info[s].directly_enabled)
+               arbitrated_rate = sensor_info[s].requested_rate;
+
+        for (i = 0; i < sensor_count; i++) {
+                       for (vidx = 0; vidx < sensor_info[i].base_count; vidx++)
+                       /* If we have a virtual sensor depending on this one - handle it */
+                               if (sensor_info[i].base_idx[vidx] == s &&
+                                       sensor_info[i].directly_enabled &&
+                                       sensor_info[i].requested_rate > arbitrated_rate)
+                                               arbitrated_rate = sensor_info[i].requested_rate;
+               }
+
+       return setup_delay_sysfs(s, arbitrated_rate);
+}
+
+/*
+ * Re-assesment for delays. We need to re-asses delays for all related groups
+ * of sensors everytime a sensor enables / disables / changes frequency.
+*/
+int arbitrate_delays (int s)
+{
+       int i;
+
+       if (!sensor_info[s].is_virtual) {
+               return arbitrate_bases(s);
+       }
+       /* Is virtual sensor - go through bases */
+       for (i = 0; i < sensor_info[s].base_count; i++)
+               arbitrate_bases(sensor_info[s].base_idx[i]);
+
+       return 0;
+}
+int sensor_activate(int s, int enabled, int from_virtual)
 {
        char device_name[PATH_MAX];
        struct epoll_event ev = {0};
@@ -592,34 +865,22 @@ int sensor_activate(int s, int enabled)
        int dev_num = sensor_info[s].dev_num;
        int is_poll_sensor = !sensor_info[s].num_channels;
 
-       /* Prepare the report timestamp field for the first event, see set_report_ts method */
-       sensor_info[s].report_ts = 0;
-
-       /* If we want to activate gyro calibrated and gyro uncalibrated is activated
-        * Deactivate gyro uncalibrated - Uncalibrated releases handler
-        * Activate gyro calibrated     - Calibrated has handler
-        * Reactivate gyro uncalibrated - Uncalibrated gets data from calibrated */
-
-       /* If we want to deactivate gyro calibrated and gyro uncalibrated is active
-        * Deactivate gyro uncalibrated - Uncalibrated no longer gets data from handler
-        * Deactivate gyro calibrated   - Calibrated releases handler
-        * 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].enabled != 0) {
-
-                               sensor_activate(sensor_info[s].pair_idx, 0);
-                               ret = sensor_activate(s, enabled);
-                               sensor_activate(sensor_info[s].pair_idx, 1);
-                               return ret;
+       if (sensor_info[s].is_virtual) {
+               sensor_activate_virtual(s, enabled, from_virtual);
+               arbitrate_delays(s);
+               return 0;
        }
 
-       ret = adjust_counters(s, enabled);
+       /* Prepare the report timestamp field for the first event, see set_report_ts method */
+       sensor_info[s].report_ts = 0;
+       ret = adjust_counters(s, enabled, from_virtual);
 
        /* If the operation was neutral in terms of state, we're done */
        if (ret <= 0)
                return ret;
 
+       arbitrate_delays(s);
+
        sensor_info[s].event_count = 0;
        sensor_info[s].meta_data_pending = 0;
 
@@ -682,7 +943,7 @@ int sensor_activate(int s, int enabled)
                if (dev_fd == -1) {
                        ALOGE("Could not open fd on %s (%s)\n",
                              device_name, strerror(errno));
-                       adjust_counters(s, 0);
+                       adjust_counters(s, 0, from_virtual);
                        return -1;
                }
 
@@ -716,25 +977,6 @@ int sensor_activate(int s, int enabled)
 }
 
 
-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.
-        */
-
-       if (sensor_info[s].type != SENSOR_TYPE_ACCELEROMETER)
-               return 0;
-
-       if (sensor_info[s].sampling_rate < 25)
-               return 0;
-
-       return 1;
-}
-
-
 static void enable_motion_trigger (int dev_num)
 {
        /*
@@ -766,7 +1008,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].enabled &&
+                   is_enabled(s) &&
                    sensor_info[s].num_channels &&
                    (!sensor_info[s].motion_trigger_name[0] ||
                     !sensor_info[s].report_initialized ||
@@ -779,7 +1021,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].enabled &&
+                   is_enabled(s) &&
                    sensor_info[s].num_channels &&
                    sensor_info[s].selected_trigger !=
                        sensor_info[s].motion_trigger_name)
@@ -839,7 +1081,7 @@ static void stamp_reports (int dev_num, int64_t ts)
 
        for (s=0; s<MAX_SENSORS; s++)
                        if (sensor_info[s].dev_num == dev_num &&
-                               sensor_info[s].enabled)
+                               is_enabled(s))
                                        set_report_ts(s, ts);
 }
 
@@ -883,7 +1125,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].enabled) {
+                   is_enabled(s)) {
 
                        sr_offset = 0;
 
@@ -923,7 +1165,7 @@ static int integrate_device_report (int dev_num)
        /* Don't trust the timestamp channel in any-motion mode */
        for (s=0; s<MAX_SENSORS; s++)
                if (sensor_info[s].dev_num == dev_num &&
-                   sensor_info[s].enabled &&
+                   is_enabled(s) &&
                    sensor_info[s].selected_trigger ==
                                        sensor_info[s].motion_trigger_name) {
                stamp_reports(dev_num, get_timestamp_boot());
@@ -952,6 +1194,16 @@ static int integrate_device_report (int dev_num)
        return 0;
 }
 
+static int propagate_vsensor_report (int s, struct sensors_event_t  *data)
+{
+       /* There's a new report stored in sensor_info.sample for this sensor; transmit it */
+
+       memcpy(data, &sensor_info[s].sample, sizeof(struct sensors_event_t));
+
+       data->sensor    = s;
+       data->type      = sensor_info[s].type;
+       return 1;
+}
 
 static int propagate_sensor_report (int s, struct sensors_event_t  *data)
 {
@@ -965,12 +1217,6 @@ static int propagate_sensor_report (int s, struct sensors_event_t  *data)
        if (!num_fields)
                return 0;
 
-
-       /* Only return uncalibrated event if also gyro active */
-       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);
@@ -1026,7 +1272,7 @@ static void synthetize_duplicate_samples (void)
        for (s=0; s<sensor_count; s++) {
 
                /* Ignore disabled sensors */
-               if (!sensor_info[s].enabled)
+               if (!is_enabled(s))
                        continue;
 
                /* If the sensor is continuously firing, leave it alone */
@@ -1105,7 +1351,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].enabled &&
+               if (is_enabled(s) &&
                    sensor_info[s].selected_trigger ==
                    sensor_info[s].motion_trigger_name &&
                    sensor_info[s].sampling_rate) {
@@ -1141,49 +1387,26 @@ int sensor_poll(struct sensors_event_t* data, int count)
        int uncal_start;
 
        /* Get one or more events from our collection of sensors */
-
 return_available_sensor_reports:
 
        /* Synthetize duplicate samples if needed */
        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_info[s].report_pending) {
                        event_count = 0;
 
-                       /* Report this event if it looks OK */
-                       event_count = propagate_sensor_report(s, &data[returned_events]);
+                       if (sensor_info[s].is_virtual)
+                               event_count = propagate_vsensor_report(s, &data[returned_events]);
+                       else {
+                               /* 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_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],
-                                                       sizeof(struct sensors_event_t) * event_count);
-
-                                       uncal_start = returned_events + event_count;
-                                       for (i = 0; i < event_count; i++) {
-                                               data[uncal_start + i].type = SENSOR_TYPE_GYROSCOPE_UNCALIBRATED;
-                                               data[uncal_start + i].sensor = sensor_info[s].pair_idx;
-
-                                               data[uncal_start + i].data[0] = data[returned_events + i].data[0] + gyro_data->bias_x;
-                                               data[uncal_start + i].data[1] = data[returned_events + i].data[1] + gyro_data->bias_y;
-                                               data[uncal_start + i].data[2] = data[returned_events + i].data[2] + gyro_data->bias_z;
-
-                                               data[uncal_start + i].uncalibrated_gyro.bias[0] = gyro_data->bias_x;
-                                               data[uncal_start + i].uncalibrated_gyro.bias[1] = gyro_data->bias_y;
-                                               data[uncal_start + i].uncalibrated_gyro.bias[2] = gyro_data->bias_z;
-                                       }
-                                       event_count <<= 1;
-                       }
-                       sensor_info[sensor_info[s].pair_idx].report_pending = 0;
                        returned_events += event_count;
                        /*
                         * If the sample was deemed invalid or unreportable,
@@ -1243,53 +1466,12 @@ await_event:
        goto return_available_sensor_reports;
 }
 
-
-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 */
-
-       /* See Android sensors.h for indication on sensor trigger modes */
-
-       char sysfs_path[PATH_MAX];
-       char avail_sysfs_path[PATH_MAX];
-       int dev_num             =       sensor_info[s].dev_num;
-       int i                   =       sensor_info[s].catalog_index;
-       const char *prefix      =       sensor_catalog[i].tag;
        float new_sampling_rate; /* Granted sampling rate after arbitration   */
-       float cur_sampling_rate; /* Currently used sampling rate              */
-       int per_sensor_sampling_rate;
-       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.0 / max_delay_us) : 1;
-       float max_supported_rate = 
-               (min_delay_us && min_delay_us != -1) ? (1000000.0 / min_delay_us) : 0;
-       char freqs_buf[100];
-       char* cursor;
-       int n;
-       float sr;
 
        if (ns <= 0) {
-               ALOGE("Rejecting non-positive delay request on sensor %d, required delay: %lld\n", s, ns);
+               ALOGE("Rejecting non-positive delay request on sensor %d,required delay: %lld\n", s, ns);
                return -EINVAL;
        }
 
@@ -1299,128 +1481,15 @@ int sensor_set_delay(int s, int64_t ns)
                s, sensor_info[s].friendly_name, sensor_info[s].sampling_rate,
                new_sampling_rate);
 
-       /*
-        * Artificially limit ourselves to 1 Hz or higher. This is mostly to
-        * avoid setting up the stage for divisions by zero.
-        */
-       if (new_sampling_rate < min_supported_rate)
-               new_sampling_rate = min_supported_rate;
-
-       if (max_supported_rate &&
-               new_sampling_rate > max_supported_rate) {
-               new_sampling_rate = max_supported_rate;
-       }
-
-       sensor_info[s].sampling_rate = new_sampling_rate;
-
-       /* If we're dealing with a poll-mode sensor */
-       if (!sensor_info[s].num_channels) {
-               /* Interrupt current sleep so the new sampling gets used */
-               pthread_cond_signal(&thread_release_cond[s]);
-               return 0;
-       }
-
-       sprintf(sysfs_path, SENSOR_SAMPLING_PATH, dev_num, prefix);
-
-       if (sysfs_read_float(sysfs_path, &cur_sampling_rate) != -1) {
-               per_sensor_sampling_rate = 1;
-               per_device_sampling_rate = 0;
-       } else {
-               per_sensor_sampling_rate = 0;
-
-               sprintf(sysfs_path, DEVICE_SAMPLING_PATH, dev_num);
-
-               if (sysfs_read_float(sysfs_path, &cur_sampling_rate) != -1)
-                       per_device_sampling_rate = 1;
-               else
-                       per_device_sampling_rate = 0;
-       }
-
-       if (!per_sensor_sampling_rate && !per_device_sampling_rate) {
-               ALOGE("No way to adjust sampling rate on sensor %d\n", s);
-               return -ENOSYS;
-       }
-
-       /* 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_info[n].dev_num == dev_num &&
-                           sensor_info[n].num_channels &&
-                           sensor_info[n].enabled &&
-                           sensor_info[n].sampling_rate > new_sampling_rate)
-                               new_sampling_rate= sensor_info[n].sampling_rate;
-
-       /* Check if we have contraints on allowed sampling rates */
-
-       sprintf(avail_sysfs_path, DEVICE_AVAIL_FREQ_PATH, dev_num);
-
-       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" */
-
-               /* While we're not at the end of the string */
-               while (*cursor && cursor[0]) {
-
-                       /* Decode a single value */
-                       sr = strtod(cursor, NULL);
-
-                       /* If this matches the selected rate, we're happy */
-                       if (new_sampling_rate == sr)
-                               break;
-
-                       /*
-                        * 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 > new_sampling_rate) {
-                               new_sampling_rate = sr;
-                               break;
-                       }
-
-                       /* Skip digits */
-                       while (cursor[0] && !isspace(cursor[0]))
-                               cursor++;
-
-                       /* Skip spaces */
-                       while (cursor[0] && isspace(cursor[0]))
-                                       cursor++;
-               }
-       }
-
-       if (max_supported_rate &&
-               new_sampling_rate > max_supported_rate) {
-               new_sampling_rate = max_supported_rate;
-       }
+       sensor_info[s].requested_rate = new_sampling_rate;
 
-       /* If the desired rate is already active we're all set */
-       if (new_sampling_rate == cur_sampling_rate)
-               return 0;
-
-       ALOGI("Sensor %d sampling rate set to %g\n", s, new_sampling_rate);
-
-       if (trig_sensors_per_dev[dev_num])
-               enable_buffer(dev_num, 0);
-
-       sysfs_write_float(sysfs_path, new_sampling_rate);
-
-       /* 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);
-
-       return 0;
+       return arbitrate_delays(s);
 }
 
 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].enabled == 0)
+       if (sensor_desc[s].flags & SENSOR_FLAG_ONE_SHOT_MODE || !is_enabled(s))
                return -EINVAL;
 
        sensor_info[s].meta_data_pending++;
index d1bfa41..1d1568b 100644 (file)
--- a/control.h
+++ b/control.h
@@ -5,7 +5,7 @@
 #ifndef __CONTROL_H__
 #define __CONTROL_H__
 
-int    sensor_activate         (int handle, int enabled);
+int    sensor_activate         (int handle, int enabled, int from_virtual);
 int    sensor_set_delay        (int handle, int64_t ns);
 int    sensor_poll     (sensors_event_t* data, int count);
 int sensor_flush       (int handle);
index a009a34..68cc52d 100644 (file)
@@ -142,6 +142,23 @@ int sensor_get_fl_prop (int s, const char* sel, float* val)
 
 char* sensor_get_name (int s)
 {
+       char buf[MAX_NAME_SIZE];
+
+       if (sensor_info[s].is_virtual) {
+               switch (sensor_info[s].type) {
+                       case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
+                       case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+                               strcpy(buf, sensor_info[sensor_info[s].base_idx[0]].friendly_name);
+                               snprintf(sensor_info[s].friendly_name,
+                                        MAX_NAME_SIZE,
+                                        "%s %s", "Uncalibrated", buf);
+                               return sensor_info[s].friendly_name;
+
+                       default:
+                               return "";
+               }
+       }
+
        if (sensor_info[s].friendly_name[0] != '\0' ||
                !sensor_get_st_prop(s, "name", sensor_info[s].friendly_name))
                        return sensor_info[s].friendly_name;
@@ -160,6 +177,19 @@ char* sensor_get_name (int s)
 
 char* sensor_get_vendor (int s)
 {
+       if (sensor_info[s].is_virtual) {
+               switch (sensor_info[s].type) {
+                       case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
+                       case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+                               return sensor_info[sensor_info[s].base_idx[0]].vendor_name;
+                       break;
+
+                       default:
+                               return "";
+
+               }
+       }
+
        if (sensor_info[s].vendor_name[0] ||
                !sensor_get_st_prop(s, "vendor", sensor_info[s].vendor_name))
                        return sensor_info[s].vendor_name;
@@ -176,6 +206,18 @@ int sensor_get_version (__attribute__((unused)) int s)
 
 float sensor_get_max_range (int s)
 {
+
+       if (sensor_info[s].is_virtual)  {
+               switch (sensor_info[s].type) {
+                       case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
+                       case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+                               return sensor_info[sensor_info[s].base_idx[0]].max_range;
+
+                       default:
+                               return 0.0;
+               }
+       }
+
        if (sensor_info[s].max_range != 0.0 ||
                !sensor_get_fl_prop(s, "max_range", &sensor_info[s].max_range))
                        return sensor_info[s].max_range;
@@ -251,6 +293,17 @@ int sensor_get_cal_steps (int s)
 
 float sensor_get_resolution (int s)
 {
+       if (sensor_info[s].is_virtual) {
+               switch (sensor_info[s].type) {
+                       case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
+                       case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+                               return sensor_info[sensor_info[s].base_idx[0]].resolution;
+
+                       default:
+                               return 0;
+               }
+       }
+
        if (sensor_info[s].resolution != 0.0 ||
                !sensor_get_fl_prop(s, "resolution", &sensor_info[s].resolution))
                        return sensor_info[s].resolution;
@@ -261,6 +314,18 @@ float sensor_get_resolution (int s)
 
 float sensor_get_power (int s)
 {
+
+       if (sensor_info[s].is_virtual) {
+               switch (sensor_info[s].type) {
+                       case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
+                       case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+                               return sensor_info[sensor_info[s].base_idx[0]].power;
+
+                       default:
+                               return 0;
+               }
+       }
+
        /* mA used while sensor is in use ; not sure about volts :) */
        if (sensor_info[s].power != 0.0 ||
                !sensor_get_fl_prop(s, "power", &sensor_info[s].power))
@@ -456,6 +521,15 @@ max_delay_t sensor_get_max_delay (int s)
            REPORTING_MODE(sensor_desc[s].flags) == SENSOR_FLAG_SPECIAL_REPORTING_MODE)
                return 0;
 
+       if (sensor_info[s].is_virtual) {
+               switch (sensor_info[s].type) {
+                       case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
+                       case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+                               return sensor_desc[sensor_info[s].base_idx[0]].maxDelay;
+                       default:
+                               return 0;
+               }
+       }
        sprintf(avail_sysfs_path, DEVICE_AVAIL_FREQ_PATH, dev_num);
 
        if (sysfs_read_str(avail_sysfs_path, freqs_buf, sizeof(freqs_buf)) < 0) {
@@ -525,6 +599,16 @@ int32_t sensor_get_min_delay(int s)
        if (REPORTING_MODE(sensor_desc[s].flags) == SENSOR_FLAG_ONE_SHOT_MODE)
                return -1;
 
+       if (sensor_info[s].is_virtual) {
+               switch (sensor_info[s].type) {
+                       case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
+                       case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+                               return sensor_desc[sensor_info[s].base_idx[0]].minDelay;
+                       default:
+                               return 0;
+               }
+       }
+
        sprintf(avail_sysfs_path, DEVICE_AVAIL_FREQ_PATH, dev_num);
 
        if (sysfs_read_str(avail_sysfs_path, freqs_buf, sizeof(freqs_buf)) < 0) {
diff --git a/entry.c b/entry.c
index e84e18d..e0121d2 100644 (file)
--- a/entry.c
+++ b/entry.c
@@ -27,17 +27,18 @@ static int activate (__attribute__((unused)) struct sensors_poll_device_t* dev,
         * a workaround for this behavior. We set the initial sampling rate to
         * 10 events per second when the sensor is enabled for the first time.
         */
+
        if (enabled && sensor_get_quirks(handle) & QUIRK_INITIAL_RATE) {
                ALOGI("Forcing initial sampling rate\n");
-               sensor_activate(handle, 1);
+               sensor_activate(handle, 1, 0);
                sensor_set_delay(handle, 100000000L);   /* Start with 100 ms */
-               sensor_activate(handle, 0);
+               sensor_activate(handle, 0, 0);
 
                /* Clear flag for this sensor as do this only once */
                sensor_info[handle].quirks ^= QUIRK_INITIAL_RATE;
        }
 
-       return sensor_activate(handle, enabled);
+       return sensor_activate(handle, enabled, 0);
 }
 
 
index c6fd7a3..49a4986 100644 (file)
@@ -39,7 +39,7 @@ struct sensor_catalog_entry_t sensor_catalog[] = {
                                         "quat_x", "quat_y", "quat_z", "quat_w")
        DECLARE_SENSOR0("temp",       SENSOR_TYPE_AMBIENT_TEMPERATURE          )
        DECLARE_SENSOR0("proximity",  SENSOR_TYPE_PROXIMITY                    )
-       DECLARE_SENSOR3("anglvel",      SENSOR_TYPE_GYROSCOPE_UNCALIBRATED, "x", "y", "z")
+       DECLARE_VIRTUAL(SENSOR_TYPE_GYROSCOPE_UNCALIBRATED)
 };
 
 #define CATALOG_SIZE   ARRAY_SIZE(sensor_catalog)
@@ -55,7 +55,6 @@ struct sensor_t      sensor_desc[MAX_SENSORS];        /* Android-level descriptors */
 struct sensor_info_t sensor_info[MAX_SENSORS]; /* Internal descriptors      */
 int sensor_count;                              /* Detected sensors          */
 
-
 static void setup_properties_from_pld(int s, int panel, int rotation,
                                      int num_channels)
 {
@@ -198,6 +197,66 @@ static void decode_placement_information (int dev_num, int num_channels, int s)
        setup_properties_from_pld(s, panel, rotation, num_channels);
 }
 
+static void populate_descriptors(int s, int sensor_type)
+{
+       /* Initialize Android-visible descriptor */
+       sensor_desc[s].name             = sensor_get_name(s);
+       sensor_desc[s].vendor           = sensor_get_vendor(s);
+       sensor_desc[s].version          = sensor_get_version(s);
+       sensor_desc[s].handle           = s;
+       sensor_desc[s].type             = sensor_type;
+
+       sensor_desc[s].maxRange         = sensor_get_max_range(s);
+       sensor_desc[s].resolution       = sensor_get_resolution(s);
+       sensor_desc[s].power            = sensor_get_power(s);
+       sensor_desc[s].stringType = sensor_get_string_type(s);
+
+       /* None of our supported sensors requires a special permission.
+       *  If this will be the case we should implement a sensor_get_perm
+       */
+       sensor_desc[s].requiredPermission = "";
+       sensor_desc[s].flags = sensor_get_flags(s);
+       sensor_desc[s].minDelay = sensor_get_min_delay(s);
+       sensor_desc[s].maxDelay = sensor_get_max_delay(s);
+
+       ALOGI("Sensor %d (%s) type(%d) minD(%d) maxD(%d) flags(%2.2x)\n",
+               s, sensor_info[s].friendly_name, sensor_desc[s].type,
+               sensor_desc[s].minDelay, sensor_desc[s].maxDelay, sensor_desc[s].flags);
+
+       /* We currently do not implement batching when we'll so
+        * these should be overriden appropriately
+        */
+       sensor_desc[s].fifoReservedEventCount = 0;
+       sensor_desc[s].fifoMaxEventCount = 0;
+}
+
+static void add_virtual_sensor (int catalog_index)
+{
+       int s;
+       int sensor_type;
+
+       if (sensor_count == MAX_SENSORS) {
+               ALOGE("Too many sensors!\n");
+               return;
+       }
+
+       sensor_type = sensor_catalog[catalog_index].type;
+
+       s = sensor_count;
+
+       sensor_info[s].is_virtual = 1;
+       sensor_info[s].catalog_index    = catalog_index;
+       sensor_info[s].type             = sensor_type;
+
+       populate_descriptors(s, sensor_type);
+
+       /* Initialize fields related to sysfs reads offloading */
+       sensor_info[s].thread_data_fd[0]  = -1;
+       sensor_info[s].thread_data_fd[1]  = -1;
+       sensor_info[s].acquisition_thread = -1;
+
+       sensor_count++;
+}
 
 static void add_sensor (int dev_num, int catalog_index, int use_polling)
 {
@@ -336,33 +395,7 @@ static void add_sensor (int dev_num, int catalog_index, int use_polling)
                if (!sensor_get_fl_prop(s, "opt_scale", &opt_scale))
                        sensor_info[s].channel[0].opt_scale = opt_scale;
 
-       /* Initialize Android-visible descriptor */
-       sensor_desc[s].name             = sensor_get_name(s);
-       sensor_desc[s].vendor           = sensor_get_vendor(s);
-       sensor_desc[s].version          = sensor_get_version(s);
-       sensor_desc[s].handle           = s;
-       sensor_desc[s].type             = sensor_type;
-       sensor_desc[s].maxRange         = sensor_get_max_range(s);
-       sensor_desc[s].resolution       = sensor_get_resolution(s);
-       sensor_desc[s].power            = sensor_get_power(s);
-       sensor_desc[s].stringType = sensor_get_string_type(s);
-
-       /* None of our supported sensors requires a special permission.
-       *  If this will be the case we should implement a sensor_get_perm
-       */
-       sensor_desc[s].requiredPermission = "";
-       sensor_desc[s].flags = sensor_get_flags(s);
-       sensor_desc[s].minDelay = sensor_get_min_delay(s);
-       sensor_desc[s].maxDelay = sensor_get_max_delay(s);
-       ALOGI("Sensor %d (%s) type(%d) minD(%d) maxD(%d) flags(%2.2x)\n",
-               s, sensor_info[s].friendly_name, sensor_desc[s].type,
-               sensor_desc[s].minDelay, sensor_desc[s].maxDelay, sensor_desc[s].flags);
-
-       /* We currently do not implement batching when we'll so
-        * these should be overriden appropriately
-        */
-       sensor_desc[s].fifoReservedEventCount = 0;
-       sensor_desc[s].fifoMaxEventCount = 0;
+       populate_descriptors(s, sensor_type);
 
        /* Populate the quirks array */
        sensor_get_quirks(s);
@@ -377,8 +410,7 @@ static void add_sensor (int dev_num, int catalog_index, int use_polling)
                strcpy(sensor_info[s].internal_name, "(null)");
        }
 
-       if (sensor_type == SENSOR_TYPE_GYROSCOPE ||
-               sensor_type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED) {
+       if (sensor_type == SENSOR_TYPE_GYROSCOPE) {
                struct gyro_cal* calibration_data = calloc(1, sizeof(struct gyro_cal));
                sensor_info[s].cal_data = calibration_data;
        }
@@ -428,9 +460,9 @@ static void discover_poll_sensors (int dev_num, char map[CATALOG_SIZE])
                        continue;
 
                /* If the name matches a catalog entry, flag it */
-               for (i = 0; i<CATALOG_SIZE; i++) {
-               /* This will be added separately later */
-               if (sensor_catalog[i].type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED)
+               for (i = 0; i < CATALOG_SIZE; i++) {
+               /* No discovery for virtual sensors */
+               if (sensor_catalog[i].is_virtual)
                        continue;
                for (c=0; c<sensor_catalog[i].num_channels; c++)
                        if (!strcmp(d->d_name,sensor_catalog[i].channel[c].raw_path) ||
@@ -470,7 +502,8 @@ static void discover_trig_sensors (int dev_num, char map[CATALOG_SIZE])
                /* Compare en entry to known ones and create matching sensors */
 
                for (i = 0; i<CATALOG_SIZE; i++) {
-                       if (sensor_catalog[i].type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED)
+                       /* No discovery for virtual sensors */
+                       if (sensor_catalog[i].is_virtual)
                                continue;
                        if (!strcmp(d->d_name,
                                        sensor_catalog[i].channel[0].en_path)) {
@@ -675,62 +708,33 @@ static void uncalibrated_gyro_check (void)
 {
        unsigned int has_gyr = 0;
        unsigned int dev_num;
-       int i, c;
-       unsigned int is_poll_sensor;
-       char buf[MAX_NAME_SIZE];
+       int i;
 
        int cal_idx = 0;
        int uncal_idx = 0;
        int catalog_size = CATALOG_SIZE; /* Avoid GCC sign comparison warning */
 
+       if (sensor_count == MAX_SENSORS)
+               return;
        /* Checking to see if we have a gyroscope - we can only have uncal if we have the base sensor */
        for (i=0; i < sensor_count; i++)
                if (sensor_info[i].type == SENSOR_TYPE_GYROSCOPE) {
                        has_gyr=1;
-                       dev_num = sensor_info[i].dev_num;
-                       is_poll_sensor = !sensor_info[i].num_channels;
                        cal_idx = i;
                        break;
                }
 
-       /*
-        * If we have a gyro we can add the uncalibrated sensor of the same type and
-        * on the same dev_num. We will save indexes for easy finding and also save the
-        * channel specific information.
-        */
-       if (has_gyr)
+       if (has_gyr) {
+               uncal_idx = sensor_count;
+               sensor_info[uncal_idx].base_count = 1;
+               sensor_info[uncal_idx].base_idx[0] = cal_idx;
+
                for (i=0; i<catalog_size; i++)
                        if (sensor_catalog[i].type == SENSOR_TYPE_GYROSCOPE_UNCALIBRATED) {
-                               add_sensor(dev_num, i, is_poll_sensor);
-
-                               uncal_idx = sensor_count - 1; /* Just added uncalibrated sensor */
-
-                               /* Similar to build_sensor_report_maps */
-                               for (c = 0; c < sensor_info[uncal_idx].num_channels; c++)
-                               {
-                                       memcpy( &(sensor_info[uncal_idx].channel[c].type_spec),
-                                               &(sensor_info[cal_idx].channel[c].type_spec),
-                                               sizeof(sensor_info[uncal_idx].channel[c].type_spec));
-                                       sensor_info[uncal_idx].channel[c].type_info = sensor_info[cal_idx].channel[c].type_info;
-                                       sensor_info[uncal_idx].channel[c].offset    = sensor_info[cal_idx].channel[c].offset;
-                                       sensor_info[uncal_idx].channel[c].size      = sensor_info[cal_idx].channel[c].size;
-                               }
-                               sensor_info[uncal_idx].pair_idx = cal_idx;
-                               sensor_info[cal_idx].pair_idx = uncal_idx;
-                               strncpy(sensor_info[uncal_idx].init_trigger_name,
-                                       sensor_info[cal_idx].init_trigger_name,
-                                       MAX_NAME_SIZE);
-                               strncpy(sensor_info[uncal_idx].motion_trigger_name,
-                                       sensor_info[cal_idx].motion_trigger_name,
-                                       MAX_NAME_SIZE);
-
-                               /* Add "Uncalibrated " prefix to sensor name */
-                               strcpy(buf, sensor_info[cal_idx].friendly_name);
-                               snprintf(sensor_info[uncal_idx].friendly_name,
-                                        MAX_NAME_SIZE,
-                                        "%s %s", "Uncalibrated", buf);
+                               add_virtual_sensor(i);
                                break;
                        }
+       }
 }
 
 void enumerate_sensors (void)
@@ -781,12 +785,7 @@ void enumerate_sensors (void)
         * This is is a new sensor type in Android 4.4.
         */
 
-       /*
-        * Patrick Porlan 11/12/2014 - Disabled for now due to a possible
-        * relation with GMINL-3234 Panorama Drift. I take full responsability
-        * for this.
-        *
-        * uncalibrated_gyro_check(); */
+         uncalibrated_gyro_check();
 }
 
 
@@ -803,7 +802,6 @@ void delete_enumeration_data (void)
                        }
                        break;
 
-               case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
                case SENSOR_TYPE_GYROSCOPE:
                        if (sensor_info[i].cal_data != NULL) {
                                free(sensor_info[i].cal_data);
index e4445be..059213d 100644 (file)
 
 #define DECLARE_GENERIC_CHANNEL(tag)           DECLARE_CHANNEL(tag, "", "")
 
+#define DECLARE_VIRTUAL(type)                  \
+{                                                      \
+       "", type, 0, 1,                         \
+       {                                               \
+               DECLARE_GENERIC_CHANNEL("")             \
+       }                                               \
+},
 
 #define DECLARE_SENSOR0(tag, type)                     \
 {                                                      \
-       tag, type, 1,                                   \
+       tag, type, 1, 0,                                        \
        {                                               \
                DECLARE_GENERIC_CHANNEL(tag)            \
        }                                               \
@@ -39,7 +46,7 @@
 
 #define DECLARE_SENSOR1(tag, type, ch1)                        \
 {                                                      \
-       tag, type, 1,                                   \
+       tag, type, 1, 0,                                        \
        {                                               \
                DECLARE_NAMED_CHANNEL(tag, ch1)         \
        }                                               \
@@ -47,7 +54,7 @@
 
 #define DECLARE_SENSOR2(tag, type, ch1, ch2)           \
 {                                                      \
-       tag, type, 2,                                   \
+       tag, type, 2, 0,                                        \
        {                                               \
                DECLARE_NAMED_CHANNEL(tag, ch1)         \
                DECLARE_NAMED_CHANNEL(tag, ch2)         \
@@ -56,7 +63,7 @@
 
 #define DECLARE_SENSOR3(tag, type, ch1, ch2, ch3)      \
 {                                                      \
-       tag, type, 3,                                   \
+       tag, type, 3, 0,                                \
        {                                               \
                DECLARE_NAMED_CHANNEL(tag, ch1)         \
                DECLARE_NAMED_CHANNEL(tag, ch2)         \
@@ -66,7 +73,7 @@
 
 #define DECLARE_SENSOR4(tag, type, ch1, ch2, ch3, ch4) \
 {                                                      \
-       tag, type, 4,                                   \
+       tag, type, 4, 0,                                        \
        {                                               \
                DECLARE_NAMED_CHANNEL(tag, ch1)         \
                DECLARE_NAMED_CHANNEL(tag, ch2)         \
index 1e5aa38..6668cf8 100644 (file)
@@ -214,7 +214,6 @@ void setup_noise_filtering (int s)
 {
        switch (sensor_info[s].type) {
                case SENSOR_TYPE_GYROSCOPE:
-               case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
                        denoise_median_init(s, 3, 5);
                        break;
        }
@@ -225,7 +224,6 @@ void denoise (int s, struct sensors_event_t* data)
 {
        switch (sensor_info[s].type) {
                case SENSOR_TYPE_GYROSCOPE:
-               case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
                        denoise_median(&sensor_info[s], data, 3);
                        break;
 
index 09fa659..b8c1217 100644 (file)
@@ -134,25 +134,11 @@ void calibrate_gyro(struct sensors_event_t* event, struct sensor_info_t* info)
                info->cal_level = gyro_collect(event->data[0], event->data[1],
                                               event->data[2], cal_data);
 
-       switch (event->type) {
-               case SENSOR_TYPE_GYROSCOPE:
-                       /* For the gyroscope apply the bias */
-                       event->data[0] = event->data[0] - cal_data->bias_x;
-                       event->data[1] = event->data[1] - cal_data->bias_y;
-                       event->data[2] = event->data[2] - cal_data->bias_z;
-
-                       if (info->cal_level)
-                              event->gyro.status = SENSOR_STATUS_ACCURACY_HIGH;
-                       break;
-
-               case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
-                       /*
-                        * For the uncalibrated gyroscope don't apply the bias,
-                        * but tell he Android framework what we think it is.
-                        */
-                       event->uncalibrated_gyro.bias[0] = cal_data->bias_x;
-                       event->uncalibrated_gyro.bias[1] = cal_data->bias_y;
-                       event->uncalibrated_gyro.bias[2] = cal_data->bias_z;
-                       break;
-       }
+
+       event->data[0] = event->data[0] - cal_data->bias_x;
+       event->data[1] = event->data[1] - cal_data->bias_y;
+       event->data[2] = event->data[2] - cal_data->bias_z;
+
+       if (info->cal_level)
+              event->gyro.status = SENSOR_STATUS_ACCURACY_HIGH;
 }
index 90834be..114f1a5 100644 (file)
@@ -194,22 +194,10 @@ static void clamp_gyro_readings_to_zero (int s, struct sensors_event_t* data)
        float x, y, z;
        float near_zero;
 
-       switch (sensor_info[s].type) {
-               case SENSOR_TYPE_GYROSCOPE:
-                       x = data->data[0];
-                       y = data->data[1];
-                       z = data->data[2];
-                       break;
-
-               case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
-                       x = data->data[0] - data->uncalibrated_gyro.bias[0];
-                       y = data->data[1] - data->uncalibrated_gyro.bias[1];
-                       z = data->data[2] - data->uncalibrated_gyro.bias[2];
-                       break;
+       x = data->data[0];
+       y = data->data[1];
+       z = data->data[2];
 
-               default:
-                       return;
-       }
 
        /* If we're calibrated, don't filter out as much */
        if (sensor_info[s].cal_level > 0)
@@ -225,26 +213,60 @@ static void clamp_gyro_readings_to_zero (int s, struct sensors_event_t* data)
                 * as composite sensors (orientation, rotation vector) don't
                 * seem to react very well to it.
                 */
-               switch (sensor_info[s].type) {
-                       case SENSOR_TYPE_GYROSCOPE:
-                               data->data[0] *= 0.000001;
-                               data->data[1] *= 0.000001;
-                               data->data[2] *= 0.000001;
-                               break;
 
+               data->data[0] *= 0.000001;
+               data->data[1] *= 0.000001;
+               data->data[2] *= 0.000001;
+       }
+}
+
+static void process_event_gyro_uncal(int s, int i, struct sensors_event_t* data)
+{
+       struct gyro_cal* gyro_data = NULL;
+
+       if (sensor_info[s].type == SENSOR_TYPE_GYROSCOPE) {
+               gyro_data = (struct gyro_cal*) sensor_info[s].cal_data;
+               memcpy(&sensor_info[i].sample, data, sizeof(struct sensors_event_t));
+
+               sensor_info[i].sample.type = SENSOR_TYPE_GYROSCOPE_UNCALIBRATED;
+               sensor_info[i].sample.sensor = s;
+
+               sensor_info[i].sample.data[0] = data->data[0] + gyro_data->bias_x;
+               sensor_info[i].sample.data[1] = data->data[1] + gyro_data->bias_y;
+               sensor_info[i].sample.data[2] = data->data[2] + gyro_data->bias_z;
+
+               sensor_info[i].sample.uncalibrated_gyro.bias[0] = gyro_data->bias_x;
+               sensor_info[i].sample.uncalibrated_gyro.bias[1] = gyro_data->bias_y;
+               sensor_info[i].sample.uncalibrated_gyro.bias[2] = gyro_data->bias_z;
+
+               sensor_info[i].report_pending = 1;
+       }
+}
+
+static void process_event(int s, struct sensors_event_t* data)
+{
+       /*
+        * This gets the real event (post process - calibration, filtering & co.)
+        * and makes it into a virtual one.
+        * The specific processing function for each sensor will populate the
+        * necessary fields and set up the report pending flag.
+        */
+
+        int i;
+
+        /* Go through out virtual sensors and check if we can use this event */
+        for (i = 0; i < sensor_count; i++) {
+               switch (sensor_info[i].type) {
                        case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
-                               data->data[0]= data->uncalibrated_gyro.bias[0]
-                                               + 0.000001 * x;
-                               data->data[1]= data->uncalibrated_gyro.bias[1]
-                                               + 0.000001 * y;
-                               data->data[2]= data->uncalibrated_gyro.bias[2]
-                                               + 0.000001 * z;
-                               break;
+                               process_event_gyro_uncal(s, i, data);
+                       break;
+
+                       default:
+                       break;
                }
        }
 }
 
-
 static int finalize_sample_default (int s, struct sensors_event_t* data)
 {
        /* Swap fields if we have a custom channel ordering on this sensor */
@@ -275,10 +297,6 @@ static int finalize_sample_default (int s, struct sensors_event_t* data)
                         */
                        data->gyro.status = SENSOR_STATUS_ACCURACY_MEDIUM;
 
-                       /* ... fall through */
-
-               case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
-
                        /*
                         * We're only trying to calibrate data from continuously
                         * firing gyroscope drivers, as motion based ones use
@@ -326,6 +344,12 @@ static int finalize_sample_default (int s, struct sensors_event_t* data)
                        sensor_info[s].prev_val = data->data[0];
                        break;
        }
+       /* If there are active virtual sensors depending on this one - process the event */
+       if (sensor_info[s].ref_count)
+               process_event(s, data);
+       /* We will drop samples if the sensor is not directly enabled */
+       if (!sensor_info[s].directly_enabled)
+               return 0;
 
        return 1; /* Return sample to Android */
 }