console.c revision 2ff39a367738422c0ca1313cac8ff380e1fdd498
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"
392ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije#include "android/config/config.h"
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "tcpdump.h"
415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "net.h"
42e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner#include "monitor.h"
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdlib.h>
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdio.h>
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdarg.h>
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <string.h>
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <unistd.h>
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <fcntl.h>
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/hw-events.h"
5134f2974ce7ec7c71beb47b5daf9089d5c8c40c79David 'Digit' Turner#include "user-events.h"
5271bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine#include "android/keycode-array.h"
5371bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine#include "android/charmap.h"
542fa5173bd1ce7341c50adac676a317945f0969c7Vladimir Chtchetkine#include "android/core-ui-protocol.h"
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(CONFIG_SLIRP)
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "libslirp.h"
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  DEBUG  1
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 1
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  D_ACTIVE   VERBOSE_CHECK(console)
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  D_ACTIVE   DEBUG
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if DEBUG
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  D(x)   do { if (D_ACTIVE) ( printf x , fflush(stdout) ); } while (0)
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  D(x)   do{}while(0)
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct ControlGlobalRec_*  ControlGlobal;
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct ControlClientRec_*  ControlClient;
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct {
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int           host_port;
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int           host_udp;
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int  guest_ip;
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int           guest_port;
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} RedirRec, *Redir;
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
86e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnertypedef int Socket;
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct ControlClientRec_
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ControlClientRec_*  next;       /* next client in list           */
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Socket                     sock;       /* socket used for communication */
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlGlobal              global;
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char                       finished;
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char                       buff[ 4096 ];
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int                        buff_len;
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} ControlClientRec;
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct ControlGlobalRec_
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* listening socket */
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Socket    listen_fd;
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* the list of current clients */
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlClient   clients;
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* the list of redirections currently active */
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Redir     redirs;
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       num_redirs;
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       max_redirs;
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} ControlGlobalRec;
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_global_add_redir( ControlGlobal  global,
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int            host_port,
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int            host_udp,
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          unsigned int   guest_ip,
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int            guest_port )
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Redir  redir;
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (global->num_redirs >= global->max_redirs)
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  old_max = global->max_redirs;
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  new_max = old_max + (old_max >> 1) + 4;
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        Redir  new_redirs = realloc( global->redirs, new_max*sizeof(global->redirs[0]) );
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (new_redirs == NULL)
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        global->redirs     = new_redirs;
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        global->max_redirs = new_max;
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir = &global->redirs[ global->num_redirs++ ];
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir->host_port  = host_port;
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir->host_udp   = host_udp;
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir->guest_ip   = guest_ip;
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir->guest_port = guest_port;
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_global_del_redir( ControlGlobal  global,
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int            host_port,
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int            host_udp )
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < global->num_redirs; nn++)
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        Redir  redir = &global->redirs[nn];
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( redir->host_port == host_port &&
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             redir->host_udp  == host_udp  )
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            memmove( redir, redir + 1, ((global->num_redirs - nn)-1)*sizeof(*redir) );
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            global->num_redirs -= 1;
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we didn't find it */
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
171e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/* Detach the socket descriptor from a given ControlClient
172e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner * and return its value. This is useful either when destroying
173e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner * the client, or redirecting the socket to another service.
174e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner *
175e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner * NOTE: this does not close the socket.
176e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner */
177e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnerstatic int
178e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnercontrol_client_detach( ControlClient  client )
179e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner{
180e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    int  result;
181e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
182e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    if (client->sock < 0)
183e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner        return -1;
184e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
185e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    qemu_set_fd_handler( client->sock, NULL, NULL, NULL );
186e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    result = client->sock;
187e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    client->sock = -1;
188e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
189e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    return result;
190e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner}
191e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
192e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnerstatic void  control_client_read( void*  _client );  /* forward */
193e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
194e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/* Reattach a control client to a given socket.
195e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner * Return the old socket descriptor for the client.
196e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner */
197e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnerstatic int
198e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnercontrol_client_reattach( ControlClient client, int fd )
199e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner{
200e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    int result = control_client_detach(client);
201e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    client->sock = fd;
202e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    qemu_set_fd_handler( fd, control_client_read, NULL, client );
203e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    return result;
204e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner}
205e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_client_destroy( ControlClient  client )
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlGlobal  global = client->global;
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlClient  *pnode = &global->clients;
211e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    int            sock;
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D(( "destroying control client %p\n", client ));
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
215e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    sock = control_client_detach( client );
216e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    if (sock >= 0)
217e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner        socket_close(sock);
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( ;; ) {
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ControlClient  node = *pnode;
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( node == NULL )
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( node == client ) {
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            *pnode     = node->next;
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            node->next = NULL;
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pnode = &node->next;
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    free( client );
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void  control_control_write( ControlClient  client, const char*  buff, int  len )
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len < 0)
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = strlen(buff);
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (len > 0) {
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = socket_send( client->sock, buff, len);
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ret < 0) {
246ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner            if (errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN)
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            buff += ret;
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len  -= ret;
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2552ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int  control_vwrite( ControlClient  client, const char*  format, va_list args )
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static char  temp[1024];
2582ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    int ret = vsnprintf( temp, sizeof(temp), format, args );
2592ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    temp[ sizeof(temp)-1 ] = 0;
2602ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    control_control_write( client, temp, -1 );
2612ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
2622ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret;
2632ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2652ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int  control_write( ControlClient  client, const char*  format, ... )
2662ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
2672ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    int ret;
2682ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    va_list      args;
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_start(args, format);
2702ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ret = control_vwrite(client, format, args);
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_end(args);
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2732ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret;
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic ControlClient
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_client_create( Socket         socket,
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       ControlGlobal  global )
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlClient  client = calloc( sizeof(*client), 1 );
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (client) {
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_set_nodelay( socket );
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_set_nonblock( socket );
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->finished = 0;
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->global  = global;
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->sock    = socket;
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->next    = global->clients;
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        global->clients = client;
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_set_fd_handler( socket, control_client_read, NULL, client );
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return client;
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef const struct CommandDefRec_  *CommandDef;
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct CommandDefRec_ {
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*  names;
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*  abstract;
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*  description;
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void        (*descriptor)( ControlClient  client );
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int         (*handler)( ControlClient  client, char* args );
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CommandDef   subcommands;   /* if handler is NULL */
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} CommandDefRec;
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec   main_commands[];  /* forward */
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic CommandDef
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectfind_command( char*  input, CommandDef  commands, char*  *pend, char*  *pargs )
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int    nn;
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*  args = strchr(input, ' ');
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args != NULL) {
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (*args == ' ')
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            args++;
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (args[0] == 0)
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            args = NULL;
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; commands[nn].names != NULL; nn++)
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*  name = commands[nn].names;
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*  sep;
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        do {
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int  len, c;
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sep = strchr( name, '|' );
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (sep)
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                len = sep - name;
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                len = strlen(name);
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            c = input[len];
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ( !memcmp( name, input, len ) && (c == ' ' || c == 0) ) {
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                *pend  = input + len;
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                *pargs = args;
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return &commands[nn];
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (sep)
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                name = sep + 1;
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } while (sep != NULL && *name);
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* NOTE: don't touch *pend and *pargs if no command is found */
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdump_help( ControlClient  client,
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           CommandDef     cmd,
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           const char*    prefix )
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cmd->description) {
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "%s", cmd->description );
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (cmd->descriptor) {
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cmd->descriptor( client );
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "%s\r\n", cmd->abstract );
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cmd->subcommands) {
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cmd = cmd->subcommands;
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "\r\navailable sub-commands:\r\n" );
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for ( ; cmd->names != NULL; cmd++ ) {
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "   %s %-15s  %s\r\n", prefix, cmd->names, cmd->abstract );
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "\r\n" );
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_client_do_command( ControlClient  client )
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       line     = client->buff;
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       args     = NULL;
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CommandDef  commands = main_commands;
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       cmdend   = client->buff;
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CommandDef  cmd      = find_command( line, commands, &cmdend, &args );
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cmd == NULL) {
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: unknown command, try 'help'\r\n" );
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (;;) {
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        CommandDef  subcmd;
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (cmd->handler) {
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ( !cmd->handler( client, args ) )
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client, "OK\r\n" );
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* no handler means we should have sub-commands */
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (cmd->subcommands == NULL) {
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "KO: internal error: buggy command table for '%.*s'\r\n",
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           cmdend - client->buff, client->buff );
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* we need a sub-command here */
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( !args ) {
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dump_help( client, cmd, "" );
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "KO: missing sub-command\r\n" );
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        line     = args;
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        commands = cmd->subcommands;
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        subcmd   = find_command( line, commands, &cmdend, &args );
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (subcmd == NULL) {
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dump_help( client, cmd, "" );
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "KO:  bad sub-command\r\n" );
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cmd = subcmd;
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* implement the 'help' command */
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_help( ControlClient  client, char*  args )
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       line;
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       start = args;
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       end   = start;
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CommandDef  cmd = main_commands;
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* without arguments, simply dump all commands */
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args == NULL) {
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "Android console command help:\r\n\r\n" );
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for ( ; cmd->names != NULL; cmd++ ) {
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "    %-15s  %s\r\n", cmd->names, cmd->abstract );
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "\r\ntry 'help <command>' for command-specific help\r\n" );
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* with an argument, find the corresponding command */
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (;;) {
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        CommandDef  subcmd;
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        line    = args;
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        subcmd  = find_command( line, cmd, &end, &args );
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (subcmd == NULL) {
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "try one of these instead:\r\n\r\n" );
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for ( ; cmd->names != NULL; cmd++ ) {
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client, "    %.*s %s\r\n",
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              end - start, start, cmd->names );
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "\r\nKO: unknown command\r\n" );
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( !args || !subcmd->subcommands ) {
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dump_help( client, subcmd, start );
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cmd = subcmd->subcommands;
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_client_read_byte( ControlClient  client, unsigned char  ch )
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ch == '\r')
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* filter them out */
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else if (ch == '\n')
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->buff[ client->buff_len ] = 0;
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_client_do_command( client );
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (client->finished)
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->buff_len = 0;
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (client->buff_len >= sizeof(client->buff)-1)
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            client->buff_len = 0;
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->buff[ client->buff_len++ ] = ch;
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_client_read( void*  _client )
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlClient  client = _client;
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned char  buf[4096];
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int            size;
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D(( "in control_client read: " ));
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    size = socket_recv( client->sock, buf, sizeof(buf) );
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (size < 0) {
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "size < 0, exiting with %d: %s\n", errno, errno_str ));
506ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner		if (errno != EWOULDBLOCK && errno != EAGAIN && errno != EINTR)
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project			control_client_destroy( client );
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (size == 0) {
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* end of connection */
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "end of connection detected !!\n" ));
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_client_destroy( client );
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  nn;
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  if DEBUG
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char  temp[16];
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int   count = size > sizeof(temp)-1 ? sizeof(temp)-1 : size;
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; nn < count; nn++) {
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int  c = buf[nn];
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (c == '\n')
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        temp[nn] = '!';
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else if (c < 32)
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        temp[nn] = '.';
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    temp[nn] = (char)c;
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        temp[nn] = 0;
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "received %d bytes: %s\n", size, temp ));
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  endif
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "received %.*s\n", size, buf ));
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; nn < size; nn++) {
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_client_read_byte( client, buf[nn] );
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (client->finished) {
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_client_destroy(client);
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* this function is called on each new client connection */
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_global_accept( void*  _global )
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlGlobal       global = _global;
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlClient       client;
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Socket              fd;
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
55680bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    D(( "control_global_accept: just in (fd=%d)\n", global->listen_fd ));
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(;;) {
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fd = socket_accept( global->listen_fd, NULL );
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (fd < 0 && errno != EINTR) {
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            D(( "problem in accept: %d: %s\n", errno, errno_str ));
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            perror("accept");
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if (fd >= 0) {
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "relooping in accept()\n" ));
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_xreuseaddr( fd );
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D(( "control_global_accept: creating new client\n" ));
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    client = control_client_create( fd, global );
5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (client) {
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "control_global_accept: new client %p\n", client ));
5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "Android Console: type 'help' for a list of commands\r\n" );
5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "OK\r\n" );
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_global_init( ControlGlobal  global,
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     int            control_port )
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Socket  fd;
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int     ret;
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SockAddress  sockaddr;
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memset( global, 0, sizeof(*global) );
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fd = socket_create_inet( SOCKET_STREAM );
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (fd < 0) {
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        perror("socket");
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_xreuseaddr( fd );
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sock_address_init_inet( &sockaddr, SOCK_ADDRESS_INET_LOOPBACK, control_port );
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = socket_bind(fd, &sockaddr );
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) {
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        perror("bind");
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_close( fd );
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = socket_listen(fd, 0);
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) {
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        perror("listen");
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_close( fd );
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_nonblock(fd);
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    global->listen_fd = fd;
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_set_fd_handler( fd, control_global_accept, NULL, global );
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_quit( ControlClient  client, char*  args )
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    client->finished = 1;
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                        N E T W O R K   S E T T I N G S                          ******/
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_network_status( ControlClient  client, char*  args )
6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "Current network status:\r\n" );
6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "  download speed:   %8d bits/s (%.1f KB/s)\r\n",
6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   (long)qemu_net_download_speed, qemu_net_download_speed/8192. );
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "  upload speed:     %8d bits/s (%.1f KB/s)\r\n",
6508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   (long)qemu_net_upload_speed, qemu_net_upload_speed/8192. );
6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "  minimum latency:  %ld ms\r\n", qemu_net_min_latency );
6538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "  maximum latency:  %ld ms\r\n", qemu_net_max_latency );
6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdump_network_speeds( ControlClient  client )
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const NetworkSpeed*  speed = android_netspeeds;
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char* const  format = "  %-8s %s\r\n";
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( ; speed->name; speed++ ) {
6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, format, speed->name, speed->display );
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, format, "<num>", "selects both upload and download speed" );
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, format, "<up>:<down>", "select individual upload/download speeds" );
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_network_speed( ControlClient  client, char*  args )
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !args ) {
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing <speed> argument, see 'help network speed'\r\n" );
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( android_parse_network_speed( args ) < 0 ) {
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: invalid <speed> argument, see 'help network speed' for valid values\r\n" );
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    netshaper_set_rate( slirp_shaper_in,  qemu_net_download_speed );
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    netshaper_set_rate( slirp_shaper_out, qemu_net_upload_speed );
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (android_modem) {
68671bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine        amodem_set_data_network_type( android_modem,
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                    android_parse_network_type( args ) );
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdescribe_network_speed( ControlClient  client )
6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client,
6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   "'network speed <speed>' allows you to dynamically change the speed of the emulated\r\n"
6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   "network on the device, where <speed> is one of the following:\r\n\r\n" );
6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dump_network_speeds( client );
6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_network_delay( ControlClient  client, char*  args )
7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !args ) {
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing <delay> argument, see 'help network delay'\r\n" );
7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( android_parse_network_latency( args ) < 0 ) {
7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: invalid <delay> argument, see 'help network delay' for valid values\r\n" );
7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    netdelay_set_latency( slirp_delay_in, qemu_net_min_latency, qemu_net_max_latency );
7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdescribe_network_delay( ControlClient  client )
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client,
7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   "'network delay <latency>' allows you to dynamically change the latency of the emulated\r\n"
7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   "network on the device, where <latency> is one of the following:\r\n\r\n" );
7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: TODO */
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_network_capture_start( ControlClient  client, char*  args )
7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !args ) {
7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing <file> argument, see 'help network capture start'\r\n" );
7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( qemu_tcpdump_start(args) < 0) {
7338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: could not start capture: %s", strerror(errno) );
7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_network_capture_stop( ControlClient  client, char*  args )
7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* no need to return an error here */
7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_tcpdump_stop();
7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  network_capture_commands[] =
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "start", "start network capture",
7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "'network capture start <file>' starts a new capture of network packets\r\n"
7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "into a specific <file>. This will stop any capture already in progress.\r\n"
7528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "the capture file can later be analyzed by tools like WireShark. It uses\r\n"
7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "the libpcap file format.\r\n\r\n"
7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "you can stop the capture anytime with 'network capture stop'\r\n", NULL,
7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      do_network_capture_start, NULL },
7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "stop", "stop network capture",
7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "'network capture stop' stops a currently running packet capture, if any.\r\n"
7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "you can start one with 'network capture start <file>'\r\n", NULL,
7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      do_network_capture_stop, NULL },
7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  network_commands[] =
7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "status", "dump network status", NULL, NULL,
7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       do_network_status, NULL },
7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "speed", "change network speed", NULL, describe_network_speed,
7718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      do_network_speed, NULL },
7728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "delay", "change network latency", NULL, describe_network_delay,
7748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       do_network_delay, NULL },
7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "capture", "dump network packets to file",
7778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows to start/stop capture of network packets to a file for later analysis\r\n", NULL,
7788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, network_capture_commands },
7798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
7818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                       P O R T   R E D I R E C T I O N S                         ******/
7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_redir_list( ControlClient  client, char*  args )
7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlGlobal  global = client->global;
7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (global->num_redirs == 0)
7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "no active redirections\r\n" );
7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  nn;
8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; nn < global->num_redirs; nn++) {
8018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            Redir  redir = &global->redirs[nn];
8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "%s:%-5d => %-5d\r\n",
8038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          redir->host_udp ? "udp" : "tcp",
8048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          redir->host_port,
8058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          redir->guest_port );
8068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
8078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
8098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* parse a protocol:port specification */
8128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
8138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectredir_parse_proto_port( char*  args, int  *pport, int  *pproto )
8148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  proto = -1;
8168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  len   = 0;
8178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*  end;
8188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !memcmp( args, "tcp:", 4 ) ) {
8208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        proto = 0;
8218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len   = 4;
8228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else if ( !memcmp( args, "udp:", 4 ) ) {
8248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        proto = 1;
8258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len   = 4;
8268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
8288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
8298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    args   += len;
8318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pproto = proto;
8328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pport  = strtol( args, &end, 10 );
8338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (end == args)
8348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
8358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len += end - args;
8378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return len;
8388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
8418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectredir_parse_guest_port( char*  arg, int  *pport )
8428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*  end;
8448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pport = strtoul( arg, &end, 10 );
8468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (end == arg)
8478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
8488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return end - arg;
8508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic Redir
8538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectredir_find( ControlGlobal  global, int  port, int  isudp )
8548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
8568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < global->num_redirs; nn++) {
8588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        Redir  redir = &global->redirs[nn];
8598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (redir->host_port == port && redir->host_udp == isudp)
8618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return redir;
8628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
8648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
8688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_redir_add( ControlClient  client, char*  args )
8698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       len, host_proto, host_port, guest_port;
8718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t  guest_ip;
8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Redir     redir;
8738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !args )
8758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto BadFormat;
8768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!slirp_is_inited()) {
8785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        control_write( client, "KO: network emulation disabled\r\n");
8795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -1;
8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = redir_parse_proto_port( args, &host_port, &host_proto );
8838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len == 0 || args[len] != ':')
8848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto BadFormat;
8858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    args += len + 1;
8878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = redir_parse_guest_port( args, &guest_port );
8888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len == 0 || args[len] != 0)
8898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto BadFormat;
8908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir = redir_find( client->global, host_port, host_proto );
8928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( redir != NULL ) {
8938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: host port already active, use 'redir del' to remove first\r\n" );
8948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
8958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8977d9a2705e7ae6d8c4b1d9d5b4e2a67ab88c19044David Turner    if (inet_strtoip("10.0.2.15", &guest_ip) < 0) {
8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: unexpected internal failure when resolving 10.0.2.15\r\n" );
8998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D(("pattern hport=%d gport=%d proto=%d\n", host_port, guest_port, host_proto ));
9038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( control_global_add_redir( client->global, host_port, host_proto,
9048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                   guest_ip, guest_port ) < 0 )
9058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
9068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: not enough memory to allocate redirection\r\n" );
9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (slirp_redir(host_proto, host_port, guest_ip, guest_port) < 0) {
9118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: can't setup redirection, port probably used by another program on host\r\n" );
9128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_global_del_redir( client->global, host_port, host_proto );
9138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
9178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectBadFormat:
9198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: bad redirection format, try (tcp|udp):hostport:guestport\r\n", -1 );
9208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
9218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
9258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_redir_del( ControlClient  client, char*  args )
9268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int    len, proto, port;
9288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Redir  redir;
9298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !args )
9318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto BadFormat;
9328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = redir_parse_proto_port( args, &port, &proto );
9338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( len == 0 || args[len] != 0 )
9348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto BadFormat;
9358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir = redir_find( client->global, port, proto );
9378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (redir == NULL) {
9388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: can't remove unknown redirection (%s:%d)\r\n",
9398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        proto ? "udp" : "tcp", port );
9408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    slirp_unredir( redir->host_udp, redir->host_port );
9448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_global_del_redir( client->global, port, proto );\
9458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
9478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectBadFormat:
9498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: bad redirection format, try (tcp|udp):hostport\r\n" );
9508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
9518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  redir_commands[] =
9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "list", "list current redirections",
9568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "list current port redirections. use 'redir add' and 'redir del' to add and remove them\r\n", NULL,
9578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_redir_list, NULL },
9588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "add",  "add new redirection",
9608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "add a new port redirection, arguments must be:\r\n\r\n"
9618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "  redir add <protocol>:<host-port>:<guest-port>\r\n\r\n"
9628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "where:   <protocol>     is either 'tcp' or 'udp'\r\n"
9638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "         <host-port>    a number indicating which port on the host to open\r\n"
9648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "         <guest-port>   a number indicating which port to route to on the device\r\n"
9658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "\r\nas an example, 'redir  tcp:5000:6000' will allow any packets sent to\r\n"
9668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "the host's TCP port 5000 to be routed to TCP port 6000 of the emulated device\r\n", NULL,
9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_redir_add, NULL },
9688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "del",  "remove existing redirection",
9708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "remove a port redirecion that was created with 'redir add', arguments must be:\r\n\r\n"
9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "  redir  del <protocol>:<host-port>\r\n\r\n"
9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "see the 'help redir add' for the meaning of <protocol> and <host-port>\r\n", NULL,
9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_redir_del, NULL },
9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
9831a000857bb7eef298efa787699050884f92311feJaime Lopez/*****                          C D M A   M O D E M                                    ******/
9841a000857bb7eef298efa787699050884f92311feJaime Lopez/*****                                                                                 ******/
9851a000857bb7eef298efa787699050884f92311feJaime Lopez/********************************************************************************************/
9861a000857bb7eef298efa787699050884f92311feJaime Lopez/********************************************************************************************/
9871a000857bb7eef298efa787699050884f92311feJaime Lopez
9881a000857bb7eef298efa787699050884f92311feJaime Lopezstatic const struct {
9891a000857bb7eef298efa787699050884f92311feJaime Lopez    const char *            name;
9901a000857bb7eef298efa787699050884f92311feJaime Lopez    const char *            display;
9911a000857bb7eef298efa787699050884f92311feJaime Lopez    ACdmaSubscriptionSource source;
9921a000857bb7eef298efa787699050884f92311feJaime Lopez} _cdma_subscription_sources[] = {
9931a000857bb7eef298efa787699050884f92311feJaime Lopez    { "nv",            "Read subscription from non-volatile RAM", A_SUBSCRIPTION_NVRAM },
9941a000857bb7eef298efa787699050884f92311feJaime Lopez    { "ruim",          "Read subscription from RUIM", A_SUBSCRIPTION_RUIM },
9951a000857bb7eef298efa787699050884f92311feJaime Lopez};
9961a000857bb7eef298efa787699050884f92311feJaime Lopez
9971a000857bb7eef298efa787699050884f92311feJaime Lopezstatic void
9981a000857bb7eef298efa787699050884f92311feJaime Lopezdump_subscription_sources( ControlClient client )
9991a000857bb7eef298efa787699050884f92311feJaime Lopez{
10001a000857bb7eef298efa787699050884f92311feJaime Lopez    int i;
10011a000857bb7eef298efa787699050884f92311feJaime Lopez    for (i = 0;
10021a000857bb7eef298efa787699050884f92311feJaime Lopez         i < sizeof(_cdma_subscription_sources) / sizeof(_cdma_subscription_sources[0]);
10031a000857bb7eef298efa787699050884f92311feJaime Lopez         i++) {
10041a000857bb7eef298efa787699050884f92311feJaime Lopez        control_write( client, "    %s: %s\r\n",
10051a000857bb7eef298efa787699050884f92311feJaime Lopez                       _cdma_subscription_sources[i].name,
10061a000857bb7eef298efa787699050884f92311feJaime Lopez                       _cdma_subscription_sources[i].display );
10071a000857bb7eef298efa787699050884f92311feJaime Lopez    }
10081a000857bb7eef298efa787699050884f92311feJaime Lopez}
10091a000857bb7eef298efa787699050884f92311feJaime Lopez
10101a000857bb7eef298efa787699050884f92311feJaime Lopezstatic void
10111a000857bb7eef298efa787699050884f92311feJaime Lopezdescribe_subscription_source( ControlClient client )
10121a000857bb7eef298efa787699050884f92311feJaime Lopez{
10131a000857bb7eef298efa787699050884f92311feJaime Lopez    control_write( client,
10141a000857bb7eef298efa787699050884f92311feJaime Lopez                   "'cdma ssource <ssource>' allows you to specify where to read the subscription from\r\n" );
10151a000857bb7eef298efa787699050884f92311feJaime Lopez    dump_subscription_sources( client );
10161a000857bb7eef298efa787699050884f92311feJaime Lopez}
10171a000857bb7eef298efa787699050884f92311feJaime Lopez
10181a000857bb7eef298efa787699050884f92311feJaime Lopezstatic int
10191a000857bb7eef298efa787699050884f92311feJaime Lopezdo_cdma_ssource( ControlClient  client, char*  args )
10201a000857bb7eef298efa787699050884f92311feJaime Lopez{
10211a000857bb7eef298efa787699050884f92311feJaime Lopez    int nn;
10221a000857bb7eef298efa787699050884f92311feJaime Lopez    if (!args) {
10231a000857bb7eef298efa787699050884f92311feJaime Lopez        control_write( client, "KO: missing argument, try 'cdma ssource <source>'\r\n" );
10241a000857bb7eef298efa787699050884f92311feJaime Lopez        return -1;
10251a000857bb7eef298efa787699050884f92311feJaime Lopez    }
10261a000857bb7eef298efa787699050884f92311feJaime Lopez
10271a000857bb7eef298efa787699050884f92311feJaime Lopez    for (nn = 0; ; nn++) {
10281a000857bb7eef298efa787699050884f92311feJaime Lopez        const char*         name    = _cdma_subscription_sources[nn].name;
10291a000857bb7eef298efa787699050884f92311feJaime Lopez        ACdmaSubscriptionSource ssource = _cdma_subscription_sources[nn].source;
10301a000857bb7eef298efa787699050884f92311feJaime Lopez
10311a000857bb7eef298efa787699050884f92311feJaime Lopez        if (!name)
10321a000857bb7eef298efa787699050884f92311feJaime Lopez            break;
10331a000857bb7eef298efa787699050884f92311feJaime Lopez
10341a000857bb7eef298efa787699050884f92311feJaime Lopez        if (!strcasecmp( args, name )) {
10351a000857bb7eef298efa787699050884f92311feJaime Lopez            amodem_set_cdma_subscription_source( android_modem, ssource );
10361a000857bb7eef298efa787699050884f92311feJaime Lopez            return 0;
10371a000857bb7eef298efa787699050884f92311feJaime Lopez        }
10381a000857bb7eef298efa787699050884f92311feJaime Lopez    }
10391a000857bb7eef298efa787699050884f92311feJaime Lopez    control_write( client, "KO: Don't know source %s\r\n", args );
10401a000857bb7eef298efa787699050884f92311feJaime Lopez    return -1;
10411a000857bb7eef298efa787699050884f92311feJaime Lopez}
10421a000857bb7eef298efa787699050884f92311feJaime Lopez
10431a000857bb7eef298efa787699050884f92311feJaime Lopezstatic int
10441a000857bb7eef298efa787699050884f92311feJaime Lopezdo_cdma_prl_version( ControlClient client, char * args )
10451a000857bb7eef298efa787699050884f92311feJaime Lopez{
10461a000857bb7eef298efa787699050884f92311feJaime Lopez    int version = 0;
10471a000857bb7eef298efa787699050884f92311feJaime Lopez    char *endptr;
10481a000857bb7eef298efa787699050884f92311feJaime Lopez
10491a000857bb7eef298efa787699050884f92311feJaime Lopez    if (!args) {
10501a000857bb7eef298efa787699050884f92311feJaime Lopez        control_write( client, "KO: missing argument, try 'cdma prl_version <version>'\r\n");
10511a000857bb7eef298efa787699050884f92311feJaime Lopez        return -1;
10521a000857bb7eef298efa787699050884f92311feJaime Lopez    }
10531a000857bb7eef298efa787699050884f92311feJaime Lopez
10541a000857bb7eef298efa787699050884f92311feJaime Lopez    version = strtol(args, &endptr, 0);
10551a000857bb7eef298efa787699050884f92311feJaime Lopez    if (endptr != args) {
10561a000857bb7eef298efa787699050884f92311feJaime Lopez        amodem_set_cdma_prl_version( android_modem, version );
10571a000857bb7eef298efa787699050884f92311feJaime Lopez    }
105880bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    return 0;
10591a000857bb7eef298efa787699050884f92311feJaime Lopez}
10601a000857bb7eef298efa787699050884f92311feJaime Lopez/********************************************************************************************/
10611a000857bb7eef298efa787699050884f92311feJaime Lopez/********************************************************************************************/
10621a000857bb7eef298efa787699050884f92311feJaime Lopez/*****                                                                                 ******/
10638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                           G S M   M O D E M                                     ******/
10648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
10658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
10668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
10678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const struct {
10698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*         name;
10708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*         display;
10718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ARegistrationState  state;
10728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} _gsm_states[] = {
10738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "unregistered",  "no network available", A_REGISTRATION_UNREGISTERED },
10748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "home",          "on local network, non-roaming", A_REGISTRATION_HOME },
10758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "roaming",       "on roaming network", A_REGISTRATION_ROAMING },
10768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "searching",     "searching networks", A_REGISTRATION_SEARCHING },
10778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "denied",        "emergency calls only", A_REGISTRATION_DENIED },
10788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "off",           "same as 'unregistered'", A_REGISTRATION_UNREGISTERED },
10798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "on",            "same as 'home'", A_REGISTRATION_HOME },
10808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, A_REGISTRATION_UNREGISTERED }
10818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
10828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const char*
10848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_state_to_string( ARegistrationState  state )
10858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
10878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; _gsm_states[nn].name != NULL; nn++) {
10888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (state == _gsm_states[nn].state)
10898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return _gsm_states[nn].name;
10908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
10918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return "<unknown>";
10928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
10958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_status( ControlClient  client, char*  args )
10968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
10988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: no argument required\r\n" );
10998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
11008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_modem) {
11028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: modem emulation not running\r\n" );
11038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
11048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "gsm voice state: %s\r\n",
11068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   gsm_state_to_string(
11078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       amodem_get_voice_registration(android_modem) ) );
11088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "gsm data state:  %s\r\n",
11098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   gsm_state_to_string(
11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       amodem_get_data_registration(android_modem) ) );
11118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
11128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
11168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecthelp_gsm_data( ControlClient  client )
11178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
11198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client,
11208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "the 'gsm data <state>' allows you to change the state of your GPRS connection\r\n"
11218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "valid values for <state> are the following:\r\n\r\n" );
11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; ; nn++) {
11238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         name    = _gsm_states[nn].name;
11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         display = _gsm_states[nn].display;
11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!name)
11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
11288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "  %-15s %s\r\n", name, display );
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "\r\n" );
11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_data( ControlClient  client, char*  args )
11378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm data <state>'\r\n" );
11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; ; nn++) {
11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         name    = _gsm_states[nn].name;
11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ARegistrationState  state   = _gsm_states[nn].state;
11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!name)
11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
11518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( !strcmp( args, name ) ) {
11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!android_modem) {
11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client, "KO: modem emulation not running\r\n" );
11558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return -1;
11568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
11578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            amodem_set_data_registration( android_modem, state );
11588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            qemu_net_disable = (state != A_REGISTRATION_HOME    &&
11598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                state != A_REGISTRATION_ROAMING );
11608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
11618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
11628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: bad GSM data state name, try 'help gsm data' for list of valid values\r\n" );
11648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
11658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
11688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecthelp_gsm_voice( ControlClient  client )
11698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
11718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client,
11728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "the 'gsm voice <state>' allows you to change the state of your GPRS connection\r\n"
11738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "valid values for <state> are the following:\r\n\r\n" );
11748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; ; nn++) {
11758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         name    = _gsm_states[nn].name;
11768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         display = _gsm_states[nn].display;
11778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!name)
11798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
11808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "  %-15s %s\r\n", name, display );
11828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "\r\n" );
11848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
11888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_voice( ControlClient  client, char*  args )
11898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
11918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
11938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm voice <state>'\r\n" );
11948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
11958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; ; nn++) {
11988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         name    = _gsm_states[nn].name;
11998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ARegistrationState  state   = _gsm_states[nn].state;
12008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!name)
12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( !strcmp( args, name ) ) {
12058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!android_modem) {
12068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client, "KO: modem emulation not running\r\n" );
12078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return -1;
12088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
12098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            amodem_set_voice_registration( android_modem, state );
12108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
12118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
12128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: bad GSM data state name, try 'help gsm voice' for list of valid values\r\n" );
12148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
12158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
12198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_check_number( char*  args )
12208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
12228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; args[nn] != 0; nn++) {
12248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = args[nn];
12258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( !isdigit(c) && c != '+' && c != '#' ) {
12268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
12278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
12288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (nn == 0)
12308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
12338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
12368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_call( ControlClient  client, char*  args )
12378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* check that we have a phone number made of digits */
12398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
12408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm call <phonenumber>'\r\n" );
12418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (gsm_check_number(args)) {
12458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: bad phone number format, use digits, # and + only\r\n" );
12468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_modem) {
12508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: modem emulation not running\r\n" );
12518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    amodem_add_inbound_call( android_modem, args );
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_cancel( ControlClient  client, char*  args )
12598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
12618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm call <phonenumber>'\r\n" );
12628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (gsm_check_number(args)) {
12658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: bad phone number format, use digits, # and + only\r\n" );
12668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_modem) {
12698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: modem emulation not running\r\n" );
12708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( amodem_disconnect_call( android_modem, args ) < 0 ) {
12738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: could not cancel this number\r\n" );
12748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
12778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const char*
12818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcall_state_to_string( ACallState  state )
12828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (state) {
12848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case A_CALL_ACTIVE:   return "active";
12858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case A_CALL_HELD:     return "held";
12868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case A_CALL_ALERTING: return "ringing";
12878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case A_CALL_WAITING:  return "waiting";
12888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case A_CALL_INCOMING: return "incoming";
12898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default: return "unknown";
12908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
12948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_list( ControlClient  client, char*  args )
12958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* check that we have a phone number made of digits */
12978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   count = amodem_get_call_count( android_modem );
12988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   nn;
12998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < count; nn++) {
13008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ACall        call = amodem_get_call( android_modem, nn );
13018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*  dir;
13028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (call == NULL)
13048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            continue;
13058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (call->dir == A_CALL_OUTBOUND)
13078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dir = "outbound to ";
13088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         else
13098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dir = "inbound from";
13108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "%s %-10s : %s\r\n", dir,
13128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       call->number, call_state_to_string(call->state) );
13138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
13158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
13188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_busy( ControlClient  client, char*  args )
13198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ACall  call;
13218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
13238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm busy <phonenumber>'\r\n" );
13248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    call = amodem_find_call_by_number( android_modem, args );
13278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (call == NULL || call->dir != A_CALL_OUTBOUND) {
13288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: no current outbound call to number '%s' (call %p)\r\n", args, call );
13298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( amodem_disconnect_call( android_modem, args ) < 0 ) {
13328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: could not cancel this number\r\n" );
13338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
13368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
13398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_hold( ControlClient  client, char*  args )
13408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ACall  call;
13428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
13448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm out hold <phonenumber>'\r\n" );
13458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    call = amodem_find_call_by_number( android_modem, args );
13488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (call == NULL) {
13498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: no current call to/from number '%s'\r\n", args );
13508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( amodem_update_call( android_modem, args, A_CALL_HELD ) < 0 ) {
13538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: could put this call on hold\r\n" );
13548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
13578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
13618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_accept( ControlClient  client, char*  args )
13628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ACall  call;
13648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
13668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm accept <phonenumber>'\r\n" );
13678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    call = amodem_find_call_by_number( android_modem, args );
13708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (call == NULL) {
13718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: no current call to/from number '%s'\r\n", args );
13728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( amodem_update_call( android_modem, args, A_CALL_ACTIVE ) < 0 ) {
13758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: could not activate this call\r\n" );
13768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
13798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
13838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  gsm_in_commands[] =
13848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "new", "create a new 'waiting' inbound call",
13868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm in create <phonenumber>' creates a new inbound phone call, placed in\r\n"
13878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "the 'waiting' state by default, until the system answers/holds/closes it\r\n", NULL
13888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_in_create, NULL },
13898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "hold", "change the state of an oubtound call to 'held'",
13918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "change the state of an outbound call to 'held'. this is only possible\r\n"
13928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "if the call in the 'waiting' or 'active' state\r\n", NULL,
13938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_out_hold, NULL },
13948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "accept", "change the state of an outbound call to 'active'",
13968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "change the state of an outbound call to 'active'. this is only possible\r\n"
13978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "if the call is in the 'waiting' or 'held' state\r\n", NULL,
13988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_out_accept, NULL },
13998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
14018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
14028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
14038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14051a000857bb7eef298efa787699050884f92311feJaime Lopezstatic const CommandDefRec  cdma_commands[] =
14061a000857bb7eef298efa787699050884f92311feJaime Lopez{
14071a000857bb7eef298efa787699050884f92311feJaime Lopez    { "ssource", "Set the current CDMA subscription source",
14081a000857bb7eef298efa787699050884f92311feJaime Lopez      NULL, describe_subscription_source,
14091a000857bb7eef298efa787699050884f92311feJaime Lopez      do_cdma_ssource, NULL },
141080bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    { "prl_version", "Dump the current PRL version",
141180bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner      NULL, NULL,
141280bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner      do_cdma_prl_version, NULL },
14131a000857bb7eef298efa787699050884f92311feJaime Lopez};
14141a000857bb7eef298efa787699050884f92311feJaime Lopez
14158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  gsm_commands[] =
14168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "list", "list current phone calls",
14188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm list' lists all inbound and outbound calls and their state\r\n", NULL,
14198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_list, NULL },
14208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "call", "create inbound phone call",
14228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm call <phonenumber>' allows you to simulate a new inbound call\r\n", NULL,
14238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_call, NULL },
14248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "busy", "close waiting outbound call as busy",
14268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm busy <remoteNumber>' closes an outbound call, reporting\r\n"
14278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "the remote phone as busy. only possible if the call is 'waiting'.\r\n", NULL,
14288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_busy, NULL },
14298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "hold", "change the state of an oubtound call to 'held'",
14318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm hold <remoteNumber>' change the state of a call to 'held'. this is only possible\r\n"
14328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "if the call in the 'waiting' or 'active' state\r\n", NULL,
14338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_hold, NULL },
14348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "accept", "change the state of an outbound call to 'active'",
14368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm accept <remoteNumber>' change the state of a call to 'active'. this is only possible\r\n"
14378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "if the call is in the 'waiting' or 'held' state\r\n", NULL,
14388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_accept, NULL },
14398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "cancel", "disconnect an inbound or outbound phone call",
14418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm cancel <phonenumber>' allows you to simulate the end of an inbound or outbound call\r\n", NULL,
14428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_cancel, NULL },
14438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "data", "modify data connection state", NULL, help_gsm_data,
14458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_data, NULL },
14468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "voice", "modify voice connection state", NULL, help_gsm_voice,
14488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_voice, NULL },
14498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "status", "display GSM status",
14518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm status' displays the current state of the GSM emulation\r\n", NULL,
14528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_status, NULL },
14538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
14558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
14568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
14588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
14598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
14608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                           S M S   C O M M A N D                                 ******/
14618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
14628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
14638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
14648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
14668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_sms_send( ControlClient  client, char*  args )
14678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*          p;
14698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int            textlen;
14708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsAddressRec  sender;
14718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsPDU*        pdus;
14728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int            nn;
14738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* check that we have a phone number made of digits */
14758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
14768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    MissingArgument:
14778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'sms send <phonenumber> <text message>'\r\n" );
14788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = strchr( args, ' ' );
14818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!p) {
14828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto MissingArgument;
14838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( sms_address_from_str( &sender, args, p - args ) < 0 ) {
14868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: bad phone number format, must be [+](0-9)*\r\n" );
14878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* un-secape message text into proper utf-8 (conversion happens in-site) */
14928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p      += 1;
14938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    textlen = strlen(p);
14948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    textlen = sms_utf8_from_message_str( p, textlen, (unsigned char*)p, textlen );
14958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (textlen < 0) {
14968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "message must be utf8 and can use the following escapes:\r\n"
14978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\n      for a newline\r\n"
14988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\xNN    where NN are two hexadecimal numbers\r\n"
14998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\uNNNN  where NNNN are four hexadecimal numbers\r\n"
15008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\\\     to send a '\\' character\r\n\r\n"
15018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    anything else is an error\r\n"
15028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "KO: badly formatted text\r\n" );
15038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
15048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_modem) {
15078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: modem emulation not running\r\n" );
15088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
15098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* create a list of SMS PDUs, then send them */
15128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pdus = smspdu_create_deliver_utf8( (cbytes_t)p, textlen, &sender, NULL );
15138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (pdus == NULL) {
15148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: internal error when creating SMS-DELIVER PDUs\n" );
15158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
15168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; pdus[nn] != NULL; nn++)
15198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        amodem_receive_sms( android_modem, pdus[nn] );
15208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    smspdu_free_list( pdus );
15228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
15238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
15268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_sms_sendpdu( ControlClient  client, char*  args )
15278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsPDU  pdu;
15298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* check that we have a phone number made of digits */
15318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
15328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'sms sendpdu <hexstring>'\r\n" );
15338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
15348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_modem) {
15378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: modem emulation not running\r\n" );
15388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
15398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pdu = smspdu_create_from_hex( args, strlen(args) );
15428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (pdu == NULL) {
15438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: badly formatted <hexstring>\r\n" );
15448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
15458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    amodem_receive_sms( android_modem, pdu );
15488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    smspdu_free( pdu );
15498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
15508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  sms_commands[] =
15538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "send", "send inbound SMS text message",
15558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'sms send <phonenumber> <message>' allows you to simulate a new inbound sms message\r\n", NULL,
15568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_sms_send, NULL },
15578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "pdu", "send inbound SMS PDU",
15598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'sms pdu <hexstring>' allows you to simulate a new inbound sms PDU\r\n"
15608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "(used internally when one emulator sends SMS messages to another instance).\r\n"
15618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "you probably don't want to play with this at all\r\n", NULL,
15628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_sms_sendpdu, NULL },
15638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
15658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
15668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
15688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_control_write(void* data, const char* string)
15698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write((ControlClient)data, string);
15718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
15748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_power_display( ControlClient client, char*  args )
15758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    goldfish_battery_display(do_control_write, client);
15778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
15788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
15818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_ac_state( ControlClient  client, char*  args )
15828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
15848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "on") == 0) {
15858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(1, POWER_SUPPLY_PROP_ONLINE, 1);
15868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
15878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "off") == 0) {
15898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(1, POWER_SUPPLY_PROP_ONLINE, 0);
15908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
15918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
15928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: Usage: \"ac on\" or \"ac off\"\n" );
15958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
15968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
15998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_battery_status( ControlClient  client, char*  args )
16008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
16028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "unknown") == 0) {
16038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_UNKNOWN);
16048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "charging") == 0) {
16078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_CHARGING);
16088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "discharging") == 0) {
16118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_DISCHARGING);
16128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "not-charging") == 0) {
16158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_NOT_CHARGING);
16168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "full") == 0) {
16198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_FULL);
16208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: Usage: \"status unknown|charging|discharging|not-charging|full\"\n" );
16258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
16268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
16298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_battery_present( ControlClient  client, char*  args )
16308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
16328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "true") == 0) {
16338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_PRESENT, 1);
16348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "false") == 0) {
16378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_PRESENT, 0);
16388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: Usage: \"present true\" or \"present false\"\n" );
16438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
16448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
16478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_battery_health( ControlClient  client, char*  args )
16488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
16508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "unknown") == 0) {
16518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_UNKNOWN);
16528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "good") == 0) {
16558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_GOOD);
16568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "overheat") == 0) {
16598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_OVERHEAT);
16608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "dead") == 0) {
16638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_DEAD);
16648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "overvoltage") == 0) {
16678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_OVERVOLTAGE);
16688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "failure") == 0) {
16718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_UNSPEC_FAILURE);
16728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: Usage: \"health unknown|good|overheat|dead|overvoltage|failure\"\n" );
16778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
16788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
16818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_battery_capacity( ControlClient  client, char*  args )
16828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
16848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int capacity;
16858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (sscanf(args, "%d", &capacity) == 1 && capacity >= 0 && capacity <= 100) {
16878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_CAPACITY, capacity);
16888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: Usage: \"capacity <percentage>\"\n" );
16938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
16948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  power_commands[] =
16988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "display", "display battery and charger state",
17008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "display battery and charger state\r\n", NULL,
17018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_power_display, NULL },
17028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "ac", "set AC charging state",
17048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'ac on|off' allows you to set the AC charging state to on or off\r\n", NULL,
17058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_ac_state, NULL },
17068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "status", "set battery status",
17088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'status unknown|charging|discharging|not-charging|full' allows you to set battery status\r\n", NULL,
17098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_battery_status, NULL },
17108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "present", "set battery present state",
17128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'present true|false' allows you to set battery present state to true or false\r\n", NULL,
17138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_battery_present, NULL },
17148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "health", "set battery health state",
17168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'health unknown|good|overheat|dead|overvoltage|failure' allows you to set battery health state\r\n", NULL,
17178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_battery_health, NULL },
17188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "capacity", "set battery capacity state",
17208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'capacity <percentage>' allows you to set battery capacity to a value 0 - 100\r\n", NULL,
17218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_battery_capacity, NULL },
17228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
17248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
17258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
17278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
17288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
17298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                         E  V  E  N  T   C O M M A N D S                         ******/
17308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
17318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
17328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
17338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
17368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_event_send( ControlClient  client, char*  args )
17378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*   p;
17398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
17418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: Usage: event send <type>:<code>:<value> ...\r\n" );
17428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
17438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = args;
17468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (*p) {
17478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char*  q;
17488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int    type, code, value, ret;
17498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p += strspn( args, " \t" );  /* skip spaces */
17518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (*p == 0)
17528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        q  = p + strcspn( p, " \t" );
17558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (q == p)
17578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
17588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = android_event_from_str( p, &type, &code, &value );
17608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ret < 0) {
17618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (ret == -1) {
17628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client,
17638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               "KO: invalid event type in '%.*s', try 'event list types' for valid values\r\n",
17648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               q-p, p );
17658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (ret == -2) {
17668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client,
17678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               "KO: invalid event code in '%.*s', try 'event list codes <type>' for valid values\r\n",
17688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               q-p, p );
17698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
17708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client,
17718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               "KO: invalid event value in '%.*s', must be an integer\r\n",
17728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               q-p, p);
17738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
17748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
17758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
177734f2974ce7ec7c71beb47b5daf9089d5c8c40c79David 'Digit' Turner        user_event_generic( type, code, value );
17788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = q;
17798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
17818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
17848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_event_types( ControlClient  client, char*  args )
17858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  count = android_event_get_type_count();
17878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
17888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "event <type> can be an integer or one of the following aliases\r\n" );
17908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < count; nn++) {
17918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char  tmp[16];
17928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char* p = tmp;
17938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char* end = p + sizeof(tmp);
17948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int   count2 = android_event_get_code_count( nn );;
17958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = android_event_bufprint_type_str( p, end, nn );
17978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "    %-8s", tmp );
17998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (count2 > 0)
18008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "  (%d code aliases)", count2 );
18018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "\r\n" );
18038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
18058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
18088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_event_codes( ControlClient  client, char*  args )
18098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  count;
18118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn, type, dummy;
18128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
18148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: argument missing, try 'event codes <type>'\r\n" );
18158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
18168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( android_event_from_str( args, &type, &dummy, &dummy ) < 0 ) {
18198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: bad argument, see 'event types' for valid values\r\n" );
18208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
18218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    count = android_event_get_code_count( type );
18248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (count == 0) {
18258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "no code aliases defined for this type\r\n" );
18268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
18278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "type '%s' accepts the following <code> aliases:\r\n",
18288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       args );
18298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; nn < count; nn++) {
18308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            char  temp[20], *p = temp, *end = p + sizeof(temp);
18318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            android_event_bufprint_code_str( p, end, type, nn );
18328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "    %-12s\r\n", temp );
18338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
18348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
18378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic __inline__ int
18408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectutf8_next( unsigned char* *pp, unsigned char*  end )
18418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned char*  p      = *pp;
18438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int             result = -1;
18448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p < end) {
18468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c= *p++;
18478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c >= 128) {
18488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((c & 0xe0) == 0xc0)
18498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c &= 0x1f;
18508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else if ((c & 0xf0) == 0xe0)
18518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c &= 0x0f;
18528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
18538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c &= 0x07;
18548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            while (p < end && (p[0] & 0xc0) == 0x80) {
18568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c = (c << 6) | (p[0] & 0x3f);
18578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
18588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
18598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = c;
18608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *pp    = p;
18618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
18638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
18668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_event_text( ControlClient  client, char*  args )
18678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
186871bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine    AKeycodeBuffer keycodes;
18698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned char*  p   = (unsigned char*) args;
18708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned char*  end = p + strlen(args);
18718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int             textlen;
187271bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine    const AKeyCharmap* charmap;
18738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
18758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: argument missing, try 'event text <message>'\r\n" );
18768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
18778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
187871bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine
187971bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine    /* Get default charmap. */
188043552dc4fa64aad0c9fdb8f4c92ae7ac79406596Vladimir Chtchetkine    charmap = android_get_default_charmap();
188171bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine    if (charmap == NULL) {
188271bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine        control_write( client, "KO: no character map active in current device layout/config\r\n" );
18838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
18848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
188671bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine    keycodes.keycode_count = 0;
188771bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine
18888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* un-secape message text into proper utf-8 (conversion happens in-site) */
18898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    textlen = strlen((char*)p);
18908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    textlen = sms_utf8_from_message_str( args, textlen, (unsigned char*)p, textlen );
18918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (textlen < 0) {
18928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "message must be utf8 and can use the following escapes:\r\n"
18938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\n      for a newline\r\n"
18948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\xNN    where NN are two hexadecimal numbers\r\n"
18958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\uNNNN  where NNNN are four hexadecimal numbers\r\n"
18968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\\\     to send a '\\' character\r\n\r\n"
18978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    anything else is an error\r\n"
18988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "KO: badly formatted text\r\n" );
18998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
19008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    end = p + textlen;
19038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (p < end) {
19048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = utf8_next( &p, end );
19058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c <= 0)
19068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
190871bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine        android_charmap_reverse_map_unicode( NULL, (unsigned)c, 1, &keycodes );
190971bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine        android_charmap_reverse_map_unicode( NULL, (unsigned)c, 0, &keycodes );
191071bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine        android_keycodes_flush( &keycodes );
19118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
19148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
19158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  event_commands[] =
19178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
19188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "send", "send a series of events to the kernel",
19198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'event send <type>:<code>:<value> ...' allows your to send one or more hardware events\r\n"
19208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "to the Android kernel. you can use text names or integers for <type> and <code>\r\n", NULL,
19218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_event_send, NULL },
19228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "types", "list all <type> aliases",
19248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'event types' list all <type> string aliases supported by the 'event' subcommands\r\n",
19258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_event_types, NULL },
19268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "codes", "list all <code> aliases for a given <type>",
19288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'event codes <type>' lists all <code> string aliases for a given event <type>\r\n",
19298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_event_codes, NULL },
19308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "text", "simulate keystrokes from a given text",
19328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'event text <message>' allows you to simulate keypresses to generate a given text\r\n"
19338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "message. <message> must be an utf-8 string. Unicode points will be reverse-mapped\r\n"
19348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "according to the current device keyboard. unsupported characters will be discarded\r\n"
19358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "silently\r\n", NULL, do_event_text, NULL },
19368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
19388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
19398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19402ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije#if CONFIG_ANDROID_SNAPSHOTS
19412ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
19422ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
19432ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/********************************************************************************************/
19442ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/********************************************************************************************/
19452ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/*****                                                                                 ******/
19462ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/*****                      S N A P S H O T   C O M M A N D S                          ******/
19472ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/*****                                                                                 ******/
19482ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/********************************************************************************************/
19492ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/********************************************************************************************/
19502ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
19512ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int
19522ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijecontrol_write_out_cb(void* opaque, const char* fmt, va_list ap)
19532ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
19542ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ControlClient client = opaque;
19552ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    int ret = control_vwrite(client, fmt, ap);
19562ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret;
19572ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
19582ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
19592ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int
19602ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijecontrol_write_err_cb(void* opaque, const char* fmt, va_list ap)
19612ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
19622ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    int ret = 0;
19632ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ControlClient client = opaque;
19642ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ret += control_write(client, "KO: ");
19652ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ret += control_vwrite(client, fmt, ap);
19662ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret;
19672ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
19682ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
19692ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int
19702ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijedo_snapshot_list( ControlClient  client, char*  args )
19712ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
19722ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    int ret;
19732ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    OutputChannel *out = output_channel_alloc(client, control_write_out_cb);
19742ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    OutputChannel *err = output_channel_alloc(client, control_write_err_cb);
19752ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    do_info_snapshots_oc(out, err);
19762ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ret = output_channel_written(err);
19772ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    output_channel_free(out);
19782ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    output_channel_free(err);
19792ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
19802ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret > 0;
19812ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
19822ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
19832ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int
19842ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijedo_snapshot_save( ControlClient  client, char*  args )
19852ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
19862ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    int ret;
19872ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    OutputChannel *err = output_channel_alloc(client, control_write_err_cb);
19882ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    do_savevm_oc(err, args);
19892ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ret = output_channel_written(err);
19902ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    output_channel_free(err);
19912ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
19922ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret > 0; // no output on error channel indicates success
19932ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
19942ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
19952ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int
19962ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijedo_snapshot_load( ControlClient  client, char*  args )
19972ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
19982ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    int ret;
19992ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    OutputChannel *err = output_channel_alloc(client, control_write_err_cb);
20002ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    do_loadvm_oc(err, args);
20012ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ret = output_channel_written(err);
20022ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    output_channel_free(err);
20032ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20042ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret > 0;
20052ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
20062ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20072ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int
20082ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijedo_snapshot_del( ControlClient  client, char*  args )
20092ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
20102ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    int ret;
20112ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    OutputChannel *err = output_channel_alloc(client, control_write_err_cb);
20122ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    do_delvm_oc(err, args);
20132ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ret = output_channel_written(err);
20142ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    output_channel_free(err);
20152ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20162ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret > 0;
20172ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
20182ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20192ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic const CommandDefRec  snapshot_commands[] =
20202ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
20212ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { "list", "list available state snapshots",
20222ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "'avd snapshot list' will show a list of all state snapshots that can be loaded\r\n",
20232ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    NULL, do_snapshot_list, NULL },
20242ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20252ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { "save", "save state snapshot",
20262ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "'avd snapshot save <name>' will save the current (run-time) state to a snapshot with the given name\r\n",
20272ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    NULL, do_snapshot_save, NULL },
20282ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20292ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { "load", "load state snapshot",
20302ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "'avd snapshot load <name>' will load the state snapshot of the given name\r\n",
20312ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    NULL, do_snapshot_load, NULL },
20322ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20332ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { "del", "delete state snapshot",
20342ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "'avd snapshot del <name>' will delete the state snapshot with the given name\r\n",
20352ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    NULL, do_snapshot_del, NULL },
20362ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20372ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { NULL, NULL, NULL, NULL, NULL, NULL }
20382ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije};
20392ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20402ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20412ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije#endif
20422ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
20458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
20468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
20478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                               V M   C O M M A N D S                             ******/
20488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
20498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
20508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
20518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
20538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_avd_stop( ControlClient  client, char*  args )
20548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
20558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!vm_running) {
20568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: virtual device already stopped\r\n" );
20578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
20588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
20598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    vm_stop(EXCP_INTERRUPT);
20608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
20618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
20628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
20648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_avd_start( ControlClient  client, char*  args )
20658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
20668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (vm_running) {
20678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: virtual device already running\r\n" );
20688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
20698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
20708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    vm_start();
20718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
20728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
20738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
20758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_avd_status( ControlClient  client, char*  args )
20768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
20778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "virtual device is %s\r\n", vm_running ? "running" : "stopped" );
20788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
20798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
20808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
20828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_avd_name( ControlClient  client, char*  args )
20838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
20848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "%s\r\n", avdInfo_getName(android_avdInfo) );
20858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
20868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
20878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  vm_commands[] =
20898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
20908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "stop", "stop the virtual device",
20918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'avd stop' stops the virtual device immediately, use 'avd start' to continue execution\r\n",
20928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_avd_stop, NULL },
20938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "start", "start/restart the virtual device",
20958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'avd start' will start or continue the virtual device, use 'avd stop' to stop it\r\n",
20968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_avd_start, NULL },
20978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "status", "query virtual device status",
20992ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "'avd status' will indicate whether the virtual device is running or not\r\n",
21008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_avd_status, NULL },
21018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "name", "query virtual device name",
21038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'avd name' will return the name of this virtual device\r\n",
21048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_avd_name, NULL },
21058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21062ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije#if CONFIG_ANDROID_SNAPSHOTS
21072ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { "snapshot", "state snapshot commands",
21082ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "allows you to save and restore the virtual device state in snapshots\r\n",
21092ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    NULL, NULL, snapshot_commands },
21102ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije#endif
21112ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
21128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
21138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
21148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
21168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
21178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
21188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                             G E O   C O M M A N D S                             ******/
21198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
21208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
21218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
21228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
21248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_geo_nmea( ControlClient  client, char*  args )
21258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
21268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
21278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: NMEA sentence missing, try 'help geo nmea'\r\n" );
21288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
21298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
21308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_gps_cs) {
21318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: no GPS emulation in this virtual device\r\n" );
21328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
21338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
21348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    android_gps_send_nmea( args );
21358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
21368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
21378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
21398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_geo_fix( ControlClient  client, char*  args )
21408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2141e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner#define  MAX_GEO_PARAMS  5
21428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*   p = args;
21438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int     n_params = 0;
21448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    double  params[ MAX_GEO_PARAMS ];
2145657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner    int     n_satellites = 1;
21468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static  int     last_time = 0;
21488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static  double  last_altitude = 0.;
21498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!p)
21518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = "";
21528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* tokenize */
21548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (*p) {
21558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char*   end;
21568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        double  val = strtod( p, &end );
21578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (end == p) {
21598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "KO: argument '%s' is not a number\n", p );
21608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
21618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
21628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        params[n_params++] = val;
21648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (n_params >= MAX_GEO_PARAMS)
21658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
21668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = end;
21688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (*p && (p[0] == ' ' || p[0] == '\t'))
21698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p += 1;
21708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
21718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* sanity check */
21738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (n_params < 2) {
21748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: not enough arguments: see 'help geo fix' for details\r\n" );
21758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
21768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
21778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2178657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner    /* check number of satellites, must be between 1 and 12 */
2179657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner    if (n_params >= 4) {
2180657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        n_satellites = (int) params[4];
2181657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        if (n_satellites != params[4] || n_satellites < 1 || n_satellites > 12) {
2182657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner            control_write( client, "KO: invalid number of satellites. Must be an integer between 1 and 12\r\n");
2183657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner            return -1;
2184657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        }
2185657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner    }
2186657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner
21878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* generate an NMEA sentence for this fix */
21888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
21898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        STRALLOC_DEFINE(s);
21908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        double   val;
21918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int      deg, min;
21928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char     hemi;
21938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2194657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        /* format overview:
2195657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    time of fix      123519     12:35:19 UTC
2196657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    latitude         4807.038   48 degrees, 07.038 minutes
2197657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    north/south      N or S
2198657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    longitude        01131.000  11 degrees, 31. minutes
2199657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    east/west        E or W
2200657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    fix quality      1          standard GPS fix
2201657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    satellites       1 to 12    number of satellites being tracked
2202657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    HDOP             <dontcare> horizontal dilution
2203657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    altitude         546.       altitude above sea-level
2204657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    altitude units   M          to indicate meters
2205657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    diff             <dontcare> height of sea-level above ellipsoid
2206657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    diff units       M          to indicate meters (should be <dontcare>)
2207657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    dgps age         <dontcare> time in seconds since last DGPS fix
2208657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    dgps sid         <dontcare> DGPS station id
2209657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         */
2210657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner
22118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* first, the time */
22128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stralloc_add_format( s, "$GPGGA,%06d", last_time );
22138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        last_time ++;
22148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* then the latitude */
22168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hemi = 'N';
22178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val  = params[1];
22188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (val < 0) {
22198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            hemi = 'S';
22208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val  = -val;
22218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
22228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        deg = (int) val;
2223657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        val = 60*(val - deg);
2224657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        min = (int) val;
2225631f2555ed2b50a07ea19eaefa495a028ab1991aDavid 'Digit' Turner        val = 10000*(val - min);
2226657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        stralloc_add_format( s, ",%02d%02d.%04d,%c", deg, min, (int)val, hemi );
22278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* the longitude */
22298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hemi = 'E';
22308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        val  = params[0];
22318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (val < 0) {
22328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            hemi = 'W';
22338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val  = -val;
22348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
22358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        deg = (int) val;
2236657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        val = 60*(val - deg);
2237657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        min = (int) val;
2238631f2555ed2b50a07ea19eaefa495a028ab1991aDavid 'Digit' Turner        val = 10000*(val - min);
2239657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        stralloc_add_format( s, ",%02d%02d.%04d,%c", deg, min, (int)val, hemi );
22408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2241657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        /* bogus fix quality, satellite count and dilution */
2242657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        stralloc_add_format( s, ",1,%02d,", n_satellites );
22438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2244657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        /* optional altitude + bogus diff */
22458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (n_params >= 3) {
2246657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner            stralloc_add_format( s, ",%.1g,M,0.,M", params[2] );
22478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            last_altitude = params[2];
22488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
2249657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner            stralloc_add_str( s, ",,,," );
22508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
22518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* bogus rest and checksum */
22528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stralloc_add_str( s, ",,,*47" );
22538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* send it, then free */
22558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        android_gps_send_nmea( stralloc_cstr(s) );
22568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stralloc_reset( s );
22578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
22588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
22598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
22608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  geo_commands[] =
22628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
22638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "nmea", "send an GPS NMEA sentence",
22648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'geo nema <sentence>' sends a NMEA 0183 sentence to the emulated device, as\r\n"
22658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "if it came from an emulated GPS modem. <sentence> must begin with '$GP'. only\r\n"
22668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'$GPGGA' and '$GPRCM' sentences are supported at the moment.\r\n",
22678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_geo_nmea, NULL },
22688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "fix", "send a simple GPS fix",
2270657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner    "'geo fix <longitude> <latitude> [<altitude> [<satellites>]]' allows you to send a\r\n"
22718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "simple GPS fix to the emulated system. the parameters are:\r\n\r\n"
22728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "  <longitude>   longitude, in decimal degrees\r\n"
22738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "  <latitude>    latitude, in decimal degrees\r\n"
22748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "  <altitude>    optional altitude in meters\r\n"
2275657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner    "  <satellites>  number of satellites being tracked (1-12)\r\n"
22768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "\r\n",
22778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_geo_fix, NULL },
22788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
22808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
22818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
22848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
22858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
22868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                           M A I N   C O M M A N D S                             ******/
22878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
22888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
22898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
22908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
22928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_window_scale( ControlClient  client, char*  args )
22938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
22948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    double  scale;
22958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int     is_dpi = 0;
22968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*   end;
22978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
22998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: argument missing, try 'window scale <scale>'\r\n" );
23008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
23018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
23028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    scale = strtol( args, &end, 10 );
23048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (end > args && !memcmp( end, "dpi", 4 )) {
23058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        is_dpi = 1;
23068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
23078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
23088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        scale = strtod( args, &end );
23098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (end == args || end[0]) {
23108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "KO: argument <scale> must be a real number, or an integer followed by 'dpi'\r\n" );
23118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
23128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
23138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
23148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23152fa5173bd1ce7341c50adac676a317945f0969c7Vladimir Chtchetkine    android_ui_set_window_scale( scale, is_dpi );
23168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
23178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  window_commands[] =
23208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "scale", "change the window scale",
23228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'window scale <scale>' allows you to change the scale of the emulator window at runtime\r\n"
23238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "<scale> must be either a real number between 0.1 and 3.0, or an integer followed by\r\n"
23248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "the 'dpi' prefix (as in '120dpi')\r\n",
23258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_window_scale, NULL },
23268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
23288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
23298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
23318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
23328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
2333e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/*****                           Q E M U   C O M M A N D S                             ******/
2334e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/*****                                                                                 ******/
2335e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/********************************************************************************************/
2336e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/********************************************************************************************/
2337e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2338e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnerstatic int
2339e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnerdo_qemu_monitor( ControlClient client, char* args )
2340e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner{
2341e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    char             socketname[32];
2342e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    int              fd;
2343e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    CharDriverState* cs;
2344e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2345e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    if (args != NULL) {
2346e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner        control_write( client, "KO: no argument for 'qemu monitor'\r\n" );
2347e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner        return -1;
2348e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    }
2349e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    /* Detach the client socket, and re-attach it to a monitor */
2350e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    fd = control_client_detach(client);
2351e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    snprintf(socketname, sizeof socketname, "tcp:socket=%d", fd);
2352e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    cs = qemu_chr_open("monitor", socketname, NULL);
2353e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    if (cs == NULL) {
2354e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner        control_client_reattach(client, fd);
2355e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner        control_write( client, "KO: internal error: could not detach from console !\r\n" );
2356e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner        return -1;
2357e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    }
2358e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    monitor_init(cs, MONITOR_USE_READLINE|MONITOR_QUIT_DOESNT_EXIT);
2359e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    control_client_destroy(client);
2360e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    return 0;
2361e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner}
2362e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2363e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnerstatic const CommandDefRec  qemu_commands[] =
2364e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner{
2365e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    { "monitor", "enter QEMU monitor",
2366e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    "Enter the QEMU virtual machine monitor\r\n",
2367e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    NULL, do_qemu_monitor, NULL },
2368e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2369e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    { NULL, NULL, NULL, NULL, NULL, NULL }
2370e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner};
2371e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2372e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2373e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/********************************************************************************************/
2374e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/********************************************************************************************/
2375e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/*****                                                                                 ******/
23768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                           M A I N   C O M M A N D S                             ******/
23778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
23788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
23798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
23808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
23828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_kill( ControlClient  client, char*  args )
23838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	control_write( client, "OK: killing emulator, bye bye\r\n" );
23858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	exit(0);
23868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec   main_commands[] =
23898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "help|h|?", "print a list of commands", NULL, NULL, do_help, NULL },
23918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "event", "simulate hardware events",
23938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "allows you to send fake hardware events to the kernel\r\n", NULL,
23948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, event_commands },
23958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "geo", "Geo-location commands",
23978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows you to change Geo-related settings, or to send GPS NMEA sentences\r\n", NULL,
23988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, geo_commands },
23998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "gsm", "GSM related commands",
24018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows you to change GSM-related settings, or to make a new inbound phone call\r\n", NULL,
24028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, gsm_commands },
24038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24041a000857bb7eef298efa787699050884f92311feJaime Lopez    { "cdma", "CDMA related commands",
24051a000857bb7eef298efa787699050884f92311feJaime Lopez      "allows you to change CDMA-related settings\r\n", NULL,
24061a000857bb7eef298efa787699050884f92311feJaime Lopez      NULL, cdma_commands },
24071a000857bb7eef298efa787699050884f92311feJaime Lopez
24088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "kill", "kill the emulator instance", NULL, NULL,
24098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project	  do_kill, NULL },
24108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "network", "manage network settings",
24128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows you to manage the settings related to the network data connection of the\r\n"
24138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "emulated device.\r\n", NULL,
24148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, network_commands },
24158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "power", "power related commands",
24178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows to change battery and AC power status\r\n", NULL,
24188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, power_commands },
24198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "quit|exit", "quit control session", NULL, NULL,
24218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      do_quit, NULL },
24228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "redir",    "manage port redirections",
24248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows you to add, list and remove UDP and/or PORT redirection from the host to the device\r\n"
24258b23a6c7e1aee255004dd19098d4c2462b61b849The 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"
24268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "to TCP port 6000 of the emulated device\r\n", NULL,
24278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, redir_commands },
24288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "sms", "SMS related commands",
24308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows you to simulate an inbound SMS\r\n", NULL,
24318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, sms_commands },
24328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24332ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { "avd", "control virtual device execution",
24342ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "allows you to control (e.g. start/stop) the execution of the virtual device\r\n", NULL,
24358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, vm_commands },
24368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "window", "manage emulator window",
24388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "allows you to modify the emulator window\r\n", NULL,
24398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, window_commands },
24408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2441e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    { "qemu", "QEMU-specific commands",
2442e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    "allows to connect to the QEMU virtual machine monitor\r\n", NULL,
2443e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    NULL, qemu_commands },
2444e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
24458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
24468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
24478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic ControlGlobalRec  _g_global;
24508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
24528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_console_start( int  port )
24538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return control_global_init( &_g_global, port );
24558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2456