OSDN Git Service

GMIN-2992: Start with -dev trigger before switching to -any-motion
authorPatrick Porlan <patrick.porlan@intel.com>
Mon, 25 Aug 2014 16:51:55 +0000 (18:51 +0200)
committerAdriana Reus <adriana.reus@intel.com>
Wed, 3 Sep 2014 07:53:38 +0000 (10:53 +0300)
Otherwise we're stuck waiting for a first sample (in order to engage
the periodic repeat-last-sample-if-nothing-arrived-for-a-while code)
which makes a variety of tests fail.

Issue: GMIN-2992

Change-Id: I13093f364455a566de80a5e185707590007d8235
Signed-off-by: Patrick Porlan <patrick.porlan@intel.com>
common.h
control.c
description.h
enumeration.c

index 209f71d..7fdadf2 100644 (file)
--- a/common.h
+++ b/common.h
@@ -99,14 +99,25 @@ struct sample_ops_t
 
 struct sensor_info_t
 {
-       char friendly_name[MAX_NAME_SIZE];      /* ex: Accelerometer */
-       char internal_name[MAX_NAME_SIZE];      /* ex: accel_3d */
-       char vendor_name[MAX_NAME_SIZE];        /* ex: Intel */
-       char trigger_name[MAX_NAME_SIZE];       /* ex: accel-name-dev1 */
+       char friendly_name[MAX_NAME_SIZE];      /* ex: Accelerometer         */
+       char internal_name[MAX_NAME_SIZE];      /* ex: accel_3d              */
+       char vendor_name[MAX_NAME_SIZE];        /* ex: Intel                 */
+       char init_trigger_name[MAX_NAME_SIZE];  /* ex: accel-name-dev1       */
+       char motion_trigger_name[MAX_NAME_SIZE];/* ex: accel-any-motion-dev1 */
        float max_range;
        float resolution;
        float power;
 
+       /*
+        * Currently active trigger - either a pointer to the initial (default)
+        * trigger name buffer, or a pointer to the motion trigger name buffer,
+        * or something else (typically NULL or a pointer to some static "\n".
+        * This is used to determine if the conditions are met to switch from
+        * the default trigger to the motion trigger for a sensor, or rather for
+        * the interrupt-driven sensors associated to a given iio device.
+        */
+       const char* selected_trigger;
+
        float offset;   /* (cooked = raw + offset) * scale */
        float scale;    /*default: 1. when set to 0, use channel specific value*/
        float illumincalib;     /* to set the calibration for the ALS */
index 3a827ae..71b72ca 100644 (file)
--- a/control.c
+++ b/control.c
@@ -52,13 +52,19 @@ static int enable_buffer(int dev_num, int enabled)
 }
 
 
-static int setup_trigger(int dev_num, const char* trigger_val)
+static void setup_trigger (int s, const char* trigger_val)
 {
        char sysfs_path[PATH_MAX];
 
-       sprintf(sysfs_path, TRIGGER_PATH, dev_num);
+       sprintf(sysfs_path, TRIGGER_PATH, sensor_info[s].dev_num);
 
-       return sysfs_write_str(sysfs_path, trigger_val);
+       if (trigger_val[0] != '\n')
+               ALOGI("Setting S%d (%s) trigger to %s\n", s,
+                       sensor_info[s].friendly_name, trigger_val);
+
+       sysfs_write_str(sysfs_path, trigger_val);
+
+       sensor_info[s].selected_trigger = trigger_val;
 }
 
 
@@ -157,7 +163,7 @@ void build_sensor_report_maps(int dev_num)
 
                /* Stop sampling - if we are recovering from hal restart */
                 enable_buffer(dev_num, 0);
-                setup_trigger(dev_num, "\n");
+                setup_trigger(s, "\n");
 
                /* Turn on channels we're aware of */
                for (c=0;c<sensor_info[s].num_channels; c++) {
@@ -524,13 +530,13 @@ int sensor_activate(int s, int enabled)
 
                /* Stop sampling */
                enable_buffer(dev_num, 0);
-               setup_trigger(dev_num, "\n");
+               setup_trigger(s, "\n");
 
                /* If there's at least one sensor enabled on this iio device */
                if (trig_sensors_per_dev[dev_num]) {
 
                        /* Start sampling */
-                       setup_trigger(dev_num, sensor_info[s].trigger_name);
+                       setup_trigger(s, sensor_info[s].init_trigger_name);
                        enable_buffer(dev_num, 1);
                }
        }
