5 * Copyright (C) 2015 The Android-x86 Open Source Project
7 * by Chih-Wei Huang <cwhuang@linux.org.tw>
9 * Licensed under GPLv2 or later
13 #define LOG_TAG "iio-sensors"
23 #include <cutils/log.h>
24 #include <hardware/sensors.h>
25 #include <cutils/properties.h>
27 static const char *IIO_DIR = "/sys/bus/iio/devices/";
30 ID_ACCELERATION = SENSORS_HANDLE_BASE,
46 #define NUMOFACCDATA (8.0f)
48 // conversion of acceleration data to SI units (m/s^2)
49 #define RANGE_A (2*GRAVITY_EARTH)
50 #define RESOLUTION_A (RANGE_A/(256*NUMOFACCDATA))
52 // conversion of magnetic data to uT units
53 #define RANGE_M (2048.0f)
54 #define RESOLUTION_M (0.01)
56 /* conversion of orientation data to degree units */
57 #define CONVERT_O (1.0f/64.0f)
58 #define CONVERT_O_A (CONVERT_O)
59 #define CONVERT_O_P (CONVERT_O)
60 #define CONVERT_O_R (-CONVERT_O)
62 // conversion of gyro data to SI units (radian/sec)
63 #define RANGE_G (2000.0f*(float)M_PI/180.0f)
64 #define RESOLUTION_G (RANGE_G/(2000*NUMOFACCDATA))
66 // conversion of pressure and temperature data
67 #define CONVERT_PRESSURE (1.0f/100.0f)
68 #define CONVERT_TEMPERATURE (1.0f/100.0f)
70 #define SENSOR_STATE_MASK (0x7FFF)
72 // proximity threshold
73 #define PROXIMITY_THRESHOLD_GP2A (5.0f)
75 // used in timespec_to_ns calculations
76 const long NSEC_PER_SEC = 1000000000L;
78 #define BIT(x) (1 << (x))
80 struct SensorEvent : public sensors_event_t {
81 SensorEvent(int32_t id, int32_t t);
84 SensorEvent::SensorEvent(int32_t id, int32_t t)
86 version = sizeof(sensors_event_t);
91 clock_gettime(CLOCK_MONOTONIC, &ts);
92 timestamp = int64_t(ts.tv_sec) * NSEC_PER_SEC + ts.tv_nsec;
95 class sensor_base : public sensor_t {
97 sensor_base() { memset(this, 0, sizeof(*this)); }
102 struct timespec delay;
105 class SensorBase : public sensor_base {
108 virtual ~SensorBase();
110 operator bool() const { return enabled; }
111 int setDelay(int64_t ns);
112 bool scan(const char *d);
113 virtual int activate(bool);
114 virtual int readEvents(sensors_event_t *data, int);
117 int read_sysfs_str(const char *file, char *buf);
118 int read_sysfs_int(const char *file);
119 float read_sysfs_float(const char *file);
122 SensorBase::SensorBase()
124 vendor = "Android-x86 Open Source Project";
127 delay.tv_nsec = 200000000L;
130 SensorBase::~SensorBase()
135 int SensorBase::setDelay(int64_t ns)
137 delay.tv_sec = ns / NSEC_PER_SEC;
138 delay.tv_nsec = ns % NSEC_PER_SEC;
142 bool SensorBase::scan(const char *p)
146 while (const char **ns = *nodes) {
147 for (i = 0; ns[i]; ++i) {
148 snprintf(node, PATH_MAX, "%s/%s", p, ns[i]);
149 if (access(node, F_OK))
159 for (i = 0; (*nodes)[i]; ++i)
160 strncat(strncat(node, (*nodes)[i], 1024), " ", 1024);
161 ALOGD("found node %s: %s", path, node);
166 int SensorBase::activate(bool e)
172 int SensorBase::readEvents(sensors_event_t *data, int)
174 nanosleep(&delay, 0);
175 SensorEvent *e = new (data) SensorEvent(handle, type);
179 int SensorBase::read_sysfs_str(const char *file, char *buf)
182 char filename[PATH_MAX];
183 snprintf(filename, PATH_MAX, "%s/%s", path, file);
184 int fd = open(filename, O_RDONLY);
186 ssize_t sz = read(fd, buf, 4096);
188 ALOGE("failed to read from %s: %s", filename, strerror(errno));
196 int SensorBase::read_sysfs_int(const char *file)
199 return read_sysfs_str(file, buf) ? 0 : atoi(buf);
202 float SensorBase::read_sysfs_float(const char *file)
205 return read_sysfs_str(file, buf) ? 0 : atof(buf);
208 template <int H> class Sensor : SensorBase {
211 virtual int readEvents(sensors_event_t *data, int);
213 static SensorBase *probe(const char *d);
217 SensorBase *Sensor<H>::probe(const char *p)
219 Sensor<H> *s = new Sensor<H>;
228 template<> Sensor<ID_ACCELERATION>::Sensor()
230 static const char *ns0[] = { "in_accel_scale", 0 };
231 static const char **ns[] = { ns0, 0 };
234 name = "IIO Accelerometer Sensor";
235 type = SENSOR_TYPE_ACCELEROMETER;
237 resolution = RESOLUTION_A;
242 template<> int Sensor<ID_ACCELERATION>::readEvents(sensors_event_t *data, int cnt)
244 static float scale = read_sysfs_float((*nodes)[0]);
245 int ret = SensorBase::readEvents(data, cnt);
246 char cm[PROPERTY_VALUE_MAX];
250 property_get("hal.sensors.iio.accel.matrix", cm, "-1,0,0,0,1,0,0,0,-1" );
251 sscanf(cm, "%f,%f,%f,%f,%f,%f,%f,%f,%f", &m[0], &m[1], &m[2], &m[3], &m[4], &m[5], &m[6], &m[7], &m[8]);
253 for (int i = 0; i < ret; ++i) {
254 v[0] = read_sysfs_int("in_accel_x_raw");
255 v[1] = read_sysfs_int("in_accel_y_raw");
256 v[2] = read_sysfs_int("in_accel_z_raw");
257 // create matrix * vector product
258 data[i].acceleration.x = scale * (m[0] * v[0] + m[1] * v[1] + m[2] * v[2]);
259 data[i].acceleration.y = scale * (m[3] * v[0] + m[4] * v[1] + m[5] * v[2]);
260 data[i].acceleration.z = scale * (m[6] * v[0] + m[7] * v[1] + m[8] * v[2]);
261 data[i].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
266 template<> Sensor<ID_MAGNETIC_FIELD>::Sensor()
268 static const char *ns0[] = { "in_magn_scale", 0, 0 };
269 static const char *ns1[] = { "in_magn_x_scale", "in_magn_y_scale", "in_magn_z_scale", 0 };
270 static const char **ns[] = { ns0, ns1, 0 };
273 name = "IIO Magnetic Sensor";
274 type = SENSOR_TYPE_MAGNETIC_FIELD;
276 resolution = RESOLUTION_M;
281 template<> int Sensor<ID_MAGNETIC_FIELD>::readEvents(sensors_event_t *data, int cnt)
283 static float scale_x = read_sysfs_float((*nodes)[0]);
284 static float scale_y = (*nodes)[1] ? read_sysfs_float((*nodes)[1]) : scale_x;
285 static float scale_z = (*nodes)[2] ? read_sysfs_float((*nodes)[2]) : scale_x;
286 int ret = SensorBase::readEvents(data, cnt);
287 char cm[PROPERTY_VALUE_MAX];
291 property_get("hal.sensors.iio.magn.matrix", cm, "1,0,0,0,1,0,0,0,1" );
292 sscanf(cm, "%f,%f,%f,%f,%f,%f,%f,%f,%f", &m[0], &m[1], &m[2], &m[3], &m[4], &m[5], &m[6], &m[7], &m[8]);
294 for (int i = 0; i < ret; ++i) {
295 v[0] = read_sysfs_int("in_magn_x_raw");
296 v[1] = read_sysfs_int("in_magn_y_raw");
297 v[2] = read_sysfs_int("in_magn_z_raw");
298 // create matrix * vector product
299 data[i].magnetic.x = scale_x * (m[0] * v[0] + m[1] * v[1] + m[2] * v[2]);
300 data[i].magnetic.y = scale_y * (m[3] * v[0] + m[4] * v[1] + m[5] * v[2]);
301 data[i].magnetic.z = scale_z * (m[6] * v[0] + m[7] * v[1] + m[8] * v[2]);
302 data[i].magnetic.status = SENSOR_STATUS_ACCURACY_HIGH;
307 template<> Sensor<ID_LIGHT>::Sensor()
309 static const char *ns0[] = { "in_illuminance_scale", 0 };
310 static const char *ns1[] = { "in_illuminance_calibscale", 0 };
311 static const char **ns[] = { ns0, ns1, 0 };
314 name = "IIO Ambient Light Sensor";
315 type = SENSOR_TYPE_LIGHT;
322 template<> int Sensor<ID_LIGHT>::readEvents(sensors_event_t *data, int cnt)
324 static float scale = read_sysfs_float((*nodes)[0]);
325 int ret = SensorBase::readEvents(data, cnt);
326 for (int i = 0; i < ret; ++i) {
327 data[i].light = scale * read_sysfs_int("in_illuminance_input");
332 template<> Sensor<ID_GYROSCOPE>::Sensor()
334 static const char *ns0[] = { "in_anglvel_scale", 0 };
335 static const char **ns[] = { ns0, 0 };
338 name = "IIO Gyro 3D Sensor";
339 type = SENSOR_TYPE_GYROSCOPE;
341 resolution = RESOLUTION_G;
346 template<> int Sensor<ID_GYROSCOPE>::readEvents(sensors_event_t *data, int cnt)
348 static float scale = read_sysfs_float((*nodes)[0]);
349 int ret = SensorBase::readEvents(data, cnt);
350 char cm[PROPERTY_VALUE_MAX];
354 property_get("hal.sensors.iio.anglvel.matrix", cm, "1,0,0,0,1,0,0,0,1" );
355 sscanf(cm, "%f,%f,%f,%f,%f,%f,%f,%f,%f", &m[0], &m[1], &m[2], &m[3], &m[4], &m[5], &m[6], &m[7], &m[8]);
357 for (int i = 0; i < ret; ++i) {
358 v[0] = read_sysfs_int("in_anglvel_x_raw");
359 v[1] = read_sysfs_int("in_anglvel_y_raw");
360 v[2] = read_sysfs_int("in_anglvel_z_raw");
361 // create matrix * vector product
362 data[i].gyro.x = scale * (m[0] * v[0] + m[1] * v[1] + m[2] * v[2]);
363 data[i].gyro.y = scale * (m[3] * v[0] + m[4] * v[1] + m[5] * v[2]);
364 data[i].gyro.z = scale * (m[6] * v[0] + m[7] * v[1] + m[8] * v[2]);
365 data[i].gyro.status = SENSOR_STATUS_ACCURACY_HIGH;
370 static SensorBase *(*probeSensors[])(const char *) = {
371 Sensor<ID_ACCELERATION>::probe,
372 Sensor<ID_MAGNETIC_FIELD>::probe,
373 Sensor<ID_LIGHT>::probe,
374 Sensor<ID_GYROSCOPE>::probe,
377 class SensorPollContext : sensors_poll_device_1 {
379 SensorPollContext(const struct hw_module_t *module, struct hw_device_t **device);
380 ~SensorPollContext();
382 bool isValid() const;
383 int getSensor(struct sensor_t const **list) const;
386 static int poll_close(struct hw_device_t *dev);
387 static int poll_activate(struct sensors_poll_device_t *dev, int handle, int enabled);
388 static int poll_setDelay(struct sensors_poll_device_t *dev, int handle, int64_t ns);
389 static int poll_poll(struct sensors_poll_device_t *dev, sensors_event_t *data, int count);
390 static int poll_batch(struct sensors_poll_device_1* dev, int sensor_handle, int flags, int64_t sampling_period_ns, int64_t max_report_latency_ns);
391 static int poll_flush(struct sensors_poll_device_1* dev, int sensor_handle);
393 int doPoll(sensors_event_t *data, int count);
395 sensor_t sensors_list[MAX_SENSORS];
396 SensorBase *sensors[MAX_SENSORS];
400 static SensorPollContext *sctx = 0;
402 SensorPollContext::SensorPollContext(const struct hw_module_t *module, struct hw_device_t **device)
404 memset(this, 0, sizeof(*this));
406 common.tag = HARDWARE_DEVICE_TAG;
407 common.version = SENSORS_DEVICE_API_VERSION_1_3;
408 common.module = const_cast<struct hw_module_t *>(module);
409 common.close = poll_close;
410 activate = poll_activate;
411 setDelay = poll_setDelay;
418 strcpy(path, IIO_DIR);
419 int len = strlen(path);
420 if (DIR *dir = opendir(path)) {
421 while (struct dirent *de = readdir(dir)) {
422 if (!strncmp(de->d_name, "iio:device", 10)) {
423 strcpy(path + len, de->d_name);
424 for (size_t i = 0; i < (sizeof(probeSensors) / sizeof(*probeSensors)); ++i) {
425 if (SensorBase *s = probeSensors[i](path)) {
427 sensors_list[count++] = *s;
428 ALOGD("found %s", s->name);
435 ALOGD("%s: module=%p sensors: %d", __FUNCTION__, module, count);
438 SensorPollContext::~SensorPollContext()
440 for (int i = 0; i < MAX_SENSORS; ++i) {
445 bool SensorPollContext::isValid() const
450 int SensorPollContext::getSensor(struct sensor_t const **list) const
452 *list = sensors_list;
456 int SensorPollContext::poll_close(struct hw_device_t *dev)
458 ALOGD("%s: dev=%p", __FUNCTION__, dev);
459 SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
464 ALOGW("close a ctx(%p) rather than sctx(%p)", ctx, sctx);
469 int SensorPollContext::poll_activate(struct sensors_poll_device_t *dev, int handle, int enabled)
471 ALOGD("%s: dev=%p handle=%d enabled=%d", __FUNCTION__, dev, handle, enabled);
472 SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
473 if (handle >= 0 && handle < MAX_SENSORS && ctx->sensors[handle])
474 return ctx->sensors[handle]->activate(enabled);
479 int SensorPollContext::poll_setDelay(struct sensors_poll_device_t *dev, int handle, int64_t ns)
481 SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
482 if (handle >= 0 && handle < MAX_SENSORS && ctx->sensors[handle])
483 return ctx->sensors[handle]->setDelay(ns);
488 int SensorPollContext::poll_poll(struct sensors_poll_device_t *dev, sensors_event_t *data, int count)
490 ALOGV("%s: dev=%p data=%p count=%d", __FUNCTION__, dev, data, count);
491 SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
492 return ctx->doPoll(data, count);
495 int SensorPollContext::poll_batch(struct sensors_poll_device_1* dev, int sensor_handle, int flags, int64_t sampling_period_ns, int64_t max_report_latency_ns)
497 ALOGD("%s: dev=%p sensor_handle=%d flags=%d sampling_period_ns=%" PRId64 " max_report_latency_ns=%" PRId64,
498 __FUNCTION__, dev, sensor_handle, flags, sampling_period_ns, max_report_latency_ns);
499 return poll_setDelay(&dev->v0, sensor_handle, sampling_period_ns);
502 int SensorPollContext::poll_flush(struct sensors_poll_device_1* dev, int sensor_handle)
504 ALOGD("%s: dev=%p sensor_handle=%d", __FUNCTION__, dev, sensor_handle);
508 int SensorPollContext::doPoll(sensors_event_t *data, int cnt)
514 for (int i = 0; cnt > 0 && i < MAX_SENSORS; ++i) {
515 if (sensors[i] && *sensors[i]) {
516 int nb = sensors[i]->readEvents(data, cnt);
526 static int open_iio_sensors(const struct hw_module_t *module, const char *id, struct hw_device_t **device)
528 ALOGD("%s: id=%s", __FUNCTION__, id);
530 sctx = new SensorPollContext(module, device);
532 return (sctx && sctx->isValid()) ? 0 : -EINVAL;
535 static int sensors_get_sensors_list(struct sensors_module_t *, struct sensor_t const **list)
537 ALOGD("enter %s", __FUNCTION__);
538 return sctx ? sctx->getSensor(list) : 0;
541 static struct hw_module_methods_t sensors_methods = {
542 .open = open_iio_sensors
545 struct sensors_module_t HAL_MODULE_INFO_SYM = {
547 .tag = HARDWARE_MODULE_TAG,
548 .module_api_version = 1,
549 .hal_api_version = 0,
550 .id = SENSORS_HARDWARE_MODULE_ID,
551 .name = "IIO Sensors",
552 .author = "Chih-Wei Huang",
553 .methods = &sensors_methods,
557 .get_sensors_list = sensors_get_sensors_list,
558 .set_operation_mode = 0