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 /* read the header */ 577 if (c->need_header) { 578 int frame_size; 579 uint8_t* data; 580 581 if (!qemud_sink_fill(c->header, (const uint8_t**)&msg, &msglen)) 582 break; 583 584 frame_size = hex2int(c->header0, 4); 585 if (frame_size == 0) { 586 D("%s: ignoring empty frame", __FUNCTION__); 587 continue; 588 } 589 if (frame_size < 0) { 590 D("%s: ignoring corrupted frame header '.*s'", 591 __FUNCTION__, FRAME_HEADER_SIZE, c->header0 ); 592 continue; 593 } 594 595 AARRAY_NEW(data, frame_size+1); /* +1 for terminating zero */ 596 qemud_sink_reset(c->payload, frame_size, data); 597 c->need_header = 0; 598 c->header->len = 0; 599 } 600 601 /* read the payload */ 602 if (!qemud_sink_fill(c->payload, (const uint8_t**)&msg, &msglen)) 603 break; 604 605 c->payload->buff[c->payload->size] = 0; 606 607 608 if (c->clie_recv) 609 c->clie_recv( c->clie_opaque, c->payload->buff, c->payload->size, c ); 610 611 AFREE(c->payload->buff); 612 c->need_header = 1; 613 } 614 } 615 616 /* disconnect a client. this automatically frees the QemudClient. 617 * note that this also removes the client from the global list 618 * and from its service's list, if any. 619 */ 620 static void 621 qemud_client_disconnect( void* opaque ) 622 { 623 QemudClient* c = opaque; 624 625 /* remove from current list */ 626 qemud_client_remove(c); 627 628 /* send a disconnect command to the daemon */ 629 if (c->channel > 0) { 630 char tmp[128], *p=tmp, *end=p+sizeof(tmp); 631 p = bufprint(tmp, end, "disconnect:%02x", c->channel); 632 qemud_serial_send(c->serial, 0, 0, (uint8_t*)tmp, p-tmp); 633 } 634 635 /* call the client close callback */ 636 if (c->clie_close) { 637 c->clie_close(c->clie_opaque); 638 c->clie_close = NULL; 639 } 640 c->clie_recv = NULL; 641 642 /* remove from service list, if any */ 643 if (c->service) { 644 qemud_service_remove_client(c->service, c); 645 c->service = NULL; 646 } 647 648 AFREE(c); 649 } 650 651 /* allocate a new QemudClient object */ 652 static QemudClient* 653 qemud_client_alloc( int channel_id, 654 void* clie_opaque, 655 QemudClientRecv clie_recv, 656 QemudClientClose clie_close, 657 QemudSerial* serial, 658 QemudClient** pclients ) 659 { 660 QemudClient* c; 661 662 ANEW0(c); 663 664 c->serial = serial; 665 c->channel = channel_id; 666 c->clie_opaque = clie_opaque; 667 c->clie_recv = clie_recv; 668 c->clie_close = clie_close; 669 670 c->framing = 0; 671 c->need_header = 1; 672 qemud_sink_reset(c->header, FRAME_HEADER_SIZE, c->header0); 673 674 qemud_client_prepend(c, pclients); 675 676 return c; 677 } 678 679 /** SERVICES 680 **/ 681 682 /* A QemudService models a _named_ service facility implemented 683 * by the emulator, that clients in the emulated system can connect 684 * to. 685 * 686 * Each service can have a limit on the number of clients they 687 * accept (this number if unlimited if 'max_clients' is 0). 688 * 689 * Each service maintains a list of active QemudClients and 690 * can also be used to create new QemudClient objects through 691 * its 'serv_opaque' and 'serv_connect' fields. 692 */ 693 struct QemudService { 694 const char* name; 695 int max_clients; 696 int num_clients; 697 QemudClient* clients; 698 QemudServiceConnect serv_connect; 699 void* serv_opaque; 700 QemudService* next; 701 }; 702 703 /* Create a new QemudService object */ 704 static QemudService* 705 qemud_service_new( const char* name, 706 int max_clients, 707 void* serv_opaque, 708 QemudServiceConnect serv_connect, 709 QemudService** pservices ) 710 { 711 QemudService* s; 712 713 ANEW0(s); 714 s->name = ASTRDUP(name); 715 s->max_clients = max_clients; 716 s->num_clients = 0; 717 s->clients = NULL; 718 719 s->serv_opaque = serv_opaque; 720 s->serv_connect = serv_connect; 721 722 s->next = *pservices; 723 *pservices = s; 724 725 return s; 726 } 727 728 /* used internally to populate a QemudService object with a 729 * new QemudClient */ 730 static void 731 qemud_service_add_client( QemudService* s, QemudClient* c ) 732 { 733 c->service = s; 734 c->next_serv = s->clients; 735 s->clients = c; 736 s->num_clients += 1; 737 } 738 739 /* used internally to remove a QemudClient from a QemudService */ 740 static void 741 qemud_service_remove_client( QemudService* s, QemudClient* c ) 742 { 743 QemudClient** pnode = &s->clients; 744 QemudClient* node; 745 746 /* remove from clients linked-list */ 747 for (;;) { 748 node = *pnode; 749 if (node == NULL) { 750 D("%s: could not find client %d for service '%s'", 751 __FUNCTION__, c->channel, s->name); 752 return; 753 } 754 if (node == c) 755 break; 756 pnode = &node->next_serv; 757 } 758 759 *pnode = node->next_serv; 760 s->num_clients -= 1; 761 } 762 763 /** MULTIPLEXER 764 **/ 765 766 /* A QemudMultiplexer object maintains the global state of the 767 * qemud service facility. It holds a QemudSerial object to 768 * maintain the state of the serial port connection. 769 * 770 * The QemudMultiplexer receives all incoming messages from 771 * the serial port, and dispatches them to the appropriate 772 * QemudClient. 773 * 774 * It also has a global list of clients, and a global list of 775 * services. 776 * 777 * Finally, the QemudMultiplexer has a special QemudClient used 778 * to handle channel 0, i.e. the control channel used to handle 779 * connections and disconnections of clients. 780 */ 781 typedef struct QemudMultiplexer QemudMultiplexer; 782 783 struct QemudMultiplexer { 784 QemudSerial serial[1]; 785 QemudClient* clients; 786 QemudService* services; 787 }; 788 789 /* this is the serial_recv callback that is called 790 * whenever an incoming message arrives through the serial port 791 */ 792 static void 793 qemud_multiplexer_serial_recv( void* opaque, 794 int channel, 795 uint8_t* msg, 796 int msglen ) 797 { 798 QemudMultiplexer* m = opaque; 799 QemudClient* c = m->clients; 800 801 /* dispatch to an existing client if possible 802 * note that channel 0 is handled by a special 803 * QemudClient that is setup in qemud_multiplexer_init() 804 */ 805 for ( ; c != NULL; c = c->next ) { 806 if (c->channel == channel) { 807 qemud_client_recv(c, msg, msglen); 808 return; 809 } 810 } 811 812 D("%s: ignoring %d bytes for unknown channel %d", 813 __FUNCTION__, msglen, channel); 814 } 815 816 /* handle a new connection attempt. This returns 0 on 817 * success, -1 if the service name is unknown, or -2 818 * if the service's maximum number of clients has been 819 * reached. 820 */ 821 static int 822 qemud_multiplexer_connect( QemudMultiplexer* m, 823 const char* service_name, 824 int channel_id ) 825 { 826 QemudService* sv; 827 QemudClient* client; 828 829 /* find the corresponding registered service by name */ 830 for (sv = m->services; sv != NULL; sv = sv->next) { 831 if (!strcmp(sv->name, service_name)) { 832 break; 833 } 834 } 835 836 if (sv == NULL) { 837 D("%s: no registered '%s' service", __FUNCTION__, service_name); 838 return -1; 839 } 840 841 /* check service's client count */ 842 if (sv->max_clients > 0 && sv->num_clients >= sv->max_clients) { 843 D("%s: registration failed for '%s' service: too many clients (%d)", 844 __FUNCTION__, service_name, sv->num_clients); 845 return -2; 846 } 847 848 /* ask the service to create a new QemudClient. Note that we 849 * assume that this calls qemud_client_new() which will add 850 * the client to the service's list automatically. 851 */ 852 client = sv->serv_connect( sv->serv_opaque, sv, channel_id ); 853 if (client == NULL) { 854 D("%s: registration failed for '%s' service", 855 __FUNCTION__, service_name); 856 return -1; 857 } 858 859 D("%s: registered client channel %d for '%s' service", 860 __FUNCTION__, channel_id, service_name); 861 return 0; 862 } 863 864 /* disconnect a given client from its channel id */ 865 static void 866 qemud_multiplexer_disconnect( QemudMultiplexer* m, 867 int channel ) 868 { 869 QemudClient* c; 870 871 /* find the client by its channel id, then disconnect it */ 872 for (c = m->clients; c; c = c->next) { 873 if (c->channel == channel) { 874 D("%s: disconnecting client %d", 875 __FUNCTION__, channel); 876 /* note thatt this removes the client from 877 * m->clients automatically. 878 */ 879 c->channel = -1; /* no need to send disconnect:<id> */ 880 qemud_client_disconnect(c); 881 return; 882 } 883 } 884 D("%s: disconnecting unknown channel %d", 885 __FUNCTION__, channel); 886 } 887 888 /* handle control messages. This is used as the receive 889 * callback for the special QemudClient setup to manage 890 * channel 0. 891 * 892 * note that the message is zero-terminated for convenience 893 * (i.e. msg[msglen] is a valid memory read that returns '\0') 894 */ 895 static void 896 qemud_multiplexer_control_recv( void* opaque, 897 uint8_t* msg, 898 int msglen, 899 QemudClient* client ) 900 { 901 QemudMultiplexer* mult = opaque; 902 uint8_t* msgend = msg + msglen; 903 char tmp[64], *p=tmp, *end=p+sizeof(tmp); 904 905 /* handle connection attempts. 906 * the client message must be "connect:<service-name>:<id>" 907 * where <id> is a 2-char hexadecimal string, which must be > 0 908 */ 909 if (msglen > 8 && !memcmp(msg, "connect:", 8)) 910 { 911 const char* service_name = (const char*)msg + 8; 912 int channel, ret; 913 char* q; 914 915 q = strchr(service_name, ':'); 916 if (q == NULL || q+3 != (char*)msgend) { 917 D("%s: malformed connect message: '%.*s' (offset=%d)", 918 __FUNCTION__, msglen, (const char*)msg, q ? q-(char*)msg : -1); 919 return; 920 } 921 *q++ = 0; /* zero-terminate service name */ 922 channel = hex2int((uint8_t*)q, 2); 923 if (channel <= 0) { 924 D("%s: malformed channel id '%.*s", 925 __FUNCTION__, 2, q); 926 return; 927 } 928 929 ret = qemud_multiplexer_connect(mult, service_name, channel); 930 /* the answer can be one of: 931 * ok:connect:<id> 932 * ko:connect:<id>:<reason-for-failure> 933 */ 934 if (ret < 0) { 935 if (ret == -1) { 936 /* could not connect */ 937 p = bufprint(tmp, end, "ko:connect:%02x:unknown service", channel); 938 } else { 939 p = bufprint(tmp, end, "ko:connect:%02x:service busy", channel); 940 } 941 } 942 else { 943 p = bufprint(tmp, end, "ok:connect:%02x", channel); 944 } 945 qemud_serial_send(mult->serial, 0, 0, (uint8_t*)tmp, p-tmp); 946 return; 947 } 948 949 /* handle client disconnections, 950 * this message arrives when the client has closed the connection. 951 * format: "disconnect:<id>" where <id> is a 2-hex channel id > 0 952 */ 953 if (msglen == 13 && !memcmp(msg, "disconnect:", 11)) { 954 int channel_id = hex2int(msg+11, 2); 955 if (channel_id <= 0) { 956 D("%s: malformed disconnect channel id: '%.*s'", 957 __FUNCTION__, 2, msg+11); 958 return; 959 } 960 qemud_multiplexer_disconnect(mult, channel_id); 961 return; 962 } 963 964 #if SUPPORT_LEGACY_QEMUD 965 /* an ok:connect:<service>:<id> message can be received if we're 966 * talking to a legacy qemud daemon, i.e. one running in a 1.0 or 967 * 1.1 system image. 968 * 969 * we should treat is as a normal "connect:" attempt, except that 970 * we must not send back any acknowledgment. 971 */ 972 if (msglen > 11 && !memcmp(msg, "ok:connect:", 11)) { 973 const char* service_name = (const char*)msg + 11; 974 char* q = strchr(service_name, ':'); 975 int channel; 976 977 if (q == NULL || q+3 != (char*)msgend) { 978 D("%s: malformed legacy connect message: '%.*s' (offset=%d)", 979 __FUNCTION__, msglen, (const char*)msg, q ? q-(char*)msg : -1); 980 return; 981 } 982 *q++ = 0; /* zero-terminate service name */ 983 channel = hex2int((uint8_t*)q, 2); 984 if (channel <= 0) { 985 D("%s: malformed legacy channel id '%.*s", 986 __FUNCTION__, 2, q); 987 return; 988 } 989 990 switch (mult->serial->version) { 991 case QEMUD_VERSION_UNKNOWN: 992 mult->serial->version = QEMUD_VERSION_LEGACY; 993 D("%s: legacy qemud daemon detected.", __FUNCTION__); 994 break; 995 996 case QEMUD_VERSION_LEGACY: 997 /* nothing unusual */ 998 break; 999 1000 default: 1001 D("%s: weird, ignoring legacy qemud control message: '%.*s'", 1002 __FUNCTION__, msglen, msg); 1003 return; 1004 } 1005 1006 /* "hw-control" was called "control" in 1.0/1.1 */ 1007 if (!strcmp(service_name,"control")) 1008 service_name = "hw-control"; 1009 1010 qemud_multiplexer_connect(mult, service_name, channel); 1011 return; 1012 } 1013 1014 /* anything else, don't answer for legacy */ 1015 if (mult->serial->version == QEMUD_VERSION_LEGACY) 1016 return; 1017 #endif /* SUPPORT_LEGACY_QEMUD */ 1018 1019 /* anything else is a problem */ 1020 p = bufprint(tmp, end, "ko:unknown command"); 1021 qemud_serial_send(mult->serial, 0, 0, (uint8_t*)tmp, p-tmp); 1022 } 1023 1024 /* initialize the global QemudMultiplexer. 1025 */ 1026 static void 1027 qemud_multiplexer_init( QemudMultiplexer* mult, 1028 CharDriverState* serial_cs ) 1029 { 1030 QemudClient* control; 1031 1032 /* initialize serial handler */ 1033 qemud_serial_init( mult->serial, 1034 serial_cs, 1035 qemud_multiplexer_serial_recv, 1036 mult ); 1037 1038 /* setup listener for channel 0 */ 1039 control = qemud_client_alloc( 0, 1040 mult, 1041 qemud_multiplexer_control_recv, 1042 NULL, 1043 mult->serial, 1044 &mult->clients ); 1045 } 1046 1047 /* the global multiplexer state */ 1048 static QemudMultiplexer _multiplexer[1]; 1049 1050 /** HIGH-LEVEL API 1051 **/ 1052 1053 /* this function must be used in the serv_connect callback 1054 * of a given QemudService object (see qemud_service_register() 1055 * below). It is used to register a new QemudClient to acknowledge 1056 * a new client connection. 1057 * 1058 * 'clie_opaque', 'clie_recv' and 'clie_close' are used to 1059 * send incoming client messages to the corresponding service 1060 * implementation, or notify the service that a client has 1061 * disconnected. 1062 */ 1063 QemudClient* 1064 qemud_client_new( QemudService* service, 1065 int channelId, 1066 void* clie_opaque, 1067 QemudClientRecv clie_recv, 1068 QemudClientClose clie_close ) 1069 { 1070 QemudMultiplexer* m = _multiplexer; 1071 QemudClient* c = qemud_client_alloc( channelId, 1072 clie_opaque, 1073 clie_recv, 1074 clie_close, 1075 m->serial, 1076 &m->clients ); 1077 1078 qemud_service_add_client(service, c); 1079 return c; 1080 } 1081 1082 /* this can be used by a service implementation to send an answer 1083 * or message to a specific client. 1084 */ 1085 void 1086 qemud_client_send ( QemudClient* client, const uint8_t* msg, int msglen ) 1087 { 1088 qemud_serial_send(client->serial, client->channel, client->framing != 0, msg, msglen); 1089 } 1090 1091 /* enable framing for this client. When TRUE, this will 1092 * use internally a simple 4-hexchar header before each 1093 * message exchanged through the serial port. 1094 */ 1095 void 1096 qemud_client_set_framing( QemudClient* client, int framing ) 1097 { 1098 /* release dynamic buffer if we're disabling framing */ 1099 if (client->framing) { 1100 if (!client->need_header) { 1101 AFREE(client->payload->buff); 1102 client->need_header = 1; 1103 } 1104 } 1105 client->framing = !!framing; 1106 } 1107 1108 /* this can be used by a service implementation to close a 1109 * specific client connection. 1110 */ 1111 void 1112 qemud_client_close( QemudClient* client ) 1113 { 1114 qemud_client_disconnect(client); 1115 } 1116 1117 1118 1119 /* this is the end of the serial charpipe that must be passed 1120 * to the emulated tty implementation. The other end of the 1121 * charpipe must be passed to qemud_multiplexer_init(). 1122 */ 1123 static CharDriverState* android_qemud_cs; 1124 1125 extern void 1126 android_qemud_init( void ) 1127 { 1128 CharDriverState* cs; 1129 1130 if (android_qemud_cs != NULL) 1131 return; 1132 1133 if (qemu_chr_open_charpipe( &android_qemud_cs, &cs ) < 0) { 1134 derror( "%s: can't create charpipe to serial port", 1135 __FUNCTION__ ); 1136 exit(1); 1137 } 1138 1139 qemud_multiplexer_init(_multiplexer, cs); 1140 } 1141 1142 /* return the serial charpipe endpoint that must be used 1143 * by the emulated tty implementation. 1144 */ 1145 CharDriverState* android_qemud_get_cs( void ) 1146 { 1147 if (android_qemud_cs == NULL) 1148 android_qemud_init(); 1149 1150 return android_qemud_cs; 1151 } 1152 1153 /* this function is used to register a new named qemud-based 1154 * service. You must provide 'serv_opaque' and 'serv_connect' 1155 * which will be called whenever a new client tries to connect 1156 * to the services. 1157 * 1158 * 'serv_connect' shall return NULL if the connection is refused, 1159 * or a handle to a new QemudClient otherwise. The latter can be 1160 * created through qemud_client_new() defined above. 1161 * 1162 * 'max_clients' is the maximum number of clients accepted by 1163 * the service concurrently. If this value is 0, then any number 1164 * of clients can connect. 1165 */ 1166 QemudService* 1167 qemud_service_register( const char* service_name, 1168 int max_clients, 1169 void* serv_opaque, 1170 QemudServiceConnect serv_connect ) 1171 { 1172 QemudMultiplexer* m = _multiplexer; 1173 QemudService* sv; 1174 1175 if (android_qemud_cs == NULL) 1176 android_qemud_init(); 1177 1178 sv = qemud_service_new(service_name, 1179 max_clients, 1180 serv_opaque, 1181 serv_connect, 1182 &m->services); 1183 1184 return sv; 1185 } 1186 1187 /* broadcast a given message to all clients of a given QemudService 1188 */ 1189 extern void 1190 qemud_service_broadcast( QemudService* sv, 1191 const uint8_t* msg, 1192 int msglen ) 1193 { 1194 QemudClient* c; 1195 1196 for (c = sv->clients; c; c = c->next_serv) 1197 qemud_client_send(c, msg, msglen); 1198 } 1199 1200 1201 1202 /* 1203 * The following code is used for backwards compatibility reasons. 1204 * It allows you to implement a given qemud-based service through 1205 * a charpipe. 1206 * 1207 * In other words, this implements a QemudService and corresponding 1208 * QemudClient that connects a qemud client running in the emulated 1209 * system, to a CharDriverState object implemented through a charpipe. 1210 * 1211 * QemudCharClient <===charpipe====> (char driver user) 1212 * 1213 * For example, this is used to implement the "gsm" service when the 1214 * modem emulation is provided through an external serial device. 1215 * 1216 * A QemudCharService can have only one client by definition. 1217 * There is no QemudCharClient object because we can store a single 1218 * CharDriverState handle in the 'opaque' field for simplicity. 1219 */ 1220 1221 typedef struct { 1222 QemudService* service; 1223 CharDriverState* cs; 1224 } QemudCharService; 1225 1226 /* called whenever a new message arrives from a qemud client. 1227 * this simply sends the message through the charpipe to the user. 1228 */ 1229 static void 1230 _qemud_char_client_recv( void* opaque, uint8_t* msg, int msglen, 1231 QemudClient* client ) 1232 { 1233 CharDriverState* cs = opaque; 1234 qemu_chr_write(cs, msg, msglen); 1235 } 1236 1237 /* we don't expect clients of char. services to exit. Just 1238 * print an error to signal an unexpected situation. We should 1239 * be able to recover from these though, so don't panic. 1240 */ 1241 static void 1242 _qemud_char_client_close( void* opaque ) 1243 { 1244 derror("unexpected qemud char. channel close"); 1245 } 1246 1247 1248 /* called by the charpipe to know how much data can be read from 1249 * the user. Since we send everything directly to the serial port 1250 * we can return an arbitrary number. 1251 */ 1252 static int 1253 _qemud_char_service_can_read( void* opaque ) 1254 { 1255 return 8192; /* whatever */ 1256 } 1257 1258 /* called to read data from the charpipe and send it to the client. 1259 * used qemud_service_broadcast() even if there is a single client 1260 * because we don't need a QemudCharClient object this way. 1261 */ 1262 static void 1263 _qemud_char_service_read( void* opaque, const uint8_t* from, int len ) 1264 { 1265 QemudService* sv = opaque; 1266 qemud_service_broadcast( sv, from, len ); 1267 } 1268 1269 /* called when a qemud client tries to connect to a char. service. 1270 * we simply create a new client and open the charpipe to receive 1271 * data from it. 1272 */ 1273 static QemudClient* 1274 _qemud_char_service_connect( void* opaque, QemudService* sv, int channel ) 1275 { 1276 CharDriverState* cs = opaque; 1277 QemudClient* c = qemud_client_new( sv, channel, 1278 cs, 1279 _qemud_char_client_recv, 1280 _qemud_char_client_close); 1281 1282 /* now we can open the gates :-) */ 1283 qemu_chr_add_handlers( cs, 1284 _qemud_char_service_can_read, 1285 _qemud_char_service_read, 1286 NULL, 1287 sv ); 1288 1289 return c; 1290 } 1291 1292 /* returns a charpipe endpoint that can be used by an emulated 1293 * device or external serial port to implement a char. service 1294 */ 1295 int 1296 android_qemud_get_channel( const char* name, CharDriverState* *pcs ) 1297 { 1298 CharDriverState* cs; 1299 1300 if (qemu_chr_open_charpipe(&cs, pcs) < 0) { 1301 derror("can't open charpipe for '%s' qemud service", name); 1302 exit(2); 1303 } 1304 qemud_service_register(name, 1, cs, _qemud_char_service_connect); 1305 return 0; 1306 } 1307 1308 /* set the character driver state for a given qemud communication channel. this 1309 * is used to attach the channel to an external char driver device directly. 1310 * returns 0 on success, -1 on error 1311 */ 1312 int 1313 android_qemud_set_channel( const char* name, CharDriverState* peer_cs ) 1314 { 1315 CharDriverState* char_buffer = qemu_chr_open_buffer(peer_cs); 1316 1317 if (char_buffer == NULL) 1318 return -1; 1319 1320 qemud_service_register(name, 1, char_buffer, _qemud_char_service_connect); 1321 return 0; 1322 } 1323