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"
22 #include <cutils/log.h>
23 #include <hardware/sensors.h>
24 #include <cutils/properties.h>
26 static const char *IIO_DIR = "/sys/bus/iio/devices/";
29 ID_ACCELERATION = SENSORS_HANDLE_BASE,
45 #define NUMOFACCDATA (8.0f)
47 // conversion of acceleration data to SI units (m/s^2)
48 #define RANGE_A (2*GRAVITY_EARTH)
49 #define RESOLUTION_A (RANGE_A/(256*NUMOFACCDATA))
51 // conversion of magnetic data to uT units
52 #define RANGE_M (2048.0f)
53 #define RESOLUTION_M (0.01)
55 /* conversion of orientation data to degree units */
56 #define CONVERT_O (1.0f/64.0f)
57 #define CONVERT_O_A (CONVERT_O)
58 #define CONVERT_O_P (CONVERT_O)
59 #define CONVERT_O_R (-CONVERT_O)
61 // conversion of gyro data to SI units (radian/sec)
62 #define RANGE_G (2000.0f*(float)M_PI/180.0f)
63 #define RESOLUTION_G (RANGE_G/(2000*NUMOFACCDATA))
65 // conversion of pressure and temperature data
66 #define CONVERT_PRESSURE (1.0f/100.0f)
67 #define CONVERT_TEMPERATURE (1.0f/100.0f)
69 #define SENSOR_STATE_MASK (0x7FFF)
71 // proximity threshold
72 #define PROXIMITY_THRESHOLD_GP2A (5.0f)
74 // used in timespec_to_ns calculations
75 const long NSEC_PER_SEC = 1000000000L;
77 #define BIT(x) (1 << (x))
79 struct SensorEvent : public sensors_event_t {
80 SensorEvent(int32_t id, int32_t t);
83 SensorEvent::SensorEvent(int32_t id, int32_t t)
85 version = sizeof(sensors_event_t);
90 clock_gettime(CLOCK_MONOTONIC, &ts);
91 timestamp = int64_t(ts.tv_sec) * NSEC_PER_SEC + ts.tv_nsec;
94 class SensorBase : public sensor_t {
97 virtual ~SensorBase();
99 operator bool() const { return enabled; }
100 int setDelay(int64_t ns);
101 bool scan(const char *d);
102 virtual int activate(bool);
103 virtual int readEvents(sensors_event_t *data, int);
106 int read_sysfs_str(const char *file, char *buf);
107 int read_sysfs_int(const char *file);
108 float read_sysfs_float(const char *file);
113 struct timespec delay;
116 SensorBase::SensorBase()
118 memset(this, 0, sizeof(SensorBase));
120 vendor = "Android-x86 Open Source Project";
123 delay.tv_nsec = 200000000L;
126 SensorBase::~SensorBase()
131 int SensorBase::setDelay(int64_t ns)
133 delay.tv_sec = ns / NSEC_PER_SEC;
134 delay.tv_nsec = ns % NSEC_PER_SEC;
138 bool SensorBase::scan(const char *p)
142 while (const char **ns = *nodes) {
143 for (i = 0; ns[i]; ++i) {
144 snprintf(node, PATH_MAX, "%s/%s", p, ns[i]);
145 if (access(node, F_OK))
155 for (i = 0; (*nodes)[i]; ++i)
156 strncat(strncat(node, (*nodes)[i], 1024), " ", 1024);
157 ALOGD("found node %s: %s", path, node);
162 int SensorBase::activate(bool e)
168 int SensorBase::readEvents(sensors_event_t *data, int)
170 nanosleep(&delay, 0);
171 SensorEvent *e = new (data) SensorEvent(handle, type);
175 int SensorBase::read_sysfs_str(const char *file, char *buf)
178 char filename[PATH_MAX];
179 snprintf(filename, PATH_MAX, "%s/%s", path, file);
180 int fd = open(filename, O_RDONLY);
182 ssize_t sz = read(fd, buf, 4096);
184 ALOGE("failed to read from %s: %s", filename, strerror(errno));
192 int SensorBase::read_sysfs_int(const char *file)
195 return read_sysfs_str(file, buf) ? 0 : atoi(buf);
198 float SensorBase::read_sysfs_float(const char *file)
201 return read_sysfs_str(file, buf) ? 0 : atof(buf);
204 template <int H> class Sensor : SensorBase {
207 virtual int readEvents(sensors_event_t *data, int);
209 static SensorBase *probe(const char *d);
213 SensorBase *Sensor<H>::probe(const char *p)
215 Sensor<H> *s = new Sensor<H>;
224 template<> Sensor<ID_ACCELERATION>::Sensor()
226 static const char *ns0[] = { "in_accel_scale", 0 };
227 static const char **ns[] = { ns0, 0 };
230 name = "IIO Accelerometer Sensor";
231 type = SENSOR_TYPE_ACCELEROMETER;
233 resolution = RESOLUTION_A;
238 template<> int Sensor<ID_ACCELERATION>::readEvents(sensors_event_t *data, int cnt)
240 static float scale = read_sysfs_float((*nodes)[0]);
241 int ret = SensorBase::readEvents(data, cnt);
242 char cm[PROPERTY_VALUE_MAX];
246 property_get("hal.sensors.iio.accel.matrix", cm, "-1,0,0,0,1,0,0,0,-1" );
247 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]);
249 for (int i = 0; i < ret; ++i) {
250 v[0] = read_sysfs_int("in_accel_x_raw");
251 v[1] = read_sysfs_int("in_accel_y_raw");
252 v[2] = read_sysfs_int("in_accel_z_raw");
253 // create matrix * vector product
254 data[i].acceleration.x = scale * (m[0] * v[0] + m[1] * v[1] + m[2] * v[2]);
255 data[i].acceleration.y = scale * (m[3] * v[0] + m[4] * v[1] + m[5] * v[2]);
256 data[i].acceleration.z = scale * (m[6] * v[0] + m[7] * v[1] + m[8] * v[2]);
257 data[i].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
262 template<> Sensor<ID_MAGNETIC_FIELD>::Sensor()
264 static const char *ns0[] = { "in_magn_scale", 0, 0 };
265 static const char *ns1[] = { "in_magn_x_scale", "in_magn_y_scale", "in_magn_z_scale", 0 };
266 static const char **ns[] = { ns0, ns1, 0 };
269 name = "IIO Magnetic Sensor";
270 type = SENSOR_TYPE_MAGNETIC_FIELD;
272 resolution = RESOLUTION_M;
277 template<> int Sensor<ID_MAGNETIC_FIELD>::readEvents(sensors_event_t *data, int cnt)
279 static float scale_x = read_sysfs_float((*nodes)[0]);
280 static float scale_y = (*nodes)[1] ? read_sysfs_float((*nodes)[1]) : scale_x;
281 static float scale_z = (*nodes)[2] ? read_sysfs_float((*nodes)[2]) : scale_x;
282 int ret = SensorBase::readEvents(data, cnt);
283 char cm[PROPERTY_VALUE_MAX];
287 property_get("hal.sensors.iio.magn.matrix", cm, "1,0,0,0,1,0,0,0,1" );
288 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]);
290 for (int i = 0; i < ret; ++i) {
291 v[0] = read_sysfs_int("in_magn_x_raw");
292 v[1] = read_sysfs_int("in_magn_y_raw");
293 v[2] = read_sysfs_int("in_magn_z_raw");
294 // create matrix * vector product
295 data[i].magnetic.x = scale_x * (m[0] * v[0] + m[1] * v[1] + m[2] * v[2]);
296 data[i].magnetic.y = scale_y * (m[3] * v[0] + m[4] * v[1] + m[5] * v[2]);
297 data[i].magnetic.z = scale_z * (m[6] * v[0] + m[7] * v[1] + m[8] * v[2]);
298 data[i].magnetic.status = SENSOR_STATUS_ACCURACY_HIGH;
303 template<> Sensor<ID_LIGHT>::Sensor()
305 static const char *ns0[] = { "in_illuminance_scale", 0 };
306 static const char *ns1[] = { "in_illuminance_calibscale", 0 };
307 static const char **ns[] = { ns0, ns1, 0 };
310 name = "IIO Ambient Light Sensor";
311 type = SENSOR_TYPE_LIGHT;
318 template<> int Sensor<ID_LIGHT>::readEvents(sensors_event_t *data, int cnt)
320 static float scale = read_sysfs_float((*nodes)[0]);
321 int ret = SensorBase::readEvents(data, cnt);
322 for (int i = 0; i < ret; ++i) {
323 data[i].light = scale * read_sysfs_int("in_illuminance_input");
328 template<> Sensor<ID_GYROSCOPE>::Sensor()
330 static const char *ns0[] = { "in_anglvel_scale", 0 };
331 static const char **ns[] = { ns0, 0 };
334 name = "IIO Gyro 3D Sensor";
335 type = SENSOR_TYPE_GYROSCOPE;
337 resolution = RESOLUTION_G;
342 template<> int Sensor<ID_GYROSCOPE>::readEvents(sensors_event_t *data, int cnt)
344 static float scale = read_sysfs_float((*nodes)[0]);
345 int ret = SensorBase::readEvents(data, cnt);
346 char cm[PROPERTY_VALUE_MAX];
350 property_get("hal.sensors.iio.anglvel.matrix", cm, "1,0,0,0,1,0,0,0,1" );
351 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]);
353 for (int i = 0; i < ret; ++i) {
354 v[0] = read_sysfs_int("in_anglvel_x_raw");
355 v[1] = read_sysfs_int("in_anglvel_y_raw");
356 v[2] = read_sysfs_int("in_anglvel_z_raw");
357 // create matrix * vector product
358 data[i].gyro.x = scale * (m[0] * v[0] + m[1] * v[1] + m[2] * v[2]);
359 data[i].gyro.y = scale * (m[3] * v[0] + m[4] * v[1] + m[5] * v[2]);
360 data[i].gyro.z = scale * (m[6] * v[0] + m[7] * v[1] + m[8] * v[2]);
361 data[i].gyro.status = SENSOR_STATUS_ACCURACY_HIGH;
366 static SensorBase *(*probeSensors[])(const char *) = {
367 Sensor<ID_ACCELERATION>::probe,
368 Sensor<ID_MAGNETIC_FIELD>::probe,
369 Sensor<ID_LIGHT>::probe,
370 Sensor<ID_GYROSCOPE>::probe,
373 class SensorPollContext : sensors_poll_device_t {
375 SensorPollContext(const struct hw_module_t *module, struct hw_device_t **device);
376 ~SensorPollContext();
378 bool isValid() const;
379 int getSensor(struct sensor_t const **list) const;
382 static int poll_close(struct hw_device_t *dev);
383 static int poll_activate(struct sensors_poll_device_t *dev, int handle, int enabled);
384 static int poll_setDelay(struct sensors_poll_device_t *dev, int handle, int64_t ns);
385 static int poll_poll(struct sensors_poll_device_t *dev, sensors_event_t *data, int count);
387 int doPoll(sensors_event_t *data, int count);
389 sensor_t sensors_list[MAX_SENSORS];
390 SensorBase *sensors[MAX_SENSORS];
394 static SensorPollContext *sctx = 0;
396 SensorPollContext::SensorPollContext(const struct hw_module_t *module, struct hw_device_t **device)
398 memset(this, 0, sizeof(*this));
400 common.tag = HARDWARE_DEVICE_TAG;
401 common.module = const_cast<struct hw_module_t *>(module);
402 common.close = poll_close;
403 activate = poll_activate;
404 setDelay = poll_setDelay;
409 strcpy(path, IIO_DIR);
410 int len = strlen(path);
411 if (DIR *dir = opendir(path)) {
412 while (struct dirent *de = readdir(dir)) {
413 if (!strncmp(de->d_name, "iio:device", 10)) {
414 strcpy(path + len, de->d_name);
415 for (size_t i = 0; i < (sizeof(probeSensors) / sizeof(*probeSensors)); ++i) {
416 if (SensorBase *s = probeSensors[i](path)) {
418 sensors_list[count++] = *s;
419 ALOGD("found %s", __FUNCTION__, s->name);
425 ALOGD("%s: module=%p sensors: %d", __FUNCTION__, module, count);
428 SensorPollContext::~SensorPollContext()
430 for (int i = 0; i < MAX_SENSORS; ++i) {
435 bool SensorPollContext::isValid() const
440 int SensorPollContext::getSensor(struct sensor_t const **list) const
442 *list = sensors_list;
446 int SensorPollContext::poll_close(struct hw_device_t *dev)
448 ALOGD("%s: dev=%p", __FUNCTION__, dev);
449 SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
454 ALOGW("close a ctx(%p) rather than sctx(%p)", ctx, sctx);
459 int SensorPollContext::poll_activate(struct sensors_poll_device_t *dev, int handle, int enabled)
461 ALOGD("%s: dev=%p handle=%d enabled=%d", __FUNCTION__, dev, handle, enabled);
462 SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
463 if (handle >= 0 && handle < MAX_SENSORS && ctx->sensors[handle])
464 return ctx->sensors[handle]->activate(enabled);
469 int SensorPollContext::poll_setDelay(struct sensors_poll_device_t *dev, int handle, int64_t ns)
471 ALOGD("%s: handle=%d delay-ns=%lld", __FUNCTION__, handle, ns);
472 SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
473 if (handle >= 0 && handle < MAX_SENSORS && ctx->sensors[handle])
474 return ctx->sensors[handle]->setDelay(ns);
479 int SensorPollContext::poll_poll(struct sensors_poll_device_t *dev, sensors_event_t *data, int count)
481 ALOGV("%s: dev=%p data=%p count=%d", __FUNCTION__, dev, data, count);
482 SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
483 return ctx->doPoll(data, count);
486 int SensorPollContext::doPoll(sensors_event_t *data, int cnt)
492 for (int i = 0; cnt > 0 && i < MAX_SENSORS; ++i) {
493 if (sensors[i] && *sensors[i]) {
494 int nb = sensors[i]->readEvents(data, cnt);
504 static int open_iio_sensors(const struct hw_module_t *module, const char *id, struct hw_device_t **device)
506 ALOGD("%s: id=%s", __FUNCTION__, id);
508 sctx = new SensorPollContext(module, device);
510 return (sctx && sctx->isValid()) ? 0 : -EINVAL;
513 static int sensors_get_sensors_list(struct sensors_module_t *, struct sensor_t const **list)
515 ALOGD("enter %s", __FUNCTION__);
516 return sctx ? sctx->getSensor(list) : 0;
519 static struct hw_module_methods_t sensors_methods = {
520 open: open_iio_sensors
523 struct sensors_module_t HAL_MODULE_INFO_SYM = {
525 tag: HARDWARE_MODULE_TAG,
528 id: SENSORS_HARDWARE_MODULE_ID,
530 author: "Chih-Wei Huang",
531 methods: &sensors_methods,
535 get_sensors_list: sensors_get_sensors_list,
536 set_operation_mode: 0