+ /* 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);
+
+ /* If the operation was neutral in terms of state, we're done */
+ if (ret <= 0)
+ return ret;
+
+ sensor[s].event_count = 0;
+ sensor[s].meta_data_pending = 0;
+
+ if (enabled)
+ setup_noise_filtering(s); /* Initialize filtering data if required */
+
+ if (sensor[s].mode == MODE_TRIGGER) {
+
+ /* Stop sampling */
+ enable_buffer(dev_num, 0);
+ 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 */
+ if (sensor[s].hrtimer_trigger_name[0] != '\0')
+ setup_trigger(s, sensor[s].hrtimer_trigger_name);
+ else
+ 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);
+ }
+ }
+
+ /*
+ * Make sure we have a fd on the character device ; conversely, close the fd if no one is using associated sensors anymore. The assumption
+ * here is that the underlying driver will power on the relevant hardware block while someone holds a fd on the device.
+ */
+ dev_fd = device_fd[dev_num];
+
+ if (!enabled) {
+ 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]) {
+ /* Stop watching this fd. This should be a no-op in case this fd was not in the poll set. */
+ epoll_ctl(poll_fd, EPOLL_CTL_DEL, dev_fd, NULL);
+
+ close(dev_fd);
+ 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);
+
+ /* Reevaluate sampling rates of linked sensors */
+ reapply_sampling_rates(s);
+ return 0;
+ }
+
+ if (dev_fd == -1) {
+ /* First enabled sensor on this iio device */
+ sprintf(device_name, DEV_FILE_PATH, dev_num);
+ dev_fd = open(device_name, O_RDONLY | O_NONBLOCK);
+
+ device_fd[dev_num] = dev_fd;
+
+ if (dev_fd == -1) {
+ ALOGE("Could not open fd on %s (%s)\n", device_name, strerror(errno));
+ adjust_counters(s, 0, from_virtual);
+ return -1;
+ }
+
+ ALOGV("Opened %s: fd=%d\n", device_name, dev_fd);
+
+ if (sensor[s].mode == MODE_TRIGGER) {
+
+ /* Add this iio device fd to the set of watched fds */
+ ev.events = EPOLLIN;
+ ev.data.u32 = dev_num;
+
+ ret = epoll_ctl(poll_fd, EPOLL_CTL_ADD, dev_fd, &ev);
+
+ if (ret == -1) {
+ ALOGE("Failed adding %d to poll set (%s)\n", dev_fd, strerror(errno));
+ return -1;
+ }
+
+ /* Note: poll-mode fds are not readable */
+#ifdef __NO_EVENTS__
+ }
+#else
+ } 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;
+ }
+ }
+#endif
+ }
+
+ /* Ensure that on-change sensors send at least one event after enable */
+ 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].mode == MODE_POLL)
+ start_acquisition_thread(s);
+
+ /* Reevaluate sampling rates of linked sensors */
+ reapply_sampling_rates(s);
+
+ return 0;
+}
+
+
+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[s].dev_num == dev_num && is_enabled(s) && sensor[s].num_channels &&
+ (!sensor[s].motion_trigger_name[0] || !sensor[s].report_initialized || is_fast_accelerometer(s) ||
+ (sensor[s].quirks & QUIRK_FORCE_CONTINUOUS)))
+ return; /* Nope */
+
+ /* Record which particular sensors need to switch */
+
+ for (s=0; s<MAX_SENSORS; s++)
+ if (sensor[s].dev_num == dev_num && is_enabled(s) && sensor[s].num_channels && sensor[s].selected_trigger != sensor[s].motion_trigger_name)
+ candidate[candidate_count++] = s;
+
+ if (!candidate_count)
+ return;