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