blob: 7d77b6227c628dd0812b383570124a7f60dbe7e9 [file] [log] [blame]
The Android Open Source Project9877e2e2009-03-18 17:39:44 -07001/* Copyright (C) 2009 The Android Open Source Project
2**
3** This software is licensed under the terms of the GNU General Public
4** License version 2, as published by the Free Software Foundation, and
5** may be copied, distributed, and modified under those terms.
6**
7** This program is distributed in the hope that it will be useful,
8** but WITHOUT ANY WARRANTY; without even the implied warranty of
9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10** GNU General Public License for more details.
11*/
12
David 'Digit' Turner593d0ea2011-02-15 03:02:34 +010013#include <math.h>
The Android Open Source Project9877e2e2009-03-18 17:39:44 -070014#include "android/hw-sensors.h"
15#include "android/utils/debug.h"
16#include "android/utils/misc.h"
David 'Digit' Turner5998b892009-06-11 14:43:03 +020017#include "android/utils/system.h"
The Android Open Source Project9877e2e2009-03-18 17:39:44 -070018#include "android/hw-qemud.h"
19#include "android/globals.h"
Ot ten Thije871da2a2010-09-20 10:29:22 +010020#include "hw/hw.h"
The Android Open Source Project9877e2e2009-03-18 17:39:44 -070021#include "qemu-char.h"
22#include "qemu-timer.h"
23
24#define D(...) VERBOSE_PRINT(sensors,__VA_ARGS__)
25
26/* define T_ACTIVE to 1 to debug transport communications */
27#define T_ACTIVE 0
28
29#if T_ACTIVE
30#define T(...) VERBOSE_PRINT(sensors,__VA_ARGS__)
31#else
32#define T(...) ((void)0)
33#endif
34
35/* this code supports emulated sensor hardware
36 *
37 * Note that currently, only the accelerometer is really emulated, and only
38 * for the purpose of allowing auto-rotating the screen in keyboard-less
39 * configurations.
40 *
41 *
42 */
43
44
45static const struct {
46 const char* name;
47 int id;
48} _sSensors[MAX_SENSORS] = {
49#define SENSOR_(x,y) { y, ANDROID_SENSOR_##x },
50 SENSORS_LIST
51#undef SENSOR_
52};
53
54
55static int
56_sensorIdFromName( const char* name )
57{
58 int nn;
59 for (nn = 0; nn < MAX_SENSORS; nn++)
60 if (!strcmp(_sSensors[nn].name,name))
61 return _sSensors[nn].id;
62 return -1;
63}
64
Tim Wan736e01f2011-01-10 10:58:25 +010065static const char*
66_sensorNameFromId( int id )
67{
68 int nn;
69 for (nn = 0; nn < MAX_SENSORS; nn++)
70 if (id == _sSensors[nn].id)
71 return _sSensors[nn].name;
72 return NULL;
73}
74
75/* For common Sensor Value struct */
76typedef struct {
77 float a, b, c;
78} SensorValues;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -070079
80typedef struct {
81 float x, y, z;
82} Acceleration;
83
84
85typedef struct {
86 float x, y, z;
87} MagneticField;
88
89
90typedef struct {
91 float azimuth;
92 float pitch;
93 float roll;
94} Orientation;
95
96
97typedef struct {
98 float celsius;
99} Temperature;
100
101
102typedef struct {
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100103 float value;
104} Proximity;
105
106typedef struct {
107 char enabled;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700108 union {
Tim Wan736e01f2011-01-10 10:58:25 +0100109 SensorValues value;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700110 Acceleration acceleration;
111 MagneticField magnetic;
112 Orientation orientation;
113 Temperature temperature;
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100114 Proximity proximity;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700115 } u;
116} Sensor;
117
118/*
119 * - when the qemu-specific sensors HAL module starts, it sends
120 * "list-sensors"
121 *
122 * - this code replies with a string containing an integer corresponding
123 * to a bitmap of available hardware sensors in the current AVD
124 * configuration (e.g. "1" a.k.a (1 << ANDROID_SENSOR_ACCELERATION))
125 *
126 * - the HAL module sends "set:<sensor>:<flag>" to enable or disable
127 * the report of a given sensor state. <sensor> must be the name of
128 * a given sensor (e.g. "accelerometer"), and <flag> must be either
129 * "1" (to enable) or "0" (to disable).
130 *
131 * - Once at least one sensor is "enabled", this code should periodically
132 * send information about the corresponding enabled sensors. The default
133 * period is 200ms.
134 *
135 * - the HAL module sends "set-delay:<delay>", where <delay> is an integer
136 * corresponding to a time delay in milli-seconds. This corresponds to
137 * a new interval between sensor events sent by this code to the HAL
138 * module.
139 *
140 * - the HAL module can also send a "wake" command. This code should simply
141 * send the "wake" back to the module. This is used internally to wake a
142 * blocking read that happens in a different thread. This ping-pong makes
143 * the code in the HAL module very simple.
144 *
145 * - each timer tick, this code sends sensor reports in the following
146 * format (each line corresponds to a different line sent to the module):
147 *
148 * acceleration:<x>:<y>:<z>
149 * magnetic-field:<x>:<y>:<z>
150 * orientation:<azimuth>:<pitch>:<roll>
151 * temperature:<celsius>
152 * sync:<time_us>
153 *
154 * Where each line before the sync:<time_us> is optional and will only
155 * appear if the corresponding sensor has been enabled by the HAL module.
156 *
157 * Note that <time_us> is the VM time in micro-seconds when the report
158 * was "taken" by this code. This is adjusted by the HAL module to
159 * emulated system time (using the first sync: to compute an adjustment
160 * offset).
161 */
162#define HEADER_SIZE 4
163#define BUFFER_SIZE 512
164
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200165typedef struct HwSensorClient HwSensorClient;
166
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700167typedef struct {
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200168 QemudService* service;
169 Sensor sensors[MAX_SENSORS];
170 HwSensorClient* clients;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700171} HwSensors;
172
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200173struct HwSensorClient {
174 HwSensorClient* next;
175 HwSensors* sensors;
176 QemudClient* client;
177 QEMUTimer* timer;
178 uint32_t enabledMask;
179 int32_t delay_ms;
180};
181
182static void
183_hwSensorClient_free( HwSensorClient* cl )
184{
185 /* remove from sensors's list */
186 if (cl->sensors) {
187 HwSensorClient** pnode = &cl->sensors->clients;
188 for (;;) {
189 HwSensorClient* node = *pnode;
190 if (node == NULL)
191 break;
192 if (node == cl) {
193 *pnode = cl->next;
194 break;
195 }
196 pnode = &node->next;
197 }
198 cl->next = NULL;
199 cl->sensors = NULL;
200 }
201
202 /* close QEMUD client, if any */
203 if (cl->client) {
204 qemud_client_close(cl->client);
205 cl->client = NULL;
206 }
207 /* remove timer, if any */
208 if (cl->timer) {
209 qemu_del_timer(cl->timer);
210 qemu_free_timer(cl->timer);
211 cl->timer = NULL;
212 }
213 AFREE(cl);
214}
215
216/* forward */
217static void _hwSensorClient_tick(void* opaque);
218
219
220static HwSensorClient*
221_hwSensorClient_new( HwSensors* sensors )
222{
223 HwSensorClient* cl;
224
225 ANEW0(cl);
226
227 cl->sensors = sensors;
228 cl->enabledMask = 0;
David 'Digit' Turner593d0ea2011-02-15 03:02:34 +0100229 cl->delay_ms = 800;
David 'Digit' Turner5973c772011-05-10 07:06:00 +0200230 cl->timer = qemu_new_timer_ns(vm_clock, _hwSensorClient_tick, cl);
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200231
232 cl->next = sensors->clients;
233 sensors->clients = cl;
234
235 return cl;
236}
237
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700238/* forward */
239
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200240static void _hwSensorClient_receive( HwSensorClient* cl,
241 uint8_t* query,
242 int querylen );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700243
244/* Qemud service management */
245
246static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200247_hwSensorClient_recv( void* opaque, uint8_t* msg, int msglen,
248 QemudClient* client )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700249{
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200250 HwSensorClient* cl = opaque;
251
252 _hwSensorClient_receive(cl, msg, msglen);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700253}
254
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200255static void
256_hwSensorClient_close( void* opaque )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700257{
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200258 HwSensorClient* cl = opaque;
259
260 /* the client is already closed here */
261 cl->client = NULL;
262 _hwSensorClient_free(cl);
263}
264
265/* send a one-line message to the HAL module through a qemud channel */
266static void
267_hwSensorClient_send( HwSensorClient* cl, const uint8_t* msg, int msglen )
268{
269 D("%s: '%s'", __FUNCTION__, quote_bytes((const void*)msg, msglen));
270 qemud_client_send(cl->client, msg, msglen);
271}
272
273static int
274_hwSensorClient_enabled( HwSensorClient* cl, int sensorId )
275{
276 return (cl->enabledMask & (1 << sensorId)) != 0;
277}
278
279/* this function is called periodically to send sensor reports
280 * to the HAL module, and re-arm the timer if necessary
281 */
282static void
283_hwSensorClient_tick( void* opaque )
284{
285 HwSensorClient* cl = opaque;
286 HwSensors* hw = cl->sensors;
287 int64_t delay = cl->delay_ms;
288 int64_t now_ns;
289 uint32_t mask = cl->enabledMask;
290 Sensor* sensor;
291 char buffer[128];
292
293 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_ACCELERATION)) {
294 sensor = &hw->sensors[ANDROID_SENSOR_ACCELERATION];
295 snprintf(buffer, sizeof buffer, "acceleration:%g:%g:%g",
296 sensor->u.acceleration.x,
297 sensor->u.acceleration.y,
298 sensor->u.acceleration.z);
299 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
300 }
301
302 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_MAGNETIC_FIELD)) {
303 sensor = &hw->sensors[ANDROID_SENSOR_MAGNETIC_FIELD];
304 snprintf(buffer, sizeof buffer, "magnetic-field:%g:%g:%g",
305 sensor->u.magnetic.x,
306 sensor->u.magnetic.y,
307 sensor->u.magnetic.z);
308 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
309 }
310
311 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_ORIENTATION)) {
312 sensor = &hw->sensors[ANDROID_SENSOR_ORIENTATION];
313 snprintf(buffer, sizeof buffer, "orientation:%g:%g:%g",
314 sensor->u.orientation.azimuth,
315 sensor->u.orientation.pitch,
316 sensor->u.orientation.roll);
317 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
318 }
319
320 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_TEMPERATURE)) {
321 sensor = &hw->sensors[ANDROID_SENSOR_TEMPERATURE];
322 snprintf(buffer, sizeof buffer, "temperature:%g",
323 sensor->u.temperature.celsius);
324 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
325 }
326
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100327 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_PROXIMITY)) {
328 sensor = &hw->sensors[ANDROID_SENSOR_PROXIMITY];
329 snprintf(buffer, sizeof buffer, "proximity:%g",
330 sensor->u.proximity.value);
331 _hwSensorClient_send(cl, (uint8_t*) buffer, strlen(buffer));
332 }
333
David 'Digit' Turner5973c772011-05-10 07:06:00 +0200334 now_ns = qemu_get_clock_ns(vm_clock);
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200335
336 snprintf(buffer, sizeof buffer, "sync:%lld", now_ns/1000);
337 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
338
339 /* rearm timer, use a minimum delay of 20 ms, just to
340 * be safe.
341 */
342 if (mask == 0)
343 return;
344
345 if (delay < 20)
346 delay = 20;
347
348 delay *= 1000000LL; /* convert to nanoseconds */
349 qemu_mod_timer(cl->timer, now_ns + delay);
350}
351
352/* handle incoming messages from the HAL module */
353static void
354_hwSensorClient_receive( HwSensorClient* cl, uint8_t* msg, int msglen )
355{
356 HwSensors* hw = cl->sensors;
357
358 D("%s: '%.*s'", __FUNCTION__, msglen, msg);
359
360 /* "list-sensors" is used to get an integer bit map of
361 * available emulated sensors. We compute the mask from the
362 * current hardware configuration.
363 */
364 if (msglen == 12 && !memcmp(msg, "list-sensors", 12)) {
365 char buff[12];
366 int mask = 0;
367 int nn;
368
369 for (nn = 0; nn < MAX_SENSORS; nn++) {
370 if (hw->sensors[nn].enabled)
371 mask |= (1 << nn);
372 }
373
374 snprintf(buff, sizeof buff, "%d", mask);
375 _hwSensorClient_send(cl, (const uint8_t*)buff, strlen(buff));
376 return;
377 }
378
379 /* "wake" is a special message that must be sent back through
380 * the channel. It is used to exit a blocking read.
381 */
382 if (msglen == 4 && !memcmp(msg, "wake", 4)) {
383 _hwSensorClient_send(cl, (const uint8_t*)"wake", 4);
384 return;
385 }
386
387 /* "set-delay:<delay>" is used to set the delay in milliseconds
388 * between sensor events
389 */
390 if (msglen > 10 && !memcmp(msg, "set-delay:", 10)) {
391 cl->delay_ms = atoi((const char*)msg+10);
392 if (cl->enabledMask != 0)
393 _hwSensorClient_tick(cl);
394
395 return;
396 }
397
398 /* "set:<name>:<state>" is used to enable/disable a given
399 * sensor. <state> must be 0 or 1
400 */
401 if (msglen > 4 && !memcmp(msg, "set:", 4)) {
402 char* q;
403 int id, enabled, oldEnabledMask = cl->enabledMask;
404 msg += 4;
405 q = strchr((char*)msg, ':');
406 if (q == NULL) { /* should not happen */
407 D("%s: ignore bad 'set' command", __FUNCTION__);
408 return;
409 }
410 *q++ = 0;
411
412 id = _sensorIdFromName((const char*)msg);
413 if (id < 0 || id >= MAX_SENSORS) {
414 D("%s: ignore unknown sensor name '%s'", __FUNCTION__, msg);
415 return;
416 }
417
418 if (!hw->sensors[id].enabled) {
419 D("%s: trying to set disabled %s sensor", __FUNCTION__, msg);
420 return;
421 }
422 enabled = (q[0] == '1');
423
424 if (enabled)
425 cl->enabledMask |= (1 << id);
426 else
427 cl->enabledMask &= ~(1 << id);
428
429 if (cl->enabledMask != oldEnabledMask) {
430 D("%s: %s %s sensor", __FUNCTION__,
431 (cl->enabledMask & (1 << id)) ? "enabling" : "disabling", msg);
432 }
433 _hwSensorClient_tick(cl);
434 return;
435 }
436
437 D("%s: ignoring unknown query", __FUNCTION__);
438}
439
Ot ten Thije871da2a2010-09-20 10:29:22 +0100440/* Saves sensor-specific client data to snapshot */
441static void
442_hwSensorClient_save( QEMUFile* f, QemudClient* client, void* opaque )
443{
444 HwSensorClient* sc = opaque;
445
446 qemu_put_be32(f, sc->delay_ms);
447 qemu_put_be32(f, sc->enabledMask);
448 qemu_put_timer(f, sc->timer);
449}
450
451/* Loads sensor-specific client data from snapshot */
452static int
453_hwSensorClient_load( QEMUFile* f, QemudClient* client, void* opaque )
454{
455 HwSensorClient* sc = opaque;
456
457 sc->delay_ms = qemu_get_be32(f);
458 sc->enabledMask = qemu_get_be32(f);
459 qemu_get_timer(f, sc->timer);
460
461 return 0;
462}
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200463
464static QemudClient*
465_hwSensors_connect( void* opaque, QemudService* service, int channel )
466{
467 HwSensors* sensors = opaque;
468 HwSensorClient* cl = _hwSensorClient_new(sensors);
469 QemudClient* client = qemud_client_new(service, channel, cl,
470 _hwSensorClient_recv,
Ot ten Thije871da2a2010-09-20 10:29:22 +0100471 _hwSensorClient_close,
472 _hwSensorClient_save,
473 _hwSensorClient_load );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700474 qemud_client_set_framing(client, 1);
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200475 cl->client = client;
476
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700477 return client;
478}
479
Tim Wan736e01f2011-01-10 10:58:25 +0100480/* change the value of the emulated sensor vector */
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700481static void
Tim Wan736e01f2011-01-10 10:58:25 +0100482_hwSensors_setSensorValue( HwSensors* h, int sensor_id, float a, float b, float c )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700483{
Tim Wan736e01f2011-01-10 10:58:25 +0100484 Sensor* s = &h->sensors[sensor_id];
485
486 s->u.value.a = a;
487 s->u.value.b = b;
488 s->u.value.c = c;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700489}
490
Ot ten Thije871da2a2010-09-20 10:29:22 +0100491/* Saves available sensors to allow checking availability when loaded.
492 */
493static void
494_hwSensors_save( QEMUFile* f, QemudService* sv, void* opaque)
495{
496 HwSensors* h = opaque;
497
498 // number of sensors
499 qemu_put_be32(f, MAX_SENSORS);
500 AndroidSensor i;
501 for (i = 0 ; i < MAX_SENSORS; i++) {
502 Sensor* s = &h->sensors[i];
503 qemu_put_be32(f, s->enabled);
504
505 /* this switch ensures that a warning is raised when a new sensor is
506 * added and is not added here as well.
507 */
508 switch (i) {
509 case ANDROID_SENSOR_ACCELERATION:
510 qemu_put_float(f, s->u.acceleration.x);
511 qemu_put_float(f, s->u.acceleration.y);
512 qemu_put_float(f, s->u.acceleration.z);
513 break;
514 case ANDROID_SENSOR_MAGNETIC_FIELD:
515 qemu_put_float(f, s->u.magnetic.x);
516 qemu_put_float(f, s->u.magnetic.y);
517 qemu_put_float(f, s->u.magnetic.z);
518 break;
519 case ANDROID_SENSOR_ORIENTATION:
520 qemu_put_float(f, s->u.orientation.azimuth);
521 qemu_put_float(f, s->u.orientation.pitch);
522 qemu_put_float(f, s->u.orientation.roll);
523 break;
524 case ANDROID_SENSOR_TEMPERATURE:
525 qemu_put_float(f, s->u.temperature.celsius);
526 break;
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100527 case ANDROID_SENSOR_PROXIMITY:
528 qemu_put_float(f, s->u.proximity.value);
529 break;
Ot ten Thije871da2a2010-09-20 10:29:22 +0100530 case MAX_SENSORS:
531 break;
532 }
533 }
534}
535
536
537static int
538_hwSensors_load( QEMUFile* f, QemudService* s, void* opaque)
539{
540 HwSensors* h = opaque;
541
542 /* check number of sensors */
543 int32_t num_sensors = qemu_get_be32(f);
David 'Digit' Turner607461d2011-02-24 16:27:48 +0100544 if (num_sensors > MAX_SENSORS) {
Ot ten Thije871da2a2010-09-20 10:29:22 +0100545 D("%s: cannot load: snapshot requires %d sensors, %d available\n",
546 __FUNCTION__, num_sensors, MAX_SENSORS);
547 return -EIO;
548 }
549
550 /* load sensor state */
551 AndroidSensor i;
David 'Digit' Turner607461d2011-02-24 16:27:48 +0100552 for (i = 0 ; i < num_sensors; i++) {
Ot ten Thije871da2a2010-09-20 10:29:22 +0100553 Sensor* s = &h->sensors[i];
554 s->enabled = qemu_get_be32(f);
555
556 /* this switch ensures that a warning is raised when a new sensor is
557 * added and is not added here as well.
558 */
559 switch (i) {
560 case ANDROID_SENSOR_ACCELERATION:
561 s->u.acceleration.x = qemu_get_float(f);
562 s->u.acceleration.y = qemu_get_float(f);
563 s->u.acceleration.z = qemu_get_float(f);
564 break;
565 case ANDROID_SENSOR_MAGNETIC_FIELD:
566 s->u.magnetic.x = qemu_get_float(f);
567 s->u.magnetic.y = qemu_get_float(f);
568 s->u.magnetic.z = qemu_get_float(f);
569 break;
570 case ANDROID_SENSOR_ORIENTATION:
571 s->u.orientation.azimuth = qemu_get_float(f);
572 s->u.orientation.pitch = qemu_get_float(f);
573 s->u.orientation.roll = qemu_get_float(f);
574 break;
575 case ANDROID_SENSOR_TEMPERATURE:
576 s->u.temperature.celsius = qemu_get_float(f);
577 break;
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100578 case ANDROID_SENSOR_PROXIMITY:
579 s->u.proximity.value = qemu_get_float(f);
580 break;
Ot ten Thije871da2a2010-09-20 10:29:22 +0100581 case MAX_SENSORS:
582 break;
583 }
584 }
585
David 'Digit' Turner607461d2011-02-24 16:27:48 +0100586 /* The following is necessary when we resume a snaphost
587 * created by an older version of the emulator that provided
588 * less hardware sensors.
589 */
590 for ( ; i < MAX_SENSORS; i++ ) {
591 h->sensors[i].enabled = 0;
592 }
593
Ot ten Thije871da2a2010-09-20 10:29:22 +0100594 return 0;
595}
596
597
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100598/* change the emulated proximity */
599static void
600_hwSensors_setProximity( HwSensors* h, float value )
601{
602 Sensor* s = &h->sensors[ANDROID_SENSOR_PROXIMITY];
603 s->u.proximity.value = value;
604}
605
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700606/* change the coarse orientation (landscape/portrait) of the emulated device */
607static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200608_hwSensors_setCoarseOrientation( HwSensors* h, AndroidCoarseOrientation orient )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700609{
610 /* The Android framework computes the orientation by looking at
611 * the accelerometer sensor (*not* the orientation sensor !)
612 *
613 * That's because the gravity is a constant 9.81 vector that
614 * can be determined quite easily.
615 *
616 * Also, for some reason, the framework code considers that the phone should
617 * be inclined by 30 degrees along the phone's X axis to be considered
618 * in its ideal "vertical" position
619 *
620 * If the phone is completely vertical, rotating it will not do anything !
621 */
622 const double g = 9.81;
David 'Digit' Turner593d0ea2011-02-15 03:02:34 +0100623 const double angle = 20.0;
624 const double cos_angle = cos(angle/M_PI);
625 const double sin_angle = sin(angle/M_PI);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700626
627 switch (orient) {
628 case ANDROID_COARSE_PORTRAIT:
Tim Wan736e01f2011-01-10 10:58:25 +0100629 _hwSensors_setSensorValue( h, ANDROID_SENSOR_ACCELERATION, 0., g*cos_angle, g*sin_angle );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700630 break;
631
632 case ANDROID_COARSE_LANDSCAPE:
Tim Wan736e01f2011-01-10 10:58:25 +0100633 _hwSensors_setSensorValue( h, ANDROID_SENSOR_ACCELERATION, g*cos_angle, 0., g*sin_angle );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700634 break;
635 default:
636 ;
637 }
638}
639
640
641/* initialize the sensors state */
642static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200643_hwSensors_init( HwSensors* h )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700644{
Ot ten Thije871da2a2010-09-20 10:29:22 +0100645 h->service = qemud_service_register("sensors", 0, h, _hwSensors_connect,
646 _hwSensors_save, _hwSensors_load);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700647
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200648 if (android_hw->hw_accelerometer)
649 h->sensors[ANDROID_SENSOR_ACCELERATION].enabled = 1;
650
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100651 if (android_hw->hw_sensors_proximity)
652 h->sensors[ANDROID_SENSOR_PROXIMITY].enabled = 1;
653
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200654 /* XXX: TODO: Add other tests when we add the corresponding
655 * properties to hardware-properties.ini et al. */
656
657 _hwSensors_setCoarseOrientation(h, ANDROID_COARSE_PORTRAIT);
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100658 _hwSensors_setProximity(h, 1);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700659}
660
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700661static HwSensors _sensorsState[1];
662
663void
664android_hw_sensors_init( void )
665{
666 HwSensors* hw = _sensorsState;
667
668 if (hw->service == NULL) {
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200669 _hwSensors_init(hw);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700670 D("%s: sensors qemud service initialized", __FUNCTION__);
671 }
672}
673
674/* change the coarse orientation value */
675extern void
676android_sensors_set_coarse_orientation( AndroidCoarseOrientation orient )
677{
678 android_hw_sensors_init();
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200679 _hwSensors_setCoarseOrientation(_sensorsState, orient);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700680}
681
Tim Wan736e01f2011-01-10 10:58:25 +0100682/* Get sensor name from sensor id */
683extern const char*
684android_sensors_get_name_from_id( int sensor_id )
685{
686 if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
687 return NULL;
688
689 return _sensorNameFromId(sensor_id);
690}
691
692/* Get sensor id from sensor name */
693extern int
694android_sensors_get_id_from_name( char* sensorname )
695{
696 HwSensors* hw = _sensorsState;
697
698 if (sensorname == NULL)
699 return SENSOR_STATUS_UNKNOWN;
700
701 int id = _sensorIdFromName(sensorname);
702
703 if (id < 0 || id >= MAX_SENSORS)
704 return SENSOR_STATUS_UNKNOWN;
705
706 if (hw->service != NULL) {
707 if (! hw->sensors[id].enabled)
708 return SENSOR_STATUS_DISABLED;
709 } else
710 return SENSOR_STATUS_NO_SERVICE;
711
712 return id;
713}
714
715/* Interface of reading the data for all sensors */
716extern int
717android_sensors_get( int sensor_id, float* a, float* b, float* c )
718{
719 HwSensors* hw = _sensorsState;
720
721 *a = 0;
722 *b = 0;
723 *c = 0;
724
725 if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
726 return SENSOR_STATUS_UNKNOWN;
727
728 Sensor* sensor = &hw->sensors[sensor_id];
729 if (hw->service != NULL) {
730 if (! sensor->enabled)
731 return SENSOR_STATUS_DISABLED;
732 } else
733 return SENSOR_STATUS_NO_SERVICE;
734
735 *a = sensor->u.value.a;
736 *b = sensor->u.value.b;
737 *c = sensor->u.value.c;
738
739 return SENSOR_STATUS_OK;
740}
741
742/* Interface of setting the data for all sensors */
743extern int
744android_sensors_set( int sensor_id, float a, float b, float c )
745{
746 HwSensors* hw = _sensorsState;
747
748 if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
749 return SENSOR_STATUS_UNKNOWN;
750
751 if (hw->service != NULL) {
752 if (! hw->sensors[sensor_id].enabled)
753 return SENSOR_STATUS_DISABLED;
754 } else
755 return SENSOR_STATUS_NO_SERVICE;
756
757 _hwSensors_setSensorValue(hw, sensor_id, a, b, c);
758
759 return SENSOR_STATUS_OK;
760}
761
762/* Get Sensor from sensor id */
763extern uint8_t
764android_sensors_get_sensor_status( int sensor_id )
765{
766 HwSensors* hw = _sensorsState;
767
768 if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
769 return SENSOR_STATUS_UNKNOWN;
770
771 return hw->sensors[sensor_id].enabled;
772}