blob: 9c391965365497e570f83d0145c18e06f2322250 [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*
Vladimir Chtchetkine4c414822011-08-20 08:55:37 -0700465_hwSensors_connect( void* opaque,
466 QemudService* service,
467 int channel,
468 const char* client_param )
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200469{
470 HwSensors* sensors = opaque;
471 HwSensorClient* cl = _hwSensorClient_new(sensors);
Vladimir Chtchetkine4c414822011-08-20 08:55:37 -0700472 QemudClient* client = qemud_client_new(service, channel, client_param, cl,
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200473 _hwSensorClient_recv,
Ot ten Thije871da2a2010-09-20 10:29:22 +0100474 _hwSensorClient_close,
475 _hwSensorClient_save,
476 _hwSensorClient_load );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700477 qemud_client_set_framing(client, 1);
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200478 cl->client = client;
479
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700480 return client;
481}
482
Tim Wan736e01f2011-01-10 10:58:25 +0100483/* change the value of the emulated sensor vector */
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700484static void
Tim Wan736e01f2011-01-10 10:58:25 +0100485_hwSensors_setSensorValue( HwSensors* h, int sensor_id, float a, float b, float c )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700486{
Tim Wan736e01f2011-01-10 10:58:25 +0100487 Sensor* s = &h->sensors[sensor_id];
488
489 s->u.value.a = a;
490 s->u.value.b = b;
491 s->u.value.c = c;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700492}
493
Ot ten Thije871da2a2010-09-20 10:29:22 +0100494/* Saves available sensors to allow checking availability when loaded.
495 */
496static void
497_hwSensors_save( QEMUFile* f, QemudService* sv, void* opaque)
498{
499 HwSensors* h = opaque;
500
501 // number of sensors
502 qemu_put_be32(f, MAX_SENSORS);
503 AndroidSensor i;
504 for (i = 0 ; i < MAX_SENSORS; i++) {
505 Sensor* s = &h->sensors[i];
506 qemu_put_be32(f, s->enabled);
507
508 /* this switch ensures that a warning is raised when a new sensor is
509 * added and is not added here as well.
510 */
511 switch (i) {
512 case ANDROID_SENSOR_ACCELERATION:
513 qemu_put_float(f, s->u.acceleration.x);
514 qemu_put_float(f, s->u.acceleration.y);
515 qemu_put_float(f, s->u.acceleration.z);
516 break;
517 case ANDROID_SENSOR_MAGNETIC_FIELD:
518 qemu_put_float(f, s->u.magnetic.x);
519 qemu_put_float(f, s->u.magnetic.y);
520 qemu_put_float(f, s->u.magnetic.z);
521 break;
522 case ANDROID_SENSOR_ORIENTATION:
523 qemu_put_float(f, s->u.orientation.azimuth);
524 qemu_put_float(f, s->u.orientation.pitch);
525 qemu_put_float(f, s->u.orientation.roll);
526 break;
527 case ANDROID_SENSOR_TEMPERATURE:
528 qemu_put_float(f, s->u.temperature.celsius);
529 break;
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100530 case ANDROID_SENSOR_PROXIMITY:
531 qemu_put_float(f, s->u.proximity.value);
532 break;
Ot ten Thije871da2a2010-09-20 10:29:22 +0100533 case MAX_SENSORS:
534 break;
535 }
536 }
537}
538
539
540static int
541_hwSensors_load( QEMUFile* f, QemudService* s, void* opaque)
542{
543 HwSensors* h = opaque;
544
545 /* check number of sensors */
546 int32_t num_sensors = qemu_get_be32(f);
David 'Digit' Turner607461d2011-02-24 16:27:48 +0100547 if (num_sensors > MAX_SENSORS) {
Ot ten Thije871da2a2010-09-20 10:29:22 +0100548 D("%s: cannot load: snapshot requires %d sensors, %d available\n",
549 __FUNCTION__, num_sensors, MAX_SENSORS);
550 return -EIO;
551 }
552
553 /* load sensor state */
554 AndroidSensor i;
David 'Digit' Turner607461d2011-02-24 16:27:48 +0100555 for (i = 0 ; i < num_sensors; i++) {
Ot ten Thije871da2a2010-09-20 10:29:22 +0100556 Sensor* s = &h->sensors[i];
557 s->enabled = qemu_get_be32(f);
558
559 /* this switch ensures that a warning is raised when a new sensor is
560 * added and is not added here as well.
561 */
562 switch (i) {
563 case ANDROID_SENSOR_ACCELERATION:
564 s->u.acceleration.x = qemu_get_float(f);
565 s->u.acceleration.y = qemu_get_float(f);
566 s->u.acceleration.z = qemu_get_float(f);
567 break;
568 case ANDROID_SENSOR_MAGNETIC_FIELD:
569 s->u.magnetic.x = qemu_get_float(f);
570 s->u.magnetic.y = qemu_get_float(f);
571 s->u.magnetic.z = qemu_get_float(f);
572 break;
573 case ANDROID_SENSOR_ORIENTATION:
574 s->u.orientation.azimuth = qemu_get_float(f);
575 s->u.orientation.pitch = qemu_get_float(f);
576 s->u.orientation.roll = qemu_get_float(f);
577 break;
578 case ANDROID_SENSOR_TEMPERATURE:
579 s->u.temperature.celsius = qemu_get_float(f);
580 break;
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100581 case ANDROID_SENSOR_PROXIMITY:
582 s->u.proximity.value = qemu_get_float(f);
583 break;
Ot ten Thije871da2a2010-09-20 10:29:22 +0100584 case MAX_SENSORS:
585 break;
586 }
587 }
588
David 'Digit' Turner607461d2011-02-24 16:27:48 +0100589 /* The following is necessary when we resume a snaphost
590 * created by an older version of the emulator that provided
591 * less hardware sensors.
592 */
593 for ( ; i < MAX_SENSORS; i++ ) {
594 h->sensors[i].enabled = 0;
595 }
596
Ot ten Thije871da2a2010-09-20 10:29:22 +0100597 return 0;
598}
599
600
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100601/* change the emulated proximity */
602static void
603_hwSensors_setProximity( HwSensors* h, float value )
604{
605 Sensor* s = &h->sensors[ANDROID_SENSOR_PROXIMITY];
606 s->u.proximity.value = value;
607}
608
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700609/* change the coarse orientation (landscape/portrait) of the emulated device */
610static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200611_hwSensors_setCoarseOrientation( HwSensors* h, AndroidCoarseOrientation orient )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700612{
613 /* The Android framework computes the orientation by looking at
614 * the accelerometer sensor (*not* the orientation sensor !)
615 *
616 * That's because the gravity is a constant 9.81 vector that
617 * can be determined quite easily.
618 *
619 * Also, for some reason, the framework code considers that the phone should
620 * be inclined by 30 degrees along the phone's X axis to be considered
621 * in its ideal "vertical" position
622 *
623 * If the phone is completely vertical, rotating it will not do anything !
624 */
625 const double g = 9.81;
David 'Digit' Turner593d0ea2011-02-15 03:02:34 +0100626 const double angle = 20.0;
627 const double cos_angle = cos(angle/M_PI);
628 const double sin_angle = sin(angle/M_PI);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700629
630 switch (orient) {
631 case ANDROID_COARSE_PORTRAIT:
Tim Wan736e01f2011-01-10 10:58:25 +0100632 _hwSensors_setSensorValue( h, ANDROID_SENSOR_ACCELERATION, 0., g*cos_angle, g*sin_angle );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700633 break;
634
635 case ANDROID_COARSE_LANDSCAPE:
Tim Wan736e01f2011-01-10 10:58:25 +0100636 _hwSensors_setSensorValue( h, ANDROID_SENSOR_ACCELERATION, g*cos_angle, 0., g*sin_angle );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700637 break;
638 default:
639 ;
640 }
641}
642
643
644/* initialize the sensors state */
645static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200646_hwSensors_init( HwSensors* h )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700647{
Ot ten Thije871da2a2010-09-20 10:29:22 +0100648 h->service = qemud_service_register("sensors", 0, h, _hwSensors_connect,
649 _hwSensors_save, _hwSensors_load);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700650
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200651 if (android_hw->hw_accelerometer)
652 h->sensors[ANDROID_SENSOR_ACCELERATION].enabled = 1;
653
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100654 if (android_hw->hw_sensors_proximity)
655 h->sensors[ANDROID_SENSOR_PROXIMITY].enabled = 1;
656
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200657 /* XXX: TODO: Add other tests when we add the corresponding
658 * properties to hardware-properties.ini et al. */
659
660 _hwSensors_setCoarseOrientation(h, ANDROID_COARSE_PORTRAIT);
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100661 _hwSensors_setProximity(h, 1);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700662}
663
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700664static HwSensors _sensorsState[1];
665
666void
667android_hw_sensors_init( void )
668{
669 HwSensors* hw = _sensorsState;
670
671 if (hw->service == NULL) {
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200672 _hwSensors_init(hw);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700673 D("%s: sensors qemud service initialized", __FUNCTION__);
674 }
675}
676
677/* change the coarse orientation value */
678extern void
679android_sensors_set_coarse_orientation( AndroidCoarseOrientation orient )
680{
681 android_hw_sensors_init();
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200682 _hwSensors_setCoarseOrientation(_sensorsState, orient);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700683}
684
Tim Wan736e01f2011-01-10 10:58:25 +0100685/* Get sensor name from sensor id */
686extern const char*
687android_sensors_get_name_from_id( int sensor_id )
688{
689 if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
690 return NULL;
691
692 return _sensorNameFromId(sensor_id);
693}
694
695/* Get sensor id from sensor name */
696extern int
697android_sensors_get_id_from_name( char* sensorname )
698{
699 HwSensors* hw = _sensorsState;
700
701 if (sensorname == NULL)
702 return SENSOR_STATUS_UNKNOWN;
703
704 int id = _sensorIdFromName(sensorname);
705
706 if (id < 0 || id >= MAX_SENSORS)
707 return SENSOR_STATUS_UNKNOWN;
708
709 if (hw->service != NULL) {
710 if (! hw->sensors[id].enabled)
711 return SENSOR_STATUS_DISABLED;
712 } else
713 return SENSOR_STATUS_NO_SERVICE;
714
715 return id;
716}
717
718/* Interface of reading the data for all sensors */
719extern int
720android_sensors_get( int sensor_id, float* a, float* b, float* c )
721{
722 HwSensors* hw = _sensorsState;
723
724 *a = 0;
725 *b = 0;
726 *c = 0;
727
728 if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
729 return SENSOR_STATUS_UNKNOWN;
730
731 Sensor* sensor = &hw->sensors[sensor_id];
732 if (hw->service != NULL) {
733 if (! sensor->enabled)
734 return SENSOR_STATUS_DISABLED;
735 } else
736 return SENSOR_STATUS_NO_SERVICE;
737
738 *a = sensor->u.value.a;
739 *b = sensor->u.value.b;
740 *c = sensor->u.value.c;
741
742 return SENSOR_STATUS_OK;
743}
744
745/* Interface of setting the data for all sensors */
746extern int
747android_sensors_set( int sensor_id, float a, float b, float c )
748{
749 HwSensors* hw = _sensorsState;
750
751 if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
752 return SENSOR_STATUS_UNKNOWN;
753
754 if (hw->service != NULL) {
755 if (! hw->sensors[sensor_id].enabled)
756 return SENSOR_STATUS_DISABLED;
757 } else
758 return SENSOR_STATUS_NO_SERVICE;
759
760 _hwSensors_setSensorValue(hw, sensor_id, a, b, c);
761
762 return SENSOR_STATUS_OK;
763}
764
765/* Get Sensor from sensor id */
766extern uint8_t
767android_sensors_get_sensor_status( int sensor_id )
768{
769 HwSensors* hw = _sensorsState;
770
771 if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
772 return SENSOR_STATUS_UNKNOWN;
773
774 return hw->sensors[sensor_id].enabled;
775}