blob: eb2cc7809fbff7a12d127f08c23229d687f27587 [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
161_hw_sensors_qemud_client_recv( void* opaque, uint8_t* msg, int msglen )
162{
163 hw_sensors_receive(opaque, msg, msglen);
164}
165
166static QemudClient*
167_hw_sensors_service_connect( void* opaque, QemudService* service, int channel )
168{
169 HwSensors* sensors = opaque;
170 QemudClient* client = qemud_client_new(service, channel,
171 sensors,
172 _hw_sensors_qemud_client_recv,
173 NULL);
174 qemud_client_set_framing(client, 1);
175 return client;
176}
177
178/* change the value of the emulated acceleration vector */
179static void
180hw_sensors_set_acceleration( HwSensors* h, float x, float y, float z )
181{
182 Sensor* s = &h->sensors[ANDROID_SENSOR_ACCELERATION];
183 s->u.acceleration.x = x;
184 s->u.acceleration.y = y;
185 s->u.acceleration.z = z;
186}
187
188#if 0 /* not used yet */
189/* change the value of the emulated magnetic vector */
190static void
191hw_sensors_set_magnetic_field( HwSensors* h, float x, float y, float z )
192{
193 Sensor* s = &h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD];
194 s->u.magnetic.x = x;
195 s->u.magnetic.y = y;
196 s->u.magnetic.z = z;
197}
198
199/* change the values of the emulated orientation */
200static void
201hw_sensors_set_orientation( HwSensors* h, float azimuth, float pitch, float roll )
202{
203 Sensor* s = &h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD];
204 s->u.orientation.azimuth = azimuth;
205 s->u.orientation.pitch = pitch;
206 s->u.orientation.roll = roll;
207}
208
209/* change the emulated temperature */
210static void
211hw_sensors_set_temperature( HwSensors* h, float celsius )
212{
213 Sensor* s = &h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD];
214 s->u.temperature.celsius = celsius;
215}
216#endif
217
218/* change the coarse orientation (landscape/portrait) of the emulated device */
219static void
220hw_sensors_set_coarse_orientation( HwSensors* h, AndroidCoarseOrientation orient )
221{
222 /* The Android framework computes the orientation by looking at
223 * the accelerometer sensor (*not* the orientation sensor !)
224 *
225 * That's because the gravity is a constant 9.81 vector that
226 * can be determined quite easily.
227 *
228 * Also, for some reason, the framework code considers that the phone should
229 * be inclined by 30 degrees along the phone's X axis to be considered
230 * in its ideal "vertical" position
231 *
232 * If the phone is completely vertical, rotating it will not do anything !
233 */
234 const double g = 9.81;
235 const double cos_30 = 0.866025403784;
236 const double sin_30 = 0.5;
237
238 switch (orient) {
239 case ANDROID_COARSE_PORTRAIT:
240 hw_sensors_set_acceleration( h, 0., g*cos_30, g*sin_30 );
241 break;
242
243 case ANDROID_COARSE_LANDSCAPE:
244 hw_sensors_set_acceleration( h, g*cos_30, 0., g*sin_30 );
245 break;
246 default:
247 ;
248 }
249}
250
251
252/* initialize the sensors state */
253static void
254hw_sensors_init( HwSensors* h )
255{
256 h->service = qemud_service_register("sensors", 1, h,
257 _hw_sensors_service_connect );
258 h->enabledMask = 0;
259 h->delay_ms = 1000;
260 h->timer = qemu_new_timer(vm_clock, hw_sensors_timer_tick, h);
261
262 hw_sensors_set_coarse_orientation(h, ANDROID_COARSE_PORTRAIT);
263}
264
265/* send a one-line message to the HAL module through a qemud channel */
266static void
267hw_sensors_send( HwSensors* hw, const uint8_t* msg, int msglen )
268{
269 D("%s: '%s'", __FUNCTION__, quote_bytes((const void*)msg, msglen));
270 qemud_service_broadcast(hw->service, msg, msglen);
271}
272
273/* this function is called periodically to send sensor reports
274 * to the HAL module, and re-arm the timer if necessary
275 */
276static void
277hw_sensors_timer_tick( void* opaque )
278{
279 HwSensors* h = opaque;
280 int64_t delay = h->delay_ms;
281 int64_t now_ns;
282 uint32_t mask = h->enabledMask;
283 Sensor* sensor;
284 char buffer[128];
285
286 sensor = &h->sensors[ANDROID_SENSOR_ACCELERATION];
287 if (sensor->enabled) {
288 snprintf(buffer, sizeof buffer, "acceleration:%g:%g:%g",
289 sensor->u.acceleration.x,
290 sensor->u.acceleration.y,
291 sensor->u.acceleration.z);
292 hw_sensors_send(h, (uint8_t*)buffer, strlen(buffer));
293 }
294
295 sensor = &h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD];
296 if (sensor->enabled) {
297 snprintf(buffer, sizeof buffer, "magnetic-field:%g:%g:%g",
298 sensor->u.magnetic.x,
299 sensor->u.magnetic.y,
300 sensor->u.magnetic.z);
301 hw_sensors_send(h, (uint8_t*)buffer, strlen(buffer));
302 }
303
304 sensor = &h->sensors[ANDROID_SENSOR_ORIENTATION];
305 if (sensor->enabled) {
306 snprintf(buffer, sizeof buffer, "orientation:%g:%g:%g",
307 sensor->u.orientation.azimuth,
308 sensor->u.orientation.pitch,
309 sensor->u.orientation.roll);
310 hw_sensors_send(h, (uint8_t*)buffer, strlen(buffer));
311 }
312
313 sensor = &h->sensors[ANDROID_SENSOR_TEMPERATURE];
314 if (sensor->enabled) {
315 snprintf(buffer, sizeof buffer, "temperature:%g",
316 sensor->u.temperature.celsius);
317 hw_sensors_send(h, (uint8_t*)buffer, strlen(buffer));
318 }
319
320 now_ns = qemu_get_clock(vm_clock);
321
322 snprintf(buffer, sizeof buffer, "sync:%lld", now_ns/1000);
323 hw_sensors_send(h, (uint8_t*)buffer, strlen(buffer));
324
325 /* rearm timer, use a minimum delay of 20 ms, just to
326 * be safe.
327 */
328 if (mask == 0)
329 return;
330
331 if (delay < 20)
332 delay = 20;
333
334 delay *= 1000000LL; /* convert to nanoseconds */
335 qemu_mod_timer(h->timer, now_ns + delay);
336}
337
338/* handle incoming messages from the HAL module */
339static void
340hw_sensors_receive( HwSensors* hw, uint8_t* msg, int msglen )
341{
342 D("%s: '%.*s'", __FUNCTION__, msglen, msg);
343
344 /* "list-sensors" is used to get an integer bit map of
345 * available emulated sensors. We compute the mask from the
346 * current hardware configuration.
347 */
348 if (msglen == 12 && !memcmp(msg, "list-sensors", 12)) {
349 char buff[12];
350 int mask = 0;
351
352 if (android_hw->hw_accelerometer)
353 mask |= (1 << ANDROID_SENSOR_ACCELERATION);
354
355 /* XXX: TODO: Add other tests when we add the corresponding
356 * properties to hardware-properties.ini et al. */
357
358 snprintf(buff, sizeof buff, "%d", mask);
359 hw_sensors_send(hw, (const uint8_t*)buff, strlen(buff));
360 return;
361 }
362
363 /* "wake" is a special message that must be sent back through
364 * the channel. It is used to exit a blocking read.
365 */
366 if (msglen == 4 && !memcmp(msg, "wake", 4)) {
367 hw_sensors_send(hw, (const uint8_t*)"wake", 4);
368 return;
369 }
370
371 /* "set-delay:<delay>" is used to set the delay in milliseconds
372 * between sensor events
373 */
374 if (msglen > 10 && !memcmp(msg, "set-delay:", 10)) {
375 hw->delay_ms = atoi((const char*)msg+10);
376 if (hw->enabledMask != 0)
377 hw_sensors_timer_tick(hw);
378
379 return;
380 }
381
382 /* "set:<name>:<state>" is used to enable/disable a given
383 * sensor. <state> must be 0 or 1
384 */
385 if (msglen > 4 && !memcmp(msg, "set:", 4)) {
386 char* q;
387 int id, enabled, oldEnabledMask = hw->enabledMask;
388 msg += 4;
389 q = strchr((char*)msg, ':');
390 if (q == NULL) { /* should not happen */
391 D("%s: ignore bad 'set' command", __FUNCTION__);
392 return;
393 }
394 *q++ = 0;
395
396 id = _sensorIdFromName((const char*)msg);
397 if (id < 0) {
398 D("%s: ignore unknown sensor name '%s'", __FUNCTION__, msg);
399 return;
400 }
401
402 enabled = (q[0] == '1');
403
404 hw->sensors[id].enabled = (char) enabled;
405 if (enabled)
406 hw->enabledMask |= (1 << id);
407 else
408 hw->enabledMask &= ~(1 << id);
409
410 D("%s: %s %s sensor", __FUNCTION__,
411 hw->sensors[id].enabled ? "enabling" : "disabling", msg);
412
413 if (oldEnabledMask == 0 && enabled) {
414 /* we enabled our first sensor, start event reporting */
415 D("%s: starting event reporting (mask=%04x)", __FUNCTION__,
416 hw->enabledMask);
417 }
418 else if (hw->enabledMask == 0 && !enabled) {
419 /* we disabled our last sensor, stop event reporting */
420 D("%s: stopping event reporting", __FUNCTION__);
421 }
422 hw_sensors_timer_tick(hw);
423 return;
424 }
425
426 D("%s: ignoring unknown query", __FUNCTION__);
427}
428
429
430static HwSensors _sensorsState[1];
431
432void
433android_hw_sensors_init( void )
434{
435 HwSensors* hw = _sensorsState;
436
437 if (hw->service == NULL) {
438 hw_sensors_init(hw);
439 D("%s: sensors qemud service initialized", __FUNCTION__);
440 }
441}
442
443/* change the coarse orientation value */
444extern void
445android_sensors_set_coarse_orientation( AndroidCoarseOrientation orient )
446{
447 android_hw_sensors_init();
448 hw_sensors_set_coarse_orientation(_sensorsState, orient);
449}
450