1 /* Copyright (C) 2007-2008 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 #include "android/hw-qemud.h" 13 #include "android/utils/debug.h" 14 #include "android/utils/misc.h" 15 #include "android/utils/system.h" 16 #include "android/utils/bufprint.h" 17 #include "qemu-char.h" 18 #include "charpipe.h" 19 #include "cbuffer.h" 20 21 #define D(...) VERBOSE_PRINT(qemud,__VA_ARGS__) 22 #define D_ACTIVE VERBOSE_CHECK(qemud) 23 24 /* the T(...) macro is used to dump traffic */ 25 #define T_ACTIVE 0 26 27 #if T_ACTIVE 28 #define T(...) VERBOSE_PRINT(qemud,__VA_ARGS__) 29 #else 30 #define T(...) ((void)0) 31 #endif 32 33 /* max serial MTU. Don't change this without modifying 34 * development/emulator/qemud/qemud.c as well. 35 */ 36 #define MAX_SERIAL_PAYLOAD 4000 37 38 /* max framed data payload. Must be < (1 << 16) 39 */ 40 #define MAX_FRAME_PAYLOAD 65535 41 42 43 /* define SUPPORT_LEGACY_QEMUD to 1 if you want to support 44 * talking to a legacy qemud daemon. See docs/ANDROID-QEMUD.TXT 45 * for details. 46 */ 47 #define SUPPORT_LEGACY_QEMUD 1 48 49 #if SUPPORT_LEGACY_QEMUD 50 #include "telephony/android_modem.h" 51 #include "telephony/modem_driver.h" 52 #endif 53 54 /* 55 * This implements support for the 'qemud' multiplexing communication 56 * channel between clients running in the emulated system and 'services' 57 * provided by the emulator. 58 * 59 * For additional details, please read docs/ANDROID-QEMUD.TXT 60 * 61 */ 62 63 /* 64 * IMPLEMENTATION DETAILS: 65 * 66 * We use one charpipe to connect the emulated serial port to the 'QemudSerial' 67 * object. This object is used to receive data from the serial port, and 68 * unframe messages (i.e. extract payload length + channel id from header, 69 * then the payload itself), before sending them to a generic receiver. 70 * 71 * The QemudSerial object can also be used to send messages to the daemon 72 * through the serial port (see qemud_serial_send()) 73 * 74 * The multiplexer is connected to one or more 'service' objects. 75 * are themselves connected through a charpipe to an emulated device or 76 * control sub-module in the emulator. 77 * 78 * tty <==charpipe==> QemudSerial ---> QemudMultiplexer ----> QemudClient 79 * ^ | 80 * | | 81 * +--------------------------------------+ 82 * 83 */ 84 85 /** HANDLING INCOMING DATA FRAMES 86 **/ 87 88 /* A QemudSink is just a handly data structure that is used to 89 * read a fixed amount of bytes into a buffer 90 */ 91 typedef struct QemudSink { 92 int len; 93 int size; 94 uint8_t* buff; 95 } QemudSink; 96 97 /* reset a QemudSink, i.e. provide a new destination buffer address 98 * and its size in bytes. 99 */ 100 static void 101 qemud_sink_reset( QemudSink* ss, int size, uint8_t* buffer ) 102 { 103 ss->len = 0; 104 ss->size = size; 105 ss->buff = buffer; 106 } 107 108 /* try to fill the sink by reading bytes from the source buffer 109 * '*pmsg' which contains '*plen' bytes 110 * 111 * this functions updates '*pmsg' and '*plen', and returns 112 * 1 if the sink's destination buffer is full, or 0 otherwise. 113 */ 114 static int 115 qemud_sink_fill( QemudSink* ss, const uint8_t* *pmsg, int *plen) 116 { 117 int avail = ss->size - ss->len; 118 119 if (avail <= 0) 120 return 1; 121 122 if (avail > *plen) 123 avail = *plen; 124 125 memcpy(ss->buff + ss->len, *pmsg, avail); 126 *pmsg += avail; 127 *plen -= avail; 128 ss->len += avail; 129 130 return (ss->len == ss->size); 131 } 132 133 /* returns the number of bytes needed to fill a sink's destination 134 * buffer. 135 */ 136 static int 137 qemud_sink_needed( QemudSink* ss ) 138 { 139 return ss->size - ss->len; 140 } 141 142 /** HANDLING SERIAL PORT CONNECTION 143 **/ 144 145 /* The QemudSerial object receives data from the serial port charpipe. 146 * It parses the header to extract the channel id and payload length, 147 * then the message itself. 148 * 149 * Incoming messages are sent to a generic receiver identified by 150 * the 'recv_opaque' and 'recv_func' parameters to qemud_serial_init() 151 * 152 * It also provides qemud_serial_send() which can be used to send 153 * messages back through the serial port. 154 */ 155 156 #define HEADER_SIZE 6 157 158 #define LENGTH_OFFSET 2 159 #define LENGTH_SIZE 4 160 161 #define CHANNEL_OFFSET 0 162 #define CHANNEL_SIZE 2 163 164 #if SUPPORT_LEGACY_QEMUD 165 typedef enum { 166 QEMUD_VERSION_UNKNOWN, 167 QEMUD_VERSION_LEGACY, 168 QEMUD_VERSION_NORMAL 169 } QemudVersion; 170 171 # define LEGACY_LENGTH_OFFSET 0 172 # define LEGACY_CHANNEL_OFFSET 4 173 #endif 174 175 /* length of the framed header */ 176 #define FRAME_HEADER_SIZE 4 177 178 #define BUFFER_SIZE MAX_SERIAL_PAYLOAD 179 180 /* out of convenience, the incoming message is zero-terminated 181 * and can be modified by the receiver (e.g. for tokenization). 182 */ 183 typedef void (*QemudSerialReceive)( void* opaque, int channel, uint8_t* msg, int msglen); 184 185 typedef struct QemudSerial { 186 CharDriverState* cs; /* serial charpipe endpoint */ 187 188 /* managing incoming packets from the serial port */ 189 ABool need_header; 190 int overflow; 191 int in_size; 192 int in_channel; 193 #if SUPPORT_LEGACY_QEMUD 194 QemudVersion version; 195 #endif 196 QemudSink header[1]; 197 QemudSink payload[1]; 198 uint8_t data0[MAX_SERIAL_PAYLOAD+1]; 199 200 /* receiver */ 201 QemudSerialReceive recv_func; /* receiver callback */ 202 void* recv_opaque; /* receiver user-specific data */ 203 } QemudSerial; 204 205 206 /* called by the charpipe to see how much bytes can be 207 * read from the serial port. 208 */ 209 static int 210 qemud_serial_can_read( void* opaque ) 211 { 212 QemudSerial* s = opaque; 213 214 if (s->overflow > 0) { 215 return s->overflow; 216 } 217 218 /* if in_size is 0, we're reading the header */ 219 if (s->need_header) 220 return qemud_sink_needed(s->header); 221 222 /* otherwise, we're reading the payload */ 223 return qemud_sink_needed(s->payload); 224 } 225 226 /* called by the charpipe to read data from the serial 227 * port. 'len' cannot be more than the value returned 228 * by 'qemud_serial_can_read'. 229 */ 230 static void 231 qemud_serial_read( void* opaque, const uint8_t* from, int len ) 232 { 233 QemudSerial* s = opaque; 234 235 T("%s: received %3d bytes: '%s'", __FUNCTION__, len, quote_bytes((const void*)from, len)); 236 237 while (len > 0) { 238 int avail; 239 240 /* skip overflow bytes */ 241 if (s->overflow > 0) { 242 avail = s->overflow; 243 if (avail > len) 244 avail = len; 245 246 from += avail; 247 len -= avail; 248 continue; 249 } 250 251 /* read header if needed */ 252 if (s->need_header) { 253 if (!qemud_sink_fill(s->header, (const uint8_t**)&from, &len)) 254 break; 255 256 #if SUPPORT_LEGACY_QEMUD 257 if (s->version == QEMUD_VERSION_UNKNOWN) { 258 /* if we receive "001200" as the first header, then we 259 * detected a legacy qemud daemon. See the comments 260 * in qemud_serial_send_legacy_probe() for details. 261 */ 262 if ( !memcmp(s->data0, "001200", 6) ) { 263 D("%s: legacy qemud detected.", __FUNCTION__); 264 s->version = QEMUD_VERSION_LEGACY; 265 /* tell the modem to use legacy emulation mode */ 266 amodem_set_legacy(android_modem); 267 } else { 268 D("%s: normal qemud detected.", __FUNCTION__); 269 s->version = QEMUD_VERSION_NORMAL; 270 } 271 } 272 273 if (s->version == QEMUD_VERSION_LEGACY) { 274 s->in_size = hex2int( s->data0 + LEGACY_LENGTH_OFFSET, LENGTH_SIZE ); 275 s->in_channel = hex2int( s->data0 + LEGACY_CHANNEL_OFFSET, CHANNEL_SIZE ); 276 } else { 277 s->in_size = hex2int( s->data0 + LENGTH_OFFSET, LENGTH_SIZE ); 278 s->in_channel = hex2int( s->data0 + CHANNEL_OFFSET, CHANNEL_SIZE ); 279 } 280 #else 281 /* extract payload length + channel id */ 282 s->in_size = hex2int( s->data0 + LENGTH_OFFSET, LENGTH_SIZE ); 283 s->in_channel = hex2int( s->data0 + CHANNEL_OFFSET, CHANNEL_SIZE ); 284 #endif 285 s->header->len = 0; 286 287 if (s->in_size <= 0 || s->in_channel < 0) { 288 D("%s: bad header: '%.*s'", __FUNCTION__, HEADER_SIZE, s->data0); 289 continue; 290 } 291 292 if (s->in_size > MAX_SERIAL_PAYLOAD) { 293 D("%s: ignoring huge serial packet: length=%d channel=%1", 294 __FUNCTION__, s->in_size, s->in_channel); 295 s->overflow = s->in_size; 296 continue; 297 } 298 299 /* prepare 'in_data' for payload */ 300 s->need_header = 0; 301 qemud_sink_reset(s->payload, s->in_size, s->data0); 302 } 303 304 /* read payload bytes */ 305 if (!qemud_sink_fill(s->payload, &from, &len)) 306 break; 307 308 /* zero-terminate payload, then send it to receiver */ 309 s->payload->buff[s->payload->size] = 0; 310 D("%s: channel=%2d len=%3d '%s'", __FUNCTION__, 311 s->in_channel, s->payload->size, 312 quote_bytes((const void*)s->payload->buff, s->payload->size)); 313 314 s->recv_func( s->recv_opaque, s->in_channel, s->payload->buff, s->payload->size ); 315 316 /* prepare for new header */ 317 s->need_header = 1; 318 } 319 } 320 321 322 #if SUPPORT_LEGACY_QEMUD 323 static void 324 qemud_serial_send_legacy_probe( QemudSerial* s ) 325 { 326 /* we're going to send a specially crafted packet to the qemud 327 * daemon, this will help us determine whether we're talking 328 * to a legacy or a normal daemon. 329 * 330 * the trick is to known that a legacy daemon uses the following 331 * header: 332 * 333 * <length><channel><payload> 334 * 335 * while the normal one uses: 336 * 337 * <channel><length><payload> 338 * 339 * where <channel> is a 2-hexchar string, and <length> a 4-hexchar 340 * string. 341 * 342 * if we send a header of "000100", it is interpreted: 343 * 344 * - as the header of a 1-byte payload by the legacy daemon 345 * - as the header of a 256-byte payload by the normal one. 346 * 347 * we're going to send something that looks like: 348 * 349 * "000100" + "X" + 350 * "000b00" + "connect:gsm" + 351 * "000b00" + "connect:gps" + 352 * "000f00" + "connect:control" + 353 * "00c210" + "0"*194 354 * 355 * the normal daemon will interpret this as a 256-byte payload 356 * for channel 0, with garbage content ("X000b00conn...") which 357 * will be silently ignored. 358 * 359 * on the other hand, the legacy daemon will see it as a 360 * series of packets: 361 * 362 * one message "X" on channel 0, which will force the daemon 363 * to send back "001200ko:unknown command" as its first answer. 364 * 365 * three "connect:<xxx>" messages used to receive the channel 366 * numbers of the three legacy services implemented by the daemon. 367 * 368 * a garbage packet of 194 zeroes for channel 16, which will be 369 * silently ignored. 370 */ 371 uint8_t tab[194]; 372 373 memset(tab, 0, sizeof(tab)); 374 qemu_chr_write(s->cs, (uint8_t*)"000100X", 7); 375 qemu_chr_write(s->cs, (uint8_t*)"000b00connect:gsm", 17); 376 qemu_chr_write(s->cs, (uint8_t*)"000b00connect:gps", 17); 377 qemu_chr_write(s->cs, (uint8_t*)"000f00connect:control", 21); 378 qemu_chr_write(s->cs, (uint8_t*)"00c210", 6); 379 qemu_chr_write(s->cs, tab, sizeof(tab)); 380 } 381 #endif /* SUPPORT_LEGACY_QEMUD */ 382 383 /* intialize a QemudSerial object with a charpipe endpoint 384 * and a receiver. 385 */ 386 static void 387 qemud_serial_init( QemudSerial* s, 388 CharDriverState* cs, 389 QemudSerialReceive recv_func, 390 void* recv_opaque ) 391 { 392 s->cs = cs; 393 s->recv_func = recv_func; 394 s->recv_opaque = recv_opaque; 395 s->need_header = 1; 396 s->overflow = 0; 397 398 qemud_sink_reset( s->header, HEADER_SIZE, s->data0 ); 399 s->in_size = 0; 400 s->in_channel = -1; 401 402 #if SUPPORT_LEGACY_QEMUD 403 s->version = QEMUD_VERSION_UNKNOWN; 404 qemud_serial_send_legacy_probe(s); 405 #endif 406 407 qemu_chr_add_handlers( cs, 408 qemud_serial_can_read, 409 qemud_serial_read, 410 NULL, 411 s ); 412 } 413 414 /* send a message to the serial port. This will add the necessary 415 * header. 416 */ 417 static void 418 qemud_serial_send( QemudSerial* s, 419 int channel, 420 ABool framing, 421 const uint8_t* msg, 422 int msglen ) 423 { 424 uint8_t header[HEADER_SIZE]; 425 uint8_t frame[FRAME_HEADER_SIZE]; 426 int avail, len = msglen; 427 428 if (msglen <= 0 || channel < 0) 429 return; 430 431 D("%s: channel=%2d len=%3d '%s'", 432 __FUNCTION__, channel, msglen, 433 quote_bytes((const void*)msg, msglen)); 434 435 if (framing) { 436 len += FRAME_HEADER_SIZE; 437 } 438 439 /* packetize the payload for the serial MTU */ 440 while (len > 0) 441 { 442 avail = len; 443 if (avail > MAX_SERIAL_PAYLOAD) 444 avail = MAX_SERIAL_PAYLOAD; 445 446 /* write this packet's header */ 447 #if SUPPORT_LEGACY_QEMUD 448 if (s->version == QEMUD_VERSION_LEGACY) { 449 int2hex(header + LEGACY_LENGTH_OFFSET, LENGTH_SIZE, avail); 450 int2hex(header + LEGACY_CHANNEL_OFFSET, CHANNEL_SIZE, channel); 451 } else { 452 int2hex(header + LENGTH_OFFSET, LENGTH_SIZE, avail); 453 int2hex(header + CHANNEL_OFFSET, CHANNEL_SIZE, channel); 454 } 455 #else 456 int2hex(header + LENGTH_OFFSET, LENGTH_SIZE, avail); 457 int2hex(header + CHANNEL_OFFSET, CHANNEL_SIZE, channel); 458 #endif 459 T("%s: '%.*s'", __FUNCTION__, HEADER_SIZE, header); 460 qemu_chr_write(s->cs, header, HEADER_SIZE); 461 462 /* insert frame header when needed */ 463 if (framing) { 464 int2hex(frame, FRAME_HEADER_SIZE, msglen); 465 T("%s: '%.*s'", __FUNCTION__, FRAME_HEADER_SIZE, frame); 466 qemu_chr_write(s->cs, frame, FRAME_HEADER_SIZE); 467 avail -= FRAME_HEADER_SIZE; 468 len -= FRAME_HEADER_SIZE; 469 framing = 0; 470 } 471 472 /* write message content */ 473 T("%s: '%.*s'", __FUNCTION__, avail, msg); 474 qemu_chr_write(s->cs, msg, avail); 475 msg += avail; 476 len -= avail; 477 } 478 } 479 480 /** CLIENTS 481 **/ 482 483 /* A QemudClient models a single client as seen by the emulator. 484 * Each client has its own channel id, and belongs to a given 485 * QemudService (see below). 486 * 487 * There is a global list of clients used to multiplex incoming 488 * messages from the channel id (see qemud_multiplexer_serial_recv()). 489 * 490 */ 491 492 struct QemudClient { 493 int channel; 494 QemudSerial* serial; 495 void* clie_opaque; 496 QemudClientRecv clie_recv; 497 QemudClientClose clie_close; 498 QemudService* service; 499 QemudClient* next_serv; /* next in same service */ 500 QemudClient* next; 501 QemudClient** pref; 502 503 /* framing support */ 504 int framing; 505 ABool need_header; 506 QemudSink header[1]; 507 uint8_t header0[FRAME_HEADER_SIZE]; 508 QemudSink payload[1]; 509 }; 510 511 static void qemud_service_remove_client( QemudService* service, 512 QemudClient* client ); 513 514 /* remove a QemudClient from global list */ 515 static void 516 qemud_client_remove( QemudClient* c ) 517 { 518 c->pref[0] = c->next; 519 if (c->next) 520 c->next->pref = c->pref; 521 522 c->next = NULL; 523 c->pref = &c->next; 524 } 525 526 /* add a QemudClient to global list */ 527 static void 528 qemud_client_prepend( QemudClient* c, QemudClient** plist ) 529 { 530 c->next = *plist; 531 c->pref = plist; 532 *plist = c; 533 if (c->next) 534 c->next->pref = &c->next; 535 } 536 537 /* receive a new message from a client, and dispatch it to 538 * the real service implementation. 539 */ 540 static void 541 qemud_client_recv( void* opaque, uint8_t* msg, int msglen ) 542 { 543 QemudClient* c = opaque; 544 545 /* no framing, things are simple */ 546 if (!c->framing) { 547 if (c->clie_recv) 548 c->clie_recv( c->clie_opaque, msg, msglen, c ); 549 return; 550 } 551 552 /* framing */ 553 554 #if 1 555 /* special case, in 99% of cases, everything is in 556 * the incoming message, and we can do all we need 557 * directly without dynamic allocation. 558 */ 559 if (msglen > FRAME_HEADER_SIZE && 560 c->need_header == 1 && 561 qemud_sink_needed(c->header) == 0) 562 { 563 int len = hex2int( msg, FRAME_HEADER_SIZE ); 564 565 if (len >= 0 && msglen == len + FRAME_HEADER_SIZE) { 566 if (c->clie_recv) 567 c->clie_recv( c->clie_opaque, 568 msg+FRAME_HEADER_SIZE, 569 msglen-FRAME_HEADER_SIZE, c ); 570 return; 571 } 572 } 573 #endif 574 575 while (msglen > 0) { 576 uint8_t *data; 577 578 /* read the header */ 579 if (c->need_header) { 580 int frame_size; 581 uint8_t* data; 582 583 if (!qemud_sink_fill(c->header, (const uint8_t**)&msg, &msglen)) 584 break; 585 586 frame_size = hex2int(c->header0, 4); 587 if (frame_size == 0) { 588 D("%s: ignoring empty frame", __FUNCTION__); 589 continue; 590 } 591 if (frame_size < 0) { 592 D("%s: ignoring corrupted frame header '.*s'", 593 __FUNCTION__, FRAME_HEADER_SIZE, c->header0 ); 594 continue; 595 } 596 597 AARRAY_NEW(data, frame_size+1); /* +1 for terminating zero */ 598 qemud_sink_reset(c->payload, frame_size, data); 599 c->need_header = 0; 600 c->header->len = 0; 601 } 602 603 /* read the payload */ 604 if (!qemud_sink_fill(c->payload, (const uint8_t**)&msg, &msglen)) 605 break; 606 607 c->payload->buff[c->payload->size] = 0; 608 c->need_header = 1; 609 data = c->payload->buff; 610 611 /* Technically, calling 'clie_recv' can destroy client object 'c' 612 * if it decides to close the connection, so ensure we don't 613 * use/dereference it after the call. */ 614 if (c->clie_recv) 615 c->clie_recv( c->clie_opaque, c->payload->buff, c->payload->size, c ); 616 617 AFREE(data); 618 } 619 } 620 621 /* disconnect a client. this automatically frees the QemudClient. 622 * note that this also removes the client from the global list 623 * and from its service's list, if any. 624 */ 625 static void 626 qemud_client_disconnect( void* opaque ) 627 { 628 QemudClient* c = opaque; 629 630 /* remove from current list */ 631 qemud_client_remove(c); 632 633 /* send a disconnect command to the daemon */ 634 if (c->channel > 0) { 635 char tmp[128], *p=tmp, *end=p+sizeof(tmp); 636 p = bufprint(tmp, end, "disconnect:%02x", c->channel); 637 qemud_serial_send(c->serial, 0, 0, (uint8_t*)tmp, p-tmp); 638 } 639 640 /* call the client close callback */ 641 if (c->clie_close) { 642 c->clie_close(c->clie_opaque); 643 c->clie_close = NULL; 644 } 645 c->clie_recv = NULL; 646 647 /* remove from service list, if any */ 648 if (c->service) { 649 qemud_service_remove_client(c->service, c); 650 c->service = NULL; 651 } 652 653 AFREE(c); 654 } 655 656 /* allocate a new QemudClient object */ 657 static QemudClient* 658 qemud_client_alloc( int channel_id, 659 void* clie_opaque, 660 QemudClientRecv clie_recv, 661 QemudClientClose clie_close, 662 QemudSerial* serial, 663 QemudClient** pclients ) 664 { 665 QemudClient* c; 666 667 ANEW0(c); 668 669 c->serial = serial; 670 c->channel = channel_id; 671 c->clie_opaque = clie_opaque; 672 c->clie_recv = clie_recv; 673 c->clie_close = clie_close; 674 675 c->framing = 0; 676 c->need_header = 1; 677 qemud_sink_reset(c->header, FRAME_HEADER_SIZE, c->header0); 678 679 qemud_client_prepend(c, pclients); 680 681 return c; 682 } 683 684 /** SERVICES 685 **/ 686 687 /* A QemudService models a _named_ service facility implemented 688 * by the emulator, that clients in the emulated system can connect 689 * to. 690 * 691 * Each service can have a limit on the number of clients they 692 * accept (this number if unlimited if 'max_clients' is 0). 693 * 694 * Each service maintains a list of active QemudClients and 695 * can also be used to create new QemudClient objects through 696 * its 'serv_opaque' and 'serv_connect' fields. 697 */ 698 struct QemudService { 699 const char* name; 700 int max_clients; 701 int num_clients; 702 QemudClient* clients; 703 QemudServiceConnect serv_connect; 704 void* serv_opaque; 705 QemudService* next; 706 }; 707 708 /* Create a new QemudService object */ 709 static QemudService* 710 qemud_service_new( const char* name, 711 int max_clients, 712 void* serv_opaque, 713 QemudServiceConnect serv_connect, 714 QemudService** pservices ) 715 { 716 QemudService* s; 717 718 ANEW0(s); 719 s->name = ASTRDUP(name); 720 s->max_clients = max_clients; 721 s->num_clients = 0; 722 s->clients = NULL; 723 724 s->serv_opaque = serv_opaque; 725 s->serv_connect = serv_connect; 726 727 s->next = *pservices; 728 *pservices = s; 729 730 return s; 731 } 732 733 /* used internally to populate a QemudService object with a 734 * new QemudClient */ 735 static void 736 qemud_service_add_client( QemudService* s, QemudClient* c ) 737 { 738 c->service = s; 739 c->next_serv = s->clients; 740 s->clients = c; 741 s->num_clients += 1; 742 } 743 744 /* used internally to remove a QemudClient from a QemudService */ 745 static void 746 qemud_service_remove_client( QemudService* s, QemudClient* c ) 747 { 748 QemudClient** pnode = &s->clients; 749 QemudClient* node; 750 751 /* remove from clients linked-list */ 752 for (;;) { 753 node = *pnode; 754 if (node == NULL) { 755 D("%s: could not find client %d for service '%s'", 756 __FUNCTION__, c->channel, s->name); 757 return; 758 } 759 if (node == c) 760 break; 761 pnode = &node->next_serv; 762 } 763 764 *pnode = node->next_serv; 765 s->num_clients -= 1; 766 } 767 768 /** MULTIPLEXER 769 **/ 770 771 /* A QemudMultiplexer object maintains the global state of the 772 * qemud service facility. It holds a QemudSerial object to 773 * maintain the state of the serial port connection. 774 * 775 * The QemudMultiplexer receives all incoming messages from 776 * the serial port, and dispatches them to the appropriate 777 * QemudClient. 778 * 779 * It also has a global list of clients, and a global list of 780 * services. 781 * 782 * Finally, the QemudMultiplexer has a special QemudClient used 783 * to handle channel 0, i.e. the control channel used to handle 784 * connections and disconnections of clients. 785 */ 786 typedef struct QemudMultiplexer QemudMultiplexer; 787 788 struct QemudMultiplexer { 789 QemudSerial serial[1]; 790 QemudClient* clients; 791 QemudService* services; 792 }; 793 794 /* this is the serial_recv callback that is called 795 * whenever an incoming message arrives through the serial port 796 */ 797 static void 798 qemud_multiplexer_serial_recv( void* opaque, 799 int channel, 800 uint8_t* msg, 801 int msglen ) 802 { 803 QemudMultiplexer* m = opaque; 804 QemudClient* c = m->clients; 805 806 /* dispatch to an existing client if possible 807 * note that channel 0 is handled by a special 808 * QemudClient that is setup in qemud_multiplexer_init() 809 */ 810 for ( ; c != NULL; c = c->next ) { 811 if (c->channel == channel) { 812 qemud_client_recv(c, msg, msglen); 813 return; 814 } 815 } 816 817 D("%s: ignoring %d bytes for unknown channel %d", 818 __FUNCTION__, msglen, channel); 819 } 820 821 /* handle a new connection attempt. This returns 0 on 822 * success, -1 if the service name is unknown, or -2 823 * if the service's maximum number of clients has been 824 * reached. 825 */ 826 static int 827 qemud_multiplexer_connect( QemudMultiplexer* m, 828 const char* service_name, 829 int channel_id ) 830 { 831 QemudService* sv; 832 QemudClient* client; 833 834 /* find the corresponding registered service by name */ 835 for (sv = m->services; sv != NULL; sv = sv->next) { 836 if (!strcmp(sv->name, service_name)) { 837 break; 838 } 839 } 840 841 if (sv == NULL) { 842 D("%s: no registered '%s' service", __FUNCTION__, service_name); 843 return -1; 844 } 845 846 /* check service's client count */ 847 if (sv->max_clients > 0 && sv->num_clients >= sv->max_clients) { 848 D("%s: registration failed for '%s' service: too many clients (%d)", 849 __FUNCTION__, service_name, sv->num_clients); 850 return -2; 851 } 852 853 /* ask the service to create a new QemudClient. Note that we 854 * assume that this calls qemud_client_new() which will add 855 * the client to the service's list automatically. 856 */ 857 client = sv->serv_connect( sv->serv_opaque, sv, channel_id ); 858 if (client == NULL) { 859 D("%s: registration failed for '%s' service", 860 __FUNCTION__, service_name); 861 return -1; 862 } 863 864 D("%s: registered client channel %d for '%s' service", 865 __FUNCTION__, channel_id, service_name); 866 return 0; 867 } 868 869 /* disconnect a given client from its channel id */ 870 static void 871 qemud_multiplexer_disconnect( QemudMultiplexer* m, 872 int channel ) 873 { 874 QemudClient* c; 875 876 /* find the client by its channel id, then disconnect it */ 877 for (c = m->clients; c; c = c->next) { 878 if (c->channel == channel) { 879 D("%s: disconnecting client %d", 880 __FUNCTION__, channel); 881 /* note thatt this removes the client from 882 * m->clients automatically. 883 */ 884 c->channel = -1; /* no need to send disconnect:<id> */ 885 qemud_client_disconnect(c); 886 return; 887 } 888 } 889 D("%s: disconnecting unknown channel %d", 890 __FUNCTION__, channel); 891 } 892 893 /* handle control messages. This is used as the receive 894 * callback for the special QemudClient setup to manage 895 * channel 0. 896 * 897 * note that the message is zero-terminated for convenience 898 * (i.e. msg[msglen] is a valid memory read that returns '\0') 899 */ 900 static void 901 qemud_multiplexer_control_recv( void* opaque, 902 uint8_t* msg, 903 int msglen, 904 QemudClient* client ) 905 { 906 QemudMultiplexer* mult = opaque; 907 uint8_t* msgend = msg + msglen; 908 char tmp[64], *p=tmp, *end=p+sizeof(tmp); 909 910 /* handle connection attempts. 911 * the client message must be "connect:<service-name>:<id>" 912 * where <id> is a 2-char hexadecimal string, which must be > 0 913 */ 914 if (msglen > 8 && !memcmp(msg, "connect:", 8)) 915 { 916 const char* service_name = (const char*)msg + 8; 917 int channel, ret; 918 char* q; 919 920 q = strchr(service_name, ':'); 921 if (q == NULL || q+3 != (char*)msgend) { 922 D("%s: malformed connect message: '%.*s' (offset=%d)", 923 __FUNCTION__, msglen, (const char*)msg, q ? q-(char*)msg : -1); 924 return; 925 } 926 *q++ = 0; /* zero-terminate service name */ 927 channel = hex2int((uint8_t*)q, 2); 928 if (channel <= 0) { 929 D("%s: malformed channel id '%.*s", 930 __FUNCTION__, 2, q); 931 return; 932 } 933 934 ret = qemud_multiplexer_connect(mult, service_name, channel); 935 /* the answer can be one of: 936 * ok:connect:<id> 937 * ko:connect:<id>:<reason-for-failure> 938 */ 939 if (ret < 0) { 940 if (ret == -1) { 941 /* could not connect */ 942 p = bufprint(tmp, end, "ko:connect:%02x:unknown service", channel); 943 } else { 944 p = bufprint(tmp, end, "ko:connect:%02x:service busy", channel); 945 } 946 } 947 else { 948 p = bufprint(tmp, end, "ok:connect:%02x", channel); 949 } 950 qemud_serial_send(mult->serial, 0, 0, (uint8_t*)tmp, p-tmp); 951 return; 952 } 953 954 /* handle client disconnections, 955 * this message arrives when the client has closed the connection. 956 * format: "disconnect:<id>" where <id> is a 2-hex channel id > 0 957 */ 958 if (msglen == 13 && !memcmp(msg, "disconnect:", 11)) { 959 int channel_id = hex2int(msg+11, 2); 960 if (channel_id <= 0) { 961 D("%s: malformed disconnect channel id: '%.*s'", 962 __FUNCTION__, 2, msg+11); 963 return; 964 } 965 qemud_multiplexer_disconnect(mult, channel_id); 966 return; 967 } 968 969 #if SUPPORT_LEGACY_QEMUD 970 /* an ok:connect:<service>:<id> message can be received if we're 971 * talking to a legacy qemud daemon, i.e. one running in a 1.0 or 972 * 1.1 system image. 973 * 974 * we should treat is as a normal "connect:" attempt, except that 975 * we must not send back any acknowledgment. 976 */ 977 if (msglen > 11 && !memcmp(msg, "ok:connect:", 11)) { 978 const char* service_name = (const char*)msg + 11; 979 char* q = strchr(service_name, ':'); 980 int channel; 981 982 if (q == NULL || q+3 != (char*)msgend) { 983 D("%s: malformed legacy connect message: '%.*s' (offset=%d)", 984 __FUNCTION__, msglen, (const char*)msg, q ? q-(char*)msg : -1); 985 return; 986 } 987 *q++ = 0; /* zero-terminate service name */ 988 channel = hex2int((uint8_t*)q, 2); 989 if (channel <= 0) { 990 D("%s: malformed legacy channel id '%.*s", 991 __FUNCTION__, 2, q); 992 return; 993 } 994 995 switch (mult->serial->version) { 996 case QEMUD_VERSION_UNKNOWN: 997 mult->serial->version = QEMUD_VERSION_LEGACY; 998 D("%s: legacy qemud daemon detected.", __FUNCTION__); 999 break; 1000 1001 case QEMUD_VERSION_LEGACY: 1002 /* nothing unusual */ 1003 break; 1004 1005 default: 1006 D("%s: weird, ignoring legacy qemud control message: '%.*s'", 1007 __FUNCTION__, msglen, msg); 1008 return; 1009 } 1010 1011 /* "hw-control" was called "control" in 1.0/1.1 */ 1012 if (!strcmp(service_name,"control")) 1013 service_name = "hw-control"; 1014 1015 qemud_multiplexer_connect(mult, service_name, channel); 1016 return; 1017 } 1018 1019 /* anything else, don't answer for legacy */ 1020 if (mult->serial->version == QEMUD_VERSION_LEGACY) 1021 return; 1022 #endif /* SUPPORT_LEGACY_QEMUD */ 1023 1024 /* anything else is a problem */ 1025 p = bufprint(tmp, end, "ko:unknown command"); 1026 qemud_serial_send(mult->serial, 0, 0, (uint8_t*)tmp, p-tmp); 1027 } 1028 1029 /* initialize the global QemudMultiplexer. 1030 */ 1031 static void 1032 qemud_multiplexer_init( QemudMultiplexer* mult, 1033 CharDriverState* serial_cs ) 1034 { 1035 QemudClient* control; 1036 1037 /* initialize serial handler */ 1038 qemud_serial_init( mult->serial, 1039 serial_cs, 1040 qemud_multiplexer_serial_recv, 1041 mult ); 1042 1043 /* setup listener for channel 0 */ 1044 control = qemud_client_alloc( 0, 1045 mult, 1046 qemud_multiplexer_control_recv, 1047 NULL, 1048 mult->serial, 1049 &mult->clients ); 1050 } 1051 1052 /* the global multiplexer state */ 1053 static QemudMultiplexer _multiplexer[1]; 1054 1055 /** HIGH-LEVEL API 1056 **/ 1057 1058 /* this function must be used in the serv_connect callback 1059 * of a given QemudService object (see qemud_service_register() 1060 * below). It is used to register a new QemudClient to acknowledge 1061 * a new client connection. 1062 * 1063 * 'clie_opaque', 'clie_recv' and 'clie_close' are used to 1064 * send incoming client messages to the corresponding service 1065 * implementation, or notify the service that a client has 1066 * disconnected. 1067 */ 1068 QemudClient* 1069 qemud_client_new( QemudService* service, 1070 int channelId, 1071 void* clie_opaque, 1072 QemudClientRecv clie_recv, 1073 QemudClientClose clie_close ) 1074 { 1075 QemudMultiplexer* m = _multiplexer; 1076 QemudClient* c = qemud_client_alloc( channelId, 1077 clie_opaque, 1078 clie_recv, 1079 clie_close, 1080 m->serial, 1081 &m->clients ); 1082 1083 qemud_service_add_client(service, c); 1084 return c; 1085 } 1086 1087 /* this can be used by a service implementation to send an answer 1088 * or message to a specific client. 1089 */ 1090 void 1091 qemud_client_send ( QemudClient* client, const uint8_t* msg, int msglen ) 1092 { 1093 qemud_serial_send(client->serial, client->channel, client->framing != 0, msg, msglen); 1094 } 1095 1096 /* enable framing for this client. When TRUE, this will 1097 * use internally a simple 4-hexchar header before each 1098 * message exchanged through the serial port. 1099 */ 1100 void 1101 qemud_client_set_framing( QemudClient* client, int framing ) 1102 { 1103 /* release dynamic buffer if we're disabling framing */ 1104 if (client->framing) { 1105 if (!client->need_header) { 1106 AFREE(client->payload->buff); 1107 client->need_header = 1; 1108 } 1109 } 1110 client->framing = !!framing; 1111 } 1112 1113 /* this can be used by a service implementation to close a 1114 * specific client connection. 1115 */ 1116 void 1117 qemud_client_close( QemudClient* client ) 1118 { 1119 qemud_client_disconnect(client); 1120 } 1121 1122 1123 1124 /* this is the end of the serial charpipe that must be passed 1125 * to the emulated tty implementation. The other end of the 1126 * charpipe must be passed to qemud_multiplexer_init(). 1127 */ 1128 static CharDriverState* android_qemud_cs; 1129 1130 extern void 1131 android_qemud_init( void ) 1132 { 1133 CharDriverState* cs; 1134 1135 if (android_qemud_cs != NULL) 1136 return; 1137 1138 if (qemu_chr_open_charpipe( &android_qemud_cs, &cs ) < 0) { 1139 derror( "%s: can't create charpipe to serial port", 1140 __FUNCTION__ ); 1141 exit(1); 1142 } 1143 1144 qemud_multiplexer_init(_multiplexer, cs); 1145 } 1146 1147 /* return the serial charpipe endpoint that must be used 1148 * by the emulated tty implementation. 1149 */ 1150 CharDriverState* android_qemud_get_cs( void ) 1151 { 1152 if (android_qemud_cs == NULL) 1153 android_qemud_init(); 1154 1155 return android_qemud_cs; 1156 } 1157 1158 /* this function is used to register a new named qemud-based 1159 * service. You must provide 'serv_opaque' and 'serv_connect' 1160 * which will be called whenever a new client tries to connect 1161 * to the services. 1162 * 1163 * 'serv_connect' shall return NULL if the connection is refused, 1164 * or a handle to a new QemudClient otherwise. The latter can be 1165 * created through qemud_client_new() defined above. 1166 * 1167 * 'max_clients' is the maximum number of clients accepted by 1168 * the service concurrently. If this value is 0, then any number 1169 * of clients can connect. 1170 */ 1171 QemudService* 1172 qemud_service_register( const char* service_name, 1173 int max_clients, 1174 void* serv_opaque, 1175 QemudServiceConnect serv_connect ) 1176 { 1177 QemudMultiplexer* m = _multiplexer; 1178 QemudService* sv; 1179 1180 if (android_qemud_cs == NULL) 1181 android_qemud_init(); 1182 1183 sv = qemud_service_new(service_name, 1184 max_clients, 1185 serv_opaque, 1186 serv_connect, 1187 &m->services); 1188 1189 return sv; 1190 } 1191 1192 /* broadcast a given message to all clients of a given QemudService 1193 */ 1194 extern void 1195 qemud_service_broadcast( QemudService* sv, 1196 const uint8_t* msg, 1197 int msglen ) 1198 { 1199 QemudClient* c; 1200 1201 for (c = sv->clients; c; c = c->next_serv) 1202 qemud_client_send(c, msg, msglen); 1203 } 1204 1205 1206 1207 /* 1208 * The following code is used for backwards compatibility reasons. 1209 * It allows you to implement a given qemud-based service through 1210 * a charpipe. 1211 * 1212 * In other words, this implements a QemudService and corresponding 1213 * QemudClient that connects a qemud client running in the emulated 1214 * system, to a CharDriverState object implemented through a charpipe. 1215 * 1216 * QemudCharClient <===charpipe====> (char driver user) 1217 * 1218 * For example, this is used to implement the "gsm" service when the 1219 * modem emulation is provided through an external serial device. 1220 * 1221 * A QemudCharService can have only one client by definition. 1222 * There is no QemudCharClient object because we can store a single 1223 * CharDriverState handle in the 'opaque' field for simplicity. 1224 */ 1225 1226 typedef struct { 1227 QemudService* service; 1228 CharDriverState* cs; 1229 } QemudCharService; 1230 1231 /* called whenever a new message arrives from a qemud client. 1232 * this simply sends the message through the charpipe to the user. 1233 */ 1234 static void 1235 _qemud_char_client_recv( void* opaque, uint8_t* msg, int msglen, 1236 QemudClient* client ) 1237 { 1238 CharDriverState* cs = opaque; 1239 qemu_chr_write(cs, msg, msglen); 1240 } 1241 1242 /* we don't expect clients of char. services to exit. Just 1243 * print an error to signal an unexpected situation. We should 1244 * be able to recover from these though, so don't panic. 1245 */ 1246 static void 1247 _qemud_char_client_close( void* opaque ) 1248 { 1249 derror("unexpected qemud char. channel close"); 1250 } 1251 1252 1253 /* called by the charpipe to know how much data can be read from 1254 * the user. Since we send everything directly to the serial port 1255 * we can return an arbitrary number. 1256 */ 1257 static int 1258 _qemud_char_service_can_read( void* opaque ) 1259 { 1260 return 8192; /* whatever */ 1261 } 1262 1263 /* called to read data from the charpipe and send it to the client. 1264 * used qemud_service_broadcast() even if there is a single client 1265 * because we don't need a QemudCharClient object this way. 1266 */ 1267 static void 1268 _qemud_char_service_read( void* opaque, const uint8_t* from, int len ) 1269 { 1270 QemudService* sv = opaque; 1271 qemud_service_broadcast( sv, from, len ); 1272 } 1273 1274 /* called when a qemud client tries to connect to a char. service. 1275 * we simply create a new client and open the charpipe to receive 1276 * data from it. 1277 */ 1278 static QemudClient* 1279 _qemud_char_service_connect( void* opaque, QemudService* sv, int channel ) 1280 { 1281 CharDriverState* cs = opaque; 1282 QemudClient* c = qemud_client_new( sv, channel, 1283 cs, 1284 _qemud_char_client_recv, 1285 _qemud_char_client_close); 1286 1287 /* now we can open the gates :-) */ 1288 qemu_chr_add_handlers( cs, 1289 _qemud_char_service_can_read, 1290 _qemud_char_service_read, 1291 NULL, 1292 sv ); 1293 1294 return c; 1295 } 1296 1297 /* returns a charpipe endpoint that can be used by an emulated 1298 * device or external serial port to implement a char. service 1299 */ 1300 int 1301 android_qemud_get_channel( const char* name, CharDriverState* *pcs ) 1302 { 1303 CharDriverState* cs; 1304 1305 if (qemu_chr_open_charpipe(&cs, pcs) < 0) { 1306 derror("can't open charpipe for '%s' qemud service", name); 1307 exit(2); 1308 } 1309 qemud_service_register(name, 1, cs, _qemud_char_service_connect); 1310 return 0; 1311 } 1312 1313 /* set the character driver state for a given qemud communication channel. this 1314 * is used to attach the channel to an external char driver device directly. 1315 * returns 0 on success, -1 on error 1316 */ 1317 int 1318 android_qemud_set_channel( const char* name, CharDriverState* peer_cs ) 1319 { 1320 CharDriverState* char_buffer = qemu_chr_open_buffer(peer_cs); 1321 1322 if (char_buffer == NULL) 1323 return -1; 1324 1325 qemud_service_register(name, 1, char_buffer, _qemud_char_service_connect); 1326 return 0; 1327 } 1328