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 // TODO: read orientation from the properties
243 for (int i = 0; i < ret; ++i) {
244 data[i].acceleration.x = -scale * read_sysfs_int("in_accel_x_raw");
245 data[i].acceleration.y = scale * read_sysfs_int("in_accel_y_raw");
246 data[i].acceleration.z = -scale * read_sysfs_int("in_accel_z_raw");
247 data[i].acceleration.status = SENSOR_STATUS_ACCURACY_HIGH;
252 template<> Sensor<ID_MAGNETIC_FIELD>::Sensor()
254 static const char *ns0[] = { "in_magn_scale", 0, 0 };
255 static const char *ns1[] = { "in_magn_x_scale", "in_magn_y_scale", "in_magn_z_scale", 0 };
256 static const char **ns[] = { ns0, ns1, 0 };
259 name = "IIO Magnetic Sensor";
260 type = SENSOR_TYPE_MAGNETIC_FIELD;
262 resolution = RESOLUTION_M;
267 template<> int Sensor<ID_MAGNETIC_FIELD>::readEvents(sensors_event_t *data, int cnt)
269 static float scale_x = read_sysfs_float((*nodes)[0]);
270 static float scale_y = (*nodes)[1] ? read_sysfs_float((*nodes)[1]) : scale_x;
271 static float scale_z = (*nodes)[2] ? read_sysfs_float((*nodes)[2]) : scale_x;
272 int ret = SensorBase::readEvents(data, cnt);
273 for (int i = 0; i < ret; ++i) {
274 data[i].magnetic.x = scale_x * read_sysfs_int("in_magn_x_raw");
275 data[i].magnetic.y = scale_y * read_sysfs_int("in_magn_y_raw");
276 data[i].magnetic.z = scale_z * read_sysfs_int("in_magn_z_raw");
277 data[i].magnetic.status = SENSOR_STATUS_ACCURACY_HIGH;
282 template<> Sensor<ID_LIGHT>::Sensor()
284 static const char *ns0[] = { "in_illuminance_scale", 0 };
285 static const char *ns1[] = { "in_illuminance_calibscale", 0 };
286 static const char **ns[] = { ns0, ns1, 0 };
289 name = "IIO Ambient Light Sensor";
290 type = SENSOR_TYPE_LIGHT;
297 template<> int Sensor<ID_LIGHT>::readEvents(sensors_event_t *data, int cnt)
299 static float scale = read_sysfs_float((*nodes)[0]);
300 int ret = SensorBase::readEvents(data, cnt);
301 for (int i = 0; i < ret; ++i) {
302 data[i].light = scale * read_sysfs_int("in_illuminance_input");
307 template<> Sensor<ID_GYROSCOPE>::Sensor()
309 static const char *ns0[] = { "in_anglvel_scale", 0 };
310 static const char **ns[] = { ns0, 0 };
313 name = "IIO Gyro 3D Sensor";
314 type = SENSOR_TYPE_GYROSCOPE;
316 resolution = RESOLUTION_G;
321 template<> int Sensor<ID_GYROSCOPE>::readEvents(sensors_event_t *data, int cnt)
323 static float scale = read_sysfs_float((*nodes)[0]);
324 int ret = SensorBase::readEvents(data, cnt);
325 // TODO: read orientation from the properties
326 for (int i = 0; i < ret; ++i) {
327 data[i].gyro.x = scale * read_sysfs_int("in_anglvel_x_raw");
328 data[i].gyro.y = scale * read_sysfs_int("in_anglvel_y_raw");
329 data[i].gyro.z = scale * read_sysfs_int("in_anglvel_z_raw");
330 data[i].gyro.status = SENSOR_STATUS_ACCURACY_HIGH;
335 static SensorBase *(*probeSensors[])(const char *) = {
336 Sensor<ID_ACCELERATION>::probe,
337 Sensor<ID_MAGNETIC_FIELD>::probe,
338 Sensor<ID_LIGHT>::probe,
339 Sensor<ID_GYROSCOPE>::probe,
342 class SensorPollContext : sensors_poll_device_t {
344 SensorPollContext(const struct hw_module_t *module, struct hw_device_t **device);
345 ~SensorPollContext();
347 bool isValid() const;
348 int getSensor(struct sensor_t const **list) const;
351 static int poll_close(struct hw_device_t *dev);
352 static int poll_activate(struct sensors_poll_device_t *dev, int handle, int enabled);
353 static int poll_setDelay(struct sensors_poll_device_t *dev, int handle, int64_t ns);
354 static int poll_poll(struct sensors_poll_device_t *dev, sensors_event_t *data, int count);
356 int doPoll(sensors_event_t *data, int count);
358 sensor_t sensors_list[MAX_SENSORS];
359 SensorBase *sensors[MAX_SENSORS];
363 static SensorPollContext *sctx = 0;
365 SensorPollContext::SensorPollContext(const struct hw_module_t *module, struct hw_device_t **device)
367 memset(this, 0, sizeof(*this));
369 common.tag = HARDWARE_DEVICE_TAG;
370 common.module = const_cast<struct hw_module_t *>(module);
371 common.close = poll_close;
372 activate = poll_activate;
373 setDelay = poll_setDelay;
378 strcpy(path, IIO_DIR);
379 int len = strlen(path);
380 if (DIR *dir = opendir(path)) {
381 while (struct dirent *de = readdir(dir)) {
382 if (!strncmp(de->d_name, "iio:device", 10)) {
383 strcpy(path + len, de->d_name);
384 for (int i = 0; probeSensors[i] && i < MAX_SENSORS; ++i) {
385 if (SensorBase *s = probeSensors[i](path)) {
387 sensors_list[count++] =*s;
393 ALOGD("%s: module=%p sensors: %d", __FUNCTION__, module, count);
396 SensorPollContext::~SensorPollContext()
398 for (int i = 0; i < MAX_SENSORS; ++i) {
403 bool SensorPollContext::isValid() const
408 int SensorPollContext::getSensor(struct sensor_t const **list) const
410 *list = sensors_list;
414 int SensorPollContext::poll_close(struct hw_device_t *dev)
416 ALOGD("%s: dev=%p", __FUNCTION__, dev);
417 SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
422 ALOGW("close a ctx(%p) rather than sctx(%p)", ctx, sctx);
427 int SensorPollContext::poll_activate(struct sensors_poll_device_t *dev, int handle, int enabled)
429 ALOGD("%s: dev=%p handle=%d enabled=%d", __FUNCTION__, dev, handle, enabled);
430 SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
431 if (handle >= 0 && handle < MAX_SENSORS && ctx->sensors[handle])
432 return ctx->sensors[handle]->activate(enabled);
437 int SensorPollContext::poll_setDelay(struct sensors_poll_device_t *dev, int handle, int64_t ns)
439 ALOGD("%s: handle=%d delay-ns=%lld", __FUNCTION__, handle, ns);
440 SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
441 if (handle >= 0 && handle < MAX_SENSORS && ctx->sensors[handle])
442 return ctx->sensors[handle]->setDelay(ns);
447 int SensorPollContext::poll_poll(struct sensors_poll_device_t *dev, sensors_event_t *data, int count)
449 ALOGV("%s: dev=%p data=%p count=%d", __FUNCTION__, dev, data, count);
450 SensorPollContext *ctx = reinterpret_cast<SensorPollContext *>(dev);
451 return ctx->doPoll(data, count);
454 int SensorPollContext::doPoll(sensors_event_t *data, int cnt)
460 for (int i = 0; cnt > 0 && i < MAX_SENSORS; ++i) {
461 if (sensors[i] && *sensors[i]) {
462 int nb = sensors[i]->readEvents(data, cnt);
472 static int open_iio_sensors(const struct hw_module_t *module, const char *id, struct hw_device_t **device)
474 ALOGD("%s: id=%s", __FUNCTION__, id);
476 sctx = new SensorPollContext(module, device);
478 return (sctx && sctx->isValid()) ? 0 : -EINVAL;
481 static int sensors_get_sensors_list(struct sensors_module_t *, struct sensor_t const **list)
483 ALOGD("enter %s", __FUNCTION__);
484 return sctx ? sctx->getSensor(list) : 0;
487 static struct hw_module_methods_t sensors_methods = {
488 open: open_iio_sensors
491 struct sensors_module_t HAL_MODULE_INFO_SYM = {
493 tag: HARDWARE_MODULE_TAG,
496 id: SENSORS_HARDWARE_MODULE_ID,
498 author: "Chih-Wei Huang",
499 methods: &sensors_methods,
503 get_sensors_list: sensors_get_sensors_list