+static int is_continuous (int s)
+{
+ /* Is sensor s of the continous trigger type kind? */
+
+ int catalog_index = sensor_info[s].catalog_index;
+ int sensor_type = sensor_catalog[catalog_index].type;
+
+ switch (sensor_type) {
+ case SENSOR_TYPE_ACCELEROMETER:
+ case SENSOR_TYPE_MAGNETIC_FIELD:
+ case SENSOR_TYPE_ORIENTATION:
+ case SENSOR_TYPE_GYROSCOPE:
+ case SENSOR_TYPE_PRESSURE:
+ case SENSOR_TYPE_GRAVITY:
+ case SENSOR_TYPE_LINEAR_ACCELERATION:
+ case SENSOR_TYPE_ROTATION_VECTOR:
+ case SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED:
+ case SENSOR_TYPE_GYROSCOPE_UNCALIBRATED:
+ case SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR:
+ return 1;
+
+ default:
+ return 0;
+ }
+}
+
+
+static void propose_new_trigger (int s, char trigger_name[MAX_NAME_SIZE],
+ int sensor_name_len)
+{
+ /*
+ * A new trigger has been enumerated for this sensor. Check if it makes
+ * sense to use it over the currently selected one, and select it if it
+ * is so. The format is something like sensor_name-dev0.
+ */
+
+ const char *suffix = trigger_name + sensor_name_len + 1;
+
+ /* dev is the default, and lowest priority; no need to update */
+ if (!memcmp(suffix, "dev", 3))
+ return;
+
+ /*
+ * 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)) {
+ /* Update the any-motion trigger name to use for this sensor */
+ strcpy(sensor_info[s].motion_trigger_name, trigger_name);
+ return;
+ }
+
+ /* Update the initial trigger name to use for this sensor */
+ strcpy(sensor_info[s].init_trigger_name, trigger_name);
+}
+
+
+static void update_sensor_matching_trigger_name (char name[MAX_NAME_SIZE])
+{
+ /*
+ * Check if we have a sensor matching the specified trigger name,
+ * which should then begin with the sensor name, and end with a number
+ * equal to the iio device number the sensor is associated to. If so,
+ * update the string we're going to write to trigger/current_trigger
+ * when enabling this sensor.
+ */
+
+ int s;
+ int dev_num;
+ int len;
+ char* cursor;
+ int sensor_name_len;
+
+ /*
+ * First determine the iio device number this trigger refers to. We
+ * expect the last few characters (typically one) of the trigger name
+ * to be this number, so perform a few checks.
+ */
+ len = strnlen(name, MAX_NAME_SIZE);
+
+ if (len < 2)
+ return;
+
+ cursor = name + len - 1;
+
+ if (!isdigit(*cursor))
+ return;
+
+ while (len && isdigit(*cursor)) {
+ len--;
+ cursor--;
+ }
+
+ dev_num = atoi(cursor+1);
+
+ /* See if that matches a sensor */
+ for (s=0; s<sensor_count; s++)
+ if (sensor_info[s].dev_num == dev_num) {
+
+ sensor_name_len = strlen(sensor_info[s].internal_name);
+
+ if (!strncmp(name,
+ sensor_info[s].internal_name,
+ sensor_name_len))
+ /* Switch to new trigger if appropriate */
+ propose_new_trigger(s, name, sensor_name_len);
+ }
+}
+
+
+static void setup_trigger_names (void)
+{
+ char filename[PATH_MAX];
+ char buf[MAX_NAME_SIZE];
+ int len;
+ int s;
+ int trigger;
+ int ret;
+
+ /* By default, use the name-dev convention that most drivers use */
+ for (s=0; s<sensor_count; s++)
+ 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 */
+
+ for (trigger=0; trigger<MAX_TRIGGERS; trigger++) {
+
+ snprintf(filename, sizeof(filename), TRIGGER_FILE_PATH,trigger);
+
+ ret = sysfs_read_str(filename, buf, sizeof(buf));
+
+ 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) default trigger: %s\n", s,
+ sensor_info[s].friendly_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);
+ }
+}
+
+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 cal_idx = 0;
+ int uncal_idx = 0;
+ int catalog_size = CATALOG_SIZE; /* Avoid GCC sign comparison warning */
+
+ /* 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_catalog[sensor_info[i].catalog_index].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)
+ 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);
+ break;
+ }
+}