blob: 6a7721c4394cef116f134c66d5087392c0d542d8 [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"
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__)
28
29/* define T_ACTIVE to 1 to debug transport communications */
30#define T_ACTIVE 0
31
32#if T_ACTIVE
33#define T(...) VERBOSE_PRINT(sensors,__VA_ARGS__)
34#else
35#define T(...) ((void)0)
36#endif
37
38/* this code supports emulated sensor hardware
39 *
40 * Note that currently, only the accelerometer is really emulated, and only
41 * for the purpose of allowing auto-rotating the screen in keyboard-less
42 * configurations.
43 *
44 *
45 */
46
47
48static const struct {
49 const char* name;
50 int id;
51} _sSensors[MAX_SENSORS] = {
52#define SENSOR_(x,y) { y, ANDROID_SENSOR_##x },
53 SENSORS_LIST
54#undef SENSOR_
55};
56
57
58static int
59_sensorIdFromName( const char* name )
60{
61 int nn;
62 for (nn = 0; nn < MAX_SENSORS; nn++)
63 if (!strcmp(_sSensors[nn].name,name))
64 return _sSensors[nn].id;
65 return -1;
66}
67
Tim Wan736e01f2011-01-10 10:58:25 +010068static const char*
69_sensorNameFromId( int id )
70{
71 int nn;
72 for (nn = 0; nn < MAX_SENSORS; nn++)
73 if (id == _sSensors[nn].id)
74 return _sSensors[nn].name;
75 return NULL;
76}
77
78/* For common Sensor Value struct */
79typedef struct {
80 float a, b, c;
81} SensorValues;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -070082
83typedef struct {
84 float x, y, z;
85} Acceleration;
86
87
88typedef struct {
89 float x, y, z;
90} MagneticField;
91
92
93typedef struct {
94 float azimuth;
95 float pitch;
96 float roll;
97} Orientation;
98
99
100typedef struct {
101 float celsius;
102} Temperature;
103
104
105typedef struct {
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100106 float value;
107} Proximity;
108
109typedef struct {
110 char enabled;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700111 union {
Tim Wan736e01f2011-01-10 10:58:25 +0100112 SensorValues value;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700113 Acceleration acceleration;
114 MagneticField magnetic;
115 Orientation orientation;
116 Temperature temperature;
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100117 Proximity proximity;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700118 } u;
119} Sensor;
120
121/*
122 * - when the qemu-specific sensors HAL module starts, it sends
123 * "list-sensors"
124 *
125 * - this code replies with a string containing an integer corresponding
126 * to a bitmap of available hardware sensors in the current AVD
127 * configuration (e.g. "1" a.k.a (1 << ANDROID_SENSOR_ACCELERATION))
128 *
129 * - the HAL module sends "set:<sensor>:<flag>" to enable or disable
130 * the report of a given sensor state. <sensor> must be the name of
131 * a given sensor (e.g. "accelerometer"), and <flag> must be either
132 * "1" (to enable) or "0" (to disable).
133 *
134 * - Once at least one sensor is "enabled", this code should periodically
135 * send information about the corresponding enabled sensors. The default
136 * period is 200ms.
137 *
138 * - the HAL module sends "set-delay:<delay>", where <delay> is an integer
139 * corresponding to a time delay in milli-seconds. This corresponds to
140 * a new interval between sensor events sent by this code to the HAL
141 * module.
142 *
143 * - the HAL module can also send a "wake" command. This code should simply
144 * send the "wake" back to the module. This is used internally to wake a
145 * blocking read that happens in a different thread. This ping-pong makes
146 * the code in the HAL module very simple.
147 *
148 * - each timer tick, this code sends sensor reports in the following
149 * format (each line corresponds to a different line sent to the module):
150 *
151 * acceleration:<x>:<y>:<z>
152 * magnetic-field:<x>:<y>:<z>
153 * orientation:<azimuth>:<pitch>:<roll>
154 * temperature:<celsius>
155 * sync:<time_us>
156 *
157 * Where each line before the sync:<time_us> is optional and will only
158 * appear if the corresponding sensor has been enabled by the HAL module.
159 *
160 * Note that <time_us> is the VM time in micro-seconds when the report
161 * was "taken" by this code. This is adjusted by the HAL module to
162 * emulated system time (using the first sync: to compute an adjustment
163 * offset).
164 */
165#define HEADER_SIZE 4
166#define BUFFER_SIZE 512
167
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200168typedef struct HwSensorClient HwSensorClient;
169
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700170typedef struct {
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700171 QemudService* service;
172 Sensor sensors[MAX_SENSORS];
173 HwSensorClient* clients;
174 AndroidSensorsPort* sensors_port;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700175} HwSensors;
176
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200177struct HwSensorClient {
178 HwSensorClient* next;
179 HwSensors* sensors;
180 QemudClient* client;
181 QEMUTimer* timer;
182 uint32_t enabledMask;
183 int32_t delay_ms;
184};
185
186static void
187_hwSensorClient_free( HwSensorClient* cl )
188{
189 /* remove from sensors's list */
190 if (cl->sensors) {
191 HwSensorClient** pnode = &cl->sensors->clients;
192 for (;;) {
193 HwSensorClient* node = *pnode;
194 if (node == NULL)
195 break;
196 if (node == cl) {
197 *pnode = cl->next;
198 break;
199 }
200 pnode = &node->next;
201 }
202 cl->next = NULL;
203 cl->sensors = NULL;
204 }
205
206 /* close QEMUD client, if any */
207 if (cl->client) {
208 qemud_client_close(cl->client);
209 cl->client = NULL;
210 }
211 /* remove timer, if any */
212 if (cl->timer) {
213 qemu_del_timer(cl->timer);
214 qemu_free_timer(cl->timer);
215 cl->timer = NULL;
216 }
217 AFREE(cl);
218}
219
220/* forward */
221static void _hwSensorClient_tick(void* opaque);
222
223
224static HwSensorClient*
225_hwSensorClient_new( HwSensors* sensors )
226{
227 HwSensorClient* cl;
228
229 ANEW0(cl);
230
231 cl->sensors = sensors;
232 cl->enabledMask = 0;
David 'Digit' Turner593d0ea2011-02-15 03:02:34 +0100233 cl->delay_ms = 800;
David 'Digit' Turner5973c772011-05-10 07:06:00 +0200234 cl->timer = qemu_new_timer_ns(vm_clock, _hwSensorClient_tick, cl);
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200235
236 cl->next = sensors->clients;
237 sensors->clients = cl;
238
239 return cl;
240}
241
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700242/* forward */
243
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200244static void _hwSensorClient_receive( HwSensorClient* cl,
245 uint8_t* query,
246 int querylen );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700247
248/* Qemud service management */
249
250static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200251_hwSensorClient_recv( void* opaque, uint8_t* msg, int msglen,
252 QemudClient* client )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700253{
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200254 HwSensorClient* cl = opaque;
255
256 _hwSensorClient_receive(cl, msg, msglen);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700257}
258
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200259static void
260_hwSensorClient_close( void* opaque )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700261{
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200262 HwSensorClient* cl = opaque;
263
264 /* the client is already closed here */
265 cl->client = NULL;
266 _hwSensorClient_free(cl);
267}
268
269/* send a one-line message to the HAL module through a qemud channel */
270static void
271_hwSensorClient_send( HwSensorClient* cl, const uint8_t* msg, int msglen )
272{
273 D("%s: '%s'", __FUNCTION__, quote_bytes((const void*)msg, msglen));
274 qemud_client_send(cl->client, msg, msglen);
275}
276
277static int
278_hwSensorClient_enabled( HwSensorClient* cl, int sensorId )
279{
280 return (cl->enabledMask & (1 << sensorId)) != 0;
281}
282
283/* this function is called periodically to send sensor reports
284 * to the HAL module, and re-arm the timer if necessary
285 */
286static void
287_hwSensorClient_tick( void* opaque )
288{
289 HwSensorClient* cl = opaque;
290 HwSensors* hw = cl->sensors;
291 int64_t delay = cl->delay_ms;
292 int64_t now_ns;
293 uint32_t mask = cl->enabledMask;
294 Sensor* sensor;
295 char buffer[128];
296
297 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_ACCELERATION)) {
298 sensor = &hw->sensors[ANDROID_SENSOR_ACCELERATION];
299 snprintf(buffer, sizeof buffer, "acceleration:%g:%g:%g",
300 sensor->u.acceleration.x,
301 sensor->u.acceleration.y,
302 sensor->u.acceleration.z);
303 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
304 }
305
306 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_MAGNETIC_FIELD)) {
307 sensor = &hw->sensors[ANDROID_SENSOR_MAGNETIC_FIELD];
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700308 /* NOTE: sensors HAL expects "magnetic", not "magnetic-field" name here. */
309 snprintf(buffer, sizeof buffer, "magnetic:%g:%g:%g",
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200310 sensor->u.magnetic.x,
311 sensor->u.magnetic.y,
312 sensor->u.magnetic.z);
313 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
314 }
315
316 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_ORIENTATION)) {
317 sensor = &hw->sensors[ANDROID_SENSOR_ORIENTATION];
318 snprintf(buffer, sizeof buffer, "orientation:%g:%g:%g",
319 sensor->u.orientation.azimuth,
320 sensor->u.orientation.pitch,
321 sensor->u.orientation.roll);
322 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
323 }
324
325 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_TEMPERATURE)) {
326 sensor = &hw->sensors[ANDROID_SENSOR_TEMPERATURE];
327 snprintf(buffer, sizeof buffer, "temperature:%g",
328 sensor->u.temperature.celsius);
329 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
330 }
331
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100332 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_PROXIMITY)) {
333 sensor = &hw->sensors[ANDROID_SENSOR_PROXIMITY];
334 snprintf(buffer, sizeof buffer, "proximity:%g",
335 sensor->u.proximity.value);
336 _hwSensorClient_send(cl, (uint8_t*) buffer, strlen(buffer));
337 }
338
David 'Digit' Turner5973c772011-05-10 07:06:00 +0200339 now_ns = qemu_get_clock_ns(vm_clock);
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200340
341 snprintf(buffer, sizeof buffer, "sync:%lld", now_ns/1000);
342 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer));
343
344 /* rearm timer, use a minimum delay of 20 ms, just to
345 * be safe.
346 */
347 if (mask == 0)
348 return;
349
350 if (delay < 20)
351 delay = 20;
352
353 delay *= 1000000LL; /* convert to nanoseconds */
354 qemu_mod_timer(cl->timer, now_ns + delay);
355}
356
357/* handle incoming messages from the HAL module */
358static void
359_hwSensorClient_receive( HwSensorClient* cl, uint8_t* msg, int msglen )
360{
361 HwSensors* hw = cl->sensors;
362
363 D("%s: '%.*s'", __FUNCTION__, msglen, msg);
364
365 /* "list-sensors" is used to get an integer bit map of
366 * available emulated sensors. We compute the mask from the
367 * current hardware configuration.
368 */
369 if (msglen == 12 && !memcmp(msg, "list-sensors", 12)) {
370 char buff[12];
371 int mask = 0;
372 int nn;
373
374 for (nn = 0; nn < MAX_SENSORS; nn++) {
375 if (hw->sensors[nn].enabled)
376 mask |= (1 << nn);
377 }
378
379 snprintf(buff, sizeof buff, "%d", mask);
380 _hwSensorClient_send(cl, (const uint8_t*)buff, strlen(buff));
381 return;
382 }
383
384 /* "wake" is a special message that must be sent back through
385 * the channel. It is used to exit a blocking read.
386 */
387 if (msglen == 4 && !memcmp(msg, "wake", 4)) {
388 _hwSensorClient_send(cl, (const uint8_t*)"wake", 4);
389 return;
390 }
391
392 /* "set-delay:<delay>" is used to set the delay in milliseconds
393 * between sensor events
394 */
395 if (msglen > 10 && !memcmp(msg, "set-delay:", 10)) {
396 cl->delay_ms = atoi((const char*)msg+10);
397 if (cl->enabledMask != 0)
398 _hwSensorClient_tick(cl);
399
400 return;
401 }
402
403 /* "set:<name>:<state>" is used to enable/disable a given
404 * sensor. <state> must be 0 or 1
405 */
406 if (msglen > 4 && !memcmp(msg, "set:", 4)) {
407 char* q;
408 int id, enabled, oldEnabledMask = cl->enabledMask;
409 msg += 4;
410 q = strchr((char*)msg, ':');
411 if (q == NULL) { /* should not happen */
412 D("%s: ignore bad 'set' command", __FUNCTION__);
413 return;
414 }
415 *q++ = 0;
416
417 id = _sensorIdFromName((const char*)msg);
418 if (id < 0 || id >= MAX_SENSORS) {
419 D("%s: ignore unknown sensor name '%s'", __FUNCTION__, msg);
420 return;
421 }
422
423 if (!hw->sensors[id].enabled) {
424 D("%s: trying to set disabled %s sensor", __FUNCTION__, msg);
425 return;
426 }
427 enabled = (q[0] == '1');
428
429 if (enabled)
430 cl->enabledMask |= (1 << id);
431 else
432 cl->enabledMask &= ~(1 << id);
433
434 if (cl->enabledMask != oldEnabledMask) {
435 D("%s: %s %s sensor", __FUNCTION__,
436 (cl->enabledMask & (1 << id)) ? "enabling" : "disabling", msg);
437 }
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700438
439 /* If emulating device is connected update sensor state there too. */
440 if (hw->sensors_port != NULL && sensors_port_is_connected(hw->sensors_port)) {
441 if (enabled) {
442 sensors_port_enable_sensor(hw->sensors_port, (const char*)msg);
443 } else {
444 sensors_port_disable_sensor(hw->sensors_port, (const char*)msg);
445 }
446 }
447
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200448 _hwSensorClient_tick(cl);
449 return;
450 }
451
452 D("%s: ignoring unknown query", __FUNCTION__);
453}
454
Ot ten Thije871da2a2010-09-20 10:29:22 +0100455/* Saves sensor-specific client data to snapshot */
456static void
457_hwSensorClient_save( QEMUFile* f, QemudClient* client, void* opaque )
458{
459 HwSensorClient* sc = opaque;
460
461 qemu_put_be32(f, sc->delay_ms);
462 qemu_put_be32(f, sc->enabledMask);
463 qemu_put_timer(f, sc->timer);
464}
465
466/* Loads sensor-specific client data from snapshot */
467static int
468_hwSensorClient_load( QEMUFile* f, QemudClient* client, void* opaque )
469{
470 HwSensorClient* sc = opaque;
471
472 sc->delay_ms = qemu_get_be32(f);
473 sc->enabledMask = qemu_get_be32(f);
474 qemu_get_timer(f, sc->timer);
475
476 return 0;
477}
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200478
479static QemudClient*
Vladimir Chtchetkine4c414822011-08-20 08:55:37 -0700480_hwSensors_connect( void* opaque,
481 QemudService* service,
482 int channel,
483 const char* client_param )
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200484{
485 HwSensors* sensors = opaque;
486 HwSensorClient* cl = _hwSensorClient_new(sensors);
Vladimir Chtchetkine4c414822011-08-20 08:55:37 -0700487 QemudClient* client = qemud_client_new(service, channel, client_param, cl,
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200488 _hwSensorClient_recv,
Ot ten Thije871da2a2010-09-20 10:29:22 +0100489 _hwSensorClient_close,
490 _hwSensorClient_save,
491 _hwSensorClient_load );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700492 qemud_client_set_framing(client, 1);
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200493 cl->client = client;
494
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700495 return client;
496}
497
Tim Wan736e01f2011-01-10 10:58:25 +0100498/* change the value of the emulated sensor vector */
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700499static void
Tim Wan736e01f2011-01-10 10:58:25 +0100500_hwSensors_setSensorValue( HwSensors* h, int sensor_id, float a, float b, float c )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700501{
Tim Wan736e01f2011-01-10 10:58:25 +0100502 Sensor* s = &h->sensors[sensor_id];
503
504 s->u.value.a = a;
505 s->u.value.b = b;
506 s->u.value.c = c;
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700507}
508
Ot ten Thije871da2a2010-09-20 10:29:22 +0100509/* Saves available sensors to allow checking availability when loaded.
510 */
511static void
512_hwSensors_save( QEMUFile* f, QemudService* sv, void* opaque)
513{
514 HwSensors* h = opaque;
515
516 // number of sensors
517 qemu_put_be32(f, MAX_SENSORS);
518 AndroidSensor i;
519 for (i = 0 ; i < MAX_SENSORS; i++) {
520 Sensor* s = &h->sensors[i];
521 qemu_put_be32(f, s->enabled);
522
523 /* this switch ensures that a warning is raised when a new sensor is
524 * added and is not added here as well.
525 */
526 switch (i) {
527 case ANDROID_SENSOR_ACCELERATION:
528 qemu_put_float(f, s->u.acceleration.x);
529 qemu_put_float(f, s->u.acceleration.y);
530 qemu_put_float(f, s->u.acceleration.z);
531 break;
532 case ANDROID_SENSOR_MAGNETIC_FIELD:
533 qemu_put_float(f, s->u.magnetic.x);
534 qemu_put_float(f, s->u.magnetic.y);
535 qemu_put_float(f, s->u.magnetic.z);
536 break;
537 case ANDROID_SENSOR_ORIENTATION:
538 qemu_put_float(f, s->u.orientation.azimuth);
539 qemu_put_float(f, s->u.orientation.pitch);
540 qemu_put_float(f, s->u.orientation.roll);
541 break;
542 case ANDROID_SENSOR_TEMPERATURE:
543 qemu_put_float(f, s->u.temperature.celsius);
544 break;
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100545 case ANDROID_SENSOR_PROXIMITY:
546 qemu_put_float(f, s->u.proximity.value);
547 break;
Ot ten Thije871da2a2010-09-20 10:29:22 +0100548 case MAX_SENSORS:
549 break;
550 }
551 }
552}
553
554
555static int
556_hwSensors_load( QEMUFile* f, QemudService* s, void* opaque)
557{
558 HwSensors* h = opaque;
559
560 /* check number of sensors */
561 int32_t num_sensors = qemu_get_be32(f);
David 'Digit' Turner607461d2011-02-24 16:27:48 +0100562 if (num_sensors > MAX_SENSORS) {
Ot ten Thije871da2a2010-09-20 10:29:22 +0100563 D("%s: cannot load: snapshot requires %d sensors, %d available\n",
564 __FUNCTION__, num_sensors, MAX_SENSORS);
565 return -EIO;
566 }
567
568 /* load sensor state */
569 AndroidSensor i;
David 'Digit' Turner607461d2011-02-24 16:27:48 +0100570 for (i = 0 ; i < num_sensors; i++) {
Ot ten Thije871da2a2010-09-20 10:29:22 +0100571 Sensor* s = &h->sensors[i];
572 s->enabled = qemu_get_be32(f);
573
574 /* this switch ensures that a warning is raised when a new sensor is
575 * added and is not added here as well.
576 */
577 switch (i) {
578 case ANDROID_SENSOR_ACCELERATION:
579 s->u.acceleration.x = qemu_get_float(f);
580 s->u.acceleration.y = qemu_get_float(f);
581 s->u.acceleration.z = qemu_get_float(f);
582 break;
583 case ANDROID_SENSOR_MAGNETIC_FIELD:
584 s->u.magnetic.x = qemu_get_float(f);
585 s->u.magnetic.y = qemu_get_float(f);
586 s->u.magnetic.z = qemu_get_float(f);
587 break;
588 case ANDROID_SENSOR_ORIENTATION:
589 s->u.orientation.azimuth = qemu_get_float(f);
590 s->u.orientation.pitch = qemu_get_float(f);
591 s->u.orientation.roll = qemu_get_float(f);
592 break;
593 case ANDROID_SENSOR_TEMPERATURE:
594 s->u.temperature.celsius = qemu_get_float(f);
595 break;
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100596 case ANDROID_SENSOR_PROXIMITY:
597 s->u.proximity.value = qemu_get_float(f);
598 break;
Ot ten Thije871da2a2010-09-20 10:29:22 +0100599 case MAX_SENSORS:
600 break;
601 }
602 }
603
David 'Digit' Turner607461d2011-02-24 16:27:48 +0100604 /* The following is necessary when we resume a snaphost
605 * created by an older version of the emulator that provided
606 * less hardware sensors.
607 */
608 for ( ; i < MAX_SENSORS; i++ ) {
609 h->sensors[i].enabled = 0;
610 }
611
Ot ten Thije871da2a2010-09-20 10:29:22 +0100612 return 0;
613}
614
615
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100616/* change the emulated proximity */
617static void
618_hwSensors_setProximity( HwSensors* h, float value )
619{
620 Sensor* s = &h->sensors[ANDROID_SENSOR_PROXIMITY];
621 s->u.proximity.value = value;
622}
623
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700624/* change the coarse orientation (landscape/portrait) of the emulated device */
625static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200626_hwSensors_setCoarseOrientation( HwSensors* h, AndroidCoarseOrientation orient )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700627{
628 /* The Android framework computes the orientation by looking at
629 * the accelerometer sensor (*not* the orientation sensor !)
630 *
631 * That's because the gravity is a constant 9.81 vector that
632 * can be determined quite easily.
633 *
634 * Also, for some reason, the framework code considers that the phone should
635 * be inclined by 30 degrees along the phone's X axis to be considered
636 * in its ideal "vertical" position
637 *
638 * If the phone is completely vertical, rotating it will not do anything !
639 */
640 const double g = 9.81;
David 'Digit' Turner593d0ea2011-02-15 03:02:34 +0100641 const double angle = 20.0;
642 const double cos_angle = cos(angle/M_PI);
643 const double sin_angle = sin(angle/M_PI);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700644
645 switch (orient) {
646 case ANDROID_COARSE_PORTRAIT:
Tim Wan736e01f2011-01-10 10:58:25 +0100647 _hwSensors_setSensorValue( h, ANDROID_SENSOR_ACCELERATION, 0., g*cos_angle, g*sin_angle );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700648 break;
649
650 case ANDROID_COARSE_LANDSCAPE:
Tim Wan736e01f2011-01-10 10:58:25 +0100651 _hwSensors_setSensorValue( h, ANDROID_SENSOR_ACCELERATION, g*cos_angle, 0., g*sin_angle );
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700652 break;
653 default:
654 ;
655 }
656}
657
658
659/* initialize the sensors state */
660static void
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200661_hwSensors_init( HwSensors* h )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700662{
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700663 /* Try to see if there is a device attached that can be used for
664 * sensor emulation. */
665 h->sensors_port = sensors_port_create(h);
666 if (h->sensors_port == NULL) {
667 W("Unable to create sensors port: %s", strerror(errno));
668 }
669
Ot ten Thije871da2a2010-09-20 10:29:22 +0100670 h->service = qemud_service_register("sensors", 0, h, _hwSensors_connect,
671 _hwSensors_save, _hwSensors_load);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700672
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700673 if (android_hw->hw_accelerometer) {
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200674 h->sensors[ANDROID_SENSOR_ACCELERATION].enabled = 1;
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700675 }
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200676
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700677 if (android_hw->hw_sensors_proximity) {
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100678 h->sensors[ANDROID_SENSOR_PROXIMITY].enabled = 1;
Vladimir Chtchetkinedb611d52011-11-01 17:35:07 -0700679 }
680
681 if (android_hw->hw_sensors_magnetic_field) {
682 h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD].enabled = 1;
683 }
684
685 if (android_hw->hw_sensors_orientation) {
686 h->sensors[ANDROID_SENSOR_ORIENTATION].enabled = 1;
687 }
688
689 if (android_hw->hw_sensors_temperature) {
690 h->sensors[ANDROID_SENSOR_TEMPERATURE].enabled = 1;
691 }
692
693 if (h->sensors_port != NULL) {
694 /* Init sensors on the attached device. */
695 sensors_port_init_sensors(h->sensors_port);
696 }
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100697
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200698 /* XXX: TODO: Add other tests when we add the corresponding
699 * properties to hardware-properties.ini et al. */
700
701 _hwSensors_setCoarseOrientation(h, ANDROID_COARSE_PORTRAIT);
Ola Albertsson7c8397a2010-12-17 14:53:44 +0100702 _hwSensors_setProximity(h, 1);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700703}
704
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700705static HwSensors _sensorsState[1];
706
707void
708android_hw_sensors_init( void )
709{
710 HwSensors* hw = _sensorsState;
711
712 if (hw->service == NULL) {
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200713 _hwSensors_init(hw);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700714 D("%s: sensors qemud service initialized", __FUNCTION__);
715 }
716}
717
718/* change the coarse orientation value */
719extern void
720android_sensors_set_coarse_orientation( AndroidCoarseOrientation orient )
721{
722 android_hw_sensors_init();
David 'Digit' Turner5998b892009-06-11 14:43:03 +0200723 _hwSensors_setCoarseOrientation(_sensorsState, orient);
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700724}
725
Tim Wan736e01f2011-01-10 10:58:25 +0100726/* Get sensor name from sensor id */
727extern const char*
728android_sensors_get_name_from_id( int sensor_id )
729{
730 if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
731 return NULL;
732
733 return _sensorNameFromId(sensor_id);
734}
735
736/* Get sensor id from sensor name */
737extern int
738android_sensors_get_id_from_name( char* sensorname )
739{
740 HwSensors* hw = _sensorsState;
741
742 if (sensorname == NULL)
743 return SENSOR_STATUS_UNKNOWN;
744
745 int id = _sensorIdFromName(sensorname);
746
747 if (id < 0 || id >= MAX_SENSORS)
748 return SENSOR_STATUS_UNKNOWN;
749
750 if (hw->service != NULL) {
751 if (! hw->sensors[id].enabled)
752 return SENSOR_STATUS_DISABLED;
753 } else
754 return SENSOR_STATUS_NO_SERVICE;
755
756 return id;
757}
758
759/* Interface of reading the data for all sensors */
760extern int
761android_sensors_get( int sensor_id, float* a, float* b, float* c )
762{
763 HwSensors* hw = _sensorsState;
764
765 *a = 0;
766 *b = 0;
767 *c = 0;
768
769 if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
770 return SENSOR_STATUS_UNKNOWN;
771
772 Sensor* sensor = &hw->sensors[sensor_id];
773 if (hw->service != NULL) {
774 if (! sensor->enabled)
775 return SENSOR_STATUS_DISABLED;
776 } else
777 return SENSOR_STATUS_NO_SERVICE;
778
779 *a = sensor->u.value.a;
780 *b = sensor->u.value.b;
781 *c = sensor->u.value.c;
782
783 return SENSOR_STATUS_OK;
784}
785
786/* Interface of setting the data for all sensors */
787extern int
788android_sensors_set( int sensor_id, float a, float b, float c )
789{
790 HwSensors* hw = _sensorsState;
791
792 if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
793 return SENSOR_STATUS_UNKNOWN;
794
795 if (hw->service != NULL) {
796 if (! hw->sensors[sensor_id].enabled)
797 return SENSOR_STATUS_DISABLED;
798 } else
799 return SENSOR_STATUS_NO_SERVICE;
800
801 _hwSensors_setSensorValue(hw, sensor_id, a, b, c);
802
803 return SENSOR_STATUS_OK;
804}
805
806/* Get Sensor from sensor id */
807extern uint8_t
808android_sensors_get_sensor_status( int sensor_id )
809{
810 HwSensors* hw = _sensorsState;
811
812 if (sensor_id < 0 || sensor_id >= MAX_SENSORS)
813 return SENSOR_STATUS_UNKNOWN;
814
815 return hw->sensors[sensor_id].enabled;
816}