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