blob: f0d82b12a4820d3fe722f21bbd17e74bc3b585fc [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"
David 'Digit' Turner7a78db72013-12-14 11:46:01 +010022#include "qemu/timer.h"
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -070023#include "android/sensors-port.h"
The Android Open Source Project9877e2e2009-03-18 17:39:44 -070024
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -070025#define E(...) derror(__VA_ARGS__)
26#define W(...) dwarning(__VA_ARGS__)
The Android Open Source Project9877e2e2009-03-18 17:39:44 -070027#define D(...) VERBOSE_PRINT(sensors,__VA_ARGS__)
Vladimir Chtchetkinebc456c52012-01-10 13:56:08 -080028#define V(...) VERBOSE_PRINT(init,__VA_ARGS__)
The Android Open Source Project9877e2e2009-03-18 17:39:44 -070029
30/* define T_ACTIVE to 1 to debug transport communications */
31#define T_ACTIVE 0
32
33#if T_ACTIVE
34#define T(...) VERBOSE_PRINT(sensors,__VA_ARGS__)
35#else
36#define T(...) ((void)0)
37#endif
38
39/* this code supports emulated sensor hardware
40 *
41 * Note that currently, only the accelerometer is really emulated, and only
42 * for the purpose of allowing auto-rotating the screen in keyboard-less
43 * configurations.
44 *
45 *
46 */
47
48
49static const struct {
50 const char* name;
51 int id;
52} _sSensors[MAX_SENSORS] = {
53#define SENSOR_(x,y) { y, ANDROID_SENSOR_##x },
54 SENSORS_LIST
55#undef SENSOR_
56};
57
58
59static int
60_sensorIdFromName( const char* name )
61{
62 int nn;
63 for (nn = 0; nn < MAX_SENSORS; nn++)
64 if (!strcmp(_sSensors[nn].name,name))
65 return _sSensors[nn].id;
66 return -1;
67}
68
Tim Wan736e01f2011-01-10 10:58:25 +010069static const char*
70_sensorNameFromId( int id )
71{
72 int nn;
73 for (nn = 0; nn < MAX_SENSORS; nn++)
74 if (id == _sSensors[nn].id)
75 return _sSensors[nn].name;
76 return NULL;
77}
78
79/* For common Sensor Value struct */
80typedef struct {
81 float a, b, c;
82} SensorValues;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -070083
84typedef struct {
85 float x, y, z;
86} Acceleration;
87
88
89typedef struct {
90 float x, y, z;
91} MagneticField;
92
93
94typedef struct {
95 float azimuth;
96 float pitch;
97 float roll;
98} Orientation;
99
100
101typedef struct {
102 float celsius;
103} Temperature;
104
105
106typedef struct {
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100107 float value;
108} Proximity;
109
110typedef struct {
111 char enabled;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700112 union {
Tim Wan736e01f2011-01-10 10:58:25 +0100113 SensorValues value;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700114 Acceleration acceleration;
115 MagneticField magnetic;
116 Orientation orientation;
117 Temperature temperature;
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100118 Proximity proximity;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700119 } u;
120} Sensor;
121
122/*
123 * - when the qemu-specific sensors HAL module starts, it sends
124 * "list-sensors"
125 *
126 * - this code replies with a string containing an integer corresponding
127 * to a bitmap of available hardware sensors in the current AVD
128 * configuration (e.g. "1" a.k.a (1 << ANDROID_SENSOR_ACCELERATION))
129 *
130 * - the HAL module sends "set:<sensor>:<flag>" to enable or disable
131 * the report of a given sensor state. <sensor> must be the name of
132 * a given sensor (e.g. "accelerometer"), and <flag> must be either
133 * "1" (to enable) or "0" (to disable).
134 *
135 * - Once at least one sensor is "enabled", this code should periodically
136 * send information about the corresponding enabled sensors. The default
137 * period is 200ms.
138 *
139 * - the HAL module sends "set-delay:<delay>", where <delay> is an integer
140 * corresponding to a time delay in milli-seconds. This corresponds to
141 * a new interval between sensor events sent by this code to the HAL
142 * module.
143 *
144 * - the HAL module can also send a "wake" command. This code should simply
145 * send the "wake" back to the module. This is used internally to wake a
146 * blocking read that happens in a different thread. This ping-pong makes
147 * the code in the HAL module very simple.
148 *
149 * - each timer tick, this code sends sensor reports in the following
150 * format (each line corresponds to a different line sent to the module):
151 *
152 * acceleration:<x>:<y>:<z>
153 * magnetic-field:<x>:<y>:<z>
154 * orientation:<azimuth>:<pitch>:<roll>
155 * temperature:<celsius>
156 * sync:<time_us>
157 *
158 * Where each line before the sync:<time_us> is optional and will only
159 * appear if the corresponding sensor has been enabled by the HAL module.
160 *
161 * Note that <time_us> is the VM time in micro-seconds when the report
162 * was "taken" by this code. This is adjusted by the HAL module to
163 * emulated system time (using the first sync: to compute an adjustment
164 * offset).
165 */
166#define HEADER_SIZE 4
167#define BUFFER_SIZE 512
168
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200169typedef struct HwSensorClient HwSensorClient;
170
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700171typedef struct {
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700172 QemudService* service;
173 Sensor sensors[MAX_SENSORS];
174 HwSensorClient* clients;
175 AndroidSensorsPort* sensors_port;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700176} HwSensors;
177
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200178struct HwSensorClient {
179 HwSensorClient* next;
180 HwSensors* sensors;
181 QemudClient* client;
182 QEMUTimer* timer;
183 uint32_t enabledMask;
184 int32_t delay_ms;
185};
186
187static void
188_hwSensorClient_free( HwSensorClient* cl )
189{
190 /* remove from sensors's list */
191 if (cl->sensors) {
192 HwSensorClient** pnode = &cl->sensors->clients;
193 for (;;) {
194 HwSensorClient* node = *pnode;
195 if (node == NULL)
196 break;
197 if (node == cl) {
198 *pnode = cl->next;
199 break;
200 }
201 pnode = &node->next;
202 }
203 cl->next = NULL;
204 cl->sensors = NULL;
205 }
206
207 /* close QEMUD client, if any */
208 if (cl->client) {
209 qemud_client_close(cl->client);
210 cl->client = NULL;
211 }
212 /* remove timer, if any */
213 if (cl->timer) {
214 qemu_del_timer(cl->timer);
215 qemu_free_timer(cl->timer);
216 cl->timer = NULL;
217 }
218 AFREE(cl);
219}
220
221/* forward */
222static void _hwSensorClient_tick(void* opaque);
223
224
225static HwSensorClient*
226_hwSensorClient_new( HwSensors* sensors )
227{
228 HwSensorClient* cl;
229
230 ANEW0(cl);
231
232 cl->sensors = sensors;
233 cl->enabledMask = 0;
David 'Digit' Turner593d0ea2011-02-15 03:02:34 +0100234 cl->delay_ms = 800;
David 'Digit' Turner5973c772011-05-10 07:06:00 +0200235 cl->timer = qemu_new_timer_ns(vm_clock, _hwSensorClient_tick, cl);
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200236
237 cl->next = sensors->clients;
238 sensors->clients = cl;
239
240 return cl;
241}
242
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700243/* forward */
244
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200245static void _hwSensorClient_receive( HwSensorClient* cl,
246 uint8_t* query,
247 int querylen );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700248
249/* Qemud service management */
250
251static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200252_hwSensorClient_recv( void* opaque, uint8_t* msg, int msglen,
253 QemudClient* client )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700254{
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200255 HwSensorClient* cl = opaque;
256
257 _hwSensorClient_receive(cl, msg, msglen);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700258}
259
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200260static void
261_hwSensorClient_close( void* opaque )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700262{
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200263 HwSensorClient* cl = opaque;
264
265 /* the client is already closed here */
266 cl->client = NULL;
267 _hwSensorClient_free(cl);
268}
269
270/* send a one-line message to the HAL module through a qemud channel */
271static void
272_hwSensorClient_send( HwSensorClient* cl, const uint8_t* msg, int msglen )
273{
274 D("%s: '%s'", __FUNCTION__, quote_bytes((const void*)msg, msglen));
275 qemud_client_send(cl->client, msg, msglen);
276}
277
278static int
279_hwSensorClient_enabled( HwSensorClient* cl, int sensorId )
280{
281 return (cl->enabledMask & (1 << sensorId)) != 0;
282}
283
284/* this function is called periodically to send sensor reports
285 * to the HAL module, and re-arm the timer if necessary
286 */
287static void
288_hwSensorClient_tick( void* opaque )
289{
290 HwSensorClient* cl = opaque;
291 HwSensors* hw = cl->sensors;
292 int64_t delay = cl->delay_ms;
293 int64_t now_ns;
294 uint32_t mask = cl->enabledMask;
295 Sensor* sensor;
296 char buffer[128];
297
298 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_ACCELERATION)) {
299 sensor = &hw->sensors[ANDROID_SENSOR_ACCELERATION];
300 snprintf(buffer, sizeof buffer, "acceleration:%g:%g:%g",
301 sensor->u.acceleration.x,
302 sensor->u.acceleration.y,
303 sensor->u.acceleration.z);
304 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
305 }
306
307 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_MAGNETIC_FIELD)) {
308 sensor = &hw->sensors[ANDROID_SENSOR_MAGNETIC_FIELD];
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700309 /* NOTE: sensors HAL expects "magnetic", not "magnetic-field" name here. */
310 snprintf(buffer, sizeof buffer, "magnetic:%g:%g:%g",
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200311 sensor->u.magnetic.x,
312 sensor->u.magnetic.y,
313 sensor->u.magnetic.z);
314 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
315 }
316
317 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_ORIENTATION)) {
318 sensor = &hw->sensors[ANDROID_SENSOR_ORIENTATION];
319 snprintf(buffer, sizeof buffer, "orientation:%g:%g:%g",
320 sensor->u.orientation.azimuth,
321 sensor->u.orientation.pitch,
322 sensor->u.orientation.roll);
323 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
324 }
325
326 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_TEMPERATURE)) {
327 sensor = &hw->sensors[ANDROID_SENSOR_TEMPERATURE];
328 snprintf(buffer, sizeof buffer, "temperature:%g",
329 sensor->u.temperature.celsius);
330 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
331 }
332
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100333 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_PROXIMITY)) {
334 sensor = &hw->sensors[ANDROID_SENSOR_PROXIMITY];
335 snprintf(buffer, sizeof buffer, "proximity:%g",
336 sensor->u.proximity.value);
337 _hwSensorClient_send(cl, (uint8_t*) buffer, strlen(buffer));
338 }
339
David 'Digit' Turner5973c772011-05-10 07:06:00 +0200340 now_ns = qemu_get_clock_ns(vm_clock);
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200341
Andrew Hsiehc7389bd2012-03-13 02:13:40 -0700342 snprintf(buffer, sizeof buffer, "sync:%" PRId64, now_ns/1000);
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200343 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
344
345 /* rearm timer, use a minimum delay of 20 ms, just to
346 * be safe.
347 */
348 if (mask == 0)
349 return;
350
351 if (delay < 20)
352 delay = 20;
353
354 delay *= 1000000LL; /* convert to nanoseconds */
355 qemu_mod_timer(cl->timer, now_ns + delay);
356}
357
358/* handle incoming messages from the HAL module */
359static void
360_hwSensorClient_receive( HwSensorClient* cl, uint8_t* msg, int msglen )
361{
362 HwSensors* hw = cl->sensors;
363
364 D("%s: '%.*s'", __FUNCTION__, msglen, msg);
365
366 /* "list-sensors" is used to get an integer bit map of
367 * available emulated sensors. We compute the mask from the
368 * current hardware configuration.
369 */
370 if (msglen == 12 && !memcmp(msg, "list-sensors", 12)) {
371 char buff[12];
372 int mask = 0;
373 int nn;
374
375 for (nn = 0; nn < MAX_SENSORS; nn++) {
376 if (hw->sensors[nn].enabled)
377 mask |= (1 << nn);
378 }
379
380 snprintf(buff, sizeof buff, "%d", mask);
381 _hwSensorClient_send(cl, (const uint8_t*)buff, strlen(buff));
382 return;
383 }
384
385 /* "wake" is a special message that must be sent back through
386 * the channel. It is used to exit a blocking read.
387 */
388 if (msglen == 4 && !memcmp(msg, "wake", 4)) {
389 _hwSensorClient_send(cl, (const uint8_t*)"wake", 4);
390 return;
391 }
392
393 /* "set-delay:<delay>" is used to set the delay in milliseconds
394 * between sensor events
395 */
396 if (msglen > 10 && !memcmp(msg, "set-delay:", 10)) {
397 cl->delay_ms = atoi((const char*)msg+10);
398 if (cl->enabledMask != 0)
399 _hwSensorClient_tick(cl);
400
401 return;
402 }
403
404 /* "set:<name>:<state>" is used to enable/disable a given
405 * sensor. <state> must be 0 or 1
406 */
407 if (msglen > 4 && !memcmp(msg, "set:", 4)) {
408 char* q;
409 int id, enabled, oldEnabledMask = cl->enabledMask;
410 msg += 4;
411 q = strchr((char*)msg, ':');
412 if (q == NULL) { /* should not happen */
413 D("%s: ignore bad 'set' command", __FUNCTION__);
414 return;
415 }
416 *q++ = 0;
417
418 id = _sensorIdFromName((const char*)msg);
419 if (id < 0 || id >= MAX_SENSORS) {
420 D("%s: ignore unknown sensor name '%s'", __FUNCTION__, msg);
421 return;
422 }
423
424 if (!hw->sensors[id].enabled) {
425 D("%s: trying to set disabled %s sensor", __FUNCTION__, msg);
426 return;
427 }
428 enabled = (q[0] == '1');
429
430 if (enabled)
431 cl->enabledMask |= (1 << id);
432 else
433 cl->enabledMask &= ~(1 << id);
434
435 if (cl->enabledMask != oldEnabledMask) {
436 D("%s: %s %s sensor", __FUNCTION__,
437 (cl->enabledMask & (1 << id)) ? "enabling" : "disabling", msg);
438 }
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700439
440 /* If emulating device is connected update sensor state there too. */
Vladimir Chtchetkine7136b052012-04-10 13:39:24 -0700441 if (hw->sensors_port != NULL) {
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700442 if (enabled) {
443 sensors_port_enable_sensor(hw->sensors_port, (const char*)msg);
444 } else {
445 sensors_port_disable_sensor(hw->sensors_port, (const char*)msg);
446 }
447 }
448
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200449 _hwSensorClient_tick(cl);
450 return;
451 }
452
453 D("%s: ignoring unknown query", __FUNCTION__);
454}
455
Ot ten Thije871da2a2010-09-20 10:29:22 +0100456/* Saves sensor-specific client data to snapshot */
457static void
458_hwSensorClient_save( QEMUFile* f, QemudClient* client, void* opaque )
459{
460 HwSensorClient* sc = opaque;
461
462 qemu_put_be32(f, sc->delay_ms);
463 qemu_put_be32(f, sc->enabledMask);
464 qemu_put_timer(f, sc->timer);
465}
466
467/* Loads sensor-specific client data from snapshot */
468static int
469_hwSensorClient_load( QEMUFile* f, QemudClient* client, void* opaque )
470{
471 HwSensorClient* sc = opaque;
472
473 sc->delay_ms = qemu_get_be32(f);
474 sc->enabledMask = qemu_get_be32(f);
475 qemu_get_timer(f, sc->timer);
476
477 return 0;
478}
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200479
480static QemudClient*
Vladimir Chtchetkine4c414822011-08-20 08:55:37 -0700481_hwSensors_connect( void* opaque,
482 QemudService* service,
483 int channel,
484 const char* client_param )
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200485{
486 HwSensors* sensors = opaque;
487 HwSensorClient* cl = _hwSensorClient_new(sensors);
Vladimir Chtchetkine4c414822011-08-20 08:55:37 -0700488 QemudClient* client = qemud_client_new(service, channel, client_param, cl,
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200489 _hwSensorClient_recv,
Ot ten Thije871da2a2010-09-20 10:29:22 +0100490 _hwSensorClient_close,
491 _hwSensorClient_save,
492 _hwSensorClient_load );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700493 qemud_client_set_framing(client, 1);
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200494 cl->client = client;
495
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700496 return client;
497}
498
Tim Wan736e01f2011-01-10 10:58:25 +0100499/* change the value of the emulated sensor vector */
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700500static void
Tim Wan736e01f2011-01-10 10:58:25 +0100501_hwSensors_setSensorValue( HwSensors* h, int sensor_id, float a, float b, float c )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700502{
Tim Wan736e01f2011-01-10 10:58:25 +0100503 Sensor* s = &h->sensors[sensor_id];
504
505 s->u.value.a = a;
506 s->u.value.b = b;
507 s->u.value.c = c;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700508}
509
Ot ten Thije871da2a2010-09-20 10:29:22 +0100510/* Saves available sensors to allow checking availability when loaded.
511 */
512static void
513_hwSensors_save( QEMUFile* f, QemudService* sv, void* opaque)
514{
515 HwSensors* h = opaque;
516
517 // number of sensors
518 qemu_put_be32(f, MAX_SENSORS);
519 AndroidSensor i;
520 for (i = 0 ; i < MAX_SENSORS; i++) {
521 Sensor* s = &h->sensors[i];
522 qemu_put_be32(f, s->enabled);
523
524 /* this switch ensures that a warning is raised when a new sensor is
525 * added and is not added here as well.
526 */
527 switch (i) {
528 case ANDROID_SENSOR_ACCELERATION:
529 qemu_put_float(f, s->u.acceleration.x);
530 qemu_put_float(f, s->u.acceleration.y);
531 qemu_put_float(f, s->u.acceleration.z);
532 break;
533 case ANDROID_SENSOR_MAGNETIC_FIELD:
534 qemu_put_float(f, s->u.magnetic.x);
535 qemu_put_float(f, s->u.magnetic.y);
536 qemu_put_float(f, s->u.magnetic.z);
537 break;
538 case ANDROID_SENSOR_ORIENTATION:
539 qemu_put_float(f, s->u.orientation.azimuth);
540 qemu_put_float(f, s->u.orientation.pitch);
541 qemu_put_float(f, s->u.orientation.roll);
542 break;
543 case ANDROID_SENSOR_TEMPERATURE:
544 qemu_put_float(f, s->u.temperature.celsius);
545 break;
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100546 case ANDROID_SENSOR_PROXIMITY:
547 qemu_put_float(f, s->u.proximity.value);
548 break;
Ot ten Thije871da2a2010-09-20 10:29:22 +0100549 case MAX_SENSORS:
550 break;
551 }
552 }
553}
554
555
556static int
557_hwSensors_load( QEMUFile* f, QemudService* s, void* opaque)
558{
559 HwSensors* h = opaque;
560
561 /* check number of sensors */
562 int32_t num_sensors = qemu_get_be32(f);
David 'Digit' Turner607461d2011-02-24 16:27:48 +0100563 if (num_sensors > MAX_SENSORS) {
Ot ten Thije871da2a2010-09-20 10:29:22 +0100564 D("%s: cannot load: snapshot requires %d sensors, %d available\n",
565 __FUNCTION__, num_sensors, MAX_SENSORS);
566 return -EIO;
567 }
568
569 /* load sensor state */
570 AndroidSensor i;
David 'Digit' Turner607461d2011-02-24 16:27:48 +0100571 for (i = 0 ; i < num_sensors; i++) {
Ot ten Thije871da2a2010-09-20 10:29:22 +0100572 Sensor* s = &h->sensors[i];
573 s->enabled = qemu_get_be32(f);
574
575 /* this switch ensures that a warning is raised when a new sensor is
576 * added and is not added here as well.
577 */
578 switch (i) {
579 case ANDROID_SENSOR_ACCELERATION:
580 s->u.acceleration.x = qemu_get_float(f);
581 s->u.acceleration.y = qemu_get_float(f);
582 s->u.acceleration.z = qemu_get_float(f);
583 break;
584 case ANDROID_SENSOR_MAGNETIC_FIELD:
585 s->u.magnetic.x = qemu_get_float(f);
586 s->u.magnetic.y = qemu_get_float(f);
587 s->u.magnetic.z = qemu_get_float(f);
588 break;
589 case ANDROID_SENSOR_ORIENTATION:
590 s->u.orientation.azimuth = qemu_get_float(f);
591 s->u.orientation.pitch = qemu_get_float(f);
592 s->u.orientation.roll = qemu_get_float(f);
593 break;
594 case ANDROID_SENSOR_TEMPERATURE:
595 s->u.temperature.celsius = qemu_get_float(f);
596 break;
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100597 case ANDROID_SENSOR_PROXIMITY:
598 s->u.proximity.value = qemu_get_float(f);
599 break;
Ot ten Thije871da2a2010-09-20 10:29:22 +0100600 case MAX_SENSORS:
601 break;
602 }
603 }
604
David 'Digit' Turner607461d2011-02-24 16:27:48 +0100605 /* The following is necessary when we resume a snaphost
606 * created by an older version of the emulator that provided
607 * less hardware sensors.
608 */
609 for ( ; i < MAX_SENSORS; i++ ) {
610 h->sensors[i].enabled = 0;
611 }
612
Ot ten Thije871da2a2010-09-20 10:29:22 +0100613 return 0;
614}
615
616
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100617/* change the emulated proximity */
618static void
619_hwSensors_setProximity( HwSensors* h, float value )
620{
621 Sensor* s = &h->sensors[ANDROID_SENSOR_PROXIMITY];
622 s->u.proximity.value = value;
623}
624
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700625/* change the coarse orientation (landscape/portrait) of the emulated device */
626static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200627_hwSensors_setCoarseOrientation( HwSensors* h, AndroidCoarseOrientation orient )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700628{
629 /* The Android framework computes the orientation by looking at
630 * the accelerometer sensor (*not* the orientation sensor !)
631 *
632 * That's because the gravity is a constant 9.81 vector that
633 * can be determined quite easily.
634 *
635 * Also, for some reason, the framework code considers that the phone should
636 * be inclined by 30 degrees along the phone's X axis to be considered
637 * in its ideal "vertical" position
638 *
639 * If the phone is completely vertical, rotating it will not do anything !
640 */
641 const double g = 9.81;
David 'Digit' Turner593d0ea2011-02-15 03:02:34 +0100642 const double angle = 20.0;
643 const double cos_angle = cos(angle/M_PI);
644 const double sin_angle = sin(angle/M_PI);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700645
646 switch (orient) {
647 case ANDROID_COARSE_PORTRAIT:
Tim Wan736e01f2011-01-10 10:58:25 +0100648 _hwSensors_setSensorValue( h, ANDROID_SENSOR_ACCELERATION, 0., g*cos_angle, g*sin_angle );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700649 break;
650
651 case ANDROID_COARSE_LANDSCAPE:
Tim Wan736e01f2011-01-10 10:58:25 +0100652 _hwSensors_setSensorValue( h, ANDROID_SENSOR_ACCELERATION, g*cos_angle, 0., g*sin_angle );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700653 break;
654 default:
655 ;
656 }
657}
658
659
660/* initialize the sensors state */
661static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200662_hwSensors_init( HwSensors* h )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700663{
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700664 /* Try to see if there is a device attached that can be used for
665 * sensor emulation. */
666 h->sensors_port = sensors_port_create(h);
667 if (h->sensors_port == NULL) {
Vladimir Chtchetkinebc456c52012-01-10 13:56:08 -0800668 V("Realistic sensor emulation is not available, since the remote controller is not accessible:\n %s",
669 strerror(errno));
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700670 }
671
Ot ten Thije871da2a2010-09-20 10:29:22 +0100672 h->service = qemud_service_register("sensors", 0, h, _hwSensors_connect,
673 _hwSensors_save, _hwSensors_load);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700674
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700675 if (android_hw->hw_accelerometer) {
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200676 h->sensors[ANDROID_SENSOR_ACCELERATION].enabled = 1;
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700677 }
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200678
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700679 if (android_hw->hw_sensors_proximity) {
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100680 h->sensors[ANDROID_SENSOR_PROXIMITY].enabled = 1;
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700681 }
682
683 if (android_hw->hw_sensors_magnetic_field) {
684 h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD].enabled = 1;
685 }
686
687 if (android_hw->hw_sensors_orientation) {
688 h->sensors[ANDROID_SENSOR_ORIENTATION].enabled = 1;
689 }
690
691 if (android_hw->hw_sensors_temperature) {
692 h->sensors[ANDROID_SENSOR_TEMPERATURE].enabled = 1;
693 }
694
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200695 /* XXX: TODO: Add other tests when we add the corresponding
696 * properties to hardware-properties.ini et al. */
697
698 _hwSensors_setCoarseOrientation(h, ANDROID_COARSE_PORTRAIT);
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100699 _hwSensors_setProximity(h, 1);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700700}
701
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700702static HwSensors _sensorsState[1];
703
704void
705android_hw_sensors_init( void )
706{
707 HwSensors* hw = _sensorsState;
708
709 if (hw->service == NULL) {
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200710 _hwSensors_init(hw);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700711 D("%s: sensors qemud service initialized", __FUNCTION__);
712 }
713}
714
715/* change the coarse orientation value */
716extern void
717android_sensors_set_coarse_orientation( AndroidCoarseOrientation orient )
718{
719 android_hw_sensors_init();
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200720 _hwSensors_setCoarseOrientation(_sensorsState, orient);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700721}
722
Tim Wan736e01f2011-01-10 10:58:25 +0100723/* Get sensor name from sensor id */
724extern const char*
725android_sensors_get_name_from_id( int sensor_id )
726{
727 if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
728 return NULL;
729
730 return _sensorNameFromId(sensor_id);
731}
732
733/* Get sensor id from sensor name */
734extern int
735android_sensors_get_id_from_name( char* sensorname )
736{
737 HwSensors* hw = _sensorsState;
738
739 if (sensorname == NULL)
740 return SENSOR_STATUS_UNKNOWN;
741
742 int id = _sensorIdFromName(sensorname);
743
744 if (id < 0 || id >= MAX_SENSORS)
745 return SENSOR_STATUS_UNKNOWN;
746
747 if (hw->service != NULL) {
748 if (! hw->sensors[id].enabled)
749 return SENSOR_STATUS_DISABLED;
750 } else
751 return SENSOR_STATUS_NO_SERVICE;
752
753 return id;
754}
755
756/* Interface of reading the data for all sensors */
757extern int
758android_sensors_get( int sensor_id, float* a, float* b, float* c )
759{
760 HwSensors* hw = _sensorsState;
761
762 *a = 0;
763 *b = 0;
764 *c = 0;
765
766 if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
767 return SENSOR_STATUS_UNKNOWN;
768
769 Sensor* sensor = &hw->sensors[sensor_id];
770 if (hw->service != NULL) {
771 if (! sensor->enabled)
772 return SENSOR_STATUS_DISABLED;
773 } else
774 return SENSOR_STATUS_NO_SERVICE;
775
776 *a = sensor->u.value.a;
777 *b = sensor->u.value.b;
778 *c = sensor->u.value.c;
779
780 return SENSOR_STATUS_OK;
781}
782
783/* Interface of setting the data for all sensors */
784extern int
785android_sensors_set( int sensor_id, float a, float b, float c )
786{
787 HwSensors* hw = _sensorsState;
788
789 if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
790 return SENSOR_STATUS_UNKNOWN;
791
792 if (hw->service != NULL) {
793 if (! hw->sensors[sensor_id].enabled)
794 return SENSOR_STATUS_DISABLED;
795 } else
796 return SENSOR_STATUS_NO_SERVICE;
797
798 _hwSensors_setSensorValue(hw, sensor_id, a, b, c);
799
800 return SENSOR_STATUS_OK;
801}
802
803/* Get Sensor from sensor id */
804extern uint8_t
805android_sensors_get_sensor_status( int sensor_id )
806{
807 HwSensors* hw = _sensorsState;
808
809 if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
810 return SENSOR_STATUS_UNKNOWN;
811
812 return hw->sensors[sensor_id].enabled;
813}