• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
control_global_add_redir(ControlGlobal global,int host_port,int host_udp,unsigned int guest_ip,int guest_port)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
control_global_del_redir(ControlGlobal global,int host_port,int host_udp)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
control_client_detach(ControlClient client)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
control_client_destroy(ControlClient client)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 
control_control_write(ControlClient client,const char * buff,int len)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 
control_vwrite(ControlClient client,const char * format,va_list args)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 
control_write(ControlClient client,const char * format,...)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
control_client_create(Socket socket,ControlGlobal global)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
find_command(char * input,CommandDef commands,char ** pend,char ** pargs)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
dump_help(ControlClient client,CommandDef cmd,const char * prefix)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
control_client_do_command(ControlClient client)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
do_help(ControlClient client,char * args)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
control_client_read_byte(ControlClient client,unsigned char ch)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
control_client_read(void * _client)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
control_global_accept(void * _global)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
control_global_init(ControlGlobal global,int control_port)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
do_quit(ControlClient client,char * args)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
do_network_status(ControlClient client,char * args)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
dump_network_speeds(ControlClient client)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
do_network_speed(ControlClient client,char * args)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
describe_network_speed(ControlClient client)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
do_network_delay(ControlClient client,char * args)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
describe_network_delay(ControlClient client)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
do_network_capture_start(ControlClient client,char * args)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
do_network_capture_stop(ControlClient client,char * args)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
do_redir_list(ControlClient client,char * args)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
redir_parse_proto_port(char * args,int * pport,int * pproto)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
redir_parse_guest_port(char * arg,int * pport)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
redir_find(ControlGlobal global,int port,int isudp)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
do_redir_add(ControlClient client,char * args)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
do_redir_del(ControlClient client,char * args)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
dump_subscription_sources(ControlClient client)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
describe_subscription_source(ControlClient client)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
do_cdma_ssource(ControlClient client,char * args)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
do_cdma_prl_version(ControlClient client,char * args)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*
gsm_state_to_string(ARegistrationState state)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
do_gsm_status(ControlClient client,char * args)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
help_gsm_data(ControlClient client)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
do_gsm_data(ControlClient client,char * args)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
help_gsm_voice(ControlClient client)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
do_gsm_voice(ControlClient client,char * args)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
gsm_check_number(char * args)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
do_gsm_call(ControlClient client,char * args)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
do_gsm_cancel(ControlClient client,char * args)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*
call_state_to_string(ACallState state)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
do_gsm_list(ControlClient client,char * args)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
do_gsm_busy(ControlClient client,char * args)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
do_gsm_hold(ControlClient client,char * args)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
do_gsm_accept(ControlClient client,char * args)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
do_gsm_signal(ControlClient client,char * args)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
do_sms_send(ControlClient client,char * args)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
do_sms_sendpdu(ControlClient client,char * args)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
do_control_write(void * data,const char * string)1658 do_control_write(void* data, const char* string)
1659 {
1660     control_write((ControlClient)data, string);
1661 }
1662 
1663 static int
do_power_display(ControlClient client,char * args)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
do_ac_state(ControlClient client,char * args)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
do_battery_status(ControlClient client,char * args)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
do_battery_present(ControlClient client,char * args)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
do_battery_health(ControlClient client,char * args)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
do_battery_capacity(ControlClient client,char * args)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
do_event_send(ControlClient client,char * args)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
do_event_types(ControlClient client,char * args)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
do_event_codes(ControlClient client,char * args)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
utf8_next(unsigned char ** pp,unsigned char * end)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
do_event_text(ControlClient client,char * args)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
control_write_out_cb(void * opaque,const char * str,int strsize)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
control_write_err_cb(void * opaque,const char * str,int strsize)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
do_snapshot_list(ControlClient client,char * args)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
do_snapshot_save(ControlClient client,char * args)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
do_snapshot_load(ControlClient client,char * args)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
do_snapshot_del(ControlClient client,char * args)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
do_avd_stop(ControlClient client,char * args)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
do_avd_start(ControlClient client,char * args)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
do_avd_status(ControlClient client,char * args)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
do_avd_name(ControlClient client,char * args)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
do_geo_nmea(ControlClient client,char * args)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
do_geo_fix(ControlClient client,char * args)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
do_sensors_get(ControlClient client,char * args)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
do_sensors_set(ControlClient client,char * args)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
do_sensors_status(ControlClient client,char * args)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
do_window_scale(ControlClient client,char * args)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
do_qemu_monitor(ControlClient client,char * args)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
do_attach_ui(ControlClient client,char * args)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
destroy_attach_ui_client(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
do_create_framebuffer_service(ControlClient client,char * args)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
do_create_user_events_service(ControlClient client,char * args)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
destroy_user_events_client(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
do_create_ui_core_ctl_service(ControlClient client,char * args)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
destroy_ui_core_ctl_client(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
destroy_corecmd_client(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
do_create_core_ui_ctl_service(ControlClient client,char * args)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
destroy_core_ui_ctl_client(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
destroy_uicmd_client(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
do_kill(ControlClient client,char * args)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
control_console_start(int port)2953 control_console_start( int  port )
2954 {
2955     return control_global_init( &_g_global, port );
2956 }
2957