LOCAL_SHARED_LIBRARIES := liblog libcutils libdl
LOCAL_PRELINK_MODULE := false
LOCAL_SRC_FILES := $(src_files)
-
+LOCAL_PROPRIETARY_MODULE := true
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := liblog libcutils libdl
LOCAL_SRC_FILES := sens.c
LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_EXECUTABLES)
include $(BUILD_EXECUTABLE)
endif
LOCAL_SHARED_LIBRARIES := liblog libcutils
LOCAL_PRELINK_MODULE := false
LOCAL_SRC_FILES := $(activity_src_files)
-
+LOCAL_PROPRIETARY_MODULE := true
include $(BUILD_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := liblog libcutils libdl
LOCAL_SRC_FILES := activity.c
LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_EXECUTABLES)
include $(BUILD_EXECUTABLE)
endif
*/
float mounting_matrix[9];
+ /** Count of available frequencies */
+ int avail_freqs_count;
+
+ /** Array of available frequencies */
+ float* avail_freqs;
+
/*
* Event counter - will be used to check if we have a significant sample for noisy sensors. We want to make sure we do not send any wrong
* events before filtering kicks in. We can also use it for statistics.
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
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");
static float select_closest_available_rate(int s, float requested_rate)
{
- char avail_sysfs_path[PATH_MAX];
- char freqs_buf[100];
- char* cursor;
float sr;
+ int j;
float selected_rate = 0;
- float max_rate_from_prop;
+ float max_rate_from_prop = sensor_get_max_freq(s);
int dev_num = sensor[s].dev_num;
- sprintf(avail_sysfs_path, DEVICE_AVAIL_FREQ_PATH, dev_num);
- if (sysfs_read_str(avail_sysfs_path, freqs_buf, sizeof(freqs_buf)) <= 0) {
+ if (!sensor[s].avail_freqs_count)
return requested_rate;
- }
- max_rate_from_prop = sensor_get_max_freq(s);
- cursor = freqs_buf;
+ for (j = 0; j < sensor[s].avail_freqs_count; j++) {
- /* 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);
+ 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)) {
if (sr > requested_rate) {
return selected_rate;
}
-
- /* Skip digits */
- while (cursor[0] && !isspace(cursor[0]))
- cursor++;
-
- /* Skip spaces */
- while (cursor[0] && isspace(cursor[0]))
- cursor++;
}
/* Check for wrong values */
* frequency and current sampling rate are different */
if (sysfs_read_float(hrtimer_sampling_path, &sr) != -1 && sr != cur_sampling_rate)
cur_sampling_rate = -1;
- }
-
- /* Check if we have contraints on allowed sampling rates */
-
- if (!(sensor_get_quirks(s) & QUIRK_HRTIMER)) {
+ } 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;
if (trig_sensors_per_dev[dev_num])
enable_buffer(dev_num, 0);
- if (sensor_get_quirks(s) & QUIRK_HRTIMER) {
+ 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);
/* 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");
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;
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;
}
#include "enumeration.h"
#include "description.h"
#include "utils.h"
+#include "transform.h"
#define IIO_SENSOR_HAL_VERSION 1
return IIO_SENSOR_HAL_VERSION;
}
+void sensor_update_max_range(int s)
+{
+ if (sensor[s].max_range)
+ return;
+
+ if (sensor[s].num_channels && sensor[s].channel[0].type_info.realbits) {
+ switch (sensor[s].type) {
+ case SENSOR_TYPE_MAGNETIC_FIELD:
+ sensor[s].max_range = (1ULL << sensor[s].channel[0].type_info.realbits) *
+ CONVERT_MICROTESLA_TO_GAUSS(sensor[s].resolution) +
+ (sensor[s].offset || sensor[s].channel[0].offset);
+ sensor[s].max_range = CONVERT_GAUSS_TO_MICROTESLA(sensor[s].max_range);
+ break;
+ case SENSOR_TYPE_PROXIMITY:
+ break;
+ default:
+ sensor[s].max_range = (1ULL << sensor[s].channel[0].type_info.realbits) *
+ sensor[s].resolution + (sensor[s].offset || sensor[s].channel[0].offset);
+ break;
+ }
+ }
+
+ if (!sensor[s].max_range) {
+ /* Try returning a sensible value given the sensor type */
+ /* We should cap returned samples accordingly... */
+ switch (sensor[s].type) {
+ case SENSOR_TYPE_ACCELEROMETER: /* m/s^2 */
+ sensor[s].max_range = 50;
+ break;
+ case SENSOR_TYPE_MAGNETIC_FIELD: /* micro-tesla */
+ sensor[s].max_range = 500;
+ break;
+ case SENSOR_TYPE_ORIENTATION: /* degrees */
+ sensor[s].max_range = 360;
+ break;
+ case SENSOR_TYPE_GYROSCOPE: /* radians/s */
+ sensor[s].max_range = 10;
+ break;
+ case SENSOR_TYPE_LIGHT: /* SI lux units */
+ sensor[s].max_range = 50000;
+ break;
+ case SENSOR_TYPE_AMBIENT_TEMPERATURE: /* °C */
+ case SENSOR_TYPE_TEMPERATURE: /* °C */
+ case SENSOR_TYPE_PROXIMITY: /* centimeters */
+ case SENSOR_TYPE_PRESSURE: /* hecto-pascal */
+ case SENSOR_TYPE_RELATIVE_HUMIDITY: /* percent */
+ sensor[s].max_range = 100;
+ break;
+ }
+ }
+
+ if (sensor[s].max_range)
+ sensor_desc[s].maxRange = sensor[s].max_range;
+}
float sensor_get_max_range (int s)
{
!sensor_get_fl_prop(s, "max_range", &sensor[s].max_range))
return sensor[s].max_range;
- /* Try returning a sensible value given the sensor type */
-
- /* We should cap returned samples accordingly... */
-
- switch (sensor_desc[s].type) {
- case SENSOR_TYPE_ACCELEROMETER: /* m/s^2 */
- return 50;
-
- case SENSOR_TYPE_MAGNETIC_FIELD: /* micro-tesla */
- return 500;
-
- case SENSOR_TYPE_ORIENTATION: /* degrees */
- return 360;
-
- case SENSOR_TYPE_GYROSCOPE: /* radians/s */
- return 10;
-
- case SENSOR_TYPE_LIGHT: /* SI lux units */
- return 50000;
-
- case SENSOR_TYPE_AMBIENT_TEMPERATURE: /* °C */
- case SENSOR_TYPE_TEMPERATURE: /* °C */
- case SENSOR_TYPE_PROXIMITY: /* centimeters */
- case SENSOR_TYPE_PRESSURE: /* hecto-pascal */
- case SENSOR_TYPE_RELATIVE_HUMIDITY: /* percent */
- return 100;
-
- default:
- return 0;
- }
+ return 0;
}
-static float sensor_get_min_freq (int s)
+float sensor_get_min_freq (int s)
{
/*
* Check if a low cap has been specified for this sensor sampling rate.
}
if (sensor[s].resolution != 0.0 ||
- !sensor_get_fl_prop(s, "resolution", &sensor[s].resolution))
- return sensor[s].resolution;
+ !sensor_get_fl_prop(s, "resolution", &sensor[s].resolution)) {
+ return sensor[s].resolution;
+ }
- return 0;
+ sensor[s].resolution = sensor[s].scale;
+ if (!sensor[s].resolution && sensor[s].num_channels)
+ sensor[s].resolution = sensor[s].channel[0].scale;
+
+ if (sensor[s].type == SENSOR_TYPE_MAGNETIC_FIELD)
+ sensor[s].resolution = CONVERT_GAUSS_TO_MICROTESLA(sensor[s].resolution);
+
+ return sensor[s].resolution ? : 1;
}
return 1; /* OK to use modified ordering map */
}
+int sensor_get_available_frequencies (int s)
+{
+ int dev_num = sensor[s].dev_num, err, i;
+ char avail_sysfs_path[PATH_MAX], freqs_buf[100];
+ char *p, *end;
+ float f;
+
+ sensor[s].avail_freqs_count = 0;
+ sensor[s].avail_freqs = 0;
+
+ sprintf(avail_sysfs_path, DEVICE_AVAIL_FREQ_PATH, dev_num);
+
+ err = sysfs_read_str(avail_sysfs_path, freqs_buf, sizeof(freqs_buf));
+ if (err < 0)
+ return 0;
+
+ for (p = freqs_buf, f = strtof(p, &end); p != end; p = end, f = strtof(p, &end))
+ sensor[s].avail_freqs_count++;
+
+ if (sensor[s].avail_freqs_count) {
+ sensor[s].avail_freqs = (float*) calloc(sensor[s].avail_freqs_count, sizeof(float));
+
+ for (p = freqs_buf, f = strtof(p, &end), i = 0; p != end; p = end, f = strtof(p, &end), i++)
+ sensor[s].avail_freqs[i] = f;
+ }
+
+ return 0;
+}
+
int sensor_get_mounting_matrix (int s, float mm[9])
{
int dev_num = sensor[s].dev_num, err, i;
*/
max_delay_t sensor_get_max_delay (int s)
{
- char avail_sysfs_path[PATH_MAX];
- int dev_num = sensor[s].dev_num;
- char freqs_buf[100];
- char* cursor;
+ int dev_num = sensor[s].dev_num, i;
float min_supported_rate;
float rate_cap;
- float sr;
/*
* continuous, on-change: maximum sampling period allowed in microseconds.
switch (sensor[s].mode) {
case MODE_TRIGGER:
/* For interrupt-based devices, obey the list of supported sampling rates */
- sprintf(avail_sysfs_path, DEVICE_AVAIL_FREQ_PATH, dev_num);
- if (!(sensor_get_quirks(s) & QUIRK_HRTIMER) &&
- sysfs_read_str(avail_sysfs_path, freqs_buf, sizeof(freqs_buf)) > 0) {
-
+ if (sensor[s].avail_freqs_count) {
min_supported_rate = 1000;
- cursor = freqs_buf;
-
- while (*cursor && cursor[0]) {
-
- /* Decode a single value */
- sr = strtod(cursor, NULL);
-
- if (sr < min_supported_rate)
- min_supported_rate = sr;
-
- /* Skip digits */
- while (cursor[0] && !isspace(cursor[0]))
- cursor++;
-
- /* Skip spaces */
- while (cursor[0] && isspace(cursor[0]))
- cursor++;
+ for (i = 0; i < sensor[s].avail_freqs_count; i++) {
+ if (sensor[s].avail_freqs[i] < min_supported_rate)
+ min_supported_rate = sensor[s].avail_freqs[i];
}
-
break;
}
-
/* Fall through ... */
default:
return (max_delay_t) (1000000.0 / min_supported_rate);
}
+float sensor_get_max_static_freq(int s)
+{
+ float max_from_prop = sensor_get_max_freq(s);
+
+ /* If we have max specified via a property use it */
+ if (max_from_prop != ANDROID_MAX_FREQ) {
+ return max_from_prop;
+ } else {
+ /* The should rate */
+ return get_cdd_freq(s, 0);
+ }
+}
int32_t sensor_get_min_delay (int s)
{
- char avail_sysfs_path[PATH_MAX];
- int dev_num = sensor[s].dev_num;
- char freqs_buf[100];
- char* cursor;
+ int dev_num = sensor[s].dev_num, i;
float max_supported_rate = 0;
float max_from_prop = sensor_get_max_freq(s);
- float sr;
- int hrtimer_quirk_enabled = sensor_get_quirks(s) & QUIRK_HRTIMER;
/* continuous, on change: minimum sampling period allowed in microseconds.
* special : 0, unless otherwise noted
}
}
- sprintf(avail_sysfs_path, DEVICE_AVAIL_FREQ_PATH, dev_num);
-
- if (hrtimer_quirk_enabled || sysfs_read_str(avail_sysfs_path, freqs_buf, sizeof(freqs_buf)) < 0) {
- if (hrtimer_quirk_enabled || (sensor[s].mode == MODE_POLL)) {
+ if (!sensor[s].avail_freqs_count) {
+ if (sensor[s].mode == MODE_POLL) {
/* If we have max specified via a property use it */
if (max_from_prop != ANDROID_MAX_FREQ)
max_supported_rate = max_from_prop;
max_supported_rate = get_cdd_freq(s, 0);
}
} else {
- cursor = freqs_buf;
- while (*cursor && cursor[0]) {
-
- /* Decode a single value */
- sr = strtod(cursor, NULL);
-
- if (sr > max_supported_rate && sr <= max_from_prop)
- max_supported_rate = sr;
-
- /* Skip digits */
- while (cursor[0] && !isspace(cursor[0]))
- cursor++;
-
- /* Skip spaces */
- while (cursor[0] && isspace(cursor[0]))
- cursor++;
+ for (i = 0; i < sensor[s].avail_freqs_count; i++) {
+ if (sensor[s].avail_freqs[i] > max_supported_rate &&
+ sensor[s].avail_freqs[i] <= max_from_prop) {
+ max_supported_rate = sensor[s].avail_freqs[i];
+ }
}
}
char* sensor_get_vendor (int s);
int sensor_get_version (int s);
float sensor_get_max_range (int s);
+void sensor_update_max_range (int s);
float sensor_get_resolution (int s);
float sensor_get_power (int s);
flag_t sensor_get_flags (int s);
int sensor_get_fl_prop (int s, const char* sel, float* val);
int sensor_get_order (int s,unsigned char map[MAX_CHANNELS]);
int sensor_get_mounting_matrix(int s,float mounting_matrix[9]);
+int sensor_get_available_frequencies(int s);
int sensor_get_cal_steps (int s);
char* sensor_get_string_type (int s);
int sensor_get_st_prop (int s, const char* sel, char val[MAX_NAME_SIZE]);
if (init_count == 0 || handle < 0 || handle >= sensor_count)
return -EINVAL;
- entry_ts = get_timestamp_boot();
+ entry_ts = get_timestamp_thread();
/*
* The Intel sensor hub seems to have trouble enabling sensors before
ret = sensor_activate(handle, enabled, 0);
- elapsed_ms = (int) ((get_timestamp_boot() - entry_ts) / 1000000);
+ elapsed_ms = (int) ((get_timestamp_thread() - entry_ts) / 1000000);
if (elapsed_ms) {
if (enabled)
sensor[s].channel[c].raw_path_present = (access(sysfs_path, R_OK) != -1);
}
+ sensor_get_available_frequencies(s);
+
if (sensor_get_mounting_matrix(s, sensor[s].mounting_matrix))
sensor[s].quirks |= QUIRK_MOUNTING_MATRIX;
else
}
}
+extern float sensor_get_max_static_freq(int s);
+extern float sensor_get_min_freq (int s);
+
static int create_hrtimer_trigger(int s, int trigger)
{
struct stat dir_status;
char buf[MAX_NAME_SIZE];
char hrtimer_path[PATH_MAX];
char hrtimer_name[MAX_NAME_SIZE];
+ float min_supported_rate = 1, min_rate_cap, max_supported_rate;
snprintf(buf, MAX_NAME_SIZE, "hrtimer-%s-hr-dev%d", sensor[s].internal_name, sensor[s].dev_num);
snprintf(hrtimer_name, MAX_NAME_SIZE, "%s-hr-dev%d", sensor[s].internal_name, sensor[s].dev_num);
strncpy (sensor[s].hrtimer_trigger_name, hrtimer_name, MAX_NAME_SIZE);
sensor[s].trigger_nr = trigger;
+
+ max_supported_rate = sensor_get_max_static_freq(s);
+
+ /* set 0 for wrong values */
+ if (max_supported_rate < 0.1) {
+ max_supported_rate = 0;
+ }
+
+ sensor[s].max_supported_rate = max_supported_rate;
+ sensor_desc[s].minDelay = max_supported_rate ? (int32_t) (1000000.0 / max_supported_rate) : 0;
+
+ /* Check if a minimum rate was specified for this sensor */
+ min_rate_cap = sensor_get_min_freq(s);
+
+ if (min_supported_rate < min_rate_cap) {
+ min_supported_rate = min_rate_cap;
+ }
+
+ sensor[s].min_supported_rate = min_supported_rate;
+ sensor_desc[s].maxDelay = (max_delay_t) (1000000.0 / min_supported_rate);
+
return 0;
}
#define CONVERT_M_Y (-CONVERT_M)
#define CONVERT_M_Z (CONVERT_M)
-#define CONVERT_GAUSS_TO_MICROTESLA(x) ((x) * 100)
-
/* Conversion of orientation data to degree units */
#define CONVERT_O (1.0 / 64)
#define CONVERT_O_A (CONVERT_O)
#include "common.h"
+#define CONVERT_GAUSS_TO_MICROTESLA(x) ((x) * 100)
+#define CONVERT_MICROTESLA_TO_GAUSS(x) ((x) / 100)
+
void select_transform (int s);
float acquire_immediate_float_value (int s, int c);
uint64_t acquire_immediate_uint64_value (int s, int c);
}
-int64_t get_timestamp_realtime (void)
+int64_t get_timestamp (clockid_t clock_id)
{
struct timespec ts = {0};
- clock_gettime(CLOCK_REALTIME, &ts);
- return 1000000000LL * ts.tv_sec + ts.tv_nsec;
+ if (!clock_gettime(clock_id, &ts))
+ return 1000000000LL * ts.tv_sec + ts.tv_nsec;
+ else /* in this case errno is set appropriately */
+ return -1;
}
+int64_t get_timestamp_realtime (void)
+{
+ return get_timestamp(CLOCK_REALTIME);
+}
int64_t get_timestamp_boot (void)
{
- struct timespec ts = {0};
- clock_gettime(CLOCK_BOOTTIME, &ts);
-
- return 1000000000LL * ts.tv_sec + ts.tv_nsec;
+ return get_timestamp(CLOCK_BOOTTIME);
}
+int64_t get_timestamp_thread (void)
+{
+ return get_timestamp(CLOCK_THREAD_CPUTIME_ID);
+}
int64_t get_timestamp_monotonic (void)
{
- struct timespec ts = {0};
- clock_gettime(CLOCK_MONOTONIC, &ts);
-
- return 1000000000LL * ts.tv_sec + ts.tv_nsec;
+ return get_timestamp(CLOCK_MONOTONIC);
}
-
void set_timestamp (struct timespec *out, int64_t target_ns)
{
out->tv_sec = target_ns / 1000000000LL;
void set_timestamp (struct timespec *out, int64_t target_ns);
int64_t get_timestamp_boot (void);
+int64_t get_timestamp_thread (void);
int64_t get_timestamp_realtime (void);
int64_t get_timestamp_monotonic (void);