console.c revision 43552dc4fa64aad0c9fdb8f4c92ae7ac79406596
18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Copyright (C) 2007-2008 The Android Open Source Project
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This software is licensed under the terms of the GNU General Public
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** License version 2, as published by the Free Software Foundation, and
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** may be copied, distributed, and modified under those terms.
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This program is distributed in the hope that it will be useful,
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** but WITHOUT ANY WARRANTY; without even the implied warranty of
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** GNU General Public License for more details.
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  Android emulator control console
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  this console is enabled automatically at emulator startup, on port 5554 by default,
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  unless some other emulator is already running. See (android_emulation_start in android_sdl.c
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  for details)
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  you can telnet to the console, then use commands like 'help' or others to dynamically
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *  change emulator settings.
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "sockets.h"
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "qemu-char.h"
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "sysemu.h"
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/android.h"
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "sockets.h"
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "cpu.h"
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "hw/goldfish_device.h"
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "hw/power_supply.h"
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "shaper.h"
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "modem_driver.h"
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/gps.h"
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/globals.h"
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/utils/bufprint.h"
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/utils/debug.h"
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/utils/stralloc.h"
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "tcpdump.h"
405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "net.h"
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdlib.h>
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdio.h>
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdarg.h>
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <string.h>
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <unistd.h>
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <fcntl.h>
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/hw-events.h"
4934f2974ce7ec7c71beb47b5daf9089d5c8c40c79David 'Digit' Turner#include "user-events.h"
5071bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine#include "android/keycode-array.h"
5171bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine#include "android/charmap.h"
522fa5173bd1ce7341c50adac676a317945f0969c7Vladimir Chtchetkine#include "android/core-ui-protocol.h"
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(CONFIG_SLIRP)
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "libslirp.h"
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* set to 1 to use the i/o and event functions
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * defined in "telephony/sysdeps.h"
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  USE_SYSDEPS  0
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "sysdeps.h"
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  DEBUG  1
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 1
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  D_ACTIVE   VERBOSE_CHECK(console)
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  D_ACTIVE   DEBUG
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if DEBUG
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  D(x)   do { if (D_ACTIVE) ( printf x , fflush(stdout) ); } while (0)
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  D(x)   do{}while(0)
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct ControlGlobalRec_*  ControlGlobal;
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct ControlClientRec_*  ControlClient;
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct {
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int           host_port;
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int           host_udp;
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int  guest_ip;
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int           guest_port;
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} RedirRec, *Redir;
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if USE_SYSDEPS
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef SysChannel  Socket;
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else /* !USE_SYSDEPS */
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef int         Socket;
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* !USE_SYSDEPS */
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct ControlClientRec_
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ControlClientRec_*  next;       /* next client in list           */
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Socket                     sock;       /* socket used for communication */
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlGlobal              global;
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char                       finished;
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char                       buff[ 4096 ];
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int                        buff_len;
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} ControlClientRec;
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct ControlGlobalRec_
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* listening socket */
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Socket    listen_fd;
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* the list of current clients */
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlClient   clients;
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* the list of redirections currently active */
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Redir     redirs;
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       num_redirs;
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       max_redirs;
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} ControlGlobalRec;
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_global_add_redir( ControlGlobal  global,
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int            host_port,
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int            host_udp,
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          unsigned int   guest_ip,
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int            guest_port )
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Redir  redir;
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (global->num_redirs >= global->max_redirs)
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  old_max = global->max_redirs;
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  new_max = old_max + (old_max >> 1) + 4;
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        Redir  new_redirs = realloc( global->redirs, new_max*sizeof(global->redirs[0]) );
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (new_redirs == NULL)
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        global->redirs     = new_redirs;
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        global->max_redirs = new_max;
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir = &global->redirs[ global->num_redirs++ ];
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir->host_port  = host_port;
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir->host_udp   = host_udp;
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir->guest_ip   = guest_ip;
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir->guest_port = guest_port;
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_global_del_redir( ControlGlobal  global,
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int            host_port,
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int            host_udp )
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < global->num_redirs; nn++)
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        Redir  redir = &global->redirs[nn];
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( redir->host_port == host_port &&
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             redir->host_udp  == host_udp  )
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            memmove( redir, redir + 1, ((global->num_redirs - nn)-1)*sizeof(*redir) );
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            global->num_redirs -= 1;
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we didn't find it */
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_client_destroy( ControlClient  client )
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlGlobal  global = client->global;
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlClient  *pnode = &global->clients;
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D(( "destroying control client %p\n", client ));
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if USE_SYSDEPS
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sys_channel_on( client->sock, 0, NULL, NULL );
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_set_fd_handler( client->sock, NULL, NULL, NULL );
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( ;; ) {
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ControlClient  node = *pnode;
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( node == NULL )
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( node == client ) {
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            *pnode     = node->next;
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            node->next = NULL;
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pnode = &node->next;
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if USE_SYSDEPS
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sys_channel_close( client->sock );
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    client->sock = NULL;
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_close( client->sock );
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    client->sock = -1;
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    free( client );
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void  control_client_read( void*  _client );  /* forward */
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void  control_control_write( ControlClient  client, const char*  buff, int  len )
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len < 0)
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = strlen(buff);
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (len > 0) {
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if USE_SYSDEPS
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = sys_channel_write( client->sock, buff, len );
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = socket_send( client->sock, buff, len);
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ret < 0) {
235ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner            if (errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN)
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            buff += ret;
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len  -= ret;
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void  control_write( ControlClient  client, const char*  format, ... )
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static char  temp[1024];
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_list      args;
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_start(args, format);
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    vsnprintf( temp, sizeof(temp), format, args );
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_end(args);
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    temp[ sizeof(temp)-1 ] = 0;
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_control_write( client, temp, -1 );
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic ControlClient
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_client_create( Socket         socket,
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       ControlGlobal  global )
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlClient  client = calloc( sizeof(*client), 1 );
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (client) {
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !USE_SYSDEPS
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_set_nodelay( socket );
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_set_nonblock( socket );
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->finished = 0;
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->global  = global;
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->sock    = socket;
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->next    = global->clients;
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        global->clients = client;
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if USE_SYSDEPS
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        sys_channel_on( socket, SYS_EVENT_READ,
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        (SysChannelCallback) control_client_read,
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        client );
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_set_fd_handler( socket, control_client_read, NULL, client );
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return client;
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef const struct CommandDefRec_  *CommandDef;
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct CommandDefRec_ {
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*  names;
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*  abstract;
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*  description;
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void        (*descriptor)( ControlClient  client );
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int         (*handler)( ControlClient  client, char* args );
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CommandDef   subcommands;   /* if handler is NULL */
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} CommandDefRec;
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec   main_commands[];  /* forward */
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic CommandDef
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectfind_command( char*  input, CommandDef  commands, char*  *pend, char*  *pargs )
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int    nn;
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*  args = strchr(input, ' ');
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args != NULL) {
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (*args == ' ')
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            args++;
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (args[0] == 0)
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            args = NULL;
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; commands[nn].names != NULL; nn++)
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*  name = commands[nn].names;
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*  sep;
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        do {
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int  len, c;
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sep = strchr( name, '|' );
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (sep)
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                len = sep - name;
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                len = strlen(name);
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            c = input[len];
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ( !memcmp( name, input, len ) && (c == ' ' || c == 0) ) {
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                *pend  = input + len;
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                *pargs = args;
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return &commands[nn];
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (sep)
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                name = sep + 1;
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } while (sep != NULL && *name);
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* NOTE: don't touch *pend and *pargs if no command is found */
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdump_help( ControlClient  client,
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           CommandDef     cmd,
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           const char*    prefix )
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cmd->description) {
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "%s", cmd->description );
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (cmd->descriptor) {
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cmd->descriptor( client );
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "%s\r\n", cmd->abstract );
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cmd->subcommands) {
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cmd = cmd->subcommands;
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "\r\navailable sub-commands:\r\n" );
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for ( ; cmd->names != NULL; cmd++ ) {
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "   %s %-15s  %s\r\n", prefix, cmd->names, cmd->abstract );
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "\r\n" );
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_client_do_command( ControlClient  client )
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       line     = client->buff;
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       args     = NULL;
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CommandDef  commands = main_commands;
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       cmdend   = client->buff;
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CommandDef  cmd      = find_command( line, commands, &cmdend, &args );
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cmd == NULL) {
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: unknown command, try 'help'\r\n" );
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (;;) {
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        CommandDef  subcmd;
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (cmd->handler) {
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ( !cmd->handler( client, args ) )
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client, "OK\r\n" );
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* no handler means we should have sub-commands */
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (cmd->subcommands == NULL) {
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "KO: internal error: buggy command table for '%.*s'\r\n",
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           cmdend - client->buff, client->buff );
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* we need a sub-command here */
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( !args ) {
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dump_help( client, cmd, "" );
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "KO: missing sub-command\r\n" );
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        line     = args;
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        commands = cmd->subcommands;
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        subcmd   = find_command( line, commands, &cmdend, &args );
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (subcmd == NULL) {
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dump_help( client, cmd, "" );
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "KO:  bad sub-command\r\n" );
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cmd = subcmd;
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* implement the 'help' command */
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_help( ControlClient  client, char*  args )
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       line;
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       start = args;
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       end   = start;
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CommandDef  cmd = main_commands;
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* without arguments, simply dump all commands */
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args == NULL) {
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "Android console command help:\r\n\r\n" );
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for ( ; cmd->names != NULL; cmd++ ) {
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "    %-15s  %s\r\n", cmd->names, cmd->abstract );
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "\r\ntry 'help <command>' for command-specific help\r\n" );
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* with an argument, find the corresponding command */
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (;;) {
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        CommandDef  subcmd;
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        line    = args;
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        subcmd  = find_command( line, cmd, &end, &args );
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (subcmd == NULL) {
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "try one of these instead:\r\n\r\n" );
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for ( ; cmd->names != NULL; cmd++ ) {
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client, "    %.*s %s\r\n",
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              end - start, start, cmd->names );
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "\r\nKO: unknown command\r\n" );
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( !args || !subcmd->subcommands ) {
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dump_help( client, subcmd, start );
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cmd = subcmd->subcommands;
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_client_read_byte( ControlClient  client, unsigned char  ch )
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ch == '\r')
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* filter them out */
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else if (ch == '\n')
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->buff[ client->buff_len ] = 0;
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_client_do_command( client );
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (client->finished)
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->buff_len = 0;
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (client->buff_len >= sizeof(client->buff)-1)
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            client->buff_len = 0;
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->buff[ client->buff_len++ ] = ch;
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_client_read( void*  _client )
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlClient  client = _client;
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned char  buf[4096];
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int            size;
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D(( "in control_client read: " ));
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if USE_SYSDEPS
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    size = sys_channel_read( client->sock, buf, sizeof(buf) );
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    size = socket_recv( client->sock, buf, sizeof(buf) );
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (size < 0) {
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "size < 0, exiting with %d: %s\n", errno, errno_str ));
500ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner		if (errno != EWOULDBLOCK && errno != EAGAIN && errno != EINTR)
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			control_client_destroy( client );
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (size == 0) {
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* end of connection */
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "end of connection detected !!\n" ));
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_client_destroy( client );
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  nn;
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  if DEBUG
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char  temp[16];
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int   count = size > sizeof(temp)-1 ? sizeof(temp)-1 : size;
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; nn < count; nn++) {
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int  c = buf[nn];
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (c == '\n')
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        temp[nn] = '!';
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else if (c < 32)
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        temp[nn] = '.';
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    temp[nn] = (char)c;
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        temp[nn] = 0;
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "received %d bytes: %s\n", size, temp ));
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  endif
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "received %.*s\n", size, buf ));
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; nn < size; nn++) {
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_client_read_byte( client, buf[nn] );
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (client->finished) {
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_client_destroy(client);
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* this function is called on each new client connection */
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_global_accept( void*  _global )
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlGlobal       global = _global;
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlClient       client;
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Socket              fd;
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D(( "control_global_accept: just in (fd=%p)\n", (void*)global->listen_fd ));
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if USE_SYSDEPS
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fd = sys_channel_create_tcp_handler( global->listen_fd );
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (fd == NULL) {
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        perror("accept");
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(;;) {
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fd = socket_accept( global->listen_fd, NULL );
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (fd < 0 && errno != EINTR) {
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            D(( "problem in accept: %d: %s\n", errno, errno_str ));
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            perror("accept");
5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if (fd >= 0) {
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "relooping in accept()\n" ));
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_xreuseaddr( fd );
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D(( "control_global_accept: creating new client\n" ));
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    client = control_client_create( fd, global );
5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (client) {
5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "control_global_accept: new client %p\n", client ));
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "Android Console: type 'help' for a list of commands\r\n" );
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "OK\r\n" );
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_global_init( ControlGlobal  global,
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     int            control_port )
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Socket  fd;
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !USE_SYSDEPS
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int     ret;
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SockAddress  sockaddr;
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memset( global, 0, sizeof(*global) );
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sys_main_init();
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if USE_SYSDEPS
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fd = sys_channel_create_tcp_server( control_port );
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (fd == NULL) {
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D(("global fd=%p\n", fd));
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    global->listen_fd = fd;
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sys_channel_on( fd, SYS_EVENT_READ,
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    (SysChannelCallback) control_global_accept,
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    global );
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fd = socket_create_inet( SOCKET_STREAM );
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (fd < 0) {
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        perror("socket");
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_xreuseaddr( fd );
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sock_address_init_inet( &sockaddr, SOCK_ADDRESS_INET_LOOPBACK, control_port );
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = socket_bind(fd, &sockaddr );
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) {
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        perror("bind");
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_close( fd );
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = socket_listen(fd, 0);
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) {
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        perror("listen");
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_close( fd );
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_nonblock(fd);
6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    global->listen_fd = fd;
6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_set_fd_handler( fd, control_global_accept, NULL, global );
6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_quit( ControlClient  client, char*  args )
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    client->finished = 1;
6508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                        N E T W O R K   S E T T I N G S                          ******/
6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_network_status( ControlClient  client, char*  args )
6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "Current network status:\r\n" );
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "  download speed:   %8d bits/s (%.1f KB/s)\r\n",
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   (long)qemu_net_download_speed, qemu_net_download_speed/8192. );
6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "  upload speed:     %8d bits/s (%.1f KB/s)\r\n",
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   (long)qemu_net_upload_speed, qemu_net_upload_speed/8192. );
6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "  minimum latency:  %ld ms\r\n", qemu_net_min_latency );
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "  maximum latency:  %ld ms\r\n", qemu_net_max_latency );
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdump_network_speeds( ControlClient  client )
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const NetworkSpeed*  speed = android_netspeeds;
6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char* const  format = "  %-8s %s\r\n";
6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( ; speed->name; speed++ ) {
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, format, speed->name, speed->display );
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, format, "<num>", "selects both upload and download speed" );
6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, format, "<up>:<down>", "select individual upload/download speeds" );
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_network_speed( ControlClient  client, char*  args )
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !args ) {
6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing <speed> argument, see 'help network speed'\r\n" );
6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( android_parse_network_speed( args ) < 0 ) {
6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: invalid <speed> argument, see 'help network speed' for valid values\r\n" );
6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    netshaper_set_rate( slirp_shaper_in,  qemu_net_download_speed );
7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    netshaper_set_rate( slirp_shaper_out, qemu_net_upload_speed );
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (android_modem) {
70671bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine        amodem_set_data_network_type( android_modem,
7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                    android_parse_network_type( args ) );
7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdescribe_network_speed( ControlClient  client )
7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client,
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   "'network speed <speed>' allows you to dynamically change the speed of the emulated\r\n"
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   "network on the device, where <speed> is one of the following:\r\n\r\n" );
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dump_network_speeds( client );
7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_network_delay( ControlClient  client, char*  args )
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !args ) {
7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing <delay> argument, see 'help network delay'\r\n" );
7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( android_parse_network_latency( args ) < 0 ) {
7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: invalid <delay> argument, see 'help network delay' for valid values\r\n" );
7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    netdelay_set_latency( slirp_delay_in, qemu_net_min_latency, qemu_net_max_latency );
7338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdescribe_network_delay( ControlClient  client )
7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client,
7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   "'network delay <latency>' allows you to dynamically change the latency of the emulated\r\n"
7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   "network on the device, where <latency> is one of the following:\r\n\r\n" );
7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: TODO */
7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_network_capture_start( ControlClient  client, char*  args )
7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !args ) {
7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing <file> argument, see 'help network capture start'\r\n" );
7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( qemu_tcpdump_start(args) < 0) {
7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: could not start capture: %s", strerror(errno) );
7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_network_capture_stop( ControlClient  client, char*  args )
7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* no need to return an error here */
7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_tcpdump_stop();
7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  network_capture_commands[] =
7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "start", "start network capture",
7708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "'network capture start <file>' starts a new capture of network packets\r\n"
7718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "into a specific <file>. This will stop any capture already in progress.\r\n"
7728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "the capture file can later be analyzed by tools like WireShark. It uses\r\n"
7738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "the libpcap file format.\r\n\r\n"
7748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "you can stop the capture anytime with 'network capture stop'\r\n", NULL,
7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      do_network_capture_start, NULL },
7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "stop", "stop network capture",
7788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "'network capture stop' stops a currently running packet capture, if any.\r\n"
7798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "you can start one with 'network capture start <file>'\r\n", NULL,
7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      do_network_capture_stop, NULL },
7818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  network_commands[] =
7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "status", "dump network status", NULL, NULL,
7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       do_network_status, NULL },
7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "speed", "change network speed", NULL, describe_network_speed,
7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      do_network_speed, NULL },
7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "delay", "change network latency", NULL, describe_network_delay,
7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       do_network_delay, NULL },
7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "capture", "dump network packets to file",
7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows to start/stop capture of network packets to a file for later analysis\r\n", NULL,
7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, network_capture_commands },
7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
8018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
8048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
8058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
8068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                       P O R T   R E D I R E C T I O N S                         ******/
8078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
8088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
8098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
8128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_redir_list( ControlClient  client, char*  args )
8138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlGlobal  global = client->global;
8158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (global->num_redirs == 0)
8178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "no active redirections\r\n" );
8188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
8198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  nn;
8208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; nn < global->num_redirs; nn++) {
8218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            Redir  redir = &global->redirs[nn];
8228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "%s:%-5d => %-5d\r\n",
8238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          redir->host_udp ? "udp" : "tcp",
8248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          redir->host_port,
8258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          redir->guest_port );
8268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
8278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
8298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* parse a protocol:port specification */
8328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
8338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectredir_parse_proto_port( char*  args, int  *pport, int  *pproto )
8348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  proto = -1;
8368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  len   = 0;
8378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*  end;
8388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !memcmp( args, "tcp:", 4 ) ) {
8408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        proto = 0;
8418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len   = 4;
8428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else if ( !memcmp( args, "udp:", 4 ) ) {
8448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        proto = 1;
8458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len   = 4;
8468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
8488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
8498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    args   += len;
8518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pproto = proto;
8528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pport  = strtol( args, &end, 10 );
8538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (end == args)
8548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
8558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len += end - args;
8578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return len;
8588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
8618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectredir_parse_guest_port( char*  arg, int  *pport )
8628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*  end;
8648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pport = strtoul( arg, &end, 10 );
8668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (end == arg)
8678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
8688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return end - arg;
8708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic Redir
8738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectredir_find( ControlGlobal  global, int  port, int  isudp )
8748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
8768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < global->num_redirs; nn++) {
8788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        Redir  redir = &global->redirs[nn];
8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (redir->host_port == port && redir->host_udp == isudp)
8818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return redir;
8828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
8848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
8888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_redir_add( ControlClient  client, char*  args )
8898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       len, host_proto, host_port, guest_port;
8918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t  guest_ip;
8928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Redir     redir;
8938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !args )
8958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto BadFormat;
8968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!slirp_is_inited()) {
8985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        control_write( client, "KO: network emulation disabled\r\n");
8995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -1;
9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = redir_parse_proto_port( args, &host_port, &host_proto );
9038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len == 0 || args[len] != ':')
9048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto BadFormat;
9058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    args += len + 1;
9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = redir_parse_guest_port( args, &guest_port );
9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len == 0 || args[len] != 0)
9098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto BadFormat;
9108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir = redir_find( client->global, host_port, host_proto );
9128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( redir != NULL ) {
9138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: host port already active, use 'redir del' to remove first\r\n" );
9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9177d9a2705e7ae6d8c4b1d9d5b4e2a67ab88c19044David Turner    if (inet_strtoip("10.0.2.15", &guest_ip) < 0) {
9188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: unexpected internal failure when resolving 10.0.2.15\r\n" );
9198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D(("pattern hport=%d gport=%d proto=%d\n", host_port, guest_port, host_proto ));
9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( control_global_add_redir( client->global, host_port, host_proto,
9248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                   guest_ip, guest_port ) < 0 )
9258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
9268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: not enough memory to allocate redirection\r\n" );
9278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (slirp_redir(host_proto, host_port, guest_ip, guest_port) < 0) {
9318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: can't setup redirection, port probably used by another program on host\r\n" );
9328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_global_del_redir( client->global, host_port, host_proto );
9338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
9378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectBadFormat:
9398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: bad redirection format, try (tcp|udp):hostport:guestport\r\n", -1 );
9408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
9418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
9458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_redir_del( ControlClient  client, char*  args )
9468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int    len, proto, port;
9488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Redir  redir;
9498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !args )
9518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto BadFormat;
9528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = redir_parse_proto_port( args, &port, &proto );
9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( len == 0 || args[len] != 0 )
9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto BadFormat;
9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir = redir_find( client->global, port, proto );
9578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (redir == NULL) {
9588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: can't remove unknown redirection (%s:%d)\r\n",
9598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        proto ? "udp" : "tcp", port );
9608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    slirp_unredir( redir->host_udp, redir->host_port );
9648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_global_del_redir( client->global, port, proto );\
9658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectBadFormat:
9698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: bad redirection format, try (tcp|udp):hostport\r\n" );
9708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  redir_commands[] =
9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "list", "list current redirections",
9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "list current port redirections. use 'redir add' and 'redir del' to add and remove them\r\n", NULL,
9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_redir_list, NULL },
9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "add",  "add new redirection",
9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "add a new port redirection, arguments must be:\r\n\r\n"
9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "  redir add <protocol>:<host-port>:<guest-port>\r\n\r\n"
9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "where:   <protocol>     is either 'tcp' or 'udp'\r\n"
9838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "         <host-port>    a number indicating which port on the host to open\r\n"
9848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "         <guest-port>   a number indicating which port to route to on the device\r\n"
9858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "\r\nas an example, 'redir  tcp:5000:6000' will allow any packets sent to\r\n"
9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "the host's TCP port 5000 to be routed to TCP port 6000 of the emulated device\r\n", NULL,
9878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_redir_add, NULL },
9888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "del",  "remove existing redirection",
9908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "remove a port redirecion that was created with 'redir add', arguments must be:\r\n\r\n"
9918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "  redir  del <protocol>:<host-port>\r\n\r\n"
9928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "see the 'help redir add' for the meaning of <protocol> and <host-port>\r\n", NULL,
9938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_redir_del, NULL },
9948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
9968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
9978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
10018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
10028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
10038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                           G S M   M O D E M                                     ******/
10048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
10058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
10068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
10078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const struct {
10098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*         name;
10108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*         display;
10118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ARegistrationState  state;
10128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} _gsm_states[] = {
10138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "unregistered",  "no network available", A_REGISTRATION_UNREGISTERED },
10148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "home",          "on local network, non-roaming", A_REGISTRATION_HOME },
10158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "roaming",       "on roaming network", A_REGISTRATION_ROAMING },
10168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "searching",     "searching networks", A_REGISTRATION_SEARCHING },
10178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "denied",        "emergency calls only", A_REGISTRATION_DENIED },
10188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "off",           "same as 'unregistered'", A_REGISTRATION_UNREGISTERED },
10198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "on",            "same as 'home'", A_REGISTRATION_HOME },
10208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, A_REGISTRATION_UNREGISTERED }
10218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
10228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const char*
10248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_state_to_string( ARegistrationState  state )
10258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
10278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; _gsm_states[nn].name != NULL; nn++) {
10288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (state == _gsm_states[nn].state)
10298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return _gsm_states[nn].name;
10308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return "<unknown>";
10328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
10358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_status( ControlClient  client, char*  args )
10368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
10388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: no argument required\r\n" );
10398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
10408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_modem) {
10428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: modem emulation not running\r\n" );
10438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
10448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "gsm voice state: %s\r\n",
10468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   gsm_state_to_string(
10478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       amodem_get_voice_registration(android_modem) ) );
10488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "gsm data state:  %s\r\n",
10498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   gsm_state_to_string(
10508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       amodem_get_data_registration(android_modem) ) );
10518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
10528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
10568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecthelp_gsm_data( ControlClient  client )
10578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
10598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client,
10608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "the 'gsm data <state>' allows you to change the state of your GPRS connection\r\n"
10618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "valid values for <state> are the following:\r\n\r\n" );
10628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; ; nn++) {
10638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         name    = _gsm_states[nn].name;
10648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         display = _gsm_states[nn].display;
10658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!name)
10678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
10688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "  %-15s %s\r\n", name, display );
10708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "\r\n" );
10728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
10768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_data( ControlClient  client, char*  args )
10778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
10798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
10818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm data <state>'\r\n" );
10828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
10838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; ; nn++) {
10868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         name    = _gsm_states[nn].name;
10878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ARegistrationState  state   = _gsm_states[nn].state;
10888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!name)
10908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
10918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( !strcmp( args, name ) ) {
10938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!android_modem) {
10948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client, "KO: modem emulation not running\r\n" );
10958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return -1;
10968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
10978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            amodem_set_data_registration( android_modem, state );
10988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            qemu_net_disable = (state != A_REGISTRATION_HOME    &&
10998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                state != A_REGISTRATION_ROAMING );
11008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
11018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
11028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: bad GSM data state name, try 'help gsm data' for list of valid values\r\n" );
11048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
11058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
11088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecthelp_gsm_voice( ControlClient  client )
11098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
11118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client,
11128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "the 'gsm voice <state>' allows you to change the state of your GPRS connection\r\n"
11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "valid values for <state> are the following:\r\n\r\n" );
11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; ; nn++) {
11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         name    = _gsm_states[nn].name;
11168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         display = _gsm_states[nn].display;
11178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!name)
11198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
11208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "  %-15s %s\r\n", name, display );
11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "\r\n" );
11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
11288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_voice( ControlClient  client, char*  args )
11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm voice <state>'\r\n" );
11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; ; nn++) {
11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         name    = _gsm_states[nn].name;
11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ARegistrationState  state   = _gsm_states[nn].state;
11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!name)
11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( !strcmp( args, name ) ) {
11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!android_modem) {
11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client, "KO: modem emulation not running\r\n" );
11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return -1;
11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            amodem_set_voice_registration( android_modem, state );
11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
11518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
11528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: bad GSM data state name, try 'help gsm voice' for list of valid values\r\n" );
11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
11558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
11598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_check_number( char*  args )
11608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
11628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; args[nn] != 0; nn++) {
11648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = args[nn];
11658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( !isdigit(c) && c != '+' && c != '#' ) {
11668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
11678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
11688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (nn == 0)
11708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
11718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
11738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
11768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_call( ControlClient  client, char*  args )
11778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* check that we have a phone number made of digits */
11798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
11808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm call <phonenumber>'\r\n" );
11818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
11828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (gsm_check_number(args)) {
11858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: bad phone number format, use digits, # and + only\r\n" );
11868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
11878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_modem) {
11908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: modem emulation not running\r\n" );
11918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
11928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    amodem_add_inbound_call( android_modem, args );
11948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
11958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
11988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_cancel( ControlClient  client, char*  args )
11998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
12018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm call <phonenumber>'\r\n" );
12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (gsm_check_number(args)) {
12058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: bad phone number format, use digits, # and + only\r\n" );
12068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_modem) {
12098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: modem emulation not running\r\n" );
12108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( amodem_disconnect_call( android_modem, args ) < 0 ) {
12138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: could not cancel this number\r\n" );
12148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
12178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const char*
12218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcall_state_to_string( ACallState  state )
12228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (state) {
12248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case A_CALL_ACTIVE:   return "active";
12258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case A_CALL_HELD:     return "held";
12268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case A_CALL_ALERTING: return "ringing";
12278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case A_CALL_WAITING:  return "waiting";
12288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case A_CALL_INCOMING: return "incoming";
12298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default: return "unknown";
12308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
12348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_list( ControlClient  client, char*  args )
12358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* check that we have a phone number made of digits */
12378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   count = amodem_get_call_count( android_modem );
12388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   nn;
12398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < count; nn++) {
12408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ACall        call = amodem_get_call( android_modem, nn );
12418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*  dir;
12428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (call == NULL)
12448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            continue;
12458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (call->dir == A_CALL_OUTBOUND)
12478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dir = "outbound to ";
12488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         else
12498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dir = "inbound from";
12508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "%s %-10s : %s\r\n", dir,
12528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       call->number, call_state_to_string(call->state) );
12538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
12558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
12588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_busy( ControlClient  client, char*  args )
12598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ACall  call;
12618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
12638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm busy <phonenumber>'\r\n" );
12648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    call = amodem_find_call_by_number( android_modem, args );
12678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (call == NULL || call->dir != A_CALL_OUTBOUND) {
12688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: no current outbound call to number '%s' (call %p)\r\n", args, call );
12698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( amodem_disconnect_call( android_modem, args ) < 0 ) {
12728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: could not cancel this number\r\n" );
12738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
12768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
12798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_hold( ControlClient  client, char*  args )
12808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ACall  call;
12828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
12848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm out hold <phonenumber>'\r\n" );
12858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    call = amodem_find_call_by_number( android_modem, args );
12888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (call == NULL) {
12898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: no current call to/from number '%s'\r\n", args );
12908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( amodem_update_call( android_modem, args, A_CALL_HELD ) < 0 ) {
12938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: could put this call on hold\r\n" );
12948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
12978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
13018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_accept( ControlClient  client, char*  args )
13028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ACall  call;
13048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
13068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm accept <phonenumber>'\r\n" );
13078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    call = amodem_find_call_by_number( android_modem, args );
13108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (call == NULL) {
13118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: no current call to/from number '%s'\r\n", args );
13128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( amodem_update_call( android_modem, args, A_CALL_ACTIVE ) < 0 ) {
13158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: could not activate this call\r\n" );
13168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
13198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
13238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  gsm_in_commands[] =
13248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "new", "create a new 'waiting' inbound call",
13268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm in create <phonenumber>' creates a new inbound phone call, placed in\r\n"
13278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "the 'waiting' state by default, until the system answers/holds/closes it\r\n", NULL
13288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_in_create, NULL },
13298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "hold", "change the state of an oubtound call to 'held'",
13318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "change the state of an outbound call to 'held'. this is only possible\r\n"
13328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "if the call in the 'waiting' or 'active' state\r\n", NULL,
13338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_out_hold, NULL },
13348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "accept", "change the state of an outbound call to 'active'",
13368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "change the state of an outbound call to 'active'. this is only possible\r\n"
13378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "if the call is in the 'waiting' or 'held' state\r\n", NULL,
13388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_out_accept, NULL },
13398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
13418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
13428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
13438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  gsm_commands[] =
13468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "list", "list current phone calls",
13488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm list' lists all inbound and outbound calls and their state\r\n", NULL,
13498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_list, NULL },
13508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "call", "create inbound phone call",
13528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm call <phonenumber>' allows you to simulate a new inbound call\r\n", NULL,
13538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_call, NULL },
13548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "busy", "close waiting outbound call as busy",
13568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm busy <remoteNumber>' closes an outbound call, reporting\r\n"
13578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "the remote phone as busy. only possible if the call is 'waiting'.\r\n", NULL,
13588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_busy, NULL },
13598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "hold", "change the state of an oubtound call to 'held'",
13618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm hold <remoteNumber>' change the state of a call to 'held'. this is only possible\r\n"
13628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "if the call in the 'waiting' or 'active' state\r\n", NULL,
13638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_hold, NULL },
13648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "accept", "change the state of an outbound call to 'active'",
13668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm accept <remoteNumber>' change the state of a call to 'active'. this is only possible\r\n"
13678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "if the call is in the 'waiting' or 'held' state\r\n", NULL,
13688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_accept, NULL },
13698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "cancel", "disconnect an inbound or outbound phone call",
13718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm cancel <phonenumber>' allows you to simulate the end of an inbound or outbound call\r\n", NULL,
13728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_cancel, NULL },
13738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "data", "modify data connection state", NULL, help_gsm_data,
13758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_data, NULL },
13768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "voice", "modify voice connection state", NULL, help_gsm_voice,
13788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_voice, NULL },
13798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "status", "display GSM status",
13818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm status' displays the current state of the GSM emulation\r\n", NULL,
13828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_status, NULL },
13838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
13858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
13868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
13888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
13898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
13908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                           S M S   C O M M A N D                                 ******/
13918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
13928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
13938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
13948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
13968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_sms_send( ControlClient  client, char*  args )
13978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*          p;
13998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int            textlen;
14008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsAddressRec  sender;
14018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsPDU*        pdus;
14028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int            nn;
14038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* check that we have a phone number made of digits */
14058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
14068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    MissingArgument:
14078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'sms send <phonenumber> <text message>'\r\n" );
14088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = strchr( args, ' ' );
14118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!p) {
14128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto MissingArgument;
14138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( sms_address_from_str( &sender, args, p - args ) < 0 ) {
14168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: bad phone number format, must be [+](0-9)*\r\n" );
14178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* un-secape message text into proper utf-8 (conversion happens in-site) */
14228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p      += 1;
14238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    textlen = strlen(p);
14248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    textlen = sms_utf8_from_message_str( p, textlen, (unsigned char*)p, textlen );
14258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (textlen < 0) {
14268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "message must be utf8 and can use the following escapes:\r\n"
14278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\n      for a newline\r\n"
14288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\xNN    where NN are two hexadecimal numbers\r\n"
14298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\uNNNN  where NNNN are four hexadecimal numbers\r\n"
14308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\\\     to send a '\\' character\r\n\r\n"
14318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    anything else is an error\r\n"
14328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "KO: badly formatted text\r\n" );
14338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_modem) {
14378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: modem emulation not running\r\n" );
14388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* create a list of SMS PDUs, then send them */
14428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pdus = smspdu_create_deliver_utf8( (cbytes_t)p, textlen, &sender, NULL );
14438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (pdus == NULL) {
14448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: internal error when creating SMS-DELIVER PDUs\n" );
14458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; pdus[nn] != NULL; nn++)
14498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        amodem_receive_sms( android_modem, pdus[nn] );
14508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    smspdu_free_list( pdus );
14528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
14538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
14568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_sms_sendpdu( ControlClient  client, char*  args )
14578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsPDU  pdu;
14598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* check that we have a phone number made of digits */
14618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
14628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'sms sendpdu <hexstring>'\r\n" );
14638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_modem) {
14678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: modem emulation not running\r\n" );
14688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pdu = smspdu_create_from_hex( args, strlen(args) );
14728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (pdu == NULL) {
14738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: badly formatted <hexstring>\r\n" );
14748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    amodem_receive_sms( android_modem, pdu );
14788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    smspdu_free( pdu );
14798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
14808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  sms_commands[] =
14838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "send", "send inbound SMS text message",
14858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'sms send <phonenumber> <message>' allows you to simulate a new inbound sms message\r\n", NULL,
14868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_sms_send, NULL },
14878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "pdu", "send inbound SMS PDU",
14898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'sms pdu <hexstring>' allows you to simulate a new inbound sms PDU\r\n"
14908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "(used internally when one emulator sends SMS messages to another instance).\r\n"
14918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "you probably don't want to play with this at all\r\n", NULL,
14928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_sms_sendpdu, NULL },
14938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
14958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
14968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
14988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_control_write(void* data, const char* string)
14998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write((ControlClient)data, string);
15018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
15048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_power_display( ControlClient client, char*  args )
15058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    goldfish_battery_display(do_control_write, client);
15078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
15088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
15118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_ac_state( ControlClient  client, char*  args )
15128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
15148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "on") == 0) {
15158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(1, POWER_SUPPLY_PROP_ONLINE, 1);
15168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
15178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "off") == 0) {
15198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(1, POWER_SUPPLY_PROP_ONLINE, 0);
15208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
15218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: Usage: \"ac on\" or \"ac off\"\n" );
15258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
15268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
15298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_battery_status( ControlClient  client, char*  args )
15308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
15328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "unknown") == 0) {
15338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_UNKNOWN);
15348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
15358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "charging") == 0) {
15378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_CHARGING);
15388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
15398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "discharging") == 0) {
15418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_DISCHARGING);
15428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
15438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "not-charging") == 0) {
15458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_NOT_CHARGING);
15468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
15478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "full") == 0) {
15498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_FULL);
15508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
15518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: Usage: \"status unknown|charging|discharging|not-charging|full\"\n" );
15558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
15568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
15598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_battery_present( ControlClient  client, char*  args )
15608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
15628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "true") == 0) {
15638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_PRESENT, 1);
15648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
15658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "false") == 0) {
15678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_PRESENT, 0);
15688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
15698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: Usage: \"present true\" or \"present false\"\n" );
15738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
15748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
15778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_battery_health( ControlClient  client, char*  args )
15788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
15808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "unknown") == 0) {
15818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_UNKNOWN);
15828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
15838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "good") == 0) {
15858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_GOOD);
15868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
15878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "overheat") == 0) {
15898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_OVERHEAT);
15908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
15918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "dead") == 0) {
15938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_DEAD);
15948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
15958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "overvoltage") == 0) {
15978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_OVERVOLTAGE);
15988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
15998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "failure") == 0) {
16018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_UNSPEC_FAILURE);
16028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: Usage: \"health unknown|good|overheat|dead|overvoltage|failure\"\n" );
16078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
16088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
16118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_battery_capacity( ControlClient  client, char*  args )
16128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
16148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int capacity;
16158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (sscanf(args, "%d", &capacity) == 1 && capacity >= 0 && capacity <= 100) {
16178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_CAPACITY, capacity);
16188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: Usage: \"capacity <percentage>\"\n" );
16238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
16248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  power_commands[] =
16288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "display", "display battery and charger state",
16308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "display battery and charger state\r\n", NULL,
16318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_power_display, NULL },
16328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "ac", "set AC charging state",
16348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'ac on|off' allows you to set the AC charging state to on or off\r\n", NULL,
16358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_ac_state, NULL },
16368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "status", "set battery status",
16388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'status unknown|charging|discharging|not-charging|full' allows you to set battery status\r\n", NULL,
16398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_battery_status, NULL },
16408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "present", "set battery present state",
16428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'present true|false' allows you to set battery present state to true or false\r\n", NULL,
16438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_battery_present, NULL },
16448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "health", "set battery health state",
16468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'health unknown|good|overheat|dead|overvoltage|failure' allows you to set battery health state\r\n", NULL,
16478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_battery_health, NULL },
16488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "capacity", "set battery capacity state",
16508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'capacity <percentage>' allows you to set battery capacity to a value 0 - 100\r\n", NULL,
16518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_battery_capacity, NULL },
16528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
16548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
16558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
16578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
16588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
16598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                         E  V  E  N  T   C O M M A N D S                         ******/
16608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
16618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
16628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
16638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
16668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_event_send( ControlClient  client, char*  args )
16678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*   p;
16698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
16718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: Usage: event send <type>:<code>:<value> ...\r\n" );
16728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
16738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = args;
16768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (*p) {
16778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char*  q;
16788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int    type, code, value, ret;
16798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p += strspn( args, " \t" );  /* skip spaces */
16818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (*p == 0)
16828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        q  = p + strcspn( p, " \t" );
16858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (q == p)
16878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
16888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = android_event_from_str( p, &type, &code, &value );
16908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ret < 0) {
16918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (ret == -1) {
16928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client,
16938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               "KO: invalid event type in '%.*s', try 'event list types' for valid values\r\n",
16948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               q-p, p );
16958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (ret == -2) {
16968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client,
16978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               "KO: invalid event code in '%.*s', try 'event list codes <type>' for valid values\r\n",
16988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               q-p, p );
16998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
17008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client,
17018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               "KO: invalid event value in '%.*s', must be an integer\r\n",
17028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               q-p, p);
17038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
17048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
17058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
170734f2974ce7ec7c71beb47b5daf9089d5c8c40c79David 'Digit' Turner        user_event_generic( type, code, value );
17088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = q;
17098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
17118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
17148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_event_types( ControlClient  client, char*  args )
17158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  count = android_event_get_type_count();
17178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
17188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "event <type> can be an integer or one of the following aliases\r\n" );
17208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < count; nn++) {
17218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char  tmp[16];
17228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char* p = tmp;
17238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char* end = p + sizeof(tmp);
17248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int   count2 = android_event_get_code_count( nn );;
17258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = android_event_bufprint_type_str( p, end, nn );
17278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "    %-8s", tmp );
17298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (count2 > 0)
17308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "  (%d code aliases)", count2 );
17318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "\r\n" );
17338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
17358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
17388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_event_codes( ControlClient  client, char*  args )
17398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  count;
17418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn, type, dummy;
17428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
17448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: argument missing, try 'event codes <type>'\r\n" );
17458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
17468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( android_event_from_str( args, &type, &dummy, &dummy ) < 0 ) {
17498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: bad argument, see 'event types' for valid values\r\n" );
17508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
17518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    count = android_event_get_code_count( type );
17548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (count == 0) {
17558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "no code aliases defined for this type\r\n" );
17568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
17578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "type '%s' accepts the following <code> aliases:\r\n",
17588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       args );
17598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; nn < count; nn++) {
17608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            char  temp[20], *p = temp, *end = p + sizeof(temp);
17618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            android_event_bufprint_code_str( p, end, type, nn );
17628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "    %-12s\r\n", temp );
17638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
17678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic __inline__ int
17708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectutf8_next( unsigned char* *pp, unsigned char*  end )
17718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned char*  p      = *pp;
17738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int             result = -1;
17748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p < end) {
17768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c= *p++;
17778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c >= 128) {
17788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((c & 0xe0) == 0xc0)
17798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c &= 0x1f;
17808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else if ((c & 0xf0) == 0xe0)
17818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c &= 0x0f;
17828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
17838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c &= 0x07;
17848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            while (p < end && (p[0] & 0xc0) == 0x80) {
17868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c = (c << 6) | (p[0] & 0x3f);
17878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
17888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = c;
17908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *pp    = p;
17918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
17938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
17968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_event_text( ControlClient  client, char*  args )
17978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
179871bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine    AKeycodeBuffer keycodes;
17998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned char*  p   = (unsigned char*) args;
18008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned char*  end = p + strlen(args);
18018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int             textlen;
180271bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine    const AKeyCharmap* charmap;
18038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
18058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: argument missing, try 'event text <message>'\r\n" );
18068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
18078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
180871bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine
180971bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine    /* Get default charmap. */
181043552dc4fa64aad0c9fdb8f4c92ae7ac79406596Vladimir Chtchetkine    charmap = android_get_default_charmap();
181171bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine    if (charmap == NULL) {
181271bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine        control_write( client, "KO: no character map active in current device layout/config\r\n" );
18138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
18148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
181671bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine    keycodes.keycode_count = 0;
181771bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine
18188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* un-secape message text into proper utf-8 (conversion happens in-site) */
18198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    textlen = strlen((char*)p);
18208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    textlen = sms_utf8_from_message_str( args, textlen, (unsigned char*)p, textlen );
18218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (textlen < 0) {
18228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "message must be utf8 and can use the following escapes:\r\n"
18238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\n      for a newline\r\n"
18248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\xNN    where NN are two hexadecimal numbers\r\n"
18258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\uNNNN  where NNNN are four hexadecimal numbers\r\n"
18268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\\\     to send a '\\' character\r\n\r\n"
18278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    anything else is an error\r\n"
18288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "KO: badly formatted text\r\n" );
18298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
18308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    end = p + textlen;
18338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (p < end) {
18348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = utf8_next( &p, end );
18358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c <= 0)
18368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
183871bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine        android_charmap_reverse_map_unicode( NULL, (unsigned)c, 1, &keycodes );
183971bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine        android_charmap_reverse_map_unicode( NULL, (unsigned)c, 0, &keycodes );
184071bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine        android_keycodes_flush( &keycodes );
18418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
18448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  event_commands[] =
18478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "send", "send a series of events to the kernel",
18498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'event send <type>:<code>:<value> ...' allows your to send one or more hardware events\r\n"
18508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "to the Android kernel. you can use text names or integers for <type> and <code>\r\n", NULL,
18518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_event_send, NULL },
18528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "types", "list all <type> aliases",
18548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'event types' list all <type> string aliases supported by the 'event' subcommands\r\n",
18558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_event_types, NULL },
18568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "codes", "list all <code> aliases for a given <type>",
18588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'event codes <type>' lists all <code> string aliases for a given event <type>\r\n",
18598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_event_codes, NULL },
18608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "text", "simulate keystrokes from a given text",
18628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'event text <message>' allows you to simulate keypresses to generate a given text\r\n"
18638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "message. <message> must be an utf-8 string. Unicode points will be reverse-mapped\r\n"
18648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "according to the current device keyboard. unsupported characters will be discarded\r\n"
18658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "silently\r\n", NULL, do_event_text, NULL },
18668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
18688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
18698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
18728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
18738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
18748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                               V M   C O M M A N D S                             ******/
18758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
18768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
18778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
18788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
18808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_avd_stop( ControlClient  client, char*  args )
18818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!vm_running) {
18838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: virtual device already stopped\r\n" );
18848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
18858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    vm_stop(EXCP_INTERRUPT);
18878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
18888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
18918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_avd_start( ControlClient  client, char*  args )
18928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (vm_running) {
18948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: virtual device already running\r\n" );
18958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
18968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    vm_start();
18988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
18998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
19008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
19028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_avd_status( ControlClient  client, char*  args )
19038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
19048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "virtual device is %s\r\n", vm_running ? "running" : "stopped" );
19058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
19068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
19078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
19098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_avd_name( ControlClient  client, char*  args )
19108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
19118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "%s\r\n", avdInfo_getName(android_avdInfo) );
19128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
19138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
19148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  vm_commands[] =
19168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
19178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "stop", "stop the virtual device",
19188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'avd stop' stops the virtual device immediately, use 'avd start' to continue execution\r\n",
19198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_avd_stop, NULL },
19208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "start", "start/restart the virtual device",
19228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'avd start' will start or continue the virtual device, use 'avd stop' to stop it\r\n",
19238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_avd_start, NULL },
19248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "status", "query virtual device status",
19268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'avd status' will indicate wether the virtual device is running or not\r\n",
19278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_avd_status, NULL },
19288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "name", "query virtual device name",
19308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'avd name' will return the name of this virtual device\r\n",
19318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_avd_name, NULL },
19328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
19348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
19358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
19378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
19388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
19398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                             G E O   C O M M A N D S                             ******/
19408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
19418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
19428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
19438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
19458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_geo_nmea( ControlClient  client, char*  args )
19468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
19478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
19488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: NMEA sentence missing, try 'help geo nmea'\r\n" );
19498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
19508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_gps_cs) {
19528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: no GPS emulation in this virtual device\r\n" );
19538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
19548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    android_gps_send_nmea( args );
19568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
19578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
19588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
19608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_geo_fix( ControlClient  client, char*  args )
19618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
19628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  MAX_GEO_PARAMS  3
19638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*   p = args;
19648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int     n_params = 0;
19658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    double  params[ MAX_GEO_PARAMS ];
19668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static  int     last_time = 0;
19688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static  double  last_altitude = 0.;
19698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!p)
19718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = "";
19728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* tokenize */
19748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (*p) {
19758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char*   end;
19768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        double  val = strtod( p, &end );
19778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (end == p) {
19798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "KO: argument '%s' is not a number\n", p );
19808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
19818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
19828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        params[n_params++] = val;
19848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (n_params >= MAX_GEO_PARAMS)
19858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = end;
19888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (*p && (p[0] == ' ' || p[0] == '\t'))
19898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p += 1;
19908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* sanity check */
19938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (n_params < 2) {
19948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: not enough arguments: see 'help geo fix' for details\r\n" );
19958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
19968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* generate an NMEA sentence for this fix */
19998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
20008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        STRALLOC_DEFINE(s);
20018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        double   val;
20028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int      deg, min;
20038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char     hemi;
20048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* first, the time */
20068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stralloc_add_format( s, "$GPGGA,%06d", last_time );
20078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        last_time ++;
20088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* then the latitude */
20108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hemi = 'N';
20118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val  = params[1];
20128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (val < 0) {
20138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            hemi = 'S';
20148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val  = -val;
20158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
20168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        deg = (int) val;
20178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        min = 60*(val - deg);
20188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = val - min/60.;
20198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stralloc_add_format( s, ",%02d%02d.%04d,%c", deg, min, (int)(val * 10000), hemi );
20208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* the longitude */
20228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hemi = 'E';
20238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val  = params[0];
20248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (val < 0) {
20258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            hemi = 'W';
20268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val  = -val;
20278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
20288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        deg = (int) val;
20298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        min = 60*(val - deg);
20308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val = val - min/60.;
20318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stralloc_add_format( s, ",%02d%02d.%04d,%c", deg, min, (int)(val * 10000), hemi );
20328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* bogus fix quality, empty satellite count and dilutions */
20348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stralloc_add_str( s, ",1,,,," );
20358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* optional altitude */
20378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (n_params >= 3) {
20388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            stralloc_add_format( s, "%.1g", params[2] );
20398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            last_altitude = params[2];
20408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
20418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            stralloc_add_str( s, "," );
20428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
20438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* bogus rest and checksum */
20448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stralloc_add_str( s, ",,,*47" );
20458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* send it, then free */
20478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        android_gps_send_nmea( stralloc_cstr(s) );
20488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stralloc_reset( s );
20498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
20508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
20518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
20528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  geo_commands[] =
20548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
20558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "nmea", "send an GPS NMEA sentence",
20568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'geo nema <sentence>' sends a NMEA 0183 sentence to the emulated device, as\r\n"
20578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "if it came from an emulated GPS modem. <sentence> must begin with '$GP'. only\r\n"
20588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'$GPGGA' and '$GPRCM' sentences are supported at the moment.\r\n",
20598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_geo_nmea, NULL },
20608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "fix", "send a simple GPS fix",
20628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'geo fix <longitude> <latitude> [<altitude>]' allows you to send a\r\n"
20638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "simple GPS fix to the emulated system. the parameters are:\r\n\r\n"
20648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "  <longitude>   longitude, in decimal degrees\r\n"
20658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "  <latitude>    latitude, in decimal degrees\r\n"
20668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "  <altitude>    optional altitude in meters\r\n"
20678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "\r\n",
20688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_geo_fix, NULL },
20698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
20718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
20728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
20758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
20768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
20778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                           M A I N   C O M M A N D S                             ******/
20788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
20798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
20808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
20818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
20838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_window_scale( ControlClient  client, char*  args )
20848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
20858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    double  scale;
20868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int     is_dpi = 0;
20878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*   end;
20888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
20908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: argument missing, try 'window scale <scale>'\r\n" );
20918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
20928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
20938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    scale = strtol( args, &end, 10 );
20958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (end > args && !memcmp( end, "dpi", 4 )) {
20968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        is_dpi = 1;
20978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
20988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
20998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        scale = strtod( args, &end );
21008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (end == args || end[0]) {
21018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "KO: argument <scale> must be a real number, or an integer followed by 'dpi'\r\n" );
21028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
21038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
21048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
21058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21062fa5173bd1ce7341c50adac676a317945f0969c7Vladimir Chtchetkine    android_ui_set_window_scale( scale, is_dpi );
21078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
21088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
21098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  window_commands[] =
21118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
21128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "scale", "change the window scale",
21138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'window scale <scale>' allows you to change the scale of the emulator window at runtime\r\n"
21148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "<scale> must be either a real number between 0.1 and 3.0, or an integer followed by\r\n"
21158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "the 'dpi' prefix (as in '120dpi')\r\n",
21168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_window_scale, NULL },
21178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
21198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
21208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
21228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
21238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
21248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                           M A I N   C O M M A N D S                             ******/
21258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
21268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
21278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
21288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
21308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_kill( ControlClient  client, char*  args )
21318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
21328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	control_write( client, "OK: killing emulator, bye bye\r\n" );
21338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	exit(0);
21348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
21358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec   main_commands[] =
21378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
21388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "help|h|?", "print a list of commands", NULL, NULL, do_help, NULL },
21398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "event", "simulate hardware events",
21418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "allows you to send fake hardware events to the kernel\r\n", NULL,
21428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, event_commands },
21438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "geo", "Geo-location commands",
21458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows you to change Geo-related settings, or to send GPS NMEA sentences\r\n", NULL,
21468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, geo_commands },
21478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "gsm", "GSM related commands",
21498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows you to change GSM-related settings, or to make a new inbound phone call\r\n", NULL,
21508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, gsm_commands },
21518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "kill", "kill the emulator instance", NULL, NULL,
21538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  do_kill, NULL },
21548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "network", "manage network settings",
21568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows you to manage the settings related to the network data connection of the\r\n"
21578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "emulated device.\r\n", NULL,
21588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, network_commands },
21598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "power", "power related commands",
21618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows to change battery and AC power status\r\n", NULL,
21628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, power_commands },
21638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "quit|exit", "quit control session", NULL, NULL,
21658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      do_quit, NULL },
21668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "redir",    "manage port redirections",
21688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows you to add, list and remove UDP and/or PORT redirection from the host to the device\r\n"
21698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "as an example, 'redir  tcp:5000:6000' will route any packet sent to the host's TCP port 5000\r\n"
21708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "to TCP port 6000 of the emulated device\r\n", NULL,
21718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, redir_commands },
21728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "sms", "SMS related commands",
21748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows you to simulate an inbound SMS\r\n", NULL,
21758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, sms_commands },
21768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "avd", "manager virtual device state",
21788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "allows to change (e.g. start/stop) the virtual device state\r\n", NULL,
21798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, vm_commands },
21808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "window", "manage emulator window",
21828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "allows you to modify the emulator window\r\n", NULL,
21838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, window_commands },
21848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
21868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
21878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic ControlGlobalRec  _g_global;
21908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
21928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_console_start( int  port )
21938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
21948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return control_global_init( &_g_global, port );
21958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2196