@@ -565,6 +571,7 @@ int sensor_activate(int s, int enabled)
                        sensor_info[s].history = NULL;
                        sensor_info[s].history_size = 0;
                }
+
                return 0;
        }
 
@@ -612,6 +619,70 @@ int sensor_activate(int s, int enabled)
 }
 
 
+static void enable_motion_trigger (int dev_num)
+{
+       /*
+        * In the ideal case, we enumerate two triggers per iio device ; the
+        * default (periodically firing) trigger, and another one (the motion
+        * trigger) that only fires up when motion is detected. This second one
+        * allows for lesser energy consumption, but requires periodic sample
+        * duplication at the HAL level for sensors that Android defines as
+        * continuous. This "duplicate last sample" logic can only be engaged
+        * once we got a first sample for the driver, so we start with the
+        * default trigger when an iio device is first opened, then adjust the
+        * trigger when we got events for all active sensors. Unfortunately in
+        * the general case several sensors can be associated to a given iio
+        * device, they can independently be controlled, and we have to adjust
+        * the trigger in use at the iio device level depending on whether or
+        * not appropriate conditions are met at the sensor level.
+        */
+
+       int s;
+       int i;
+       int active_sensors = trig_sensors_per_dev[dev_num];
+       int candidate[MAX_SENSORS];
+       int candidate_count = 0;
+
+       if  (!active_sensors)
+               return;
+
+       /* Check that all active sensors are ready to switch */
+
+       for (s=0; s<MAX_SENSORS; s++)
+               if (sensor_info[s].dev_num == dev_num &&
+                   sensor_info[s].enable_count &&
+                   sensor_info[s].num_channels &&
+                   (!sensor_info[s].motion_trigger_name[0] ||
+                    !sensor_info[s].report_initialized)
+                   )
+                       return; /* Nope */
+
+       /* Record which particular sensors need to switch */
+
+       for (s=0; s<MAX_SENSORS; s++)
+               if (sensor_info[s].dev_num == dev_num &&
+                   sensor_info[s].enable_count &&
+                   sensor_info[s].num_channels &&
+                   sensor_info[s].selected_trigger !=
+                       sensor_info[s].motion_trigger_name)
+                               candidate[candidate_count++] = s;
+
+       if (!candidate_count)
+               return;
+
+       /* Now engage the motion trigger for sensors which aren't using it */
+
+       enable_buffer(dev_num, 0);
+
+       for (i=0; i<candidate_count; i++) {
+               s = candidate[i];
+               setup_trigger(s, sensor_info[s].motion_trigger_name);
+       }
+
+       enable_buffer(dev_num, 1);
+}
+
+
 static int integrate_device_report(int dev_num)
 {
        int len;
@@ -678,6 +749,9 @@ static int integrate_device_report(int dev_num)
                        sensor_info[s].report_initialized = 1;
                }
 
+       /* Tentatively switch to an any-motion trigger if conditions are met */
+       enable_motion_trigger(dev_num);
+
        return 0;
 }
 
@@ -761,7 +835,9 @@ static void synthetize_duplicate_samples (void)
                        continue;
 
                /* If the sensor can generate duplicates, leave it alone */
-               if (!(sensor_info[s].quirks & QUIRK_TERSE_DRIVER))
+               if (!(sensor_info[s].quirks & QUIRK_TERSE_DRIVER) &&
+                       sensor_info[s].selected_trigger !=
+                       sensor_info[s].motion_trigger_name)
                        continue;
 
                /* If we haven't seen a sample, there's nothing to duplicate */
