OSDN Git Service

Reverse the default orientation of accelerometer
[android-x86/hardware-intel-libsensors.git] / control.c
index 1ffb5e3..b366917 100644 (file)
--- a/control.c
+++ b/control.c
@@ -1,6 +1,18 @@
 /*
- * Copyright (C) 2014-2015 Intel Corporation.
- */
+// Copyright (c) 2015 Intel Corporation
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+*/
 
 #include <stdlib.h>
 #include <ctype.h>
@@ -13,7 +25,7 @@
 #include <sys/socket.h>
 #include <utils/Log.h>
 #include <hardware/sensors.h>
-#include <linux/iio/events.h>
+#include <linux/ioctl.h>
 #include "control.h"
 #include "enumeration.h"
 #include "utils.h"
 #include "calibration.h"
 #include "description.h"
 #include "filtering.h"
+#ifndef __NO_EVENTS__
+#include <linux/iio/events.h>
+#include <linux/iio/types.h>
+#endif
+#include <errno.h>
 
 /* Currently active sensors count, per device */
 static int poll_sensors_per_dev[MAX_DEVICES];          /* poll-mode sensors                            */
@@ -34,11 +51,14 @@ static int poll_fd;                                 /* epoll instance covering all enabled sensors  */
 
 static int active_poll_sensors;                                /* Number of enabled poll-mode sensors          */
 
+static int flush_event_fd[2];                          /* Pipe used for flush signaling */
+
 /* We use pthread condition variables to get worker threads out of sleep */
 static pthread_condattr_t thread_cond_attr     [MAX_SENSORS];
 static pthread_cond_t     thread_release_cond  [MAX_SENSORS];
 static pthread_mutex_t    thread_release_mutex [MAX_SENSORS];
 
+#define FLUSH_REPORT_TAG                       900
 /*
  * We associate tags to each of our poll set entries. These tags have the following values:
  * - a iio device number if the fd is a iio character device fd
@@ -300,6 +320,8 @@ void build_sensor_report_maps (int dev_num)
                        known_channels++;
                }
 
+               sensor_update_max_range(s);
+
                /* Stop sampling - if we are recovering from hal restart */
                 enable_buffer(dev_num, 0);
                 setup_trigger(s, "\n");
@@ -373,12 +395,16 @@ int adjust_counters (int s, int enabled, int from_virtual)
                ALOGI("Enabling sensor %d (iio device %d: %s)\n", s, dev_num, sensor[s].friendly_name);
 
                switch (sensor[s].type) {
+                       case SENSOR_TYPE_ACCELEROMETER:
+                               accel_cal_init(s);
+                               break;
+
                        case SENSOR_TYPE_MAGNETIC_FIELD:
-                               compass_read_data(&sensor[s]);
+                               compass_read_data(s);
                                break;
 
                        case SENSOR_TYPE_GYROSCOPE:
-                               gyro_cal_init(&sensor[s]);
+                               gyro_cal_init(s);
                                break;
                }
        } else {
@@ -387,11 +413,20 @@ int adjust_counters (int s, int enabled, int from_virtual)
                /* Sensor disabled, lower report available flag */
                sensor[s].report_pending = 0;
 
-               if (sensor[s].type == SENSOR_TYPE_MAGNETIC_FIELD)
-                       compass_store_data(&sensor[s]);
+               /* Save calibration data to persistent storage */
+               switch (sensor[s].type) {
+                       case SENSOR_TYPE_ACCELEROMETER:
+                               accel_cal_store(s);
+                               break;
 
-               if (sensor[s].type == SENSOR_TYPE_GYROSCOPE)
-                       gyro_store_data(&sensor[s]);
+                       case SENSOR_TYPE_MAGNETIC_FIELD:
+                               compass_store_data(s);
+                               break;
+
+                       case SENSOR_TYPE_GYROSCOPE:
+                               gyro_store_data(s);
+                               break;
+               }
        }
 
        /* We changed the state of a sensor: adjust device ref counts */
