/*
- * Copyright (C) 2014 Intel Corporation.
+ * Copyright (C) 2014-2015 Intel Corporation.
*/
#include <stdlib.h>
#include <fcntl.h>
+#include <sys/ioctl.h>
#include <utils/Log.h>
#include <hardware/sensors.h>
+#include <utils/Atomic.h>
+#include <linux/android_alarm.h>
+
+#include "common.h"
#include "utils.h"
* possible sysfs attributes. As an optimization we may want to cache which
* ones are valid and immediately return in error for inexistent entries.
*/
-
-int sysfs_write_int(const char path[PATH_MAX], int value)
+int sysfs_read(const char path[PATH_MAX], void *buf, int buf_len)
{
- int ret;
- int fd;
- int len;
- char buf[20];
+ int fd, len;
- if (!path[0]) {
+ if (!path[0] || !buf || buf_len < 1)
return -1;
- }
- fd = open(path, O_WRONLY);
+ fd = open(path, O_RDONLY);
if (fd == -1) {
ALOGV("Cannot open %s (%s)\n", path, strerror(errno));
return -1;
}
- len = sprintf(buf, "%d", value) + 1;
-
- ret = write(fd, buf, len);
-
- if (ret != len) {
- ALOGW("Cannot write %s (%d bytes) to %s (%s)\n", buf, len, path,
- strerror(errno));
- }
+ len = read(fd, buf, buf_len);
close(fd);
- return ret;
+ if (len == -1)
+ ALOGW("Cannot read from %s (%s)\n", path, strerror(errno));
+ else
+ ALOGV("Read %d bytes from %s\n", len, path);
+
+ return len;
}
-int sysfs_read_int(const char path[PATH_MAX], int *value)
+int sysfs_write(const char path[PATH_MAX], const void *buf, const int buf_len)
{
- int fd;
- int len;
- char buf[20] = {0};
+ int fd, len;
- if (!path[0] || !value) {
+ if (!path[0] || !buf || buf_len < 1)
return -1;
- }
- fd = open(path, O_RDONLY);
+ fd = open(path, O_WRONLY);
if (fd == -1) {
ALOGV("Cannot open %s (%s)\n", path, strerror(errno));
return -1;
}
- len = read(fd, buf, sizeof(buf));
+ len = write(fd, buf, buf_len);
close(fd);
- if (len <= 0) {
- ALOGW("Cannot read integer from %s (%s)\n", path,
- strerror(errno));
- return -1;
- }
+ if (len == -1)
+ ALOGW("Cannot write to %s (%s)\n", path, strerror(errno));
+ else if (len != buf_len)
+ ALOGW("Cannot write %d bytes to %s (%d)\n", buf_len, path, len);
+ else
+ ALOGV("Wrote %d bytes to %s\n", buf_len, path);
- *value = atoi(buf);
+ return len;
+}
- ALOGV("Read %d from %s\n", *value, path);
- return 0;
+static void str2int(const char* buf, void *v)
+{
+ *(int*)v = atoi(buf);
}
-int sysfs_write_str(const char path[PATH_MAX], const char *str)
+static void str2float(const char* buf, void *v)
{
- int ret;
- int fd;
- int len;
+ *(float*)v = strtof(buf, NULL);
+}
- if (!path[0] || !str || !str[0]) {
- return -1;
- }
- fd = open(path, O_WRONLY);
+static void str2uint64(const char* buf, void *v)
+{
+ *(uint64_t*)v = atoll(buf);
+}
- if (fd == -1) {
- ALOGV("Cannot open %s (%s)\n", path, strerror(errno));
+
+int sysfs_read_num(const char path[PATH_MAX], void *v,
+ void (*str2num)(const char* buf, void *v))
+{
+ char buf[20];
+ int len = sysfs_read_str(path, buf, sizeof(buf));
+
+ if (len <= 0) {
+ ALOGW("Cannot read number from %s (%s)\n", path,
+ strerror(errno));
return -1;
}
- len = strlen(str);
+ str2num(buf, v);
+ return 0;
+}
- ret = write(fd, str, len);
- if (ret != len) {
- ALOGW("Cannot write %s (%d bytes) to %s (%s)\n", str, len, path,
- strerror(errno));
- }
- else
- ALOGV("Wrote %s to %s\n", str, path);
+int sysfs_read_int(const char path[PATH_MAX], int *value)
+{
+ return sysfs_read_num(path, value, str2int);
+}
- close(fd);
- return ret;
+int sysfs_read_float(const char path[PATH_MAX], float *value)
+{
+ return sysfs_read_num(path, value, str2float);
}
-int sysfs_read_str(const char path[PATH_MAX], char *buf, int buf_len)
+int sysfs_read_uint64(const char path[PATH_MAX], uint64_t *value)
{
- int fd;
- int len;
+ return sysfs_read_num(path, value, str2uint64);
+}
- if (!path[0] || !buf || buf_len < 1)
- return -1;
- fd = open(path, O_RDONLY);
+int sysfs_write_int(const char path[PATH_MAX], int value)
+{
+ char buf[20];
+ int len = snprintf(buf, sizeof(buf), "%d", value);
- if (fd == -1) {
- ALOGV("Cannot open %s (%s)\n", path, strerror(errno));
+ if (len <= 0) {
+ ALOGE("Unexpected condition in sysfs_write_int\n");
return -1;
}
- len = read(fd, buf, buf_len);
+ return sysfs_write(path, buf, len);
+}
- close(fd);
+int sysfs_write_float(const char path[PATH_MAX], float value)
+{
+ char buf[20];
+ int len = snprintf(buf, sizeof(buf), "%g", value);
- if (len == -1) {
- ALOGW("Cannot read string from %s (%s)\n", path,
- strerror(errno));
+ if (len <= 0) {
+ ALOGE("Unexpected condition in sysfs_write_float\n");
return -1;
}
- buf[len == 0 ? 0 : len-1] = '\0';
+ return sysfs_write(path, buf, len);
+}
- ALOGV("Read %s from %s\n", buf, path);
- return len;
+int sysfs_write_str(const char path[PATH_MAX], const char *str)
+{
+ if (!str || !str[0])
+ return -1;
+
+ return sysfs_write(path, str, strlen(str));
}
-int sysfs_read_float(const char path[PATH_MAX], float *value)
+int sysfs_read_str(const char path[PATH_MAX], char *buf, int buf_len)
{
- int fd;
int len;
- char buf[20] = {0};
- if (!path[0] || !value) {
+ if (!buf || buf_len < 1)
return -1;
- }
- fd = open(path, O_RDONLY);
+ len = sysfs_read(path, buf, buf_len);
- if (fd == -1) {
- ALOGV("Cannot open %s (%s)\n", path, strerror(errno));
- return -1;
- }
-
- len = read(fd, buf, sizeof(buf));
-
- close(fd);
-
- if (len <= 0) {
- ALOGW("Cannot read float from %s (%s)\n", path,
+ if (len == -1) {
+ ALOGW("Cannot read string from %s (%s)\n", path,
strerror(errno));
return -1;
}
- *value = (float) strtod(buf, NULL);
+ buf[len == 0 ? 0 : len - 1] = '\0';
- ALOGV("Read %f from %s\n", *value, path);
+ ALOGV("Read %s from %s\n", buf, path);
- return 0;
+ return len;
}
-int decode_type_spec( const char type_buf[MAX_TYPE_SPEC_LEN],
- struct datum_info_t *type_info)
+int64_t get_timestamp (clockid_t clock_id)
{
- /* Return size in bytes for this type specification, or -1 in error */
- char sign;
- char endianness;
- unsigned int realbits, storagebits, shift;
- int tokens;
-
- /* Valid specs: "le:u10/16>>0", "le:s16/32>>0" or "le:s32/32>>0" */
-
- tokens = sscanf(type_buf, "%ce:%c%u/%u>>%u",
- &endianness, &sign, &realbits, &storagebits, &shift);
-
- if (tokens != 5 ||
- (endianness != 'b' && endianness != 'l') ||
- (sign != 'u' && sign != 's') ||
- realbits > storagebits ||
- (storagebits != 16 && storagebits != 32 && storagebits != 64)) {
- ALOGE("Invalid iio channel type spec: %s\n", type_buf);
- return -1;
- }
-
- type_info->endianness = endianness;
- type_info->sign = sign;
- type_info->realbits = (short) realbits;
- type_info->storagebits = (short) storagebits;
- type_info->shift = (short) shift;
-
- return storagebits / 8;
-}
+ struct timespec ts = {0};
+ 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 sample_as_int64(unsigned char* sample, struct datum_info_t* type)
+int64_t get_timestamp_realtime (void)
{
- uint16_t u16;
- uint32_t u32;
- uint64_t u64;
- int i;
-
- switch (type->storagebits) {
- case 64:
- u64 = 0;
-
- if (type->endianness == 'b')
- for (i=0; i<8; i++)
- u64 = (u64 << 8) | sample[i];
- else
- for (i=7; i>=0; i--)
- u64 = (u64 << 8) | sample[i];
-
- if (type->sign == 'u')
- return (int64_t) (u64 >> type->shift);
-
- return ((int64_t) u64) >> type->shift;
-
- case 32:
- if (type->endianness == 'b')
- u32 = (sample[0] << 24) | (sample[1] << 16) |
- (sample[2] << 8) | sample[3];
- else
- u32 = (sample[3] << 24) | (sample[2] << 16) |
- (sample[1] << 8) | sample[0];
-
- if (type->sign == 'u')
- return u32 >> type->shift;
-
- return ((int32_t) u32) >> type->shift;
-
- case 16:
- if (type->endianness == 'b')
- u16 = (sample[0] << 8) | sample[1];
- else
- u16 = (sample[1] << 8) | sample[0];
-
- if (type->sign == 'u')
- return u16 >> type->shift;
-
- return ((int16_t) u16) >> type->shift;
- }
-
- ALOGE("Unhandled sample storage size\n");
- return 0;
+ return get_timestamp(CLOCK_REALTIME);
}
-
-float transform_sample (int sensor_type, int channel, float val)
+int64_t get_timestamp_boot (void)
{
- /* Last opportunity to alter sample data before it goes to Android */
- switch (sensor_type) {
- case SENSOR_TYPE_ACCELEROMETER:
- /*
- * Invert x axis orientation from SI units - see
- * /hardware/libhardware/include/hardware/sensors.h
- * for a discussion of what Android expects
- */
- if (channel == 0)
- return -val;
- break;
-
- case SENSOR_TYPE_GYROSCOPE:
- /* Limit drift */
- if (val > -0.05 && val < 0.05)
- return 0;
- break;
- }
-
- return val;
+ return get_timestamp(CLOCK_BOOTTIME);
}
-
-int64_t get_timestamp(void)
+int64_t get_timestamp_thread (void)
{
- struct timespec ts = {0};
-
- clock_gettime(CLOCK_MONOTONIC, &ts);
+ return get_timestamp(CLOCK_THREAD_CPUTIME_ID);
+}
- return 1000000000LL * ts.tv_sec + ts.tv_nsec;
+int64_t get_timestamp_monotonic (void)
+{
+ return get_timestamp(CLOCK_MONOTONIC);
}
+void set_timestamp (struct timespec *out, int64_t target_ns)
+{
+ out->tv_sec = target_ns / 1000000000LL;
+ out->tv_nsec = target_ns % 1000000000LL;
+}