blob: 37d4af7b5033675b3f6120af4b93e4371b461b30 [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
13#include "android/hw-sensors.h"
14#include "android/utils/debug.h"
15#include "android/utils/misc.h"
16#include "android/hw-qemud.h"
17#include "android/globals.h"
18#include "qemu-char.h"
19#include "qemu-timer.h"
20
21#define D(...) VERBOSE_PRINT(sensors,__VA_ARGS__)
22
23/* define T_ACTIVE to 1 to debug transport communications */
24#define T_ACTIVE 0
25
26#if T_ACTIVE
27#define T(...) VERBOSE_PRINT(sensors,__VA_ARGS__)
28#else
29#define T(...) ((void)0)
30#endif
31
32/* this code supports emulated sensor hardware
33 *
34 * Note that currently, only the accelerometer is really emulated, and only
35 * for the purpose of allowing auto-rotating the screen in keyboard-less
36 * configurations.
37 *
38 *
39 */
40
41
42static const struct {
43 const char* name;
44 int id;
45} _sSensors[MAX_SENSORS] = {
46#define SENSOR_(x,y) { y, ANDROID_SENSOR_##x },
47 SENSORS_LIST
48#undef SENSOR_
49};
50
51
52static int
53_sensorIdFromName( const char* name )
54{
55 int nn;
56 for (nn = 0; nn < MAX_SENSORS; nn++)
57 if (!strcmp(_sSensors[nn].name,name))
58 return _sSensors[nn].id;
59 return -1;
60}
61
62
63typedef struct {
64 float x, y, z;
65} Acceleration;
66
67
68typedef struct {
69 float x, y, z;
70} MagneticField;
71
72
73typedef struct {
74 float azimuth;
75 float pitch;
76 float roll;
77} Orientation;
78
79
80typedef struct {
81 float celsius;
82} Temperature;
83
84
85typedef struct {
86 char enabled;
87 union {
88 Acceleration acceleration;
89 MagneticField magnetic;
90 Orientation orientation;
91 Temperature temperature;
92 } u;
93} Sensor;
94
95/*
96 * - when the qemu-specific sensors HAL module starts, it sends
97 * "list-sensors"
98 *
99 * - this code replies with a string containing an integer corresponding
100 * to a bitmap of available hardware sensors in the current AVD
101 * configuration (e.g. "1" a.k.a (1 << ANDROID_SENSOR_ACCELERATION))
102 *
103 * - the HAL module sends "set:<sensor>:<flag>" to enable or disable
104 * the report of a given sensor state. <sensor> must be the name of
105 * a given sensor (e.g. "accelerometer"), and <flag> must be either
106 * "1" (to enable) or "0" (to disable).
107 *
108 * - Once at least one sensor is "enabled", this code should periodically
109 * send information about the corresponding enabled sensors. The default
110 * period is 200ms.
111 *
112 * - the HAL module sends "set-delay:<delay>", where <delay> is an integer
113 * corresponding to a time delay in milli-seconds. This corresponds to
114 * a new interval between sensor events sent by this code to the HAL
115 * module.
116 *
117 * - the HAL module can also send a "wake" command. This code should simply
118 * send the "wake" back to the module. This is used internally to wake a
119 * blocking read that happens in a different thread. This ping-pong makes
120 * the code in the HAL module very simple.
121 *
122 * - each timer tick, this code sends sensor reports in the following
123 * format (each line corresponds to a different line sent to the module):
124 *
125 * acceleration:<x>:<y>:<z>
126 * magnetic-field:<x>:<y>:<z>
127 * orientation:<azimuth>:<pitch>:<roll>
128 * temperature:<celsius>
129 * sync:<time_us>
130 *
131 * Where each line before the sync:<time_us> is optional and will only
132 * appear if the corresponding sensor has been enabled by the HAL module.
133 *
134 * Note that <time_us> is the VM time in micro-seconds when the report
135 * was "taken" by this code. This is adjusted by the HAL module to
136 * emulated system time (using the first sync: to compute an adjustment
137 * offset).
138 */
139#define HEADER_SIZE 4
140#define BUFFER_SIZE 512
141
142typedef struct {
143 QemudService* service;
144 int32_t delay_ms;
145 uint32_t enabledMask;
146 QEMUTimer* timer;
147 Sensor sensors[MAX_SENSORS];
148} HwSensors;
149
150/* forward */
151
152static void hw_sensors_receive( HwSensors* h,
153 uint8_t* query,
154 int querylen );
155
156static void hw_sensors_timer_tick(void* opaque);
157
158/* Qemud service management */
159
160static void
David 'Digit' Turner318e4f22009-05-25 18:01:03 +0200161_hw_sensors_qemud_client_recv( void* opaque, uint8_t* msg, int msglen,
162 QemudClient* client )
The Android Open Source Project9877e2e2009-03-18 17:39:44 -0700163{
164 hw_sensors_receive(opaque, msg, msglen);
165}
166
167static QemudClient*
168_hw_sensors_service_connect( void* opaque, QemudService* service, int channel )
169{
170 HwSensors* sensors = opaque;
171 QemudClient* client = qemud_client_new(service, channel,
172 sensors,
173 _hw_sensors_qemud_client_recv,
174 NULL);
175 qemud_client_set_framing(client, 1);
176 return client;
177}
178
179/* change the value of the emulated acceleration vector */
180static void
181hw_sensors_set_acceleration( HwSensors* h, float x, float y, float z )
182{
183 Sensor* s = &h->sensors[ANDROID_SENSOR_ACCELERATION];
184 s->u.acceleration.x = x;
185 s->u.acceleration.y = y;
186 s->u.acceleration.z = z;
187}
188
189#if 0 /* not used yet */
190/* change the value of the emulated magnetic vector */
191static void
192hw_sensors_set_magnetic_field( HwSensors* h, float x, float y, float z )
193{
194 Sensor* s = &h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD];
195 s->u.magnetic.x = x;
196 s->u.magnetic.y = y;
197 s->u.magnetic.z = z;
198}
199
200/* change the values of the emulated orientation */
201static void
202hw_sensors_set_orientation( HwSensors* h, float azimuth, float pitch, float roll )
203{
204 Sensor* s = &h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD];
205 s->u.orientation.azimuth = azimuth;
206 s->u.orientation.pitch = pitch;
207 s->u.orientation.roll = roll;
208}
209
210/* change the emulated temperature */
211static void
212hw_sensors_set_temperature( HwSensors* h, float celsius )
213{
214 Sensor* s = &h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD];
215 s->u.temperature.celsius = celsius;
216}
217#endif
218
219/* change the coarse orientation (landscape/portrait) of the emulated device */
220static void
221hw_sensors_set_coarse_orientation( HwSensors* h, AndroidCoarseOrientation orient )
222{
223 /* The Android framework computes the orientation by looking at
224 * the accelerometer sensor (*not* the orientation sensor !)
225 *
226 * That's because the gravity is a constant 9.81 vector that
227 * can be determined quite easily.
228 *
229 * Also, for some reason, the framework code considers that the phone should
230 * be inclined by 30 degrees along the phone's X axis to be considered
231 * in its ideal "vertical" position
232 *
233 * If the phone is completely vertical, rotating it will not do anything !
234 */
235 const double g = 9.81;
236 const double cos_30 = 0.866025403784;
237 const double sin_30 = 0.5;
238
239 switch (orient) {
240 case ANDROID_COARSE_PORTRAIT:
241 hw_sensors_set_acceleration( h, 0., g*cos_30, g*sin_30 );
242 break;
243
244 case ANDROID_COARSE_LANDSCAPE:
245 hw_sensors_set_acceleration( h, g*cos_30, 0., g*sin_30 );
246 break;
247 default:
248 ;
249 }
250}
251
252
253/* initialize the sensors state */
254static void
255hw_sensors_init( HwSensors* h )
256{
257 h->service = qemud_service_register("sensors", 1, h,
258 _hw_sensors_service_connect );
259 h->enabledMask = 0;
260 h->delay_ms = 1000;
261 h->timer = qemu_new_timer(vm_clock, hw_sensors_timer_tick, h);
262
263 hw_sensors_set_coarse_orientation(h, ANDROID_COARSE_PORTRAIT);
264}
265
266/* send a one-line message to the HAL module through a qemud channel */
267static void
268hw_sensors_send( HwSensors* hw, const uint8_t* msg, int msglen )
269{
270 D("%s: '%s'", __FUNCTION__, quote_bytes((const void*)msg, msglen));
271 qemud_service_broadcast(hw->service, msg, msglen);
272}
273
274/* this function is called periodically to send sensor reports
275 * to the HAL module, and re-arm the timer if necessary
276 */
277static void
278hw_sensors_timer_tick( void* opaque )
279{
280 HwSensors* h = opaque;
281 int64_t delay = h->delay_ms;
282 int64_t now_ns;
283 uint32_t mask = h->enabledMask;
284 Sensor* sensor;
285 char buffer[128];
286
287 sensor = &h->sensors[ANDROID_SENSOR_ACCELERATION];
288 if (sensor->enabled) {
289 snprintf(buffer, sizeof buffer, "acceleration:%g:%g:%g",
290 sensor->u.acceleration.x,
291 sensor->u.acceleration.y,
292 sensor->u.acceleration.z);
293 hw_sensors_send(h, (uint8_t*)buffer, strlen(buffer));
294 }
295
296 sensor = &h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD];
297 if (sensor->enabled) {
298 snprintf(buffer, sizeof buffer, "magnetic-field:%g:%g:%g",
299 sensor->u.magnetic.x,
300 sensor->u.magnetic.y,
301 sensor->u.magnetic.z);
302 hw_sensors_send(h, (uint8_t*)buffer, strlen(buffer));
303 }
304
305 sensor = &h->sensors[ANDROID_SENSOR_ORIENTATION];
306 if (sensor->enabled) {
307 snprintf(buffer, sizeof buffer, "orientation:%g:%g:%g",
308 sensor->u.orientation.azimuth,
309 sensor->u.orientation.pitch,
310 sensor->u.orientation.roll);
311 hw_sensors_send(h, (uint8_t*)buffer, strlen(buffer));
312 }
313
314 sensor = &h->sensors[ANDROID_SENSOR_TEMPERATURE];
315 if (sensor->enabled) {
316 snprintf(buffer, sizeof buffer, "temperature:%g",
317 sensor->u.temperature.celsius);
318 hw_sensors_send(h, (uint8_t*)buffer, strlen(buffer));
319 }
320
321 now_ns = qemu_get_clock(vm_clock);
322
323 snprintf(buffer, sizeof buffer, "sync:%lld", now_ns/1000);
324 hw_sensors_send(h, (uint8_t*)buffer, strlen(buffer));
325
326 /* rearm timer, use a minimum delay of 20 ms, just to
327 * be safe.
328 */
329 if (mask == 0)
330 return;
331
332 if (delay < 20)
333 delay = 20;
334
335 delay *= 1000000LL; /* convert to nanoseconds */
336 qemu_mod_timer(h->timer, now_ns + delay);
337}
338
339/* handle incoming messages from the HAL module */
340static void
341hw_sensors_receive( HwSensors* hw, uint8_t* msg, int msglen )
342{
343 D("%s: '%.*s'", __FUNCTION__, msglen, msg);
344
345 /* "list-sensors" is used to get an integer bit map of
346 * available emulated sensors. We compute the mask from the
347 * current hardware configuration.
348 */
349 if (msglen == 12 && !memcmp(msg, "list-sensors", 12)) {
350 char buff[12];
351 int mask = 0;
352
353 if (android_hw->hw_accelerometer)
354 mask |= (1 << ANDROID_SENSOR_ACCELERATION);
355
356 /* XXX: TODO: Add other tests when we add the corresponding
357 * properties to hardware-properties.ini et al. */
358
359 snprintf(buff, sizeof buff, "%d", mask);
360 hw_sensors_send(hw, (const uint8_t*)buff, strlen(buff));
361 return;
362 }
363
364 /* "wake" is a special message that must be sent back through
365 * the channel. It is used to exit a blocking read.
366 */
367 if (msglen == 4 && !memcmp(msg, "wake", 4)) {
368 hw_sensors_send(hw, (const uint8_t*)"wake", 4);
369 return;
370 }
371
372 /* "set-delay:<delay>" is used to set the delay in milliseconds
373 * between sensor events
374 */
375 if (msglen > 10 && !memcmp(msg, "set-delay:", 10)) {
376 hw->delay_ms = atoi((const char*)msg+10);
377 if (hw->enabledMask != 0)
378 hw_sensors_timer_tick(hw);
379
380 return;
381 }
382
383 /* "set:<name>:<state>" is used to enable/disable a given
384 * sensor. <state> must be 0 or 1
385 */
386 if (msglen > 4 && !memcmp(msg, "set:", 4)) {
387 char* q;
388 int id, enabled, oldEnabledMask = hw->enabledMask;
389 msg += 4;
390 q = strchr((char*)msg, ':');
391 if (q == NULL) { /* should not happen */
392 D("%s: ignore bad 'set' command", __FUNCTION__);
393 return;
394 }
395 *q++ = 0;
396
397 id = _sensorIdFromName((const char*)msg);
398 if (id < 0) {
399 D("%s: ignore unknown sensor name '%s'", __FUNCTION__, msg);
400 return;
401 }
402
403 enabled = (q[0] == '1');
404
405 hw->sensors[id].enabled = (char) enabled;
406 if (enabled)
407 hw->enabledMask |= (1 << id);
408 else
409 hw->enabledMask &= ~(1 << id);
410
411 D("%s: %s %s sensor", __FUNCTION__,
412 hw->sensors[id].enabled ? "enabling" : "disabling", msg);
413
414 if (oldEnabledMask == 0 && enabled) {
415 /* we enabled our first sensor, start event reporting */
416 D("%s: starting event reporting (mask=%04x)", __FUNCTION__,
417 hw->enabledMask);
418 }
419 else if (hw->enabledMask == 0 && !enabled) {
420 /* we disabled our last sensor, stop event reporting */
421 D("%s: stopping event reporting", __FUNCTION__);
422 }
423 hw_sensors_timer_tick(hw);
424 return;
425 }
426
427 D("%s: ignoring unknown query", __FUNCTION__);
428}
429
430
431static HwSensors _sensorsState[1];
432
433void
434android_hw_sensors_init( void )
435{
436 HwSensors* hw = _sensorsState;
437
438 if (hw->service == NULL) {
439 hw_sensors_init(hw);
440 D("%s: sensors qemud service initialized", __FUNCTION__);
441 }
442}
443
444/* change the coarse orientation value */
445extern void
446android_sensors_set_coarse_orientation( AndroidCoarseOrientation orient )
447{
448 android_hw_sensors_init();
449 hw_sensors_set_coarse_orientation(_sensorsState, orient);
450}
451