@@ -426,6 +461,7 @@ int adjust_counters (int s, int enabled, int from_virtual)
 static int get_field_count (int s, size_t *field_size)
 {
        *field_size = sizeof(float);
+
        switch (sensor[s].type) {
                case SENSOR_TYPE_ACCELEROMETER:         /* m/s^2        */
                case SENSOR_TYPE_MAGNETIC_FIELD:        /* micro-tesla  */
@@ -434,6 +470,8 @@ static int get_field_count (int s, size_t *field_size)
                case SENSOR_TYPE_GYROSCOPE:             /* radians/s    */
                        return 3;
 
+               case SENSOR_TYPE_INTERNAL_INTENSITY:
+               case SENSOR_TYPE_INTERNAL_ILLUMINANCE:
                case SENSOR_TYPE_LIGHT:                 /* SI lux units */
                case SENSOR_TYPE_AMBIENT_TEMPERATURE:   /* °C          */
                case SENSOR_TYPE_TEMPERATURE:           /* °C          */
@@ -520,7 +558,7 @@ static void* acquisition_routine (void* param)
        /* Initialize data fields that will be shared by all sensor reports */
        data.version    = sizeof(sensors_event_t);
        data.sensor     = s;
-       data.type       = sensor[s].type;
+       data.type       = sensor_desc[s].type;
 
        num_fields = get_field_count(s, &field_size);
 
@@ -558,7 +596,7 @@ static void* acquisition_routine (void* param)
                        ret = write(sensor[s].thread_data_fd[1], &data, sizeof(sensors_event_t));
 
                        if (ret != sizeof(sensors_event_t))
-                               ALOGE("S%d write failure: wrote %d, got %d\n", s, sizeof(sensors_event_t), ret);
+                               ALOGE("S%d write failure: wrote %zd, got %d\n", s, sizeof(sensors_event_t), ret);
                }
 
                /* Check and honor termination requests */
@@ -711,25 +749,66 @@ static float get_group_max_sampling_rate (int s)
        return arbitrated_rate;
 }
 
+extern float sensor_get_max_freq (int s);
+
+static float select_closest_available_rate(int s, float requested_rate)
+{
+       float sr;
+       int j;
+       float selected_rate = 0;
+       float max_rate_from_prop = sensor_get_max_freq(s);
+
+       if (!sensor[s].avail_freqs_count)
+               return requested_rate;
+
+       for (j = 0; j < sensor[s].avail_freqs_count; j++) {
+
+               sr = sensor[s].avail_freqs[j];
+
+               /* If this matches the selected rate, we're happy.  Have some tolerance for rounding errors and avoid needless jumps to higher rates */
+               if ((fabs(requested_rate - sr) <= 0.01) && (sr <= max_rate_from_prop)) {
+                       return sr;
+               }
+
+               /* Select rate if it's less than max freq */
+               if ((sr > selected_rate) && (sr <= max_rate_from_prop)) {
+                       selected_rate = sr;
+               }
+
+               /*
+                * 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 > requested_rate) {
+                       return selected_rate;
+               }
+       }
+
+       /* Check for wrong values */
+       if (selected_rate < 0.1) {
+               return requested_rate;
+       } else {
+               return selected_rate;
+       }
+}
 
 static int sensor_set_rate (int s, float requested_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];
        int dev_num             =       sensor[s].dev_num;
        int i                   =       sensor[s].catalog_index;
        const char *prefix      =       sensor_catalog[i].tag;
        int per_sensor_sampling_rate;
        int per_device_sampling_rate;
-       char freqs_buf[100];
-       char* cursor;
        int n;
        float sr;
        float group_max_sampling_rate;
        float cur_sampling_rate; /* Currently used sampling rate              */
        float arb_sampling_rate; /* Granted sampling rate after arbitration   */
+       char hrtimer_sampling_path[PATH_MAX];
+       char trigger_path[PATH_MAX];
 
        ALOGV("Sampling rate %g requested on sensor %d (%s)\n", requested_rate, s, sensor[s].friendly_name);
 
@@ -789,58 +868,28 @@ static int sensor_set_rate (int s, float requested_rate)
                return -ENOSYS;
        }
 
-       /* 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.  Have some tolerance for rounding errors and avoid needless jumps to higher rates */
-                       if (fabs(arb_sampling_rate - sr) <= 0.001) {
-                               arb_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 > arb_sampling_rate) {
-                               arb_sampling_rate = sr;
-                               break;
-                       }
-
-                       /* Skip digits */
-                       while (cursor[0] && !isspace(cursor[0]))
-                               cursor++;
-
-                       /* Skip spaces */
-                       while (cursor[0] && isspace(cursor[0]))
-                                       cursor++;
-               }
+       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);
        }
 
