hw-sensors.c revision 7c8397abd80cd6ba6a2665ef22739e603ae4c290
1/* 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/utils/system.h" 17#include "android/hw-qemud.h" 18#include "android/globals.h" 19#include "hw/hw.h" 20#include "qemu-char.h" 21#include "qemu-timer.h" 22 23#define D(...) VERBOSE_PRINT(sensors,__VA_ARGS__) 24 25/* define T_ACTIVE to 1 to debug transport communications */ 26#define T_ACTIVE 0 27 28#if T_ACTIVE 29#define T(...) VERBOSE_PRINT(sensors,__VA_ARGS__) 30#else 31#define T(...) ((void)0) 32#endif 33 34/* this code supports emulated sensor hardware 35 * 36 * Note that currently, only the accelerometer is really emulated, and only 37 * for the purpose of allowing auto-rotating the screen in keyboard-less 38 * configurations. 39 * 40 * 41 */ 42 43 44static const struct { 45 const char* name; 46 int id; 47} _sSensors[MAX_SENSORS] = { 48#define SENSOR_(x,y) { y, ANDROID_SENSOR_##x }, 49 SENSORS_LIST 50#undef SENSOR_ 51}; 52 53 54static int 55_sensorIdFromName( const char* name ) 56{ 57 int nn; 58 for (nn = 0; nn < MAX_SENSORS; nn++) 59 if (!strcmp(_sSensors[nn].name,name)) 60 return _sSensors[nn].id; 61 return -1; 62} 63 64 65typedef struct { 66 float x, y, z; 67} Acceleration; 68 69 70typedef struct { 71 float x, y, z; 72} MagneticField; 73 74 75typedef struct { 76 float azimuth; 77 float pitch; 78 float roll; 79} Orientation; 80 81 82typedef struct { 83 float celsius; 84} Temperature; 85 86 87typedef struct { 88 float value; 89} Proximity; 90 91typedef struct { 92 char enabled; 93 union { 94 Acceleration acceleration; 95 MagneticField magnetic; 96 Orientation orientation; 97 Temperature temperature; 98 Proximity proximity; 99 } u; 100} Sensor; 101 102/* 103 * - when the qemu-specific sensors HAL module starts, it sends 104 * "list-sensors" 105 * 106 * - this code replies with a string containing an integer corresponding 107 * to a bitmap of available hardware sensors in the current AVD 108 * configuration (e.g. "1" a.k.a (1 << ANDROID_SENSOR_ACCELERATION)) 109 * 110 * - the HAL module sends "set:<sensor>:<flag>" to enable or disable 111 * the report of a given sensor state. <sensor> must be the name of 112 * a given sensor (e.g. "accelerometer"), and <flag> must be either 113 * "1" (to enable) or "0" (to disable). 114 * 115 * - Once at least one sensor is "enabled", this code should periodically 116 * send information about the corresponding enabled sensors. The default 117 * period is 200ms. 118 * 119 * - the HAL module sends "set-delay:<delay>", where <delay> is an integer 120 * corresponding to a time delay in milli-seconds. This corresponds to 121 * a new interval between sensor events sent by this code to the HAL 122 * module. 123 * 124 * - the HAL module can also send a "wake" command. This code should simply 125 * send the "wake" back to the module. This is used internally to wake a 126 * blocking read that happens in a different thread. This ping-pong makes 127 * the code in the HAL module very simple. 128 * 129 * - each timer tick, this code sends sensor reports in the following 130 * format (each line corresponds to a different line sent to the module): 131 * 132 * acceleration:<x>:<y>:<z> 133 * magnetic-field:<x>:<y>:<z> 134 * orientation:<azimuth>:<pitch>:<roll> 135 * temperature:<celsius> 136 * sync:<time_us> 137 * 138 * Where each line before the sync:<time_us> is optional and will only 139 * appear if the corresponding sensor has been enabled by the HAL module. 140 * 141 * Note that <time_us> is the VM time in micro-seconds when the report 142 * was "taken" by this code. This is adjusted by the HAL module to 143 * emulated system time (using the first sync: to compute an adjustment 144 * offset). 145 */ 146#define HEADER_SIZE 4 147#define BUFFER_SIZE 512 148 149typedef struct HwSensorClient HwSensorClient; 150 151typedef struct { 152 QemudService* service; 153 Sensor sensors[MAX_SENSORS]; 154 HwSensorClient* clients; 155} HwSensors; 156 157struct HwSensorClient { 158 HwSensorClient* next; 159 HwSensors* sensors; 160 QemudClient* client; 161 QEMUTimer* timer; 162 uint32_t enabledMask; 163 int32_t delay_ms; 164}; 165 166static void 167_hwSensorClient_free( HwSensorClient* cl ) 168{ 169 /* remove from sensors's list */ 170 if (cl->sensors) { 171 HwSensorClient** pnode = &cl->sensors->clients; 172 for (;;) { 173 HwSensorClient* node = *pnode; 174 if (node == NULL) 175 break; 176 if (node == cl) { 177 *pnode = cl->next; 178 break; 179 } 180 pnode = &node->next; 181 } 182 cl->next = NULL; 183 cl->sensors = NULL; 184 } 185 186 /* close QEMUD client, if any */ 187 if (cl->client) { 188 qemud_client_close(cl->client); 189 cl->client = NULL; 190 } 191 /* remove timer, if any */ 192 if (cl->timer) { 193 qemu_del_timer(cl->timer); 194 qemu_free_timer(cl->timer); 195 cl->timer = NULL; 196 } 197 AFREE(cl); 198} 199 200/* forward */ 201static void _hwSensorClient_tick(void* opaque); 202 203 204static HwSensorClient* 205_hwSensorClient_new( HwSensors* sensors ) 206{ 207 HwSensorClient* cl; 208 209 ANEW0(cl); 210 211 cl->sensors = sensors; 212 cl->enabledMask = 0; 213 cl->delay_ms = 1000; 214 cl->timer = qemu_new_timer(vm_clock, _hwSensorClient_tick, cl); 215 216 cl->next = sensors->clients; 217 sensors->clients = cl; 218 219 return cl; 220} 221 222/* forward */ 223 224static void _hwSensorClient_receive( HwSensorClient* cl, 225 uint8_t* query, 226 int querylen ); 227 228/* Qemud service management */ 229 230static void 231_hwSensorClient_recv( void* opaque, uint8_t* msg, int msglen, 232 QemudClient* client ) 233{ 234 HwSensorClient* cl = opaque; 235 236 _hwSensorClient_receive(cl, msg, msglen); 237} 238 239static void 240_hwSensorClient_close( void* opaque ) 241{ 242 HwSensorClient* cl = opaque; 243 244 /* the client is already closed here */ 245 cl->client = NULL; 246 _hwSensorClient_free(cl); 247} 248 249/* send a one-line message to the HAL module through a qemud channel */ 250static void 251_hwSensorClient_send( HwSensorClient* cl, const uint8_t* msg, int msglen ) 252{ 253 D("%s: '%s'", __FUNCTION__, quote_bytes((const void*)msg, msglen)); 254 qemud_client_send(cl->client, msg, msglen); 255} 256 257static int 258_hwSensorClient_enabled( HwSensorClient* cl, int sensorId ) 259{ 260 return (cl->enabledMask & (1 << sensorId)) != 0; 261} 262 263/* this function is called periodically to send sensor reports 264 * to the HAL module, and re-arm the timer if necessary 265 */ 266static void 267_hwSensorClient_tick( void* opaque ) 268{ 269 HwSensorClient* cl = opaque; 270 HwSensors* hw = cl->sensors; 271 int64_t delay = cl->delay_ms; 272 int64_t now_ns; 273 uint32_t mask = cl->enabledMask; 274 Sensor* sensor; 275 char buffer[128]; 276 277 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_ACCELERATION)) { 278 sensor = &hw->sensors[ANDROID_SENSOR_ACCELERATION]; 279 snprintf(buffer, sizeof buffer, "acceleration:%g:%g:%g", 280 sensor->u.acceleration.x, 281 sensor->u.acceleration.y, 282 sensor->u.acceleration.z); 283 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer)); 284 } 285 286 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_MAGNETIC_FIELD)) { 287 sensor = &hw->sensors[ANDROID_SENSOR_MAGNETIC_FIELD]; 288 snprintf(buffer, sizeof buffer, "magnetic-field:%g:%g:%g", 289 sensor->u.magnetic.x, 290 sensor->u.magnetic.y, 291 sensor->u.magnetic.z); 292 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer)); 293 } 294 295 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_ORIENTATION)) { 296 sensor = &hw->sensors[ANDROID_SENSOR_ORIENTATION]; 297 snprintf(buffer, sizeof buffer, "orientation:%g:%g:%g", 298 sensor->u.orientation.azimuth, 299 sensor->u.orientation.pitch, 300 sensor->u.orientation.roll); 301 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer)); 302 } 303 304 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_TEMPERATURE)) { 305 sensor = &hw->sensors[ANDROID_SENSOR_TEMPERATURE]; 306 snprintf(buffer, sizeof buffer, "temperature:%g", 307 sensor->u.temperature.celsius); 308 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer)); 309 } 310 311 if (_hwSensorClient_enabled(cl, ANDROID_SENSOR_PROXIMITY)) { 312 sensor = &hw->sensors[ANDROID_SENSOR_PROXIMITY]; 313 snprintf(buffer, sizeof buffer, "proximity:%g", 314 sensor->u.proximity.value); 315 _hwSensorClient_send(cl, (uint8_t*) buffer, strlen(buffer)); 316 } 317 318 now_ns = qemu_get_clock(vm_clock); 319 320 snprintf(buffer, sizeof buffer, "sync:%lld", now_ns/1000); 321 _hwSensorClient_send(cl, (uint8_t*)buffer, strlen(buffer)); 322 323 /* rearm timer, use a minimum delay of 20 ms, just to 324 * be safe. 325 */ 326 if (mask == 0) 327 return; 328 329 if (delay < 20) 330 delay = 20; 331 332 delay *= 1000000LL; /* convert to nanoseconds */ 333 qemu_mod_timer(cl->timer, now_ns + delay); 334} 335 336/* handle incoming messages from the HAL module */ 337static void 338_hwSensorClient_receive( HwSensorClient* cl, uint8_t* msg, int msglen ) 339{ 340 HwSensors* hw = cl->sensors; 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 int nn; 352 353 for (nn = 0; nn < MAX_SENSORS; nn++) { 354 if (hw->sensors[nn].enabled) 355 mask |= (1 << nn); 356 } 357 358 snprintf(buff, sizeof buff, "%d", mask); 359 _hwSensorClient_send(cl, (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 _hwSensorClient_send(cl, (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 cl->delay_ms = atoi((const char*)msg+10); 376 if (cl->enabledMask != 0) 377 _hwSensorClient_tick(cl); 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 = cl->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 || id >= MAX_SENSORS) { 398 D("%s: ignore unknown sensor name '%s'", __FUNCTION__, msg); 399 return; 400 } 401 402 if (!hw->sensors[id].enabled) { 403 D("%s: trying to set disabled %s sensor", __FUNCTION__, msg); 404 return; 405 } 406 enabled = (q[0] == '1'); 407 408 if (enabled) 409 cl->enabledMask |= (1 << id); 410 else 411 cl->enabledMask &= ~(1 << id); 412 413 if (cl->enabledMask != oldEnabledMask) { 414 D("%s: %s %s sensor", __FUNCTION__, 415 (cl->enabledMask & (1 << id)) ? "enabling" : "disabling", msg); 416 } 417 _hwSensorClient_tick(cl); 418 return; 419 } 420 421 D("%s: ignoring unknown query", __FUNCTION__); 422} 423 424/* Saves sensor-specific client data to snapshot */ 425static void 426_hwSensorClient_save( QEMUFile* f, QemudClient* client, void* opaque ) 427{ 428 HwSensorClient* sc = opaque; 429 430 qemu_put_be32(f, sc->delay_ms); 431 qemu_put_be32(f, sc->enabledMask); 432 qemu_put_timer(f, sc->timer); 433} 434 435/* Loads sensor-specific client data from snapshot */ 436static int 437_hwSensorClient_load( QEMUFile* f, QemudClient* client, void* opaque ) 438{ 439 HwSensorClient* sc = opaque; 440 441 sc->delay_ms = qemu_get_be32(f); 442 sc->enabledMask = qemu_get_be32(f); 443 qemu_get_timer(f, sc->timer); 444 445 return 0; 446} 447 448static QemudClient* 449_hwSensors_connect( void* opaque, QemudService* service, int channel ) 450{ 451 HwSensors* sensors = opaque; 452 HwSensorClient* cl = _hwSensorClient_new(sensors); 453 QemudClient* client = qemud_client_new(service, channel, cl, 454 _hwSensorClient_recv, 455 _hwSensorClient_close, 456 _hwSensorClient_save, 457 _hwSensorClient_load ); 458 qemud_client_set_framing(client, 1); 459 cl->client = client; 460 461 return client; 462} 463 464/* change the value of the emulated acceleration vector */ 465static void 466_hwSensors_setAcceleration( HwSensors* h, float x, float y, float z ) 467{ 468 Sensor* s = &h->sensors[ANDROID_SENSOR_ACCELERATION]; 469 s->u.acceleration.x = x; 470 s->u.acceleration.y = y; 471 s->u.acceleration.z = z; 472} 473 474/* Saves available sensors to allow checking availability when loaded. 475 */ 476static void 477_hwSensors_save( QEMUFile* f, QemudService* sv, void* opaque) 478{ 479 HwSensors* h = opaque; 480 481 // number of sensors 482 qemu_put_be32(f, MAX_SENSORS); 483 AndroidSensor i; 484 for (i = 0 ; i < MAX_SENSORS; i++) { 485 Sensor* s = &h->sensors[i]; 486 qemu_put_be32(f, s->enabled); 487 488 /* this switch ensures that a warning is raised when a new sensor is 489 * added and is not added here as well. 490 */ 491 switch (i) { 492 case ANDROID_SENSOR_ACCELERATION: 493 qemu_put_float(f, s->u.acceleration.x); 494 qemu_put_float(f, s->u.acceleration.y); 495 qemu_put_float(f, s->u.acceleration.z); 496 break; 497 case ANDROID_SENSOR_MAGNETIC_FIELD: 498 qemu_put_float(f, s->u.magnetic.x); 499 qemu_put_float(f, s->u.magnetic.y); 500 qemu_put_float(f, s->u.magnetic.z); 501 break; 502 case ANDROID_SENSOR_ORIENTATION: 503 qemu_put_float(f, s->u.orientation.azimuth); 504 qemu_put_float(f, s->u.orientation.pitch); 505 qemu_put_float(f, s->u.orientation.roll); 506 break; 507 case ANDROID_SENSOR_TEMPERATURE: 508 qemu_put_float(f, s->u.temperature.celsius); 509 break; 510 case ANDROID_SENSOR_PROXIMITY: 511 qemu_put_float(f, s->u.proximity.value); 512 break; 513 case MAX_SENSORS: 514 break; 515 } 516 } 517} 518 519 520static int 521_hwSensors_load( QEMUFile* f, QemudService* s, void* opaque) 522{ 523 HwSensors* h = opaque; 524 525 /* check number of sensors */ 526 int32_t num_sensors = qemu_get_be32(f); 527 if (num_sensors != MAX_SENSORS) { 528 D("%s: cannot load: snapshot requires %d sensors, %d available\n", 529 __FUNCTION__, num_sensors, MAX_SENSORS); 530 return -EIO; 531 } 532 533 /* load sensor state */ 534 AndroidSensor i; 535 for (i = 0 ; i < MAX_SENSORS; i++) { 536 Sensor* s = &h->sensors[i]; 537 s->enabled = qemu_get_be32(f); 538 539 /* this switch ensures that a warning is raised when a new sensor is 540 * added and is not added here as well. 541 */ 542 switch (i) { 543 case ANDROID_SENSOR_ACCELERATION: 544 s->u.acceleration.x = qemu_get_float(f); 545 s->u.acceleration.y = qemu_get_float(f); 546 s->u.acceleration.z = qemu_get_float(f); 547 break; 548 case ANDROID_SENSOR_MAGNETIC_FIELD: 549 s->u.magnetic.x = qemu_get_float(f); 550 s->u.magnetic.y = qemu_get_float(f); 551 s->u.magnetic.z = qemu_get_float(f); 552 break; 553 case ANDROID_SENSOR_ORIENTATION: 554 s->u.orientation.azimuth = qemu_get_float(f); 555 s->u.orientation.pitch = qemu_get_float(f); 556 s->u.orientation.roll = qemu_get_float(f); 557 break; 558 case ANDROID_SENSOR_TEMPERATURE: 559 s->u.temperature.celsius = qemu_get_float(f); 560 break; 561 case ANDROID_SENSOR_PROXIMITY: 562 s->u.proximity.value = qemu_get_float(f); 563 break; 564 case MAX_SENSORS: 565 break; 566 } 567 } 568 569 return 0; 570} 571 572 573#if 0 /* not used yet */ 574/* change the value of the emulated magnetic vector */ 575static void 576_hwSensors_setMagneticField( HwSensors* h, float x, float y, float z ) 577{ 578 Sensor* s = &h->sensors[ANDROID_SENSOR_MAGNETIC_FIELD]; 579 s->u.magnetic.x = x; 580 s->u.magnetic.y = y; 581 s->u.magnetic.z = z; 582} 583 584/* change the values of the emulated orientation */ 585static void 586_hwSensors_setOrientation( HwSensors* h, float azimuth, float pitch, float roll ) 587{ 588 Sensor* s = &h->sensors[ANDROID_SENSOR_ORIENTATION]; 589 s->u.orientation.azimuth = azimuth; 590 s->u.orientation.pitch = pitch; 591 s->u.orientation.roll = roll; 592} 593 594/* change the emulated temperature */ 595static void 596_hwSensors_setTemperature( HwSensors* h, float celsius ) 597{ 598 Sensor* s = &h->sensors[ANDROID_SENSOR_TEMPERATURE]; 599 s->u.temperature.celsius = celsius; 600} 601#endif 602 603/* change the emulated proximity */ 604static void 605_hwSensors_setProximity( HwSensors* h, float value ) 606{ 607 Sensor* s = &h->sensors[ANDROID_SENSOR_PROXIMITY]; 608 s->u.proximity.value = value; 609} 610 611/* change the coarse orientation (landscape/portrait) of the emulated device */ 612static void 613_hwSensors_setCoarseOrientation( HwSensors* h, AndroidCoarseOrientation orient ) 614{ 615 /* The Android framework computes the orientation by looking at 616 * the accelerometer sensor (*not* the orientation sensor !) 617 * 618 * That's because the gravity is a constant 9.81 vector that 619 * can be determined quite easily. 620 * 621 * Also, for some reason, the framework code considers that the phone should 622 * be inclined by 30 degrees along the phone's X axis to be considered 623 * in its ideal "vertical" position 624 * 625 * If the phone is completely vertical, rotating it will not do anything ! 626 */ 627 const double g = 9.81; 628 const double cos_30 = 0.866025403784; 629 const double sin_30 = 0.5; 630 631 switch (orient) { 632 case ANDROID_COARSE_PORTRAIT: 633 _hwSensors_setAcceleration( h, 0., g*cos_30, g*sin_30 ); 634 break; 635 636 case ANDROID_COARSE_LANDSCAPE: 637 _hwSensors_setAcceleration( h, g*cos_30, 0., g*sin_30 ); 638 break; 639 default: 640 ; 641 } 642} 643 644 645/* initialize the sensors state */ 646static void 647_hwSensors_init( HwSensors* h ) 648{ 649 h->service = qemud_service_register("sensors", 0, h, _hwSensors_connect, 650 _hwSensors_save, _hwSensors_load); 651 652 if (android_hw->hw_accelerometer) 653 h->sensors[ANDROID_SENSOR_ACCELERATION].enabled = 1; 654 655 if (android_hw->hw_sensors_proximity) 656 h->sensors[ANDROID_SENSOR_PROXIMITY].enabled = 1; 657 658 /* XXX: TODO: Add other tests when we add the corresponding 659 * properties to hardware-properties.ini et al. */ 660 661 _hwSensors_setCoarseOrientation(h, ANDROID_COARSE_PORTRAIT); 662 _hwSensors_setProximity(h, 1); 663} 664 665static HwSensors _sensorsState[1]; 666 667void 668android_hw_sensors_init( void ) 669{ 670 HwSensors* hw = _sensorsState; 671 672 if (hw->service == NULL) { 673 _hwSensors_init(hw); 674 D("%s: sensors qemud service initialized", __FUNCTION__); 675 } 676} 677 678/* change the coarse orientation value */ 679extern void 680android_sensors_set_coarse_orientation( AndroidCoarseOrientation orient ) 681{ 682 android_hw_sensors_init(); 683 _hwSensors_setCoarseOrientation(_sensorsState, orient); 684} 685 686