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