-       if (sensor[s].max_supported_rate &&
-               arb_sampling_rate > sensor[s].max_supported_rate) {
-               arb_sampling_rate = sensor[s].max_supported_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].sampling_rate > arb_sampling_rate) {
+                       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].sampling_rate, arb_sampling_rate);
-                               arb_sampling_rate = sensor[n].sampling_rate;
+                                                                                                         sensor[n].semi_arbitrated_rate, arb_sampling_rate);
+                               arb_sampling_rate = sensor[n].semi_arbitrated_rate;
                        }
 
        sensor[s].sampling_rate = arb_sampling_rate;
@@ -857,10 +906,17 @@ static int sensor_set_rate (int s, float requested_rate)
 
        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);
 
-       sysfs_write_float(sysfs_path, arb_sampling_rate);
+       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);
@@ -971,7 +1027,11 @@ int sensor_activate (int s, int enabled, int from_virtual)
                if (trig_sensors_per_dev[dev_num]) {
 
                        /* Start sampling */
-                       setup_trigger(s, sensor[s].init_trigger_name);
+                       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) {
@@ -1049,6 +1109,9 @@ int sensor_activate (int s, int enabled, int from_virtual)
                        }
 
                        /* Note: poll-mode fds are not readable */
+#ifdef __NO_EVENTS__
+               }
+#else
                } else if (sensor[s].mode == MODE_EVENT) {
                        event_fd = events_fd[dev_num];
 
@@ -1080,6 +1143,7 @@ int sensor_activate (int s, int enabled, int from_virtual)
                                device_fd[dev_num] = -1;
                        }
                }
+#endif
        }
 
        /* Ensure that on-change sensors send at least one event after enable */
@@ -1154,8 +1218,12 @@ static void stamp_reports (int dev_num, int64_t ts)
        int s;
 
        for (s=0; s<MAX_SENSORS; s++)
-               if (sensor[s].dev_num == dev_num && is_enabled(s) && sensor[s].mode != MODE_POLL)
-                       set_report_ts(s, ts);
+               if (sensor[s].dev_num == dev_num && is_enabled(s) && sensor[s].mode != MODE_POLL) {
+                       if (sensor[s].quirks & QUIRK_SPOTTY)
+                               set_report_ts(s, ts);
+                       else
+                               sensor[s].report_ts = ts;
+               }
 }
 
 
@@ -1213,7 +1281,6 @@ static int integrate_device_report_from_dev(int dev_num, int fd)
                        sensor[s].report_pending = DATA_TRIGGER;
                        sensor[s].report_initialized = 1;
 
-                       ts_offset += sr_offset;
                }
 
        /* Tentatively switch to an any-motion trigger if conditions are met */
@@ -1245,7 +1312,7 @@ static int integrate_device_report_from_dev(int dev_num, int fd)
                return 0;
        }
 
-       ALOGV("Driver timestamp on iio device %d: ts=%lld\n", dev_num, ts);
+       ALOGV("Driver timestamp on iio device %d: ts=%jd\n", dev_num, ts);
 
        boot_to_rt_delta = get_timestamp_boot() - get_timestamp_realtime();
 
@@ -1254,11 +1321,13 @@ static int integrate_device_report_from_dev(int dev_num, int fd)
        return 0;
 }
 
+#ifndef __NO_EVENTS__
 static int integrate_device_report_from_event(int dev_num, int fd)
 {
        int len, s;
        int64_t ts;
        struct iio_event_data event;
+       int64_t boot_to_rt_delta = get_timestamp_boot() - get_timestamp_realtime();
 
        /* There's an incoming report on the specified iio device char dev fd */
        if (fd == -1) {
@@ -1275,14 +1344,15 @@ static int integrate_device_report_from_event(int dev_num, int fd)
                return -1;
        }
 
-       ts = event.timestamp;
+       ts = event.timestamp + boot_to_rt_delta;
 
-       ALOGV("Read event %ld from fd %d of iio device %d\n", event.id, fd, dev_num);
+       ALOGV("Read event %lld from fd %d of iio device %d - ts %jd\n", event.id, fd, dev_num, ts);
 
        /* Map device report to sensor reports */
        for (s = 0; s < MAX_SENSORS; s++)
                if (sensor[s].dev_num == dev_num &&
                    is_enabled(s)) {
+                       sensor[s].event_id = event.id;
                        sensor[s].report_ts = ts;
                        sensor[s].report_pending = 1;
                        sensor[s].report_initialized = 1;
@@ -1290,6 +1360,7 @@ static int integrate_device_report_from_event(int dev_num, int fd)
                }
        return 0;
 }
+#endif
 
 static int integrate_device_report(int dev_num)
 {
@@ -1300,11 +1371,13 @@ static int integrate_device_report(int dev_num)
                return -1;
        }
 