@@ -830,8 +906,10 @@ static int get_poll_wait_timeout (void)
         */
        for (s=0; s<sensor_count; s++)
                if (sensor_info[s].enable_count &&
-                   (sensor_info[s].quirks & QUIRK_TERSE_DRIVER) &&
-                   sensor_info[s].sampling_rate) {
+                   ((sensor_info[s].quirks & QUIRK_TERSE_DRIVER) ||
+                     sensor_info[s].selected_trigger ==
+                     sensor_info[s].motion_trigger_name) &&
+                    sensor_info[s].sampling_rate) {
                        period = (int64_t) (1000000000.0 /
                                                sensor_info[s].sampling_rate);
 
index abeb6ee..a398b81 100644 (file)
@@ -7,11 +7,11 @@
 
 #include "common.h"
 
-#define QUIRK_ALREADY_DECODED  0x01  /* Sensor quirks have been read       */
-#define QUIRK_INITIAL_RATE     0x02  /* Force initial sensor sampling rate */
-#define QUIRK_FIELD_ORDERING   0x04
-#define QUIRK_TERSE_DRIVER     0x08  /* Force duplicate events generation  */
-#define QUIRK_NOISY            0x10  /* High noise level on readings       */
+#define QUIRK_ALREADY_DECODED  0x01  /* Sensor quirks have been read         */
+#define QUIRK_INITIAL_RATE     0x02  /* Force initial sensor sampling rate   */
+#define QUIRK_FIELD_ORDERING   0x04  /* Do field remapping for this sensor   */
+#define QUIRK_TERSE_DRIVER     0x08  /* Force duplicate events generation    */
+#define QUIRK_NOISY            0x10  /* High noise level on readings         */
 
 char*  sensor_get_name         (int handle);
 char*  sensor_get_vendor       (int handle);
index 68d0a4f..6e29f64 100644 (file)
@@ -542,25 +542,19 @@ static void propose_new_trigger (int s, char trigger_name[MAX_NAME_SIZE],
                return;
 
        /*
-        * Anything else is higher priority. However if we already found an
-        * any-motion trigger, don't select anything else.
-        */
-
-       if (!memcmp(sensor_info[s].trigger_name + sensor_name_len + 1,
-                   "any-motion-", 11))
-               return;
-
-       /*
-        * If we're switching to an any-motion trigger, force the sensor to
+        * If we found any-motion trigger, record it and force the sensor to
         * automatic intermediate event generation mode, at least if it is of a
         * continuously firing sensor type.
         */
 
-       if (!memcmp(suffix, "any-motion-", 11) && is_continuous(s))
-               sensor_info[s].quirks |= QUIRK_TERSE_DRIVER;
+       if (!memcmp(suffix, "any-motion-", 11) && is_continuous(s)) {
+               /* Update the any-motion trigger name to use for this sensor */
+               strcpy(sensor_info[s].motion_trigger_name, trigger_name);
+               return;
+       }
 
-       /* Update the trigger name to use for this sensor */
-       strcpy(sensor_info[s].trigger_name, trigger_name);
+       /* Update the initial trigger name to use for this sensor */
+       strcpy(sensor_info[s].init_trigger_name, trigger_name);
 }
 
 
@@ -628,8 +622,9 @@ static void setup_trigger_names (void)
 
        /* By default, use the name-dev convention that most drivers use */
        for (s=0; s<sensor_count; s++)
-               snprintf(sensor_info[s].trigger_name, MAX_NAME_SIZE, "%s-dev%d",
-                       sensor_info[s].internal_name, sensor_info[s].dev_num);
+               snprintf(sensor_info[s].init_trigger_name,
+                        MAX_NAME_SIZE, "%s-dev%d",
+                        sensor_info[s].internal_name, sensor_info[s].dev_num);
 
        /* Now have a look to /sys/bus/iio/devices/triggerX entries */
 
@@ -642,14 +637,19 @@ static void setup_trigger_names (void)
                if (ret < 0)
                        break;
 
+               /* Record initial and any-motion triggers names */
                update_sensor_matching_trigger_name(buf);
        }
 
        for (s=0; s<sensor_count; s++)
                if (sensor_info[s].num_channels) {
-                       ALOGI(  "Sensor %d (%s) using iio trigger %s\n", s,
+                       ALOGI(  "Sensor %d (%s) default trigger: %s\n", s,
                                sensor_info[s].friendly_name,
-                               sensor_info[s].trigger_name);
+                               sensor_info[s].init_trigger_name);
+                       if (sensor_info[s].motion_trigger_name[0])
+                               ALOGI(  "Sensor %d (%s) motion trigger: %s\n",
+                               s, sensor_info[s].friendly_name,
+                               sensor_info[s].motion_trigger_name);
                }
 }
 
@@ -699,6 +699,12 @@ static void uncalibrated_gyro_check (void)
                                }
                                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);
                                break;
                        }
 }