Home | History | Annotate | Download | only in android
      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 /*
     13  *  Android emulator control console
     14  *
     15  *  this console is enabled automatically at emulator startup, on port 5554 by default,
     16  *  unless some other emulator is already running. See (android_emulation_start in android_sdl.c
     17  *  for details)
     18  *
     19  *  you can telnet to the console, then use commands like 'help' or others to dynamically
     20  *  change emulator settings.
     21  *
     22  */
     23 
     24 #include "sockets.h"
     25 #include "qemu-char.h"
     26 #include "sysemu.h"
     27 #include "android/android.h"
     28 #include "cpu.h"
     29 #include "hw/goldfish_device.h"
     30 #include "hw/power_supply.h"
     31 #include "shaper.h"
     32 #include "modem_driver.h"
     33 #include "android/gps.h"
     34 #include "android/globals.h"
     35 #include "android/utils/bufprint.h"
     36 #include "android/utils/debug.h"
     37 #include "android/utils/stralloc.h"
     38 #include "android/config/config.h"
     39 #include "tcpdump.h"
     40 #include "net.h"
     41 #include "monitor.h"
     42 
     43 #include <stdlib.h>
     44 #include <stdio.h>
     45 #include <stdarg.h>
     46 #include <string.h>
     47 #include <unistd.h>
     48 #include <fcntl.h>
     49 #include "android/hw-events.h"
     50 #include "user-events.h"
     51 #include "android/hw-sensors.h"
     52 #include "android/keycode-array.h"
     53 #include "android/charmap.h"
     54 #include "android/display-core.h"
     55 #include "android/protocol/fb-updates-proxy.h"
     56 #include "android/protocol/user-events-impl.h"
     57 #include "android/protocol/ui-commands-api.h"
     58 #include "android/protocol/core-commands-impl.h"
     59 #include "android/protocol/ui-commands-proxy.h"
     60 #include "android/protocol/attach-ui-proxy.h"
     61 
     62 #if defined(CONFIG_SLIRP)
     63 #include "libslirp.h"
     64 #endif
     65 
     66 #define  DEBUG  1
     67 
     68 #if 1
     69 #  define  D_ACTIVE   VERBOSE_CHECK(console)
     70 #else
     71 #  define  D_ACTIVE   DEBUG
     72 #endif
     73 
     74 #if DEBUG
     75 #  define  D(x)   do { if (D_ACTIVE) ( printf x , fflush(stdout) ); } while (0)
     76 #else
     77 #  define  D(x)   do{}while(0)
     78 #endif
     79 
     80 typedef struct ControlGlobalRec_*  ControlGlobal;
     81 
     82 typedef struct ControlClientRec_*  ControlClient;
     83 
     84 typedef struct {
     85     int           host_port;
     86     int           host_udp;
     87     unsigned int  guest_ip;
     88     int           guest_port;
     89 } RedirRec, *Redir;
     90 
     91 
     92 typedef int Socket;
     93 
     94 typedef struct ControlClientRec_
     95 {
     96     struct ControlClientRec_*  next;       /* next client in list           */
     97     Socket                     sock;       /* socket used for communication */
     98     ControlGlobal              global;
     99     char                       finished;
    100     char                       buff[ 4096 ];
    101     int                        buff_len;
    102 
    103 } ControlClientRec;
    104 
    105 
    106 typedef struct ControlGlobalRec_
    107 {
    108     /* listening socket */
    109     Socket    listen_fd;
    110 
    111     /* the list of current clients */
    112     ControlClient   clients;
    113 
    114     /* the list of redirections currently active */
    115     Redir     redirs;
    116     int       num_redirs;
    117     int       max_redirs;
    118 
    119 } ControlGlobalRec;
    120 
    121 #ifdef CONFIG_STANDALONE_CORE
    122 /* UI client currently attached to the core. */
    123 ControlClient attached_ui_client = NULL;
    124 
    125 /* User events service client. */
    126 ControlClient user_events_client = NULL;
    127 
    128 /* UI control service client (UI -> Core). */
    129 ControlClient ui_core_ctl_client = NULL;
    130 
    131 /* UI control service (UI -> Core. */
    132 // CoreUICtl* ui_core_ctl = NULL;
    133 
    134 /* UI control service client (Core-> UI). */
    135 ControlClient core_ui_ctl_client = NULL;
    136 #endif  // CONFIG_STANDALONE_CORE
    137 
    138 static int
    139 control_global_add_redir( ControlGlobal  global,
    140                           int            host_port,
    141                           int            host_udp,
    142                           unsigned int   guest_ip,
    143                           int            guest_port )
    144 {
    145     Redir  redir;
    146 
    147     if (global->num_redirs >= global->max_redirs)
    148     {
    149         int  old_max = global->max_redirs;
    150         int  new_max = old_max + (old_max >> 1) + 4;
    151 
    152         Redir  new_redirs = realloc( global->redirs, new_max*sizeof(global->redirs[0]) );
    153         if (new_redirs == NULL)
    154             return -1;
    155 
    156         global->redirs     = new_redirs;
    157         global->max_redirs = new_max;
    158     }
    159 
    160     redir = &global->redirs[ global->num_redirs++ ];
    161 
    162     redir->host_port  = host_port;
    163     redir->host_udp   = host_udp;
    164     redir->guest_ip   = guest_ip;
    165     redir->guest_port = guest_port;
    166 
    167     return 0;
    168 }
    169 
    170 static int
    171 control_global_del_redir( ControlGlobal  global,
    172                           int            host_port,
    173                           int            host_udp )
    174 {
    175     int  nn;
    176 
    177     for (nn = 0; nn < global->num_redirs; nn++)
    178     {
    179         Redir  redir = &global->redirs[nn];
    180 
    181         if ( redir->host_port == host_port &&
    182              redir->host_udp  == host_udp  )
    183         {
    184             memmove( redir, redir + 1, ((global->num_redirs - nn)-1)*sizeof(*redir) );
    185             global->num_redirs -= 1;
    186             return 0;
    187         }
    188     }
    189     /* we didn't find it */
    190     return -1;
    191 }
    192 
    193 /* Detach the socket descriptor from a given ControlClient
    194  * and return its value. This is useful either when destroying
    195  * the client, or redirecting the socket to another service.
    196  *
    197  * NOTE: this does not close the socket.
    198  */
    199 static int
    200 control_client_detach( ControlClient  client )
    201 {
    202     int  result;
    203 
    204     if (client->sock < 0)
    205         return -1;
    206 
    207     qemu_set_fd_handler( client->sock, NULL, NULL, NULL );
    208     result = client->sock;
    209     client->sock = -1;
    210 
    211     return result;
    212 }
    213 
    214 static void  control_client_read( void*  _client );  /* forward */
    215 
    216 /* Reattach a control client to a given socket.
    217  * Return the old socket descriptor for the client.
    218  */
    219 static int
    220 control_client_reattach( ControlClient client, int fd )
    221 {
    222     int result = control_client_detach(client);
    223     client->sock = fd;
    224     qemu_set_fd_handler( fd, control_client_read, NULL, client );
    225     return result;
    226 }
    227 
    228 static void
    229 control_client_destroy( ControlClient  client )
    230 {
    231     ControlGlobal  global = client->global;
    232     ControlClient  *pnode = &global->clients;
    233     int            sock;
    234 
    235     D(( "destroying control client %p\n", client ));
    236 
    237 #ifdef CONFIG_STANDALONE_CORE
    238     if (client == attached_ui_client) {
    239         attachUiProxy_destroy();
    240         attached_ui_client = NULL;
    241     }
    242 
    243     if (client == user_events_client) {
    244         userEventsImpl_destroy();
    245         user_events_client = NULL;
    246     }
    247 
    248     if (client == ui_core_ctl_client) {
    249         coreCmdImpl_destroy();
    250         ui_core_ctl_client = NULL;
    251     }
    252 
    253     if (client == core_ui_ctl_client) {
    254         uiCmdProxy_destroy();
    255         core_ui_ctl_client = NULL;
    256     }
    257 #endif  // CONFIG_STANDALONE_CORE
    258 
    259     sock = control_client_detach( client );
    260     if (sock >= 0)
    261         socket_close(sock);
    262 
    263     for ( ;; ) {
    264         ControlClient  node = *pnode;
    265         if ( node == NULL )
    266             break;
    267         if ( node == client ) {
    268             *pnode     = node->next;
    269             node->next = NULL;
    270             break;
    271         }
    272         pnode = &node->next;
    273     }
    274 
    275     free( client );
    276 }
    277 
    278 
    279 
    280 static void  control_control_write( ControlClient  client, const char*  buff, int  len )
    281 {
    282     int ret;
    283 
    284     if (len < 0)
    285         len = strlen(buff);
    286 
    287     while (len > 0) {
    288         ret = socket_send( client->sock, buff, len);
    289         if (ret < 0) {
    290             if (errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN)
    291                 return;
    292         } else {
    293             buff += ret;
    294             len  -= ret;
    295         }
    296     }
    297 }
    298 
    299 static int  control_vwrite( ControlClient  client, const char*  format, va_list args )
    300 {
    301     static char  temp[1024];
    302     int ret = vsnprintf( temp, sizeof(temp), format, args );
    303     temp[ sizeof(temp)-1 ] = 0;
    304     control_control_write( client, temp, -1 );
    305 
    306     return ret;
    307 }
    308 
    309 static int  control_write( ControlClient  client, const char*  format, ... )
    310 {
    311     int ret;
    312     va_list      args;
    313     va_start(args, format);
    314     ret = control_vwrite(client, format, args);
    315     va_end(args);
    316 
    317     return ret;
    318 }
    319 
    320 
    321 static ControlClient
    322 control_client_create( Socket         socket,
    323                        ControlGlobal  global )
    324 {
    325     ControlClient  client = calloc( sizeof(*client), 1 );
    326 
    327     if (client) {
    328         socket_set_nodelay( socket );
    329         socket_set_nonblock( socket );
    330         client->finished = 0;
    331         client->global  = global;
    332         client->sock    = socket;
    333         client->next    = global->clients;
    334         global->clients = client;
    335 
    336         qemu_set_fd_handler( socket, control_client_read, NULL, client );
    337     }
    338     return client;
    339 }
    340 
    341 typedef const struct CommandDefRec_  *CommandDef;
    342 
    343 typedef struct CommandDefRec_ {
    344     const char*  names;
    345     const char*  abstract;
    346     const char*  description;
    347     void        (*descriptor)( ControlClient  client );
    348     int         (*handler)( ControlClient  client, char* args );
    349     CommandDef   subcommands;   /* if handler is NULL */
    350 
    351 } CommandDefRec;
    352 
    353 static const CommandDefRec   main_commands[];  /* forward */
    354 
    355 static CommandDef
    356 find_command( char*  input, CommandDef  commands, char*  *pend, char*  *pargs )
    357 {
    358     int    nn;
    359     char*  args = strchr(input, ' ');
    360 
    361     if (args != NULL) {
    362         while (*args == ' ')
    363             args++;
    364 
    365         if (args[0] == 0)
    366             args = NULL;
    367     }
    368 
    369     for (nn = 0; commands[nn].names != NULL; nn++)
    370     {
    371         const char*  name = commands[nn].names;
    372         const char*  sep;
    373 
    374         do {
    375             int  len, c;
    376 
    377             sep = strchr( name, '|' );
    378             if (sep)
    379                 len = sep - name;
    380             else
    381                 len = strlen(name);
    382 
    383             c = input[len];
    384             if ( !memcmp( name, input, len ) && (c == ' ' || c == 0) ) {
    385                 *pend  = input + len;
    386                 *pargs = args;
    387                 return &commands[nn];
    388             }
    389 
    390             if (sep)
    391                 name = sep + 1;
    392 
    393         } while (sep != NULL && *name);
    394     }
    395     /* NOTE: don't touch *pend and *pargs if no command is found */
    396     return NULL;
    397 }
    398 
    399 static void
    400 dump_help( ControlClient  client,
    401            CommandDef     cmd,
    402            const char*    prefix )
    403 {
    404     if (cmd->description) {
    405         control_write( client, "%s", cmd->description );
    406     } else if (cmd->descriptor) {
    407         cmd->descriptor( client );
    408     } else
    409         control_write( client, "%s\r\n", cmd->abstract );
    410 
    411     if (cmd->subcommands) {
    412         cmd = cmd->subcommands;
    413         control_write( client, "\r\navailable sub-commands:\r\n" );
    414         for ( ; cmd->names != NULL; cmd++ ) {
    415             control_write( client, "   %s %-15s  %s\r\n", prefix, cmd->names, cmd->abstract );
    416         }
    417         control_write( client, "\r\n" );
    418     }
    419 }
    420 
    421 static void
    422 control_client_do_command( ControlClient  client )
    423 {
    424     char*       line     = client->buff;
    425     char*       args     = NULL;
    426     CommandDef  commands = main_commands;
    427     char*       cmdend   = client->buff;
    428     CommandDef  cmd      = find_command( line, commands, &cmdend, &args );
    429 
    430     if (cmd == NULL) {
    431         control_write( client, "KO: unknown command, try 'help'\r\n" );
    432         return;
    433     }
    434 
    435     for (;;) {
    436         CommandDef  subcmd;
    437 
    438         if (cmd->handler) {
    439             if ( !cmd->handler( client, args ) ) {
    440                 control_write( client, "OK\r\n" );
    441             }
    442             break;
    443         }
    444 
    445         /* no handler means we should have sub-commands */
    446         if (cmd->subcommands == NULL) {
    447             control_write( client, "KO: internal error: buggy command table for '%.*s'\r\n",
    448                            cmdend - client->buff, client->buff );
    449             break;
    450         }
    451 
    452         /* we need a sub-command here */
    453         if ( !args ) {
    454             dump_help( client, cmd, "" );
    455             control_write( client, "KO: missing sub-command\r\n" );
    456             break;
    457         }
    458 
    459         line     = args;
    460         commands = cmd->subcommands;
    461         subcmd   = find_command( line, commands, &cmdend, &args );
    462         if (subcmd == NULL) {
    463             dump_help( client, cmd, "" );
    464             control_write( client, "KO:  bad sub-command\r\n" );
    465             break;
    466         }
    467         cmd = subcmd;
    468     }
    469 }
    470 
    471 /* implement the 'help' command */
    472 static int
    473 do_help( ControlClient  client, char*  args )
    474 {
    475     char*       line;
    476     char*       start = args;
    477     char*       end   = start;
    478     CommandDef  cmd = main_commands;
    479 
    480     /* without arguments, simply dump all commands */
    481     if (args == NULL) {
    482         control_write( client, "Android console command help:\r\n\r\n" );
    483         for ( ; cmd->names != NULL; cmd++ ) {
    484             control_write( client, "    %-15s  %s\r\n", cmd->names, cmd->abstract );
    485         }
    486         control_write( client, "\r\ntry 'help <command>' for command-specific help\r\n" );
    487         return 0;
    488     }
    489 
    490     /* with an argument, find the corresponding command */
    491     for (;;) {
    492         CommandDef  subcmd;
    493 
    494         line    = args;
    495         subcmd  = find_command( line, cmd, &end, &args );
    496         if (subcmd == NULL) {
    497             control_write( client, "try one of these instead:\r\n\r\n" );
    498             for ( ; cmd->names != NULL; cmd++ ) {
    499                 control_write( client, "    %.*s %s\r\n",
    500                               end - start, start, cmd->names );
    501             }
    502             control_write( client, "\r\nKO: unknown command\r\n" );
    503             return -1;
    504         }
    505 
    506         if ( !args || !subcmd->subcommands ) {
    507             dump_help( client, subcmd, start );
    508             return 0;
    509         }
    510         cmd = subcmd->subcommands;
    511     }
    512 }
    513 
    514 
    515 static void
    516 control_client_read_byte( ControlClient  client, unsigned char  ch )
    517 {
    518     if (ch == '\r')
    519     {
    520         /* filter them out */
    521     }
    522     else if (ch == '\n')
    523     {
    524         client->buff[ client->buff_len ] = 0;
    525         control_client_do_command( client );
    526         if (client->finished)
    527             return;
    528 
    529         client->buff_len = 0;
    530     }
    531     else
    532     {
    533         if (client->buff_len >= sizeof(client->buff)-1)
    534             client->buff_len = 0;
    535 
    536         client->buff[ client->buff_len++ ] = ch;
    537     }
    538 }
    539 
    540 static void
    541 control_client_read( void*  _client )
    542 {
    543     ControlClient  client = _client;
    544     unsigned char  buf[4096];
    545     int            size;
    546 
    547     D(( "in control_client read: " ));
    548     size = socket_recv( client->sock, buf, sizeof(buf) );
    549     if (size < 0) {
    550         D(( "size < 0, exiting with %d: %s\n", errno, errno_str ));
    551         if (errno != EWOULDBLOCK && errno != EAGAIN)
    552             control_client_destroy( client );
    553         return;
    554     }
    555 
    556     if (size == 0) {
    557         /* end of connection */
    558         D(( "end of connection detected !!\n" ));
    559         control_client_destroy( client );
    560     }
    561     else {
    562         int  nn;
    563 #ifdef _WIN32
    564 #  if DEBUG
    565         char  temp[16];
    566         int   count = size > sizeof(temp)-1 ? sizeof(temp)-1 : size;
    567         for (nn = 0; nn < count; nn++) {
    568                 int  c = buf[nn];
    569                 if (c == '\n')
    570                         temp[nn] = '!';
    571             else if (c < 32)
    572                         temp[nn] = '.';
    573                 else
    574                     temp[nn] = (char)c;
    575         }
    576         temp[nn] = 0;
    577         D(( "received %d bytes: %s\n", size, temp ));
    578 #  endif
    579 #else
    580         D(( "received %.*s\n", size, buf ));
    581 #endif
    582         for (nn = 0; nn < size; nn++) {
    583             control_client_read_byte( client, buf[nn] );
    584             if (client->finished) {
    585                 control_client_destroy(client);
    586                 return;
    587             }
    588         }
    589     }
    590 }
    591 
    592 
    593 /* this function is called on each new client connection */
    594 static void
    595 control_global_accept( void*  _global )
    596 {
    597     ControlGlobal       global = _global;
    598     ControlClient       client;
    599     Socket              fd;
    600 
    601     D(( "control_global_accept: just in (fd=%d)\n", global->listen_fd ));
    602 
    603     for(;;) {
    604         fd = socket_accept( global->listen_fd, NULL );
    605         if (fd < 0 && errno != EINTR) {
    606             D(( "problem in accept: %d: %s\n", errno, errno_str ));
    607             perror("accept");
    608             return;
    609         } else if (fd >= 0) {
    610             break;
    611         }
    612         D(( "relooping in accept()\n" ));
    613     }
    614 
    615     socket_set_xreuseaddr( fd );
    616 
    617     D(( "control_global_accept: creating new client\n" ));
    618     client = control_client_create( fd, global );
    619     if (client) {
    620         D(( "control_global_accept: new client %p\n", client ));
    621         control_write( client, "Android Console: type 'help' for a list of commands\r\n" );
    622         control_write( client, "OK\r\n" );
    623     }
    624 }
    625 
    626 
    627 static int
    628 control_global_init( ControlGlobal  global,
    629                      int            control_port )
    630 {
    631     Socket  fd;
    632     int     ret;
    633     SockAddress  sockaddr;
    634 
    635     memset( global, 0, sizeof(*global) );
    636 
    637     fd = socket_create_inet( SOCKET_STREAM );
    638     if (fd < 0) {
    639         perror("socket");
    640         return -1;
    641     }
    642 
    643     socket_set_xreuseaddr( fd );
    644 
    645     sock_address_init_inet( &sockaddr, SOCK_ADDRESS_INET_LOOPBACK, control_port );
    646 
    647     ret = socket_bind(fd, &sockaddr );
    648     if (ret < 0) {
    649         perror("bind");
    650         socket_close( fd );
    651         return -1;
    652     }
    653 
    654     ret = socket_listen(fd, 0);
    655     if (ret < 0) {
    656         perror("listen");
    657         socket_close( fd );
    658         return -1;
    659     }
    660 
    661     socket_set_nonblock(fd);
    662 
    663     global->listen_fd = fd;
    664 
    665     qemu_set_fd_handler( fd, control_global_accept, NULL, global );
    666     return 0;
    667 }
    668 
    669 
    670 
    671 static int
    672 do_quit( ControlClient  client, char*  args )
    673 {
    674     client->finished = 1;
    675     return -1;
    676 }
    677 
    678 /********************************************************************************************/
    679 /********************************************************************************************/
    680 /*****                                                                                 ******/
    681 /*****                        N E T W O R K   S E T T I N G S                          ******/
    682 /*****                                                                                 ******/
    683 /********************************************************************************************/
    684 /********************************************************************************************/
    685 
    686 static int
    687 do_network_status( ControlClient  client, char*  args )
    688 {
    689     control_write( client, "Current network status:\r\n" );
    690 
    691     control_write( client, "  download speed:   %8d bits/s (%.1f KB/s)\r\n",
    692                    (long)qemu_net_download_speed, qemu_net_download_speed/8192. );
    693 
    694     control_write( client, "  upload speed:     %8d bits/s (%.1f KB/s)\r\n",
    695                    (long)qemu_net_upload_speed, qemu_net_upload_speed/8192. );
    696 
    697     control_write( client, "  minimum latency:  %ld ms\r\n", qemu_net_min_latency );
    698     control_write( client, "  maximum latency:  %ld ms\r\n", qemu_net_max_latency );
    699     return 0;
    700 }
    701 
    702 static void
    703 dump_network_speeds( ControlClient  client )
    704 {
    705     const NetworkSpeed*  speed = android_netspeeds;
    706     const char* const  format = "  %-8s %s\r\n";
    707     for ( ; speed->name; speed++ ) {
    708         control_write( client, format, speed->name, speed->display );
    709     }
    710     control_write( client, format, "<num>", "selects both upload and download speed" );
    711     control_write( client, format, "<up>:<down>", "select individual upload/download speeds" );
    712 }
    713 
    714 
    715 static int
    716 do_network_speed( ControlClient  client, char*  args )
    717 {
    718     if ( !args ) {
    719         control_write( client, "KO: missing <speed> argument, see 'help network speed'\r\n" );
    720         return -1;
    721     }
    722     if ( android_parse_network_speed( args ) < 0 ) {
    723         control_write( client, "KO: invalid <speed> argument, see 'help network speed' for valid values\r\n" );
    724         return -1;
    725     }
    726 
    727     netshaper_set_rate( slirp_shaper_in,  qemu_net_download_speed );
    728     netshaper_set_rate( slirp_shaper_out, qemu_net_upload_speed );
    729 
    730     if (android_modem) {
    731         amodem_set_data_network_type( android_modem,
    732                                     android_parse_network_type( args ) );
    733     }
    734     return 0;
    735 }
    736 
    737 static void
    738 describe_network_speed( ControlClient  client )
    739 {
    740     control_write( client,
    741                    "'network speed <speed>' allows you to dynamically change the speed of the emulated\r\n"
    742                    "network on the device, where <speed> is one of the following:\r\n\r\n" );
    743     dump_network_speeds( client );
    744 }
    745 
    746 static int
    747 do_network_delay( ControlClient  client, char*  args )
    748 {
    749     if ( !args ) {
    750         control_write( client, "KO: missing <delay> argument, see 'help network delay'\r\n" );
    751         return -1;
    752     }
    753     if ( android_parse_network_latency( args ) < 0 ) {
    754         control_write( client, "KO: invalid <delay> argument, see 'help network delay' for valid values\r\n" );
    755         return -1;
    756     }
    757     netdelay_set_latency( slirp_delay_in, qemu_net_min_latency, qemu_net_max_latency );
    758     return 0;
    759 }
    760 
    761 static void
    762 describe_network_delay( ControlClient  client )
    763 {
    764     control_write( client,
    765                    "'network delay <latency>' allows you to dynamically change the latency of the emulated\r\n"
    766                    "network on the device, where <latency> is one of the following:\r\n\r\n" );
    767     /* XXX: TODO */
    768 }
    769 
    770 static int
    771 do_network_capture_start( ControlClient  client, char*  args )
    772 {
    773     if ( !args ) {
    774         control_write( client, "KO: missing <file> argument, see 'help network capture start'\r\n" );
    775         return -1;
    776     }
    777     if ( qemu_tcpdump_start(args) < 0) {
    778         control_write( client, "KO: could not start capture: %s", strerror(errno) );
    779         return -1;
    780     }
    781     return 0;
    782 }
    783 
    784 static int
    785 do_network_capture_stop( ControlClient  client, char*  args )
    786 {
    787     /* no need to return an error here */
    788     qemu_tcpdump_stop();
    789     return 0;
    790 }
    791 
    792 static const CommandDefRec  network_capture_commands[] =
    793 {
    794     { "start", "start network capture",
    795       "'network capture start <file>' starts a new capture of network packets\r\n"
    796       "into a specific <file>. This will stop any capture already in progress.\r\n"
    797       "the capture file can later be analyzed by tools like WireShark. It uses\r\n"
    798       "the libpcap file format.\r\n\r\n"
    799       "you can stop the capture anytime with 'network capture stop'\r\n", NULL,
    800       do_network_capture_start, NULL },
    801 
    802     { "stop", "stop network capture",
    803       "'network capture stop' stops a currently running packet capture, if any.\r\n"
    804       "you can start one with 'network capture start <file>'\r\n", NULL,
    805       do_network_capture_stop, NULL },
    806 
    807     { NULL, NULL, NULL, NULL, NULL, NULL }
    808 };
    809 
    810 static const CommandDefRec  network_commands[] =
    811 {
    812     { "status", "dump network status", NULL, NULL,
    813        do_network_status, NULL },
    814 
    815     { "speed", "change network speed", NULL, describe_network_speed,
    816       do_network_speed, NULL },
    817 
    818     { "delay", "change network latency", NULL, describe_network_delay,
    819        do_network_delay, NULL },
    820 
    821     { "capture", "dump network packets to file",
    822       "allows to start/stop capture of network packets to a file for later analysis\r\n", NULL,
    823       NULL, network_capture_commands },
    824 
    825     { NULL, NULL, NULL, NULL, NULL, NULL }
    826 };
    827 
    828 /********************************************************************************************/
    829 /********************************************************************************************/
    830 /*****                                                                                 ******/
    831 /*****                       P O R T   R E D I R E C T I O N S                         ******/
    832 /*****                                                                                 ******/
    833 /********************************************************************************************/
    834 /********************************************************************************************/
    835 
    836 static int
    837 do_redir_list( ControlClient  client, char*  args )
    838 {
    839     ControlGlobal  global = client->global;
    840 
    841     if (global->num_redirs == 0)
    842         control_write( client, "no active redirections\r\n" );
    843     else {
    844         int  nn;
    845         for (nn = 0; nn < global->num_redirs; nn++) {
    846             Redir  redir = &global->redirs[nn];
    847             control_write( client, "%s:%-5d => %-5d\r\n",
    848                           redir->host_udp ? "udp" : "tcp",
    849                           redir->host_port,
    850                           redir->guest_port );
    851         }
    852     }
    853     return 0;
    854 }
    855 
    856 /* parse a protocol:port specification */
    857 static int
    858 redir_parse_proto_port( char*  args, int  *pport, int  *pproto )
    859 {
    860     int  proto = -1;
    861     int  len   = 0;
    862     char*  end;
    863 
    864     if ( !memcmp( args, "tcp:", 4 ) ) {
    865         proto = 0;
    866         len   = 4;
    867     }
    868     else if ( !memcmp( args, "udp:", 4 ) ) {
    869         proto = 1;
    870         len   = 4;
    871     }
    872     else
    873         return 0;
    874 
    875     args   += len;
    876     *pproto = proto;
    877     *pport  = strtol( args, &end, 10 );
    878     if (end == args)
    879         return 0;
    880 
    881     len += end - args;
    882     return len;
    883 }
    884 
    885 static int
    886 redir_parse_guest_port( char*  arg, int  *pport )
    887 {
    888     char*  end;
    889 
    890     *pport = strtoul( arg, &end, 10 );
    891     if (end == arg)
    892         return 0;
    893 
    894     return end - arg;
    895 }
    896 
    897 static Redir
    898 redir_find( ControlGlobal  global, int  port, int  isudp )
    899 {
    900     int  nn;
    901 
    902     for (nn = 0; nn < global->num_redirs; nn++) {
    903         Redir  redir = &global->redirs[nn];
    904 
    905         if (redir->host_port == port && redir->host_udp == isudp)
    906             return redir;
    907     }
    908     return NULL;
    909 }
    910 
    911 
    912 static int
    913 do_redir_add( ControlClient  client, char*  args )
    914 {
    915     int       len, host_proto, host_port, guest_port;
    916     uint32_t  guest_ip;
    917     Redir     redir;
    918 
    919     if ( !args )
    920         goto BadFormat;
    921 
    922     if (!slirp_is_inited()) {
    923         control_write( client, "KO: network emulation disabled\r\n");
    924         return -1;
    925     }
    926 
    927     len = redir_parse_proto_port( args, &host_port, &host_proto );
    928     if (len == 0 || args[len] != ':')
    929         goto BadFormat;
    930 
    931     args += len + 1;
    932     len = redir_parse_guest_port( args, &guest_port );
    933     if (len == 0 || args[len] != 0)
    934         goto BadFormat;
    935 
    936     redir = redir_find( client->global, host_port, host_proto );
    937     if ( redir != NULL ) {
    938         control_write( client, "KO: host port already active, use 'redir del' to remove first\r\n" );
    939         return -1;
    940     }
    941 
    942     if (inet_strtoip("10.0.2.15", &guest_ip) < 0) {
    943         control_write( client, "KO: unexpected internal failure when resolving 10.0.2.15\r\n" );
    944         return -1;
    945     }
    946 
    947     D(("pattern hport=%d gport=%d proto=%d\n", host_port, guest_port, host_proto ));
    948     if ( control_global_add_redir( client->global, host_port, host_proto,
    949                                    guest_ip, guest_port ) < 0 )
    950     {
    951         control_write( client, "KO: not enough memory to allocate redirection\r\n" );
    952         return -1;
    953     }
    954 
    955     if (slirp_redir(host_proto, host_port, guest_ip, guest_port) < 0) {
    956         control_write( client, "KO: can't setup redirection, port probably used by another program on host\r\n" );
    957         control_global_del_redir( client->global, host_port, host_proto );
    958         return -1;
    959     }
    960 
    961     return 0;
    962 
    963 BadFormat:
    964     control_write( client, "KO: bad redirection format, try (tcp|udp):hostport:guestport\r\n", -1 );
    965     return -1;
    966 }
    967 
    968 
    969 static int
    970 do_redir_del( ControlClient  client, char*  args )
    971 {
    972     int    len, proto, port;
    973     Redir  redir;
    974 
    975     if ( !args )
    976         goto BadFormat;
    977     len = redir_parse_proto_port( args, &port, &proto );
    978     if ( len == 0 || args[len] != 0 )
    979         goto BadFormat;
    980 
    981     redir = redir_find( client->global, port, proto );
    982     if (redir == NULL) {
    983         control_write( client, "KO: can't remove unknown redirection (%s:%d)\r\n",
    984                         proto ? "udp" : "tcp", port );
    985         return -1;
    986     }
    987 
    988     slirp_unredir( redir->host_udp, redir->host_port );
    989     control_global_del_redir( client->global, port, proto );\
    990 
    991     return 0;
    992 
    993 BadFormat:
    994     control_write( client, "KO: bad redirection format, try (tcp|udp):hostport\r\n" );
    995     return -1;
    996 }
    997 
    998 static const CommandDefRec  redir_commands[] =
    999 {
   1000     { "list", "list current redirections",
   1001     "list current port redirections. use 'redir add' and 'redir del' to add and remove them\r\n", NULL,
   1002     do_redir_list, NULL },
   1003 
   1004     { "add",  "add new redirection",
   1005     "add a new port redirection, arguments must be:\r\n\r\n"
   1006             "  redir add <protocol>:<host-port>:<guest-port>\r\n\r\n"
   1007             "where:   <protocol>     is either 'tcp' or 'udp'\r\n"
   1008             "         <host-port>    a number indicating which port on the host to open\r\n"
   1009             "         <guest-port>   a number indicating which port to route to on the device\r\n"
   1010             "\r\nas an example, 'redir  tcp:5000:6000' will allow any packets sent to\r\n"
   1011             "the host's TCP port 5000 to be routed to TCP port 6000 of the emulated device\r\n", NULL,
   1012     do_redir_add, NULL },
   1013 
   1014     { "del",  "remove existing redirection",
   1015     "remove a port redirecion that was created with 'redir add', arguments must be:\r\n\r\n"
   1016             "  redir  del <protocol>:<host-port>\r\n\r\n"
   1017             "see the 'help redir add' for the meaning of <protocol> and <host-port>\r\n", NULL,
   1018     do_redir_del, NULL },
   1019 
   1020     { NULL, NULL, NULL, NULL, NULL, NULL }
   1021 };
   1022 
   1023 
   1024 
   1025 /********************************************************************************************/
   1026 /********************************************************************************************/
   1027 /*****                                                                                 ******/
   1028 /*****                          C D M A   M O D E M                                    ******/
   1029 /*****                                                                                 ******/
   1030 /********************************************************************************************/
   1031 /********************************************************************************************/
   1032 
   1033 static const struct {
   1034     const char *            name;
   1035     const char *            display;
   1036     ACdmaSubscriptionSource source;
   1037 } _cdma_subscription_sources[] = {
   1038     { "nv",            "Read subscription from non-volatile RAM", A_SUBSCRIPTION_NVRAM },
   1039     { "ruim",          "Read subscription from RUIM", A_SUBSCRIPTION_RUIM },
   1040 };
   1041 
   1042 static void
   1043 dump_subscription_sources( ControlClient client )
   1044 {
   1045     int i;
   1046     for (i = 0;
   1047          i < sizeof(_cdma_subscription_sources) / sizeof(_cdma_subscription_sources[0]);
   1048          i++) {
   1049         control_write( client, "    %s: %s\r\n",
   1050                        _cdma_subscription_sources[i].name,
   1051                        _cdma_subscription_sources[i].display );
   1052     }
   1053 }
   1054 
   1055 static void
   1056 describe_subscription_source( ControlClient client )
   1057 {
   1058     control_write( client,
   1059                    "'cdma ssource <ssource>' allows you to specify where to read the subscription from\r\n" );
   1060     dump_subscription_sources( client );
   1061 }
   1062 
   1063 static int
   1064 do_cdma_ssource( ControlClient  client, char*  args )
   1065 {
   1066     int nn;
   1067     if (!args) {
   1068         control_write( client, "KO: missing argument, try 'cdma ssource <source>'\r\n" );
   1069         return -1;
   1070     }
   1071 
   1072     for (nn = 0; ; nn++) {
   1073         const char*         name    = _cdma_subscription_sources[nn].name;
   1074         ACdmaSubscriptionSource ssource = _cdma_subscription_sources[nn].source;
   1075 
   1076         if (!name)
   1077             break;
   1078 
   1079         if (!strcasecmp( args, name )) {
   1080             amodem_set_cdma_subscription_source( android_modem, ssource );
   1081             return 0;
   1082         }
   1083     }
   1084     control_write( client, "KO: Don't know source %s\r\n", args );
   1085     return -1;
   1086 }
   1087 
   1088 static int
   1089 do_cdma_prl_version( ControlClient client, char * args )
   1090 {
   1091     int version = 0;
   1092     char *endptr;
   1093 
   1094     if (!args) {
   1095         control_write( client, "KO: missing argument, try 'cdma prl_version <version>'\r\n");
   1096         return -1;
   1097     }
   1098 
   1099     version = strtol(args, &endptr, 0);
   1100     if (endptr != args) {
   1101         amodem_set_cdma_prl_version( android_modem, version );
   1102     }
   1103     return 0;
   1104 }
   1105 /********************************************************************************************/
   1106 /********************************************************************************************/
   1107 /*****                                                                                 ******/
   1108 /*****                           G S M   M O D E M                                     ******/
   1109 /*****                                                                                 ******/
   1110 /********************************************************************************************/
   1111 /********************************************************************************************/
   1112 
   1113 static const struct {
   1114     const char*         name;
   1115     const char*         display;
   1116     ARegistrationState  state;
   1117 } _gsm_states[] = {
   1118     { "unregistered",  "no network available", A_REGISTRATION_UNREGISTERED },
   1119     { "home",          "on local network, non-roaming", A_REGISTRATION_HOME },
   1120     { "roaming",       "on roaming network", A_REGISTRATION_ROAMING },
   1121     { "searching",     "searching networks", A_REGISTRATION_SEARCHING },
   1122     { "denied",        "emergency calls only", A_REGISTRATION_DENIED },
   1123     { "off",           "same as 'unregistered'", A_REGISTRATION_UNREGISTERED },
   1124     { "on",            "same as 'home'", A_REGISTRATION_HOME },
   1125     { NULL, NULL, A_REGISTRATION_UNREGISTERED }
   1126 };
   1127 
   1128 static const char*
   1129 gsm_state_to_string( ARegistrationState  state )
   1130 {
   1131     int  nn;
   1132     for (nn = 0; _gsm_states[nn].name != NULL; nn++) {
   1133         if (state == _gsm_states[nn].state)
   1134             return _gsm_states[nn].name;
   1135     }
   1136     return "<unknown>";
   1137 }
   1138 
   1139 static int
   1140 do_gsm_status( ControlClient  client, char*  args )
   1141 {
   1142     if (args) {
   1143         control_write( client, "KO: no argument required\r\n" );
   1144         return -1;
   1145     }
   1146     if (!android_modem) {
   1147         control_write( client, "KO: modem emulation not running\r\n" );
   1148         return -1;
   1149     }
   1150     control_write( client, "gsm voice state: %s\r\n",
   1151                    gsm_state_to_string(
   1152                        amodem_get_voice_registration(android_modem) ) );
   1153     control_write( client, "gsm data state:  %s\r\n",
   1154                    gsm_state_to_string(
   1155                        amodem_get_data_registration(android_modem) ) );
   1156     return 0;
   1157 }
   1158 
   1159 
   1160 static void
   1161 help_gsm_data( ControlClient  client )
   1162 {
   1163     int  nn;
   1164     control_write( client,
   1165             "the 'gsm data <state>' allows you to change the state of your GPRS connection\r\n"
   1166             "valid values for <state> are the following:\r\n\r\n" );
   1167     for (nn = 0; ; nn++) {
   1168         const char*         name    = _gsm_states[nn].name;
   1169         const char*         display = _gsm_states[nn].display;
   1170 
   1171         if (!name)
   1172             break;
   1173 
   1174         control_write( client, "  %-15s %s\r\n", name, display );
   1175     }
   1176     control_write( client, "\r\n" );
   1177 }
   1178 
   1179 
   1180 static int
   1181 do_gsm_data( ControlClient  client, char*  args )
   1182 {
   1183     int  nn;
   1184 
   1185     if (!args) {
   1186         control_write( client, "KO: missing argument, try 'gsm data <state>'\r\n" );
   1187         return -1;
   1188     }
   1189 
   1190     for (nn = 0; ; nn++) {
   1191         const char*         name    = _gsm_states[nn].name;
   1192         ARegistrationState  state   = _gsm_states[nn].state;
   1193 
   1194         if (!name)
   1195             break;
   1196 
   1197         if ( !strcmp( args, name ) ) {
   1198             if (!android_modem) {
   1199                 control_write( client, "KO: modem emulation not running\r\n" );
   1200                 return -1;
   1201             }
   1202             amodem_set_data_registration( android_modem, state );
   1203             qemu_net_disable = (state != A_REGISTRATION_HOME    &&
   1204                                 state != A_REGISTRATION_ROAMING );
   1205             return 0;
   1206         }
   1207     }
   1208     control_write( client, "KO: bad GSM data state name, try 'help gsm data' for list of valid values\r\n" );
   1209     return -1;
   1210 }
   1211 
   1212 static void
   1213 help_gsm_voice( ControlClient  client )
   1214 {
   1215     int  nn;
   1216     control_write( client,
   1217             "the 'gsm voice <state>' allows you to change the state of your GPRS connection\r\n"
   1218             "valid values for <state> are the following:\r\n\r\n" );
   1219     for (nn = 0; ; nn++) {
   1220         const char*         name    = _gsm_states[nn].name;
   1221         const char*         display = _gsm_states[nn].display;
   1222 
   1223         if (!name)
   1224             break;
   1225 
   1226         control_write( client, "  %-15s %s\r\n", name, display );
   1227     }
   1228     control_write( client, "\r\n" );
   1229 }
   1230 
   1231 
   1232 static int
   1233 do_gsm_voice( ControlClient  client, char*  args )
   1234 {
   1235     int  nn;
   1236 
   1237     if (!args) {
   1238         control_write( client, "KO: missing argument, try 'gsm voice <state>'\r\n" );
   1239         return -1;
   1240     }
   1241 
   1242     for (nn = 0; ; nn++) {
   1243         const char*         name    = _gsm_states[nn].name;
   1244         ARegistrationState  state   = _gsm_states[nn].state;
   1245 
   1246         if (!name)
   1247             break;
   1248 
   1249         if ( !strcmp( args, name ) ) {
   1250             if (!android_modem) {
   1251                 control_write( client, "KO: modem emulation not running\r\n" );
   1252                 return -1;
   1253             }
   1254             amodem_set_voice_registration( android_modem, state );
   1255             return 0;
   1256         }
   1257     }
   1258     control_write( client, "KO: bad GSM data state name, try 'help gsm voice' for list of valid values\r\n" );
   1259     return -1;
   1260 }
   1261 
   1262 
   1263 static int
   1264 gsm_check_number( char*  args )
   1265 {
   1266     int  nn;
   1267 
   1268     for (nn = 0; args[nn] != 0; nn++) {
   1269         int  c = args[nn];
   1270         if ( !isdigit(c) && c != '+' && c != '#' ) {
   1271             return -1;
   1272         }
   1273     }
   1274     if (nn == 0)
   1275         return -1;
   1276 
   1277     return 0;
   1278 }
   1279 
   1280 static int
   1281 do_gsm_call( ControlClient  client, char*  args )
   1282 {
   1283     /* check that we have a phone number made of digits */
   1284     if (!args) {
   1285         control_write( client, "KO: missing argument, try 'gsm call <phonenumber>'\r\n" );
   1286         return -1;
   1287     }
   1288 
   1289     if (gsm_check_number(args)) {
   1290         control_write( client, "KO: bad phone number format, use digits, # and + only\r\n" );
   1291         return -1;
   1292     }
   1293 
   1294     if (!android_modem) {
   1295         control_write( client, "KO: modem emulation not running\r\n" );
   1296         return -1;
   1297     }
   1298     amodem_add_inbound_call( android_modem, args );
   1299     return 0;
   1300 }
   1301 
   1302 static int
   1303 do_gsm_cancel( ControlClient  client, char*  args )
   1304 {
   1305     if (!args) {
   1306         control_write( client, "KO: missing argument, try 'gsm call <phonenumber>'\r\n" );
   1307         return -1;
   1308     }
   1309     if (gsm_check_number(args)) {
   1310         control_write( client, "KO: bad phone number format, use digits, # and + only\r\n" );
   1311         return -1;
   1312     }
   1313     if (!android_modem) {
   1314         control_write( client, "KO: modem emulation not running\r\n" );
   1315         return -1;
   1316     }
   1317     if ( amodem_disconnect_call( android_modem, args ) < 0 ) {
   1318         control_write( client, "KO: could not cancel this number\r\n" );
   1319         return -1;
   1320     }
   1321     return 0;
   1322 }
   1323 
   1324 
   1325 static const char*
   1326 call_state_to_string( ACallState  state )
   1327 {
   1328     switch (state) {
   1329         case A_CALL_ACTIVE:   return "active";
   1330         case A_CALL_HELD:     return "held";
   1331         case A_CALL_ALERTING: return "ringing";
   1332         case A_CALL_WAITING:  return "waiting";
   1333         case A_CALL_INCOMING: return "incoming";
   1334         default: return "unknown";
   1335     }
   1336 }
   1337 
   1338 static int
   1339 do_gsm_list( ControlClient  client, char*  args )
   1340 {
   1341     /* check that we have a phone number made of digits */
   1342     int   count = amodem_get_call_count( android_modem );
   1343     int   nn;
   1344     for (nn = 0; nn < count; nn++) {
   1345         ACall        call = amodem_get_call( android_modem, nn );
   1346         const char*  dir;
   1347 
   1348         if (call == NULL)
   1349             continue;
   1350 
   1351         if (call->dir == A_CALL_OUTBOUND)
   1352             dir = "outbound to ";
   1353          else
   1354             dir = "inbound from";
   1355 
   1356         control_write( client, "%s %-10s : %s\r\n", dir,
   1357                        call->number, call_state_to_string(call->state) );
   1358     }
   1359     return 0;
   1360 }
   1361 
   1362 static int
   1363 do_gsm_busy( ControlClient  client, char*  args )
   1364 {
   1365     ACall  call;
   1366 
   1367     if (!args) {
   1368         control_write( client, "KO: missing argument, try 'gsm busy <phonenumber>'\r\n" );
   1369         return -1;
   1370     }
   1371     call = amodem_find_call_by_number( android_modem, args );
   1372     if (call == NULL || call->dir != A_CALL_OUTBOUND) {
   1373         control_write( client, "KO: no current outbound call to number '%s' (call %p)\r\n", args, call );
   1374         return -1;
   1375     }
   1376     if ( amodem_disconnect_call( android_modem, args ) < 0 ) {
   1377         control_write( client, "KO: could not cancel this number\r\n" );
   1378         return -1;
   1379     }
   1380     return 0;
   1381 }
   1382 
   1383 static int
   1384 do_gsm_hold( ControlClient  client, char*  args )
   1385 {
   1386     ACall  call;
   1387 
   1388     if (!args) {
   1389         control_write( client, "KO: missing argument, try 'gsm out hold <phonenumber>'\r\n" );
   1390         return -1;
   1391     }
   1392     call = amodem_find_call_by_number( android_modem, args );
   1393     if (call == NULL) {
   1394         control_write( client, "KO: no current call to/from number '%s'\r\n", args );
   1395         return -1;
   1396     }
   1397     if ( amodem_update_call( android_modem, args, A_CALL_HELD ) < 0 ) {
   1398         control_write( client, "KO: could put this call on hold\r\n" );
   1399         return -1;
   1400     }
   1401     return 0;
   1402 }
   1403 
   1404 
   1405 static int
   1406 do_gsm_accept( ControlClient  client, char*  args )
   1407 {
   1408     ACall  call;
   1409 
   1410     if (!args) {
   1411         control_write( client, "KO: missing argument, try 'gsm accept <phonenumber>'\r\n" );
   1412         return -1;
   1413     }
   1414     call = amodem_find_call_by_number( android_modem, args );
   1415     if (call == NULL) {
   1416         control_write( client, "KO: no current call to/from number '%s'\r\n", args );
   1417         return -1;
   1418     }
   1419     if ( amodem_update_call( android_modem, args, A_CALL_ACTIVE ) < 0 ) {
   1420         control_write( client, "KO: could not activate this call\r\n" );
   1421         return -1;
   1422     }
   1423     return 0;
   1424 }
   1425 
   1426 static int
   1427 do_gsm_signal( ControlClient  client, char*  args )
   1428 {
   1429       enum { SIGNAL_RSSI = 0, SIGNAL_BER, NUM_SIGNAL_PARAMS };
   1430       char*   p = args;
   1431       int     top_param = -1;
   1432       int     params[ NUM_SIGNAL_PARAMS ];
   1433 
   1434       static  int  last_ber = 99;
   1435 
   1436       if (!p)
   1437           p = "";
   1438 
   1439       /* tokenize */
   1440       while (*p) {
   1441           char*   end;
   1442           int  val = strtol( p, &end, 10 );
   1443 
   1444           if (end == p) {
   1445               control_write( client, "KO: argument '%s' is not a number\n", p );
   1446               return -1;
   1447           }
   1448 
   1449           params[++top_param] = val;
   1450           if (top_param + 1 == NUM_SIGNAL_PARAMS)
   1451               break;
   1452 
   1453           p = end;
   1454           while (*p && (p[0] == ' ' || p[0] == '\t'))
   1455               p += 1;
   1456       }
   1457 
   1458       /* sanity check */
   1459       if (top_param < SIGNAL_RSSI) {
   1460           control_write( client, "KO: not enough arguments: see 'help gsm signal' for details\r\n" );
   1461           return -1;
   1462       }
   1463 
   1464       int rssi = params[SIGNAL_RSSI];
   1465       if ((rssi < 0 || rssi > 31) && rssi != 99) {
   1466           control_write( client, "KO: invalid RSSI - must be 0..31 or 99\r\n");
   1467           return -1;
   1468       }
   1469 
   1470       /* check ber is 0..7 or 99 */
   1471       if (top_param >= SIGNAL_BER) {
   1472           int ber = params[SIGNAL_BER];
   1473           if ((ber < 0 || ber > 7) && ber != 99) {
   1474               control_write( client, "KO: invalid BER - must be 0..7 or 99\r\n");
   1475               return -1;
   1476           }
   1477           last_ber = ber;
   1478       }
   1479 
   1480       amodem_set_signal_strength( android_modem, rssi, last_ber );
   1481 
   1482       return 0;
   1483   }
   1484 
   1485 
   1486 #if 0
   1487 static const CommandDefRec  gsm_in_commands[] =
   1488 {
   1489     { "new", "create a new 'waiting' inbound call",
   1490     "'gsm in create <phonenumber>' creates a new inbound phone call, placed in\r\n"
   1491     "the 'waiting' state by default, until the system answers/holds/closes it\r\n", NULL
   1492     do_gsm_in_create, NULL },
   1493 
   1494     { "hold", "change the state of an oubtound call to 'held'",
   1495     "change the state of an outbound call to 'held'. this is only possible\r\n"
   1496     "if the call in the 'waiting' or 'active' state\r\n", NULL,
   1497     do_gsm_out_hold, NULL },
   1498 
   1499     { "accept", "change the state of an outbound call to 'active'",
   1500     "change the state of an outbound call to 'active'. this is only possible\r\n"
   1501     "if the call is in the 'waiting' or 'held' state\r\n", NULL,
   1502     do_gsm_out_accept, NULL },
   1503 
   1504     { NULL, NULL, NULL, NULL, NULL, NULL }
   1505 };
   1506 #endif
   1507 
   1508 
   1509 static const CommandDefRec  cdma_commands[] =
   1510 {
   1511     { "ssource", "Set the current CDMA subscription source",
   1512       NULL, describe_subscription_source,
   1513       do_cdma_ssource, NULL },
   1514     { "prl_version", "Dump the current PRL version",
   1515       NULL, NULL,
   1516       do_cdma_prl_version, NULL },
   1517 };
   1518 
   1519 static const CommandDefRec  gsm_commands[] =
   1520 {
   1521     { "list", "list current phone calls",
   1522     "'gsm list' lists all inbound and outbound calls and their state\r\n", NULL,
   1523     do_gsm_list, NULL },
   1524 
   1525     { "call", "create inbound phone call",
   1526     "'gsm call <phonenumber>' allows you to simulate a new inbound call\r\n", NULL,
   1527     do_gsm_call, NULL },
   1528 
   1529     { "busy", "close waiting outbound call as busy",
   1530     "'gsm busy <remoteNumber>' closes an outbound call, reporting\r\n"
   1531     "the remote phone as busy. only possible if the call is 'waiting'.\r\n", NULL,
   1532     do_gsm_busy, NULL },
   1533 
   1534     { "hold", "change the state of an oubtound call to 'held'",
   1535     "'gsm hold <remoteNumber>' change the state of a call to 'held'. this is only possible\r\n"
   1536     "if the call in the 'waiting' or 'active' state\r\n", NULL,
   1537     do_gsm_hold, NULL },
   1538 
   1539     { "accept", "change the state of an outbound call to 'active'",
   1540     "'gsm accept <remoteNumber>' change the state of a call to 'active'. this is only possible\r\n"
   1541     "if the call is in the 'waiting' or 'held' state\r\n", NULL,
   1542     do_gsm_accept, NULL },
   1543 
   1544     { "cancel", "disconnect an inbound or outbound phone call",
   1545     "'gsm cancel <phonenumber>' allows you to simulate the end of an inbound or outbound call\r\n", NULL,
   1546     do_gsm_cancel, NULL },
   1547 
   1548     { "data", "modify data connection state", NULL, help_gsm_data,
   1549     do_gsm_data, NULL },
   1550 
   1551     { "voice", "modify voice connection state", NULL, help_gsm_voice,
   1552     do_gsm_voice, NULL },
   1553 
   1554     { "status", "display GSM status",
   1555     "'gsm status' displays the current state of the GSM emulation\r\n", NULL,
   1556     do_gsm_status, NULL },
   1557 
   1558     { "signal", "set sets the rssi and ber",
   1559     "'gsm signal <rssi> [<ber>]' changes the reported strength and error rate on next (15s) update.\r\n"
   1560     "rssi range is 0..31 and 99 for unknown\r\n"
   1561     "ber range is 0..7 percent and 99 for unknown\r\n",
   1562     NULL, do_gsm_signal, NULL },
   1563 
   1564     { NULL, NULL, NULL, NULL, NULL, NULL }
   1565 };
   1566 
   1567 /********************************************************************************************/
   1568 /********************************************************************************************/
   1569 /*****                                                                                 ******/
   1570 /*****                           S M S   C O M M A N D                                 ******/
   1571 /*****                                                                                 ******/
   1572 /********************************************************************************************/
   1573 /********************************************************************************************/
   1574 
   1575 static int
   1576 do_sms_send( ControlClient  client, char*  args )
   1577 {
   1578     char*          p;
   1579     int            textlen;
   1580     SmsAddressRec  sender;
   1581     SmsPDU*        pdus;
   1582     int            nn;
   1583 
   1584     /* check that we have a phone number made of digits */
   1585     if (!args) {
   1586     MissingArgument:
   1587         control_write( client, "KO: missing argument, try 'sms send <phonenumber> <text message>'\r\n" );
   1588         return -1;
   1589     }
   1590     p = strchr( args, ' ' );
   1591     if (!p) {
   1592         goto MissingArgument;
   1593     }
   1594 
   1595     if ( sms_address_from_str( &sender, args, p - args ) < 0 ) {
   1596         control_write( client, "KO: bad phone number format, must be [+](0-9)*\r\n" );
   1597         return -1;
   1598     }
   1599 
   1600 
   1601     /* un-secape message text into proper utf-8 (conversion happens in-site) */
   1602     p      += 1;
   1603     textlen = strlen(p);
   1604     textlen = sms_utf8_from_message_str( p, textlen, (unsigned char*)p, textlen );
   1605     if (textlen < 0) {
   1606         control_write( client, "message must be utf8 and can use the following escapes:\r\n"
   1607                        "    \\n      for a newline\r\n"
   1608                        "    \\xNN    where NN are two hexadecimal numbers\r\n"
   1609                        "    \\uNNNN  where NNNN are four hexadecimal numbers\r\n"
   1610                        "    \\\\     to send a '\\' character\r\n\r\n"
   1611                        "    anything else is an error\r\n"
   1612                        "KO: badly formatted text\r\n" );
   1613         return -1;
   1614     }
   1615 
   1616     if (!android_modem) {
   1617         control_write( client, "KO: modem emulation not running\r\n" );
   1618         return -1;
   1619     }
   1620 
   1621     /* create a list of SMS PDUs, then send them */
   1622     pdus = smspdu_create_deliver_utf8( (cbytes_t)p, textlen, &sender, NULL );
   1623     if (pdus == NULL) {
   1624         control_write( client, "KO: internal error when creating SMS-DELIVER PDUs\n" );
   1625         return -1;
   1626     }
   1627 
   1628     for (nn = 0; pdus[nn] != NULL; nn++)
   1629         amodem_receive_sms( android_modem, pdus[nn] );
   1630 
   1631     smspdu_free_list( pdus );
   1632     return 0;
   1633 }
   1634 
   1635 static int
   1636 do_sms_sendpdu( ControlClient  client, char*  args )
   1637 {
   1638     SmsPDU  pdu;
   1639 
   1640     /* check that we have a phone number made of digits */
   1641     if (!args) {
   1642         control_write( client, "KO: missing argument, try 'sms sendpdu <hexstring>'\r\n" );
   1643         return -1;
   1644     }
   1645 
   1646     if (!android_modem) {
   1647         control_write( client, "KO: modem emulation not running\r\n" );
   1648         return -1;
   1649     }
   1650 
   1651     pdu = smspdu_create_from_hex( args, strlen(args) );
   1652     if (pdu == NULL) {
   1653         control_write( client, "KO: badly formatted <hexstring>\r\n" );
   1654         return -1;
   1655     }
   1656 
   1657     amodem_receive_sms( android_modem, pdu );
   1658     smspdu_free( pdu );
   1659     return 0;
   1660 }
   1661 
   1662 static const CommandDefRec  sms_commands[] =
   1663 {
   1664     { "send", "send inbound SMS text message",
   1665     "'sms send <phonenumber> <message>' allows you to simulate a new inbound sms message\r\n", NULL,
   1666     do_sms_send, NULL },
   1667 
   1668     { "pdu", "send inbound SMS PDU",
   1669     "'sms pdu <hexstring>' allows you to simulate a new inbound sms PDU\r\n"
   1670     "(used internally when one emulator sends SMS messages to another instance).\r\n"
   1671     "you probably don't want to play with this at all\r\n", NULL,
   1672     do_sms_sendpdu, NULL },
   1673 
   1674     { NULL, NULL, NULL, NULL, NULL, NULL }
   1675 };
   1676 
   1677 static void
   1678 do_control_write(void* data, const char* string)
   1679 {
   1680     control_write((ControlClient)data, string);
   1681 }
   1682 
   1683 static int
   1684 do_power_display( ControlClient client, char*  args )
   1685 {
   1686     goldfish_battery_display(do_control_write, client);
   1687     return 0;
   1688 }
   1689 
   1690 static int
   1691 do_ac_state( ControlClient  client, char*  args )
   1692 {
   1693     if (args) {
   1694         if (strcasecmp(args, "on") == 0) {
   1695             goldfish_battery_set_prop(1, POWER_SUPPLY_PROP_ONLINE, 1);
   1696             return 0;
   1697         }
   1698         if (strcasecmp(args, "off") == 0) {
   1699             goldfish_battery_set_prop(1, POWER_SUPPLY_PROP_ONLINE, 0);
   1700             return 0;
   1701         }
   1702     }
   1703 
   1704     control_write( client, "KO: Usage: \"ac on\" or \"ac off\"\n" );
   1705     return -1;
   1706 }
   1707 
   1708 static int
   1709 do_battery_status( ControlClient  client, char*  args )
   1710 {
   1711     if (args) {
   1712         if (strcasecmp(args, "unknown") == 0) {
   1713             goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_UNKNOWN);
   1714             return 0;
   1715         }
   1716         if (strcasecmp(args, "charging") == 0) {
   1717             goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_CHARGING);
   1718             return 0;
   1719         }
   1720         if (strcasecmp(args, "discharging") == 0) {
   1721             goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_DISCHARGING);
   1722             return 0;
   1723         }
   1724         if (strcasecmp(args, "not-charging") == 0) {
   1725             goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_NOT_CHARGING);
   1726             return 0;
   1727         }
   1728         if (strcasecmp(args, "full") == 0) {
   1729             goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_FULL);
   1730             return 0;
   1731         }
   1732     }
   1733 
   1734     control_write( client, "KO: Usage: \"status unknown|charging|discharging|not-charging|full\"\n" );
   1735     return -1;
   1736 }
   1737 
   1738 static int
   1739 do_battery_present( ControlClient  client, char*  args )
   1740 {
   1741     if (args) {
   1742         if (strcasecmp(args, "true") == 0) {
   1743             goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_PRESENT, 1);
   1744             return 0;
   1745         }
   1746         if (strcasecmp(args, "false") == 0) {
   1747             goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_PRESENT, 0);
   1748             return 0;
   1749         }
   1750     }
   1751 
   1752     control_write( client, "KO: Usage: \"present true\" or \"present false\"\n" );
   1753     return -1;
   1754 }
   1755 
   1756 static int
   1757 do_battery_health( ControlClient  client, char*  args )
   1758 {
   1759     if (args) {
   1760         if (strcasecmp(args, "unknown") == 0) {
   1761             goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_UNKNOWN);
   1762             return 0;
   1763         }
   1764         if (strcasecmp(args, "good") == 0) {
   1765             goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_GOOD);
   1766             return 0;
   1767         }
   1768         if (strcasecmp(args, "overheat") == 0) {
   1769             goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_OVERHEAT);
   1770             return 0;
   1771         }
   1772         if (strcasecmp(args, "dead") == 0) {
   1773             goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_DEAD);
   1774             return 0;
   1775         }
   1776         if (strcasecmp(args, "overvoltage") == 0) {
   1777             goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_OVERVOLTAGE);
   1778             return 0;
   1779         }
   1780         if (strcasecmp(args, "failure") == 0) {
   1781             goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_UNSPEC_FAILURE);
   1782             return 0;
   1783         }
   1784     }
   1785 
   1786     control_write( client, "KO: Usage: \"health unknown|good|overheat|dead|overvoltage|failure\"\n" );
   1787     return -1;
   1788 }
   1789 
   1790 static int
   1791 do_battery_capacity( ControlClient  client, char*  args )
   1792 {
   1793     if (args) {
   1794         int capacity;
   1795 
   1796         if (sscanf(args, "%d", &capacity) == 1 && capacity >= 0 && capacity <= 100) {
   1797             goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_CAPACITY, capacity);
   1798             return 0;
   1799         }
   1800     }
   1801 
   1802     control_write( client, "KO: Usage: \"capacity <percentage>\"\n" );
   1803     return -1;
   1804 }
   1805 
   1806 
   1807 static const CommandDefRec  power_commands[] =
   1808 {
   1809     { "display", "display battery and charger state",
   1810     "display battery and charger state\r\n", NULL,
   1811     do_power_display, NULL },
   1812 
   1813     { "ac", "set AC charging state",
   1814     "'ac on|off' allows you to set the AC charging state to on or off\r\n", NULL,
   1815     do_ac_state, NULL },
   1816 
   1817     { "status", "set battery status",
   1818     "'status unknown|charging|discharging|not-charging|full' allows you to set battery status\r\n", NULL,
   1819     do_battery_status, NULL },
   1820 
   1821     { "present", "set battery present state",
   1822     "'present true|false' allows you to set battery present state to true or false\r\n", NULL,
   1823     do_battery_present, NULL },
   1824 
   1825     { "health", "set battery health state",
   1826     "'health unknown|good|overheat|dead|overvoltage|failure' allows you to set battery health state\r\n", NULL,
   1827     do_battery_health, NULL },
   1828 
   1829     { "capacity", "set battery capacity state",
   1830     "'capacity <percentage>' allows you to set battery capacity to a value 0 - 100\r\n", NULL,
   1831     do_battery_capacity, NULL },
   1832 
   1833     { NULL, NULL, NULL, NULL, NULL, NULL }
   1834 };
   1835 
   1836 /********************************************************************************************/
   1837 /********************************************************************************************/
   1838 /*****                                                                                 ******/
   1839 /*****                         E  V  E  N  T   C O M M A N D S                         ******/
   1840 /*****                                                                                 ******/
   1841 /********************************************************************************************/
   1842 /********************************************************************************************/
   1843 
   1844 
   1845 static int
   1846 do_event_send( ControlClient  client, char*  args )
   1847 {
   1848     char*   p;
   1849 
   1850     if (!args) {
   1851         control_write( client, "KO: Usage: event send <type>:<code>:<value> ...\r\n" );
   1852         return -1;
   1853     }
   1854 
   1855     p = args;
   1856     while (*p) {
   1857         char*  q;
   1858         char   temp[128];
   1859         int    type, code, value, ret;
   1860 
   1861         p += strspn( p, " \t" );  /* skip spaces */
   1862         if (*p == 0)
   1863             break;
   1864 
   1865         q  = p + strcspn( p, " \t" );
   1866 
   1867         if (q == p)
   1868             break;
   1869 
   1870         snprintf(temp, sizeof temp, "%.*s", (int)(intptr_t)(q-p), p);
   1871         ret = android_event_from_str( temp, &type, &code, &value );
   1872         if (ret < 0) {
   1873             if (ret == -1) {
   1874                 control_write( client,
   1875                                "KO: invalid event type in '%.*s', try 'event list types' for valid values\r\n",
   1876                                q-p, p );
   1877             } else if (ret == -2) {
   1878                 control_write( client,
   1879                                "KO: invalid event code in '%.*s', try 'event list codes <type>' for valid values\r\n",
   1880                                q-p, p );
   1881             } else {
   1882                 control_write( client,
   1883                                "KO: invalid event value in '%.*s', must be an integer\r\n",
   1884                                q-p, p);
   1885             }
   1886             return -1;
   1887         }
   1888 
   1889         user_event_generic( type, code, value );
   1890         p = q;
   1891     }
   1892     return 0;
   1893 }
   1894 
   1895 static int
   1896 do_event_types( ControlClient  client, char*  args )
   1897 {
   1898     int  count = android_event_get_type_count();
   1899     int  nn;
   1900 
   1901     control_write( client, "event <type> can be an integer or one of the following aliases\r\n" );
   1902     for (nn = 0; nn < count; nn++) {
   1903         char  tmp[16];
   1904         char* p = tmp;
   1905         char* end = p + sizeof(tmp);
   1906         int   count2 = android_event_get_code_count( nn );;
   1907 
   1908         p = android_event_bufprint_type_str( p, end, nn );
   1909 
   1910         control_write( client, "    %-8s", tmp );
   1911         if (count2 > 0)
   1912             control_write( client, "  (%d code aliases)", count2 );
   1913 
   1914         control_write( client, "\r\n" );
   1915     }
   1916     return 0;
   1917 }
   1918 
   1919 static int
   1920 do_event_codes( ControlClient  client, char*  args )
   1921 {
   1922     int  count;
   1923     int  nn, type, dummy;
   1924 
   1925     if (!args) {
   1926         control_write( client, "KO: argument missing, try 'event codes <type>'\r\n" );
   1927         return -1;
   1928     }
   1929 
   1930     if ( android_event_from_str( args, &type, &dummy, &dummy ) < 0 ) {
   1931         control_write( client, "KO: bad argument, see 'event types' for valid values\r\n" );
   1932         return -1;
   1933     }
   1934 
   1935     count = android_event_get_code_count( type );
   1936     if (count == 0) {
   1937         control_write( client, "no code aliases defined for this type\r\n" );
   1938     } else {
   1939         control_write( client, "type '%s' accepts the following <code> aliases:\r\n",
   1940                        args );
   1941         for (nn = 0; nn < count; nn++) {
   1942             char  temp[20], *p = temp, *end = p + sizeof(temp);
   1943             android_event_bufprint_code_str( p, end, type, nn );
   1944             control_write( client, "    %-12s\r\n", temp );
   1945         }
   1946     }
   1947 
   1948     return 0;
   1949 }
   1950 
   1951 static __inline__ int
   1952 utf8_next( unsigned char* *pp, unsigned char*  end )
   1953 {
   1954     unsigned char*  p      = *pp;
   1955     int             result = -1;
   1956 
   1957     if (p < end) {
   1958         int  c= *p++;
   1959         if (c >= 128) {
   1960             if ((c & 0xe0) == 0xc0)
   1961                 c &= 0x1f;
   1962             else if ((c & 0xf0) == 0xe0)
   1963                 c &= 0x0f;
   1964             else
   1965                 c &= 0x07;
   1966 
   1967             while (p < end && (p[0] & 0xc0) == 0x80) {
   1968                 c = (c << 6) | (p[0] & 0x3f);
   1969             }
   1970         }
   1971         result = c;
   1972         *pp    = p;
   1973     }
   1974     return result;
   1975 }
   1976 
   1977 static int
   1978 do_event_text( ControlClient  client, char*  args )
   1979 {
   1980     AKeycodeBuffer keycodes;
   1981     unsigned char*  p   = (unsigned char*) args;
   1982     unsigned char*  end = p + strlen(args);
   1983     int             textlen;
   1984     const AKeyCharmap* charmap;
   1985 
   1986     if (!args) {
   1987         control_write( client, "KO: argument missing, try 'event text <message>'\r\n" );
   1988         return -1;
   1989     }
   1990 
   1991     /* Get active charmap. */
   1992     charmap = android_get_charmap();
   1993     if (charmap == NULL) {
   1994         control_write( client, "KO: no character map active in current device layout/config\r\n" );
   1995         return -1;
   1996     }
   1997 
   1998     keycodes.keycode_count = 0;
   1999 
   2000     /* un-secape message text into proper utf-8 (conversion happens in-site) */
   2001     textlen = strlen((char*)p);
   2002     textlen = sms_utf8_from_message_str( args, textlen, (unsigned char*)p, textlen );
   2003     if (textlen < 0) {
   2004         control_write( client, "message must be utf8 and can use the following escapes:\r\n"
   2005                        "    \\n      for a newline\r\n"
   2006                        "    \\xNN    where NN are two hexadecimal numbers\r\n"
   2007                        "    \\uNNNN  where NNNN are four hexadecimal numbers\r\n"
   2008                        "    \\\\     to send a '\\' character\r\n\r\n"
   2009                        "    anything else is an error\r\n"
   2010                        "KO: badly formatted text\r\n" );
   2011         return -1;
   2012     }
   2013 
   2014     end = p + textlen;
   2015     while (p < end) {
   2016         int  c = utf8_next( &p, end );
   2017         if (c <= 0)
   2018             break;
   2019 
   2020         android_charmap_reverse_map_unicode( NULL, (unsigned)c, 1, &keycodes );
   2021         android_charmap_reverse_map_unicode( NULL, (unsigned)c, 0, &keycodes );
   2022         android_keycodes_flush( &keycodes );
   2023     }
   2024 
   2025     return 0;
   2026 }
   2027 
   2028 static const CommandDefRec  event_commands[] =
   2029 {
   2030     { "send", "send a series of events to the kernel",
   2031     "'event send <type>:<code>:<value> ...' allows your to send one or more hardware events\r\n"
   2032     "to the Android kernel. you can use text names or integers for <type> and <code>\r\n", NULL,
   2033     do_event_send, NULL },
   2034 
   2035     { "types", "list all <type> aliases",
   2036     "'event types' list all <type> string aliases supported by the 'event' subcommands\r\n",
   2037     NULL, do_event_types, NULL },
   2038 
   2039     { "codes", "list all <code> aliases for a given <type>",
   2040     "'event codes <type>' lists all <code> string aliases for a given event <type>\r\n",
   2041     NULL, do_event_codes, NULL },
   2042 
   2043     { "text", "simulate keystrokes from a given text",
   2044     "'event text <message>' allows you to simulate keypresses to generate a given text\r\n"
   2045     "message. <message> must be an utf-8 string. Unicode points will be reverse-mapped\r\n"
   2046     "according to the current device keyboard. unsupported characters will be discarded\r\n"
   2047     "silently\r\n", NULL, do_event_text, NULL },
   2048 
   2049     { NULL, NULL, NULL, NULL, NULL, NULL }
   2050 };
   2051 
   2052 
   2053 /********************************************************************************************/
   2054 /********************************************************************************************/
   2055 /*****                                                                                 ******/
   2056 /*****                      S N A P S H O T   C O M M A N D S                          ******/
   2057 /*****                                                                                 ******/
   2058 /********************************************************************************************/
   2059 /********************************************************************************************/
   2060 
   2061 static int
   2062 control_write_out_cb(void* opaque, const char* str, int strsize)
   2063 {
   2064     ControlClient client = opaque;
   2065     control_control_write(client, str, strsize);
   2066     return strsize;
   2067 }
   2068 
   2069 static int
   2070 control_write_err_cb(void* opaque, const char* str, int strsize)
   2071 {
   2072     int ret = 0;
   2073     ControlClient client = opaque;
   2074     ret += control_write(client, "KO: ");
   2075     control_control_write(client, str, strsize);
   2076     return ret + strsize;
   2077 }
   2078 
   2079 static int
   2080 do_snapshot_list( ControlClient  client, char*  args )
   2081 {
   2082     int64_t ret;
   2083     Monitor *out = monitor_fake_new(client, control_write_out_cb);
   2084     Monitor *err = monitor_fake_new(client, control_write_err_cb);
   2085     do_info_snapshots(out, err);
   2086     ret = monitor_fake_get_bytes(err);
   2087     monitor_fake_free(err);
   2088     monitor_fake_free(out);
   2089 
   2090     return ret > 0;
   2091 }
   2092 
   2093 static int
   2094 do_snapshot_save( ControlClient  client, char*  args )
   2095 {
   2096     int64_t ret;
   2097 
   2098     if (args == NULL) {
   2099         control_write(client, "KO: argument missing, try 'avd snapshot save <name>'\r\n");
   2100         return -1;
   2101     }
   2102 
   2103     Monitor *err = monitor_fake_new(client, control_write_err_cb);
   2104     do_savevm(err, args);
   2105     ret = monitor_fake_get_bytes(err);
   2106     monitor_fake_free(err);
   2107 
   2108     return ret > 0; // no output on error channel indicates success
   2109 }
   2110 
   2111 static int
   2112 do_snapshot_load( ControlClient  client, char*  args )
   2113 {
   2114     int64_t ret;
   2115 
   2116     if (args == NULL) {
   2117         control_write(client, "KO: argument missing, try 'avd snapshot load <name>'\r\n");
   2118         return -1;
   2119     }
   2120 
   2121     Monitor *err = monitor_fake_new(client, control_write_err_cb);
   2122     do_loadvm(err, args);
   2123     ret = monitor_fake_get_bytes(err);
   2124     monitor_fake_free(err);
   2125 
   2126     return ret > 0;
   2127 }
   2128 
   2129 static int
   2130 do_snapshot_del( ControlClient  client, char*  args )
   2131 {
   2132     int64_t ret;
   2133 
   2134     if (args == NULL) {
   2135         control_write(client, "KO: argument missing, try 'avd snapshot del <name>'\r\n");
   2136         return -1;
   2137     }
   2138 
   2139     Monitor *err = monitor_fake_new(client, control_write_err_cb);
   2140     do_delvm(err, args);
   2141     ret = monitor_fake_get_bytes(err);
   2142     monitor_fake_free(err);
   2143 
   2144     return ret > 0;
   2145 }
   2146 
   2147 static const CommandDefRec  snapshot_commands[] =
   2148 {
   2149     { "list", "list available state snapshots",
   2150     "'avd snapshot list' will show a list of all state snapshots that can be loaded\r\n",
   2151     NULL, do_snapshot_list, NULL },
   2152 
   2153     { "save", "save state snapshot",
   2154     "'avd snapshot save <name>' will save the current (run-time) state to a snapshot with the given name\r\n",
   2155     NULL, do_snapshot_save, NULL },
   2156 
   2157     { "load", "load state snapshot",
   2158     "'avd snapshot load <name>' will load the state snapshot of the given name\r\n",
   2159     NULL, do_snapshot_load, NULL },
   2160 
   2161     { "del", "delete state snapshot",
   2162     "'avd snapshot del <name>' will delete the state snapshot with the given name\r\n",
   2163     NULL, do_snapshot_del, NULL },
   2164 
   2165     { NULL, NULL, NULL, NULL, NULL, NULL }
   2166 };
   2167 
   2168 
   2169 
   2170 /********************************************************************************************/
   2171 /********************************************************************************************/
   2172 /*****                                                                                 ******/
   2173 /*****                               V M   C O M M A N D S                             ******/
   2174 /*****                                                                                 ******/
   2175 /********************************************************************************************/
   2176 /********************************************************************************************/
   2177 
   2178 static int
   2179 do_avd_stop( ControlClient  client, char*  args )
   2180 {
   2181     if (!vm_running) {
   2182         control_write( client, "KO: virtual device already stopped\r\n" );
   2183         return -1;
   2184     }
   2185     vm_stop(EXCP_INTERRUPT);
   2186     return 0;
   2187 }
   2188 
   2189 static int
   2190 do_avd_start( ControlClient  client, char*  args )
   2191 {
   2192     if (vm_running) {
   2193         control_write( client, "KO: virtual device already running\r\n" );
   2194         return -1;
   2195     }
   2196     vm_start();
   2197     return 0;
   2198 }
   2199 
   2200 static int
   2201 do_avd_status( ControlClient  client, char*  args )
   2202 {
   2203     control_write( client, "virtual device is %s\r\n", vm_running ? "running" : "stopped" );
   2204     return 0;
   2205 }
   2206 
   2207 static int
   2208 do_avd_name( ControlClient  client, char*  args )
   2209 {
   2210     control_write( client, "%s\r\n", android_hw->avd_name);
   2211     return 0;
   2212 }
   2213 
   2214 static const CommandDefRec  vm_commands[] =
   2215 {
   2216     { "stop", "stop the virtual device",
   2217     "'avd stop' stops the virtual device immediately, use 'avd start' to continue execution\r\n",
   2218     NULL, do_avd_stop, NULL },
   2219 
   2220     { "start", "start/restart the virtual device",
   2221     "'avd start' will start or continue the virtual device, use 'avd stop' to stop it\r\n",
   2222     NULL, do_avd_start, NULL },
   2223 
   2224     { "status", "query virtual device status",
   2225     "'avd status' will indicate whether the virtual device is running or not\r\n",
   2226     NULL, do_avd_status, NULL },
   2227 
   2228     { "name", "query virtual device name",
   2229     "'avd name' will return the name of this virtual device\r\n",
   2230     NULL, do_avd_name, NULL },
   2231 
   2232     { "snapshot", "state snapshot commands",
   2233     "allows you to save and restore the virtual device state in snapshots\r\n",
   2234     NULL, NULL, snapshot_commands },
   2235 
   2236     { NULL, NULL, NULL, NULL, NULL, NULL }
   2237 };
   2238 
   2239 /********************************************************************************************/
   2240 /********************************************************************************************/
   2241 /*****                                                                                 ******/
   2242 /*****                             G E O   C O M M A N D S                             ******/
   2243 /*****                                                                                 ******/
   2244 /********************************************************************************************/
   2245 /********************************************************************************************/
   2246 
   2247 static int
   2248 do_geo_nmea( ControlClient  client, char*  args )
   2249 {
   2250     if (!args) {
   2251         control_write( client, "KO: NMEA sentence missing, try 'help geo nmea'\r\n" );
   2252         return -1;
   2253     }
   2254     if (!android_gps_cs) {
   2255         control_write( client, "KO: no GPS emulation in this virtual device\r\n" );
   2256         return -1;
   2257     }
   2258     android_gps_send_nmea( args );
   2259     return 0;
   2260 }
   2261 
   2262 static int
   2263 do_geo_fix( ControlClient  client, char*  args )
   2264 {
   2265     // GEO_SAT2 provides bug backwards compatibility.
   2266     enum { GEO_LONG = 0, GEO_LAT, GEO_ALT, GEO_SAT, GEO_SAT2, NUM_GEO_PARAMS };
   2267     char*   p = args;
   2268     int     top_param = -1;
   2269     double  params[ NUM_GEO_PARAMS ];
   2270     int     n_satellites = 1;
   2271 
   2272     static  int     last_time = 0;
   2273     static  double  last_altitude = 0.;
   2274 
   2275     if (!p)
   2276         p = "";
   2277 
   2278     /* tokenize */
   2279     while (*p) {
   2280         char*   end;
   2281         double  val = strtod( p, &end );
   2282 
   2283         if (end == p) {
   2284             control_write( client, "KO: argument '%s' is not a number\n", p );
   2285             return -1;
   2286         }
   2287 
   2288         params[++top_param] = val;
   2289         if (top_param + 1 == NUM_GEO_PARAMS)
   2290             break;
   2291 
   2292         p = end;
   2293         while (*p && (p[0] == ' ' || p[0] == '\t'))
   2294             p += 1;
   2295     }
   2296 
   2297     /* sanity check */
   2298     if (top_param < GEO_LAT) {
   2299         control_write( client, "KO: not enough arguments: see 'help geo fix' for details\r\n" );
   2300         return -1;
   2301     }
   2302 
   2303     /* check number of satellites, must be integer between 1 and 12 */
   2304     if (top_param >= GEO_SAT) {
   2305         int sat_index = (top_param >= GEO_SAT2) ? GEO_SAT2 : GEO_SAT;
   2306         n_satellites = (int) params[sat_index];
   2307         if (n_satellites != params[sat_index]
   2308             || n_satellites < 1 || n_satellites > 12) {
   2309             control_write( client, "KO: invalid number of satellites. Must be an integer between 1 and 12\r\n");
   2310             return -1;
   2311         }
   2312     }
   2313 
   2314     /* generate an NMEA sentence for this fix */
   2315     {
   2316         STRALLOC_DEFINE(s);
   2317         double   val;
   2318         int      deg, min;
   2319         char     hemi;
   2320 
   2321         /* format overview:
   2322          *    time of fix      123519     12:35:19 UTC
   2323          *    latitude         4807.038   48 degrees, 07.038 minutes
   2324          *    north/south      N or S
   2325          *    longitude        01131.000  11 degrees, 31. minutes
   2326          *    east/west        E or W
   2327          *    fix quality      1          standard GPS fix
   2328          *    satellites       1 to 12    number of satellites being tracked
   2329          *    HDOP             <dontcare> horizontal dilution
   2330          *    altitude         546.       altitude above sea-level
   2331          *    altitude units   M          to indicate meters
   2332          *    diff             <dontcare> height of sea-level above ellipsoid
   2333          *    diff units       M          to indicate meters (should be <dontcare>)
   2334          *    dgps age         <dontcare> time in seconds since last DGPS fix
   2335          *    dgps sid         <dontcare> DGPS station id
   2336          */
   2337 
   2338         /* first, the time */
   2339         stralloc_add_format( s, "$GPGGA,%06d", last_time );
   2340         last_time ++;
   2341 
   2342         /* then the latitude */
   2343         hemi = 'N';
   2344         val  = params[GEO_LAT];
   2345         if (val < 0) {
   2346             hemi = 'S';
   2347             val  = -val;
   2348         }
   2349         deg = (int) val;
   2350         val = 60*(val - deg);
   2351         min = (int) val;
   2352         val = 10000*(val - min);
   2353         stralloc_add_format( s, ",%02d%02d.%04d,%c", deg, min, (int)val, hemi );
   2354 
   2355         /* the longitude */
   2356         hemi = 'E';
   2357         val  = params[GEO_LONG];
   2358         if (val < 0) {
   2359             hemi = 'W';
   2360             val  = -val;
   2361         }
   2362         deg = (int) val;
   2363         val = 60*(val - deg);
   2364         min = (int) val;
   2365         val = 10000*(val - min);
   2366         stralloc_add_format( s, ",%02d%02d.%04d,%c", deg, min, (int)val, hemi );
   2367 
   2368         /* bogus fix quality, satellite count and dilution */
   2369         stralloc_add_format( s, ",1,%02d,", n_satellites );
   2370 
   2371         /* optional altitude + bogus diff */
   2372         if (top_param >= GEO_ALT) {
   2373             stralloc_add_format( s, ",%.1g,M,0.,M", params[GEO_ALT] );
   2374             last_altitude = params[GEO_ALT];
   2375         } else {
   2376             stralloc_add_str( s, ",,,," );
   2377         }
   2378         /* bogus rest and checksum */
   2379         stralloc_add_str( s, ",,,*47" );
   2380 
   2381         /* send it, then free */
   2382         android_gps_send_nmea( stralloc_cstr(s) );
   2383         stralloc_reset( s );
   2384     }
   2385     return 0;
   2386 }
   2387 
   2388 static const CommandDefRec  geo_commands[] =
   2389 {
   2390     { "nmea", "send an GPS NMEA sentence",
   2391     "'geo nema <sentence>' sends a NMEA 0183 sentence to the emulated device, as\r\n"
   2392     "if it came from an emulated GPS modem. <sentence> must begin with '$GP'. only\r\n"
   2393     "'$GPGGA' and '$GPRCM' sentences are supported at the moment.\r\n",
   2394     NULL, do_geo_nmea, NULL },
   2395 
   2396     { "fix", "send a simple GPS fix",
   2397     "'geo fix <longitude> <latitude> [<altitude> [<satellites>]]'\r\n"
   2398     " allows you to send a simple GPS fix to the emulated system.\r\n"
   2399     " The parameters are:\r\n\r\n"
   2400     "  <longitude>   longitude, in decimal degrees\r\n"
   2401     "  <latitude>    latitude, in decimal degrees\r\n"
   2402     "  <altitude>    optional altitude in meters\r\n"
   2403     "  <satellites>  number of satellites being tracked (1-12)\r\n"
   2404     "\r\n",
   2405     NULL, do_geo_fix, NULL },
   2406 
   2407     { NULL, NULL, NULL, NULL, NULL, NULL }
   2408 };
   2409 
   2410 
   2411 /********************************************************************************************/
   2412 /********************************************************************************************/
   2413 /*****                                                                                 ******/
   2414 /*****                        S E N S O R S  C O M M A N D S                           ******/
   2415 /*****                                                                                 ******/
   2416 /********************************************************************************************/
   2417 /********************************************************************************************/
   2418 
   2419 /* For sensors user prompt string size.*/
   2420 #define SENSORS_INFO_SIZE 150
   2421 
   2422 /* Get sensor data - (a,b,c) from sensor name */
   2423 static int
   2424 do_sensors_get( ControlClient client, char* args )
   2425 {
   2426     if (! args) {
   2427         control_write( client, "KO: Usage: \"get <sensorname>\"\n" );
   2428         return -1;
   2429     }
   2430 
   2431     int status = SENSOR_STATUS_UNKNOWN;
   2432     char sensor[strlen(args) + 1];
   2433     if (1 != sscanf( args, "%s", &sensor[0] ))
   2434         goto SENSOR_STATUS_ERROR;
   2435 
   2436     int sensor_id = android_sensors_get_id_from_name( sensor );
   2437     char buffer[SENSORS_INFO_SIZE] = { 0 };
   2438     float a, b, c;
   2439 
   2440     if (sensor_id < 0) {
   2441         status = sensor_id;
   2442         goto SENSOR_STATUS_ERROR;
   2443     } else {
   2444         status = android_sensors_get( sensor_id, &a, &b, &c );
   2445         if (status != SENSOR_STATUS_OK)
   2446             goto SENSOR_STATUS_ERROR;
   2447         snprintf( buffer, sizeof(buffer),
   2448                 "%s = %g:%g:%g\r\n", sensor, a, b, c );
   2449         do_control_write( client, buffer );
   2450         return 0;
   2451     }
   2452 
   2453 SENSOR_STATUS_ERROR:
   2454     switch(status) {
   2455     case SENSOR_STATUS_NO_SERVICE:
   2456         snprintf( buffer, sizeof(buffer), "KO: No sensor service found!\r\n" );
   2457         break;
   2458     case SENSOR_STATUS_DISABLED:
   2459         snprintf( buffer, sizeof(buffer), "KO: '%s' sensor is disabled.\r\n", sensor );
   2460         break;
   2461     case SENSOR_STATUS_UNKNOWN:
   2462         snprintf( buffer, sizeof(buffer),
   2463                 "KO: unknown sensor name: %s, run 'sensor status' to get available sensors.\r\n", sensor );
   2464         break;
   2465     default:
   2466         snprintf( buffer, sizeof(buffer), "KO: '%s' sensor: exception happens.\r\n", sensor );
   2467     }
   2468     do_control_write( client, buffer );
   2469     return -1;
   2470 }
   2471 
   2472 /* set sensor data - (a,b,c) from sensor name */
   2473 static int
   2474 do_sensors_set( ControlClient client, char* args )
   2475 {
   2476     if (! args) {
   2477         control_write( client, "KO: Usage: \"set <sensorname> <value-a>[:<value-b>[:<value-c>]]\"\n" );
   2478         return -1;
   2479     }
   2480 
   2481     int status;
   2482     char* sensor;
   2483     char* value;
   2484     char* args_dup = strdup( args );
   2485     if (args_dup == NULL) {
   2486         control_write( client, "KO: Memory allocation failed.\n" );
   2487         return -1;
   2488     }
   2489     char* p = args_dup;
   2490 
   2491     /* Parsing the args to get sensor name string */
   2492     while (*p && isspace(*p)) p++;
   2493     if (*p == 0)
   2494         goto INPUT_ERROR;
   2495     sensor = p;
   2496 
   2497     /* Parsing the args to get value string */
   2498     while (*p && (! isspace(*p))) p++;
   2499     if (*p == 0 || *(p + 1) == 0/* make sure value isn't NULL */)
   2500         goto INPUT_ERROR;
   2501     *p = 0;
   2502     value = p + 1;
   2503 
   2504     if (! (strlen(sensor) && strlen(value)))
   2505         goto INPUT_ERROR;
   2506 
   2507     int sensor_id = android_sensors_get_id_from_name( sensor );
   2508     char buffer[SENSORS_INFO_SIZE] = { 0 };
   2509 
   2510     if (sensor_id < 0) {
   2511         status = sensor_id;
   2512         goto SENSOR_STATUS_ERROR;
   2513     } else {
   2514         float fvalues[3];
   2515         status = android_sensors_get( sensor_id, &fvalues[0], &fvalues[1], &fvalues[2] );
   2516         if (status != SENSOR_STATUS_OK)
   2517             goto SENSOR_STATUS_ERROR;
   2518 
   2519         /* Parsing the value part to get the sensor values(a, b, c) */
   2520         int i;
   2521         char* pnext;
   2522         char* pend = value + strlen(value);
   2523         for (i = 0; i < 3; i++, value = pnext + 1) {
   2524             pnext=strchr( value, ':' );
   2525             if (pnext) {
   2526                 *pnext = 0;
   2527             } else {
   2528                 pnext = pend;
   2529             }
   2530 
   2531             if (pnext > value) {
   2532                 if (1 != sscanf( value,"%g", &fvalues[i] ))
   2533                     goto INPUT_ERROR;
   2534             }
   2535         }
   2536 
   2537         status = android_sensors_set( sensor_id, fvalues[0], fvalues[1], fvalues[2] );
   2538         if (status != SENSOR_STATUS_OK)
   2539             goto SENSOR_STATUS_ERROR;
   2540 
   2541         free( args_dup );
   2542         return 0;
   2543     }
   2544 
   2545 SENSOR_STATUS_ERROR:
   2546     switch(status) {
   2547     case SENSOR_STATUS_NO_SERVICE:
   2548         snprintf( buffer, sizeof(buffer), "KO: No sensor service found!\r\n" );
   2549         break;
   2550     case SENSOR_STATUS_DISABLED:
   2551         snprintf( buffer, sizeof(buffer), "KO: '%s' sensor is disabled.\r\n", sensor );
   2552         break;
   2553     case SENSOR_STATUS_UNKNOWN:
   2554         snprintf( buffer, sizeof(buffer),
   2555                 "KO: unknown sensor name: %s, run 'sensor status' to get available sensors.\r\n", sensor );
   2556         break;
   2557     default:
   2558         snprintf( buffer, sizeof(buffer), "KO: '%s' sensor: exception happens.\r\n", sensor );
   2559     }
   2560     do_control_write( client, buffer );
   2561     free( args_dup );
   2562     return -1;
   2563 
   2564 INPUT_ERROR:
   2565     control_write( client, "KO: Usage: \"set <sensorname> <value-a>[:<value-b>[:<value-c>]]\"\n" );
   2566     free( args_dup );
   2567     return -1;
   2568 }
   2569 
   2570 /* get all available sensor names and enable status respectively. */
   2571 static int
   2572 do_sensors_status( ControlClient client, char* args )
   2573 {
   2574     uint8_t id, status;
   2575     char buffer[SENSORS_INFO_SIZE] = { 0 };
   2576 
   2577     for(id = 0; id < MAX_SENSORS; id++) {
   2578         status = android_sensors_get_sensor_status( id );
   2579         snprintf( buffer, sizeof(buffer), "%s: %s\n",
   2580                 android_sensors_get_name_from_id(id), (status ? "enabled.":"disabled.") );
   2581         control_write( client, buffer );
   2582     }
   2583 
   2584     return 0;
   2585 }
   2586 
   2587 /* Sensor commands for get/set sensor values and get available sensor names. */
   2588 static const CommandDefRec sensor_commands[] =
   2589 {
   2590     { "status", "list all sensors and their status.",
   2591       "'status': list all sensors and their status.\r\n",
   2592       NULL, do_sensors_status, NULL },
   2593 
   2594     { "get", "get sensor values",
   2595       "'get <sensorname>' returns the values of a given sensor.\r\n",
   2596       NULL, do_sensors_get, NULL },
   2597 
   2598     { "set", "set sensor values",
   2599       "'set <sensorname> <value-a>[:<value-b>[:<value-c>]]' set the values of a given sensor.\r\n",
   2600       NULL, do_sensors_set, NULL },
   2601 
   2602     { NULL, NULL, NULL, NULL, NULL, NULL }
   2603 };
   2604 
   2605 /********************************************************************************************/
   2606 /********************************************************************************************/
   2607 /*****                                                                                 ******/
   2608 /*****                           M A I N   C O M M A N D S                             ******/
   2609 /*****                                                                                 ******/
   2610 /********************************************************************************************/
   2611 /********************************************************************************************/
   2612 
   2613 static int
   2614 do_window_scale( ControlClient  client, char*  args )
   2615 {
   2616     double  scale;
   2617     int     is_dpi = 0;
   2618     char*   end;
   2619 
   2620     if (!args) {
   2621         control_write( client, "KO: argument missing, try 'window scale <scale>'\r\n" );
   2622         return -1;
   2623     }
   2624 
   2625     scale = strtol( args, &end, 10 );
   2626     if (end > args && !memcmp( end, "dpi", 4 )) {
   2627         is_dpi = 1;
   2628     }
   2629     else {
   2630         scale = strtod( args, &end );
   2631         if (end == args || end[0]) {
   2632             control_write( client, "KO: argument <scale> must be a real number, or an integer followed by 'dpi'\r\n" );
   2633             return -1;
   2634         }
   2635     }
   2636 
   2637     uicmd_set_window_scale( scale, is_dpi );
   2638     return 0;
   2639 }
   2640 
   2641 static const CommandDefRec  window_commands[] =
   2642 {
   2643     { "scale", "change the window scale",
   2644     "'window scale <scale>' allows you to change the scale of the emulator window at runtime\r\n"
   2645     "<scale> must be either a real number between 0.1 and 3.0, or an integer followed by\r\n"
   2646     "the 'dpi' prefix (as in '120dpi')\r\n",
   2647     NULL, do_window_scale, NULL },
   2648 
   2649     { NULL, NULL, NULL, NULL, NULL, NULL }
   2650 };
   2651 
   2652 /********************************************************************************************/
   2653 /********************************************************************************************/
   2654 /*****                                                                                 ******/
   2655 /*****                           Q E M U   C O M M A N D S                             ******/
   2656 /*****                                                                                 ******/
   2657 /********************************************************************************************/
   2658 /********************************************************************************************/
   2659 
   2660 static int
   2661 do_qemu_monitor( ControlClient client, char* args )
   2662 {
   2663     char             socketname[32];
   2664     int              fd;
   2665     CharDriverState* cs;
   2666 
   2667     if (args != NULL) {
   2668         control_write( client, "KO: no argument for 'qemu monitor'\r\n" );
   2669         return -1;
   2670     }
   2671     /* Detach the client socket, and re-attach it to a monitor */
   2672     fd = control_client_detach(client);
   2673     snprintf(socketname, sizeof socketname, "tcp:socket=%d", fd);
   2674     cs = qemu_chr_open("monitor", socketname, NULL);
   2675     if (cs == NULL) {
   2676         control_client_reattach(client, fd);
   2677         control_write( client, "KO: internal error: could not detach from console !\r\n" );
   2678         return -1;
   2679     }
   2680     monitor_init(cs, MONITOR_USE_READLINE|MONITOR_QUIT_DOESNT_EXIT);
   2681     control_client_destroy(client);
   2682     return 0;
   2683 }
   2684 
   2685 #ifdef CONFIG_STANDALONE_CORE
   2686 /* UI settings, passed to the core via -ui-settings command line parameter. */
   2687 extern char* android_op_ui_settings;
   2688 
   2689 static int
   2690 do_attach_ui( ControlClient client, char* args )
   2691 {
   2692     // Make sure that there are no UI already attached to this console.
   2693     if (attached_ui_client != NULL) {
   2694         control_write( client, "KO: Another UI is attached to this core!\r\n" );
   2695         control_client_destroy(client);
   2696         return -1;
   2697     }
   2698 
   2699     if (!attachUiProxy_create(client->sock)) {
   2700         char reply_buf[4096];
   2701         attached_ui_client = client;
   2702         // Reply "OK" with the saved -ui-settings property.
   2703         snprintf(reply_buf, sizeof(reply_buf), "OK: %s\r\n", android_op_ui_settings);
   2704         control_write( client, reply_buf);
   2705     } else {
   2706         control_write( client, "KO\r\n" );
   2707         control_client_destroy(client);
   2708         return -1;
   2709     }
   2710 
   2711     return 0;
   2712 }
   2713 
   2714 void
   2715 destroy_attach_ui_client(void)
   2716 {
   2717     if (attached_ui_client != NULL) {
   2718         control_client_destroy(attached_ui_client);
   2719     }
   2720 }
   2721 
   2722 static int
   2723 do_create_framebuffer_service( ControlClient client, char* args )
   2724 {
   2725     ProxyFramebuffer* core_fb;
   2726     const char* protocol = "-raw";   // Default framebuffer exchange protocol.
   2727     char reply_buf[64];
   2728 
   2729     // Protocol type is defined by the arguments passed with the stream switch
   2730     // command.
   2731     if (args != NULL && *args != '\0') {
   2732         size_t token_len;
   2733         const char* param_end = strchr(args, ' ');
   2734         if (param_end == NULL) {
   2735             param_end = args + strlen(args);
   2736         }
   2737         token_len = param_end - args;
   2738         protocol = args;
   2739 
   2740         // Make sure that this is one of the supported protocols.
   2741         if (strncmp(protocol, "-raw", token_len) &&
   2742             strncmp(protocol, "-shared", token_len)) {
   2743             derror("Invalid framebuffer parameter %s\n", protocol);
   2744             control_write( client, "KO: Invalid parameter\r\n" );
   2745             control_client_destroy(client);
   2746             return -1;
   2747         }
   2748     }
   2749 
   2750     core_fb = proxyFb_create(client->sock, protocol);
   2751     if (core_fb == NULL) {
   2752         control_write( client, "KO\r\n" );
   2753         control_client_destroy(client);
   2754         return -1;
   2755     }
   2756 
   2757     // Reply "OK" with the framebuffer's bits per pixel
   2758     snprintf(reply_buf, sizeof(reply_buf), "OK: -bitsperpixel=%d\r\n",
   2759              proxyFb_get_bits_per_pixel(core_fb));
   2760     control_write( client, reply_buf);
   2761     return 0;
   2762 }
   2763 
   2764 static int
   2765 do_create_user_events_service( ControlClient client, char* args )
   2766 {
   2767     // Make sure that there are no user events client already existing.
   2768     if (user_events_client != NULL) {
   2769         control_write( client, "KO: Another user events service is already existing!\r\n" );
   2770         control_client_destroy(client);
   2771         return -1;
   2772     }
   2773 
   2774     if (!userEventsImpl_create(client->sock)) {
   2775         char reply_buf[4096];
   2776         user_events_client = client;
   2777         snprintf(reply_buf, sizeof(reply_buf), "OK\r\n");
   2778         control_write( client, reply_buf);
   2779     } else {
   2780         control_write( client, "KO\r\n" );
   2781         control_client_destroy(client);
   2782         return -1;
   2783     }
   2784 
   2785     return 0;
   2786 }
   2787 
   2788 void
   2789 destroy_user_events_client(void)
   2790 {
   2791     if (user_events_client != NULL) {
   2792         control_client_destroy(user_events_client);
   2793     }
   2794 }
   2795 
   2796 static int
   2797 do_create_ui_core_ctl_service( ControlClient client, char* args )
   2798 {
   2799     // Make sure that there are no ui control client already existing.
   2800     if (ui_core_ctl_client != NULL) {
   2801         control_write( client, "KO: Another UI control service is already existing!\r\n" );
   2802         control_client_destroy(client);
   2803         return -1;
   2804     }
   2805 
   2806     if (!coreCmdImpl_create(client->sock)) {
   2807         char reply_buf[4096];
   2808         ui_core_ctl_client = client;
   2809         snprintf(reply_buf, sizeof(reply_buf), "OK\r\n");
   2810         control_write( client, reply_buf);
   2811     } else {
   2812         control_write( client, "KO\r\n" );
   2813         control_client_destroy(client);
   2814         return -1;
   2815     }
   2816 
   2817     return 0;
   2818 }
   2819 
   2820 void
   2821 destroy_ui_core_ctl_client(void)
   2822 {
   2823     if (ui_core_ctl_client != NULL) {
   2824         control_client_destroy(ui_core_ctl_client);
   2825     }
   2826 }
   2827 
   2828 void
   2829 destroy_corecmd_client(void)
   2830 {
   2831     if (ui_core_ctl_client != NULL) {
   2832         control_client_destroy(ui_core_ctl_client);
   2833     }
   2834 }
   2835 
   2836 static int
   2837 do_create_core_ui_ctl_service( ControlClient client, char* args )
   2838 {
   2839     // Make sure that there are no ui control client already existing.
   2840     if (core_ui_ctl_client != NULL) {
   2841         control_write( client, "KO: Another UI control service is already existing!\r\n" );
   2842         control_client_destroy(client);
   2843         return -1;
   2844     }
   2845 
   2846     if (!uiCmdProxy_create(client->sock)) {
   2847         char reply_buf[4096];
   2848         core_ui_ctl_client = client;
   2849         snprintf(reply_buf, sizeof(reply_buf), "OK\r\n");
   2850         control_write( client, reply_buf);
   2851     } else {
   2852         control_write( client, "KO\r\n" );
   2853         control_client_destroy(client);
   2854         return -1;
   2855     }
   2856 
   2857     return 0;
   2858 }
   2859 
   2860 void
   2861 destroy_core_ui_ctl_client(void)
   2862 {
   2863     if (core_ui_ctl_client != NULL) {
   2864         control_client_destroy(core_ui_ctl_client);
   2865     }
   2866 }
   2867 
   2868 void
   2869 destroy_uicmd_client(void)
   2870 {
   2871     if (core_ui_ctl_client != NULL) {
   2872         control_client_destroy(core_ui_ctl_client);
   2873     }
   2874 }
   2875 
   2876 #endif  // CONFIG_STANDALONE_CORE
   2877 
   2878 static const CommandDefRec  qemu_commands[] =
   2879 {
   2880     { "monitor", "enter QEMU monitor",
   2881     "Enter the QEMU virtual machine monitor\r\n",
   2882     NULL, do_qemu_monitor, NULL },
   2883 
   2884 #ifdef CONFIG_STANDALONE_CORE
   2885     { "attach-UI", "attach UI to the core",
   2886     "Attach UI to the core\r\n",
   2887     NULL, do_attach_ui, NULL },
   2888 
   2889     { "framebuffer", "create framebuffer service",
   2890     "Create framebuffer service\r\n",
   2891     NULL, do_create_framebuffer_service, NULL },
   2892 
   2893     { "user-events", "create user events service",
   2894     "Create user events service\r\n",
   2895     NULL, do_create_user_events_service, NULL },
   2896 
   2897     { "ui-core-control", "create UI control service",
   2898     "Create UI control service\r\n",
   2899     NULL, do_create_ui_core_ctl_service, NULL },
   2900 
   2901     { "core-ui-control", "create UI control service",
   2902     "Create UI control service\r\n",
   2903     NULL, do_create_core_ui_ctl_service, NULL },
   2904 #endif  // CONFIG_STANDALONE_CORE
   2905 
   2906     { NULL, NULL, NULL, NULL, NULL, NULL }
   2907 };
   2908 
   2909 
   2910 /********************************************************************************************/
   2911 /********************************************************************************************/
   2912 /*****                                                                                 ******/
   2913 /*****                           M A I N   C O M M A N D S                             ******/
   2914 /*****                                                                                 ******/
   2915 /********************************************************************************************/
   2916 /********************************************************************************************/
   2917 
   2918 static int
   2919 do_kill( ControlClient  client, char*  args )
   2920 {
   2921     control_write( client, "OK: killing emulator, bye bye\r\n" );
   2922     exit(0);
   2923 }
   2924 
   2925 static const CommandDefRec   main_commands[] =
   2926 {
   2927     { "help|h|?", "print a list of commands", NULL, NULL, do_help, NULL },
   2928 
   2929     { "event", "simulate hardware events",
   2930     "allows you to send fake hardware events to the kernel\r\n", NULL,
   2931     NULL, event_commands },
   2932 
   2933     { "geo", "Geo-location commands",
   2934       "allows you to change Geo-related settings, or to send GPS NMEA sentences\r\n", NULL,
   2935       NULL, geo_commands },
   2936 
   2937     { "gsm", "GSM related commands",
   2938       "allows you to change GSM-related settings, or to make a new inbound phone call\r\n", NULL,
   2939       NULL, gsm_commands },
   2940 
   2941     { "cdma", "CDMA related commands",
   2942       "allows you to change CDMA-related settings\r\n", NULL,
   2943       NULL, cdma_commands },
   2944 
   2945     { "kill", "kill the emulator instance", NULL, NULL,
   2946       do_kill, NULL },
   2947 
   2948     { "network", "manage network settings",
   2949       "allows you to manage the settings related to the network data connection of the\r\n"
   2950       "emulated device.\r\n", NULL,
   2951       NULL, network_commands },
   2952 
   2953     { "power", "power related commands",
   2954       "allows to change battery and AC power status\r\n", NULL,
   2955       NULL, power_commands },
   2956 
   2957     { "quit|exit", "quit control session", NULL, NULL,
   2958       do_quit, NULL },
   2959 
   2960     { "redir",    "manage port redirections",
   2961       "allows you to add, list and remove UDP and/or PORT redirection from the host to the device\r\n"
   2962       "as an example, 'redir  tcp:5000:6000' will route any packet sent to the host's TCP port 5000\r\n"
   2963       "to TCP port 6000 of the emulated device\r\n", NULL,
   2964       NULL, redir_commands },
   2965 
   2966     { "sms", "SMS related commands",
   2967       "allows you to simulate an inbound SMS\r\n", NULL,
   2968       NULL, sms_commands },
   2969 
   2970     { "avd", "control virtual device execution",
   2971     "allows you to control (e.g. start/stop) the execution of the virtual device\r\n", NULL,
   2972     NULL, vm_commands },
   2973 
   2974     { "window", "manage emulator window",
   2975     "allows you to modify the emulator window\r\n", NULL,
   2976     NULL, window_commands },
   2977 
   2978     { "qemu", "QEMU-specific commands",
   2979     "allows to connect to the QEMU virtual machine monitor\r\n", NULL,
   2980     NULL, qemu_commands },
   2981 
   2982     { "sensor", "manage emulator sensors",
   2983       "allows you to request the emulator sensors\r\n", NULL,
   2984       NULL, sensor_commands },
   2985 
   2986     { NULL, NULL, NULL, NULL, NULL, NULL }
   2987 };
   2988 
   2989 
   2990 static ControlGlobalRec  _g_global;
   2991 
   2992 int
   2993 control_console_start( int  port )
   2994 {
   2995     return control_global_init( &_g_global, port );
   2996 }
   2997