blob: f3c0b3a51c948291ea8060c650d6be078cedf004 [file] [log] [blame]
The Android Open Source Projectd6054a32008-10-21 07:00:00 -07001/*
2 * Copyright 2008, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#define LOG_TAG "Sensors"
18
19#include <hardware/sensors.h>
20#include <fcntl.h>
21#include <errno.h>
22#include <dirent.h>
23#include <math.h>
24#include <poll.h>
25
26#include <linux/input.h>
27#include <linux/akm8976.h>
28
29#include <cutils/log.h>
30#include <cutils/atomic.h>
31
32/*****************************************************************************/
33
34#define AKM_DEVICE_NAME "/dev/akm8976_aot"
35
36#define SUPPORTED_SENSORS (SENSORS_ORIENTATION | \
37 SENSORS_ACCELERATION | \
38 SENSORS_MAGNETIC_FIELD | \
39 SENSORS_ORIENTATION_RAW)
40
41
42// sensor IDs must be a power of two and
43// must match values in SensorManager.java
44#define EVENT_TYPE_ACCEL_X ABS_X
45#define EVENT_TYPE_ACCEL_Y ABS_Z
46#define EVENT_TYPE_ACCEL_Z ABS_Y
47#define EVENT_TYPE_ACCEL_STATUS ABS_WHEEL
48
49#define EVENT_TYPE_YAW ABS_RX
50#define EVENT_TYPE_PITCH ABS_RY
51#define EVENT_TYPE_ROLL ABS_RZ
52#define EVENT_TYPE_ORIENT_STATUS ABS_RUDDER
53
54#define EVENT_TYPE_MAGV_X ABS_HAT0X
55#define EVENT_TYPE_MAGV_Y ABS_HAT0Y
56#define EVENT_TYPE_MAGV_Z ABS_BRAKE
57
58#define EVENT_TYPE_TEMPERATURE ABS_THROTTLE
59#define EVENT_TYPE_STEP_COUNT ABS_GAS
60
61// 720 LSG = 1G
62#define LSG (720.0f)
63
64// conversion of acceleration data to SI units (m/s^2)
65#define CONVERT_A (GRAVITY_EARTH / LSG)
66#define CONVERT_A_X (CONVERT_A)
67#define CONVERT_A_Y (-CONVERT_A)
68#define CONVERT_A_Z (CONVERT_A)
69
70// conversion of magnetic data to uT units
71#define CONVERT_M (1.0f/16.0f)
72#define CONVERT_M_X (CONVERT_M)
73#define CONVERT_M_Y (CONVERT_M)
74#define CONVERT_M_Z (CONVERT_M)
75
76#define SENSOR_STATE_MASK (0x7FFF)
77
78/*****************************************************************************/
79
80static int sAkmFD = -1;
81static uint32_t sActiveSensors = 0;
82
83/*****************************************************************************/
84
85/*
86 * We use a Least Mean Squares filter to smooth out the output of the yaw
87 * sensor.
88 *
89 * The goal is to estimate the output of the sensor based on previous acquired
90 * samples.
91 *
92 * We approximate the input by a line with the equation:
93 * Z(t) = a * t + b
94 *
95 * We use the Least Mean Squares method to calculate a and b so that the
96 * distance between the line and the measured COUNT inputs Z(t) is minimal.
97 *
98 * In practice we only need to compute b, which is the value we're looking for
99 * (it's the estimated Z at t=0). However, to improve the latency a little bit,
100 * we're going to discard a certain number of samples that are too far from
101 * the estimated line and compute b again with the new (trimmed down) samples.
102 *
103 * notes:
104 * 'a' is the slope of the line, and physicaly represent how fast the input
105 * is changing. In our case, how fast the yaw is changing, that is, how fast the
106 * user is spinning the device (in degre / nanosecond). This value should be
107 * zero when the device is not moving.
108 *
109 * The minimum distance between the line and the samples (which we are not
110 * explicitely computing here), is an indication of how bad the samples are
111 * and gives an idea of the "quality" of the estimation (well, really of the
112 * sensor values).
113 *
114 */
115
116/* sensor rate in me */
117#define SENSORS_RATE_MS 20
118/* timeout (constant value) in ms */
119#define SENSORS_TIMEOUT_MS 100
120/* # of samples to look at in the past for filtering */
121#define COUNT 24
122/* prediction ratio */
123#define PREDICTION_RATIO (1.0f/3.0f)
124/* prediction time in seconds (>=0) */
125#define PREDICTION_TIME ((SENSORS_RATE_MS*COUNT/1000.0f)*PREDICTION_RATIO)
126
127static float mV[COUNT*2];
128static float mT[COUNT*2];
129static int mIndex;
130
131static inline
132float normalize(float x)
133{
134 x *= (1.0f / 360.0f);
135 if (fabsf(x) >= 0.5f)
136 x = x - ceilf(x + 0.5f) + 1.0f;
137 if (x < 0)
138 x += 1.0f;
139 x *= 360.0f;
140 return x;
141}
142
143static void LMSInit(void)
144{
145 memset(mV, 0, sizeof(mV));
146 memset(mT, 0, sizeof(mT));
147 mIndex = COUNT;
148}
149
150static float LMSFilter(int64_t time, int v)
151{
152 const float ns = 1.0f / 1000000000.0f;
153 const float t = time*ns;
154 float v1 = mV[mIndex];
155 if ((v-v1) > 180) {
156 v -= 360;
157 } else if ((v1-v) > 180) {
158 v += 360;
159 }
160 /* Manage the circular buffer, we write the data twice spaced by COUNT
161 * values, so that we don't have to memcpy() the array when it's full */
162 mIndex++;
163 if (mIndex >= COUNT*2)
164 mIndex = COUNT;
165 mV[mIndex] = v;
166 mT[mIndex] = t;
167 mV[mIndex-COUNT] = v;
168 mT[mIndex-COUNT] = t;
169
170 float A, B, C, D, E;
171 float a, b;
172 int i;
173
174 A = B = C = D = E = 0;
175 for (i=0 ; i<COUNT-1 ; i++) {
176 const int j = mIndex - 1 - i;
177 const float Z = mV[j];
178 const float T = 0.5f*(mT[j] + mT[j+1]) - t;
179 float dT = mT[j] - mT[j+1];
180 dT *= dT;
181 A += Z*dT;
182 B += T*(T*dT);
183 C += (T*dT);
184 D += Z*(T*dT);
185 E += dT;
186 }
187 b = (A*B + C*D) / (E*B + C*C);
188 a = (E*b - A) / C;
189 float f = b + PREDICTION_TIME*a;
190
191 //LOGD("A=%f, B=%f, C=%f, D=%f, E=%f", A,B,C,D,E);
192 //LOGD("%lld %d %f %f", time, v, f, a);
193
194 f = normalize(f);
195 return f;
196}
197
198/*****************************************************************************/
199
200static int open_input()
201{
202 /* scan all input drivers and look for "compass" */
203 int fd = -1;
204 const char *dirname = "/dev/input";
205 char devname[PATH_MAX];
206 char *filename;
207 DIR *dir;
208 struct dirent *de;
209 dir = opendir(dirname);
210 if(dir == NULL)
211 return -1;
212 strcpy(devname, dirname);
213 filename = devname + strlen(devname);
214 *filename++ = '/';
215 while((de = readdir(dir))) {
216 if(de->d_name[0] == '.' &&
217 (de->d_name[1] == '\0' ||
218 (de->d_name[1] == '.' && de->d_name[2] == '\0')))
219 continue;
220 strcpy(filename, de->d_name);
221 fd = open(devname, O_RDONLY);
222 if (fd>=0) {
223 char name[80];
224 if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) {
225 name[0] = '\0';
226 }
227 if (!strcmp(name, "compass")) {
228 LOGD("using %s (name=%s)", devname, name);
229 break;
230 }
231 close(fd);
232 fd = -1;
233 }
234 }
235 closedir(dir);
236
237 if (fd < 0) {
238 LOGE("Couldn't find or open 'compass' driver (%s)", strerror(errno));
239 }
240 return fd;
241}
242
243static int open_akm()
244{
245 if (sAkmFD <= 0) {
246 sAkmFD = open(AKM_DEVICE_NAME, O_RDONLY);
247 LOGD("%s, fd=%d", __PRETTY_FUNCTION__, sAkmFD);
248 LOGE_IF(sAkmFD<0, "Couldn't open %s (%s)",
249 AKM_DEVICE_NAME, strerror(errno));
250 if (sAkmFD >= 0) {
251 sActiveSensors = 0;
252 }
253 }
254 return sAkmFD;
255}
256
257static void close_akm()
258{
259 if (sAkmFD > 0) {
260 LOGD("%s, fd=%d", __PRETTY_FUNCTION__, sAkmFD);
261 close(sAkmFD);
262 sAkmFD = -1;
263 }
264}
265
266static void enable_disable(int fd, uint32_t sensors, uint32_t mask)
267{
268 if (fd<0) return;
269 short flags;
270
271 if (sensors & SENSORS_ORIENTATION_RAW) {
272 sensors |= SENSORS_ORIENTATION;
273 mask |= SENSORS_ORIENTATION;
274 } else if (mask & SENSORS_ORIENTATION_RAW) {
275 mask |= SENSORS_ORIENTATION;
276 }
277
278 if (mask & SENSORS_ORIENTATION) {
279 flags = (sensors & SENSORS_ORIENTATION) ? 1 : 0;
280 if (ioctl(fd, ECS_IOCTL_APP_SET_MFLAG, &flags) < 0) {
281 LOGE("ECS_IOCTL_APP_SET_MFLAG error (%s)", strerror(errno));
282 }
283 }
284 if (mask & SENSORS_ACCELERATION) {
285 flags = (sensors & SENSORS_ACCELERATION) ? 1 : 0;
286 if (ioctl(fd, ECS_IOCTL_APP_SET_AFLAG, &flags) < 0) {
287 LOGE("ECS_IOCTL_APP_SET_AFLAG error (%s)", strerror(errno));
288 }
289 }
290 if (mask & SENSORS_TEMPERATURE) {
291 flags = (sensors & SENSORS_TEMPERATURE) ? 1 : 0;
292 if (ioctl(fd, ECS_IOCTL_APP_SET_TFLAG, &flags) < 0) {
293 LOGE("ECS_IOCTL_APP_SET_TFLAG error (%s)", strerror(errno));
294 }
295 }
296#ifdef ECS_IOCTL_APP_SET_MVFLAG
297 if (mask & SENSORS_MAGNETIC_FIELD) {
298 flags = (sensors & SENSORS_MAGNETIC_FIELD) ? 1 : 0;
299 if (ioctl(fd, ECS_IOCTL_APP_SET_MVFLAG, &flags) < 0) {
300 LOGE("ECS_IOCTL_APP_SET_MVFLAG error (%s)", strerror(errno));
301 }
302 }
303#endif
304}
305
306static uint32_t read_sensors_state(int fd)
307{
308 if (fd<0) return 0;
309 short flags;
310 uint32_t sensors = 0;
311 // read the actual value of all sensors
312 if (!ioctl(fd, ECS_IOCTL_APP_GET_MFLAG, &flags)) {
313 if (flags) sensors |= SENSORS_ORIENTATION;
314 else sensors &= ~SENSORS_ORIENTATION;
315 }
316 if (!ioctl(fd, ECS_IOCTL_APP_GET_AFLAG, &flags)) {
317 if (flags) sensors |= SENSORS_ACCELERATION;
318 else sensors &= ~SENSORS_ACCELERATION;
319 }
320 if (!ioctl(fd, ECS_IOCTL_APP_GET_TFLAG, &flags)) {
321 if (flags) sensors |= SENSORS_TEMPERATURE;
322 else sensors &= ~SENSORS_TEMPERATURE;
323 }
324#ifdef ECS_IOCTL_APP_SET_MVFLAG
325 if (!ioctl(fd, ECS_IOCTL_APP_GET_MVFLAG, &flags)) {
326 if (flags) sensors |= SENSORS_MAGNETIC_FIELD;
327 else sensors &= ~SENSORS_MAGNETIC_FIELD;
328 }
329#endif
330 return sensors;
331}
332
333/*****************************************************************************/
334
335uint32_t sensors_control_init()
336{
337 return SUPPORTED_SENSORS;
338}
339
340int sensors_control_open()
341{
342 return open_input();
343}
344
345uint32_t sensors_control_activate(uint32_t sensors, uint32_t mask)
346{
347 mask &= SUPPORTED_SENSORS;
348 uint32_t active = sActiveSensors;
349 uint32_t new_sensors = (active & ~mask) | (sensors & mask);
350 uint32_t changed = active ^ new_sensors;
351 if (changed) {
352 int fd = open_akm();
353 if (fd < 0) return 0;
354
355 if (!active && new_sensors) {
356 // force all sensors to be updated
357 changed = SUPPORTED_SENSORS;
358 }
359
360 enable_disable(fd, new_sensors, changed);
361
362 if (active && !new_sensors) {
363 // close the driver
364 close_akm();
365 }
366 sActiveSensors = active = new_sensors;
367 LOGD("sensors=%08x, real=%08x",
368 sActiveSensors, read_sensors_state(fd));
369 }
370 return active;
371}
372
373int sensors_control_delay(int32_t ms)
374{
375#ifdef ECS_IOCTL_APP_SET_DELAY
376 if (sAkmFD <= 0) {
377 return -1;
378 }
379 short delay = ms;
380 if (!ioctl(sAkmFD, ECS_IOCTL_APP_SET_DELAY, &delay)) {
381 return -errno;
382 }
383 return 0;
384#else
385 return -1;
386#endif
387}
388
389/*****************************************************************************/
390
391#define MAX_NUM_SENSORS 8
392static int sInputFD = -1;
393static const int ID_O = 0;
394static const int ID_A = 1;
395static const int ID_T = 2;
396static const int ID_M = 3;
397static const int ID_OR = 7; // orientation raw
398static sensors_data_t sSensors[MAX_NUM_SENSORS];
399static uint32_t sPendingSensors;
400
401int sensors_data_open(int fd)
402{
403 int i;
404 LMSInit();
405 memset(&sSensors, 0, sizeof(sSensors));
406 for (i=0 ; i<MAX_NUM_SENSORS ; i++) {
407 // by default all sensors have high accuracy
408 // (we do this because we don't get an update if the value doesn't
409 // change).
410 sSensors[i].vector.status = SENSOR_STATUS_ACCURACY_HIGH;
411 }
412 sPendingSensors = 0;
413 sInputFD = dup(fd);
414 LOGD("sensors_data_open: fd = %d", sInputFD);
415 return 0;
416}
417
418int sensors_data_close()
419{
420 close(sInputFD);
421 sInputFD = -1;
422 return 0;
423}
424
425static int pick_sensor(sensors_data_t* values)
426{
427 uint32_t mask = SENSORS_MASK;
428 while(mask) {
429 uint32_t i = 31 - __builtin_clz(mask);
430 mask &= ~(1<<i);
431 if (sPendingSensors & (1<<i)) {
432 sPendingSensors &= ~(1<<i);
433 *values = sSensors[i];
434 values->sensor = (1<<i);
435 LOGD_IF(0, "%d [%f, %f, %f]", (1<<i),
436 values->vector.x,
437 values->vector.y,
438 values->vector.z);
439 return (1<<i);
440 }
441 }
442 LOGE("No sensor to return!!! sPendingSensors=%08x", sPendingSensors);
443 // we may end-up in a busy loop, slow things down, just in case.
444 usleep(100000);
445 return -1;
446}
447
448int sensors_data_poll(sensors_data_t* values, uint32_t sensors_of_interest)
449{
450 struct input_event event;
451 int nread;
452 int64_t t;
453
454 int fd = sInputFD;
455 if (fd <= 0)
456 return -1;
457
458 // there are pending sensors, returns them now...
459 if (sPendingSensors) {
460 return pick_sensor(values);
461 }
462
463 uint32_t new_sensors = 0;
464 struct pollfd fds;
465 fds.fd = fd;
466 fds.events = POLLIN;
467 fds.revents = 0;
468
469 // wait until we get a complete event for an enabled sensor
470 while (1) {
471 nread = 0;
472 if (sensors_of_interest & SENSORS_ORIENTATION) {
473 /* We do some special processing if the orientation sensor is
474 * activated. In particular the yaw value is filtered with a
475 * LMS filter. Since the kernel only sends an event when the
476 * value changes, we need to wake up at regular intervals to
477 * generate an output value (the output value may not be
478 * constant when the input value is constant)
479 */
480 int err = poll(&fds, 1, SENSORS_TIMEOUT_MS);
481 if (err == 0) {
482 struct timespec time;
483 time.tv_sec = time.tv_nsec = 0;
484 clock_gettime(CLOCK_MONOTONIC, &time);
485
486 /* generate an output value */
487 t = time.tv_sec*1000000000LL+time.tv_nsec;
488 new_sensors |= SENSORS_ORIENTATION;
489 sSensors[ID_O].orientation.yaw =
490 LMSFilter(t, sSensors[ID_O].orientation.yaw);
491
492 /* generate a fake sensors event */
493 event.type = EV_SYN;
494 event.time.tv_sec = time.tv_sec;
495 event.time.tv_usec = time.tv_nsec/1000;
496 nread = sizeof(event);
497 }
498 }
499 if (nread == 0) {
500 /* read the next event */
501 nread = read(fd, &event, sizeof(event));
502 }
503 if (nread == sizeof(event)) {
504 uint32_t v;
505 if (event.type == EV_ABS) {
506 //LOGD("type: %d code: %d value: %-5d time: %ds",
507 // event.type, event.code, event.value,
508 // (int)event.time.tv_sec);
509 switch (event.code) {
510
511 case EVENT_TYPE_ACCEL_X:
512 new_sensors |= SENSORS_ACCELERATION;
513 sSensors[ID_A].acceleration.x = event.value * CONVERT_A_X;
514 break;
515 case EVENT_TYPE_ACCEL_Y:
516 new_sensors |= SENSORS_ACCELERATION;
517 sSensors[ID_A].acceleration.y = event.value * CONVERT_A_Y;
518 break;
519 case EVENT_TYPE_ACCEL_Z:
520 new_sensors |= SENSORS_ACCELERATION;
521 sSensors[ID_A].acceleration.z = event.value * CONVERT_A_Z;
522 break;
523
524 case EVENT_TYPE_MAGV_X:
525 new_sensors |= SENSORS_MAGNETIC_FIELD;
526 sSensors[ID_M].magnetic.x = event.value * CONVERT_M_X;
527 break;
528 case EVENT_TYPE_MAGV_Y:
529 new_sensors |= SENSORS_MAGNETIC_FIELD;
530 sSensors[ID_M].magnetic.y = event.value * CONVERT_M_Y;
531 break;
532 case EVENT_TYPE_MAGV_Z:
533 new_sensors |= SENSORS_MAGNETIC_FIELD;
534 sSensors[ID_M].magnetic.z = event.value * CONVERT_M_Z;
535 break;
536
537 case EVENT_TYPE_YAW:
538 new_sensors |= SENSORS_ORIENTATION | SENSORS_ORIENTATION_RAW;
539 t = event.time.tv_sec*1000000000LL +
540 event.time.tv_usec*1000;
541 sSensors[ID_O].orientation.yaw =
542 (sensors_of_interest & SENSORS_ORIENTATION) ?
543 LMSFilter(t, event.value) : event.value;
544 sSensors[ID_OR].orientation.yaw = event.value;
545 break;
546 case EVENT_TYPE_PITCH:
547 new_sensors |= SENSORS_ORIENTATION | SENSORS_ORIENTATION_RAW;
548 sSensors[ID_O].orientation.pitch = event.value;
549 sSensors[ID_OR].orientation.pitch = event.value;
550 break;
551 case EVENT_TYPE_ROLL:
552 new_sensors |= SENSORS_ORIENTATION | SENSORS_ORIENTATION_RAW;
553 sSensors[ID_O].orientation.roll = event.value;
554 sSensors[ID_OR].orientation.roll = event.value;
555 break;
556
557 case EVENT_TYPE_TEMPERATURE:
558 new_sensors |= SENSORS_TEMPERATURE;
559 sSensors[ID_T].temperature = event.value;
560 break;
561
562 case EVENT_TYPE_STEP_COUNT:
563 // step count (only reported in MODE_FFD)
564 // we do nothing with it for now.
565 break;
566 case EVENT_TYPE_ACCEL_STATUS:
567 // accuracy of the calibration (never returned!)
568 //LOGD("G-Sensor status %d", event.value);
569 break;
570 case EVENT_TYPE_ORIENT_STATUS:
571 // accuracy of the calibration
572 v = (uint32_t)(event.value & SENSOR_STATE_MASK);
573 LOGD_IF(sSensors[ID_O].orientation.status != (uint8_t)v,
574 "M-Sensor status %d", v);
575 sSensors[ID_O].orientation.status = (uint8_t)v;
576 sSensors[ID_OR].orientation.status = (uint8_t)v;
577 break;
578 }
579 } else if (event.type == EV_SYN) {
580 if (new_sensors) {
581 sPendingSensors = new_sensors;
582 int64_t t = event.time.tv_sec*1000000000LL +
583 event.time.tv_usec*1000;
584 while (new_sensors) {
585 uint32_t i = 31 - __builtin_clz(new_sensors);
586 new_sensors &= ~(1<<i);
587 sSensors[i].time = t;
588 }
589 return pick_sensor(values);
590 }
591 }
592 }
593 }
594}
595
596uint32_t sensors_data_get_sensors() {
597 return SUPPORTED_SENSORS;
598}
599