+ sensor[s].sampling_rate = arb_sampling_rate;
+
+ /* If the sensor is virtual, we're done */
+ if (sensor[s].is_virtual)
+ return 0;
+
+ /* If we're dealing with a poll-mode sensor */
+ 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;
+ }
+
+ 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;
+ }
+
+ if (sensor[s].hrtimer_trigger_name[0] != '\0') {
+ snprintf(trigger_path, PATH_MAX, "%s%s%d/", IIO_DEVICES, "trigger", sensor[s].trigger_nr);
+ snprintf(hrtimer_sampling_path, PATH_MAX, "%s%s", trigger_path, "sampling_frequency");
+ /* Enforce frequency update when software trigger
+ * frequency and current sampling rate are different */
+ if (sysfs_read_float(hrtimer_sampling_path, &sr) != -1 && sr != cur_sampling_rate)
+ cur_sampling_rate = -1;
+ } else {
+ arb_sampling_rate = select_closest_available_rate(s, arb_sampling_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].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].semi_arbitrated_rate, arb_sampling_rate);
+ arb_sampling_rate = sensor[n].semi_arbitrated_rate;
+ }
+
+ sensor[s].sampling_rate = arb_sampling_rate;
+
+ /* Update actual sampling rate field for this sensor and others which may be sharing the same sampling rate */
+ if (per_device_sampling_rate)
+ for (n=0; n<sensor_count; n++)
+ if (sensor[n].dev_num == dev_num && n != s && sensor[n].num_channels)
+ sensor[n].sampling_rate = arb_sampling_rate;
+
+ /* If the desired rate is already active we're all set */
+ 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);
+
+ if (sensor[s].hrtimer_trigger_name[0] != '\0')
+ sysfs_write_float(hrtimer_sampling_path, ceilf(arb_sampling_rate));
+
+ if (trig_sensors_per_dev[dev_num])
+ enable_buffer(dev_num, 0);
+
+ if (sensor[s].hrtimer_trigger_name[0] != '\0') {
+ sysfs_write_float(sysfs_path, select_closest_available_rate(s, arb_sampling_rate));
+ } else {
+ sysfs_write_float(sysfs_path, arb_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;
+}
+
+
+static void reapply_sampling_rates (int s)
+{
+ /*
+ * The specified sensor was either enabled or disabled. Other sensors in the same group may have constraints related to this sensor
+ * sampling rate on their own sampling rate, so reevaluate them by retrying to use their requested sampling rate, rather than the one
+ * that ended up being used after arbitration.
+ */
+
+ int i, j, base;
+
+ if (sensor[s].is_virtual) {
+ /* Take care of downwards dependencies */
+ for (i=0; i<sensor[s].base_count; i++) {
+ base = sensor[s].base[i];
+ sensor_set_rate(base, sensor[base].requested_rate);
+ }
+ return;
+ }
+
+ /* Upwards too */
+ for (i=0; i<sensor_count; i++)
+ for (j=0; j<sensor[i].base_count; j++)
+ if (sensor[i].base[j] == s) /* If sensor i depends on sensor s */
+ sensor_set_rate(i, sensor[i].requested_rate);
+}
+
+
+static int sensor_activate_virtual (int s, int enabled, int from_virtual)
+{
+ int i, base;
+
+ sensor[s].event_count = 0;
+ sensor[s].meta_data_pending = 0;
+
+ if (!check_state_change(s, enabled, from_virtual))
+ return 0; /* The state of the sensor remains the same ; we're done */
+
+ if (enabled)
+ ALOGI("Enabling sensor %d (%s)\n", s, sensor[s].friendly_name);
+ else
+ ALOGI("Disabling sensor %d (%s)\n", s, sensor[s].friendly_name);
+
+ sensor[s].report_pending = 0;
+
+ for (i=0; i<sensor[s].base_count; i++) {
+
+ base = sensor[s].base[i];
+ sensor_activate(base, enabled, 1);
+
+ if (enabled)
+ sensor[base].ref_count++;
+ else
+ sensor[base].ref_count--;
+ }
+
+ /* Reevaluate sampling rates of linked sensors */
+ reapply_sampling_rates(s);
+ return 0;
+}
+
+
+int sensor_activate (int s, int enabled, int from_virtual)
+{
+ char device_name[PATH_MAX];
+ struct epoll_event ev = {0};
+ 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);
+
+ /* Prepare the report timestamp field for the first event, see set_report_ts method */
+ sensor[s].report_ts = 0;
+
+ ret = adjust_counters(s, enabled, from_virtual);