+#ifndef __NO_EVENTS__
        if (events_fd[dev_num] != -1) {
                ret = integrate_device_report_from_event(dev_num, events_fd[dev_num]);
                if (ret < 0)
                        return ret;
        }
+#endif
 
        if (device_fd[dev_num] != -1)
                ret = integrate_device_report_from_dev(dev_num, device_fd[dev_num]);
@@ -1319,7 +1392,7 @@ static int propagate_vsensor_report (int s, sensors_event_t *data)
        memcpy(data, &sensor[s].sample, sizeof(sensors_event_t));
 
        data->sensor    = s;
-       data->type      = sensor[s].type;
+       data->type      = sensor_desc[s].type; /* sensor_desc[s].type can differ from sensor[s].type ; internal types are remapped */
        return 1;
 }
 
@@ -1355,17 +1428,31 @@ static int propagate_sensor_report (int s, sensors_event_t *data)
 
        data->version   = sizeof(sensors_event_t);
        data->sensor    = s;
-       data->type      = sensor[s].type;
+       data->type      = sensor_desc[s].type;  /* sensor_desc[s].type can differ from sensor[s].type ; internal types are remapped */
        data->timestamp = sensor[s].report_ts;
 
+#ifndef __NO_EVENTS__
        if (sensor[s].mode == MODE_EVENT) {
                ALOGV("Reporting event\n");
                /* Android requires events to return 1.0 */
-               data->data[0] = 1.0;
+               int dir = IIO_EVENT_CODE_EXTRACT_DIR(sensor[s].event_id);
+               switch (sensor[s].type) {
+                       case SENSOR_TYPE_PROXIMITY:
+                               if (dir == IIO_EV_DIR_FALLING)
+                                       data->data[0] = 0.0;
+                               else
+                                       data->data[0] = 1.0;
+                               break;
+                       default:
+                               data->data[0] = 1.0;
+                               break;
+
+               }
                data->data[1] = 0.0;
                data->data[2] = 0.0;
                return 1;
        }
+#endif
 
        /* Convert the data into the expected Android-level format */
 
@@ -1572,6 +1659,12 @@ await_event:
                                        /* Get report from acquisition thread */
                                        integrate_thread_report(ev[i].data.u32);
                                        break;
+                               case FLUSH_REPORT_TAG:
+                                       {
+                                               char flush_event_content;
+                                               read(flush_event_fd[0], &flush_event_content, sizeof(flush_event_content));
+                                               break;
+                                       }
 
                                default:
                                        ALOGW("Unexpected event source!\n");
@@ -1587,7 +1680,7 @@ int sensor_set_delay (int s, int64_t ns)
        float requested_sampling_rate;
 
        if (ns <= 0) {
-               ALOGE("Invalid delay requested on sensor %d: %lld\n", s, ns);
+               ALOGE("Invalid delay requested on sensor %d: %jd\n", s, ns);
                return -EINVAL;
        }
 
@@ -1611,18 +1704,21 @@ int sensor_set_delay (int s, int64_t ns)
 
 int sensor_flush (int s)
 {
+       char flush_event_content = 0;
        /* If one shot or not enabled return -EINVAL */
        if (sensor_desc[s].flags & SENSOR_FLAG_ONE_SHOT_MODE || !is_enabled(s))
                return -EINVAL;
 
        sensor[s].meta_data_pending++;
+       write(flush_event_fd[1], &flush_event_content, sizeof(flush_event_content));
        return 0;
 }
 
 
 int allocate_control_data (void)
 {
-       int i;
+       int i, ret;
+       struct epoll_event ev = {0};
 
        for (i=0; i<MAX_DEVICES; i++) {
                device_fd[i] = -1;
@@ -1636,6 +1732,21 @@ int allocate_control_data (void)
                return -1;
        }
 
+       ret = pipe(flush_event_fd);
+       if (ret) {
+               ALOGE("Cannot create flush_event_fd");
+               return -1;
+       }
+
+       ev.events = EPOLLIN;
+       ev.data.u32 = FLUSH_REPORT_TAG;
+       ret = epoll_ctl(poll_fd, EPOLL_CTL_ADD, flush_event_fd[0] , &ev);
+       if (ret == -1) {
+               ALOGE("Failed adding %d to poll set (%s)\n",
+                       flush_event_fd[0], strerror(errno));
+               return -1;
+       }
+
        return poll_fd;
 }