console.c revision 90c6235ce7bdc6f7afbcfe56ea6f2c3d2b128447
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 "cpu.h"
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "hw/goldfish_device.h"
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "hw/power_supply.h"
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "shaper.h"
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "modem_driver.h"
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/gps.h"
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/globals.h"
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/utils/bufprint.h"
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/utils/debug.h"
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/utils/stralloc.h"
382ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije#include "android/config/config.h"
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "tcpdump.h"
405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "net.h"
41e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner#include "monitor.h"
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdlib.h>
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdio.h>
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdarg.h>
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <string.h>
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <unistd.h>
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <fcntl.h>
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/hw-events.h"
5034f2974ce7ec7c71beb47b5daf9089d5c8c40c79David 'Digit' Turner#include "user-events.h"
5171bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine#include "android/keycode-array.h"
5271bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine#include "android/charmap.h"
532fa5173bd1ce7341c50adac676a317945f0969c7Vladimir Chtchetkine#include "android/core-ui-protocol.h"
54e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#include "android/display-core.h"
55e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#include "android/framebuffer-core.h"
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(CONFIG_SLIRP)
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "libslirp.h"
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  DEBUG  1
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 1
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  D_ACTIVE   VERBOSE_CHECK(console)
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  D_ACTIVE   DEBUG
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if DEBUG
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  D(x)   do { if (D_ACTIVE) ( printf x , fflush(stdout) ); } while (0)
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  D(x)   do{}while(0)
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct ControlGlobalRec_*  ControlGlobal;
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct ControlClientRec_*  ControlClient;
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct {
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int           host_port;
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int           host_udp;
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int  guest_ip;
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int           guest_port;
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} RedirRec, *Redir;
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
87e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnertypedef int Socket;
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct ControlClientRec_
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ControlClientRec_*  next;       /* next client in list           */
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Socket                     sock;       /* socket used for communication */
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlGlobal              global;
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char                       finished;
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char                       buff[ 4096 ];
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int                        buff_len;
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} ControlClientRec;
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct ControlGlobalRec_
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* listening socket */
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Socket    listen_fd;
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* the list of current clients */
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlClient   clients;
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* the list of redirections currently active */
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Redir     redirs;
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       num_redirs;
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       max_redirs;
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} ControlGlobalRec;
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
116e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#ifdef CONFIG_STANDALONE_CORE
117d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine/* UI client currently attached to the core. */
118d87b080495e71ada650b165a1f06616b433e6073Vladimir ChtchetkineControlClient attached_ui_client = NULL;
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
120e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine/* Core framebuffer service client. */
121e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir ChtchetkineControlClient framebuffer_client = NULL;
122e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#endif  // CONFIG_STANDALONE_CORE
123e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine
12490c6235ce7bdc6f7afbcfe56ea6f2c3d2b128447Vladimir Chtchetkine/* -android-avdname option value. Defined in vl-android.c */
12590c6235ce7bdc6f7afbcfe56ea6f2c3d2b128447Vladimir Chtchetkineextern char* android_op_avd_name;
12690c6235ce7bdc6f7afbcfe56ea6f2c3d2b128447Vladimir Chtchetkine
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_global_add_redir( ControlGlobal  global,
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int            host_port,
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int            host_udp,
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          unsigned int   guest_ip,
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int            guest_port )
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Redir  redir;
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (global->num_redirs >= global->max_redirs)
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  old_max = global->max_redirs;
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  new_max = old_max + (old_max >> 1) + 4;
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        Redir  new_redirs = realloc( global->redirs, new_max*sizeof(global->redirs[0]) );
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (new_redirs == NULL)
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        global->redirs     = new_redirs;
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        global->max_redirs = new_max;
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir = &global->redirs[ global->num_redirs++ ];
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir->host_port  = host_port;
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir->host_udp   = host_udp;
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir->guest_ip   = guest_ip;
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir->guest_port = guest_port;
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_global_del_redir( ControlGlobal  global,
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int            host_port,
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int            host_udp )
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < global->num_redirs; nn++)
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        Redir  redir = &global->redirs[nn];
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( redir->host_port == host_port &&
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             redir->host_udp  == host_udp  )
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            memmove( redir, redir + 1, ((global->num_redirs - nn)-1)*sizeof(*redir) );
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            global->num_redirs -= 1;
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we didn't find it */
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
182e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/* Detach the socket descriptor from a given ControlClient
183e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner * and return its value. This is useful either when destroying
184e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner * the client, or redirecting the socket to another service.
185e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner *
186e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner * NOTE: this does not close the socket.
187e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner */
188e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnerstatic int
189e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnercontrol_client_detach( ControlClient  client )
190e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner{
191e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    int  result;
192e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
193e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    if (client->sock < 0)
194e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner        return -1;
195e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
196e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    qemu_set_fd_handler( client->sock, NULL, NULL, NULL );
197e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    result = client->sock;
198e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    client->sock = -1;
199e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
200e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    return result;
201e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner}
202e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
203e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnerstatic void  control_client_read( void*  _client );  /* forward */
204e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
205e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/* Reattach a control client to a given socket.
206e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner * Return the old socket descriptor for the client.
207e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner */
208e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnerstatic int
209e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnercontrol_client_reattach( ControlClient client, int fd )
210e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner{
211e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    int result = control_client_detach(client);
212e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    client->sock = fd;
213e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    qemu_set_fd_handler( fd, control_client_read, NULL, client );
214e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    return result;
215e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner}
216e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_client_destroy( ControlClient  client )
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlGlobal  global = client->global;
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlClient  *pnode = &global->clients;
222e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    int            sock;
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D(( "destroying control client %p\n", client ));
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
226e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#ifdef CONFIG_STANDALONE_CORE
227d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    if (client == attached_ui_client) {
228d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine        attached_ui_client = NULL;
229d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    }
230d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine
231e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    if (client == framebuffer_client) {
232e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        CoreFramebuffer* core_fb = coredisplay_detach_fb_service();
233e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        if (core_fb != NULL) {
234e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine            corefb_destroy(core_fb);
235e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine            AFREE(core_fb);
236e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        }
237e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        framebuffer_client = NULL;
238e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    }
239e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#endif  // CONFIG_STANDALONE_CORE
240e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine
241e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    sock = control_client_detach( client );
242e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    if (sock >= 0)
243e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner        socket_close(sock);
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( ;; ) {
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ControlClient  node = *pnode;
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( node == NULL )
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( node == client ) {
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            *pnode     = node->next;
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            node->next = NULL;
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pnode = &node->next;
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    free( client );
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void  control_control_write( ControlClient  client, const char*  buff, int  len )
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len < 0)
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = strlen(buff);
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (len > 0) {
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = socket_send( client->sock, buff, len);
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ret < 0) {
272ce0f4b02160ee72d7d2428867fe757bc37c68c98David 'Digit' Turner            if (errno != EINTR && errno != EWOULDBLOCK && errno != EAGAIN)
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            buff += ret;
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len  -= ret;
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2812ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int  control_vwrite( ControlClient  client, const char*  format, va_list args )
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static char  temp[1024];
2842ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    int ret = vsnprintf( temp, sizeof(temp), format, args );
2852ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    temp[ sizeof(temp)-1 ] = 0;
2862ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    control_control_write( client, temp, -1 );
2872ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
2882ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret;
2892ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2912ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int  control_write( ControlClient  client, const char*  format, ... )
2922ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
2932ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    int ret;
2942ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    va_list      args;
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_start(args, format);
2962ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ret = control_vwrite(client, format, args);
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_end(args);
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2992ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret;
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic ControlClient
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_client_create( Socket         socket,
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       ControlGlobal  global )
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlClient  client = calloc( sizeof(*client), 1 );
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (client) {
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_set_nodelay( socket );
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_set_nonblock( socket );
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->finished = 0;
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->global  = global;
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->sock    = socket;
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->next    = global->clients;
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        global->clients = client;
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_set_fd_handler( socket, control_client_read, NULL, client );
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return client;
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef const struct CommandDefRec_  *CommandDef;
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct CommandDefRec_ {
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*  names;
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*  abstract;
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*  description;
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void        (*descriptor)( ControlClient  client );
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int         (*handler)( ControlClient  client, char* args );
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CommandDef   subcommands;   /* if handler is NULL */
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} CommandDefRec;
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec   main_commands[];  /* forward */
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic CommandDef
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectfind_command( char*  input, CommandDef  commands, char*  *pend, char*  *pargs )
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int    nn;
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*  args = strchr(input, ' ');
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args != NULL) {
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (*args == ' ')
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            args++;
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (args[0] == 0)
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            args = NULL;
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; commands[nn].names != NULL; nn++)
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*  name = commands[nn].names;
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*  sep;
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        do {
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int  len, c;
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sep = strchr( name, '|' );
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (sep)
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                len = sep - name;
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                len = strlen(name);
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            c = input[len];
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ( !memcmp( name, input, len ) && (c == ' ' || c == 0) ) {
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                *pend  = input + len;
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                *pargs = args;
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return &commands[nn];
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (sep)
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                name = sep + 1;
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } while (sep != NULL && *name);
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* NOTE: don't touch *pend and *pargs if no command is found */
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdump_help( ControlClient  client,
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           CommandDef     cmd,
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           const char*    prefix )
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cmd->description) {
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "%s", cmd->description );
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (cmd->descriptor) {
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cmd->descriptor( client );
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "%s\r\n", cmd->abstract );
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cmd->subcommands) {
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cmd = cmd->subcommands;
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "\r\navailable sub-commands:\r\n" );
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for ( ; cmd->names != NULL; cmd++ ) {
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "   %s %-15s  %s\r\n", prefix, cmd->names, cmd->abstract );
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "\r\n" );
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_client_do_command( ControlClient  client )
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       line     = client->buff;
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       args     = NULL;
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CommandDef  commands = main_commands;
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       cmdend   = client->buff;
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CommandDef  cmd      = find_command( line, commands, &cmdend, &args );
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cmd == NULL) {
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: unknown command, try 'help'\r\n" );
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (;;) {
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        CommandDef  subcmd;
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (cmd->handler) {
421d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine            if ( !cmd->handler( client, args ) ) {
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client, "OK\r\n" );
423d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine            }
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* no handler means we should have sub-commands */
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (cmd->subcommands == NULL) {
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "KO: internal error: buggy command table for '%.*s'\r\n",
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           cmdend - client->buff, client->buff );
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* we need a sub-command here */
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( !args ) {
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dump_help( client, cmd, "" );
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "KO: missing sub-command\r\n" );
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        line     = args;
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        commands = cmd->subcommands;
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        subcmd   = find_command( line, commands, &cmdend, &args );
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (subcmd == NULL) {
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dump_help( client, cmd, "" );
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "KO:  bad sub-command\r\n" );
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cmd = subcmd;
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* implement the 'help' command */
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_help( ControlClient  client, char*  args )
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       line;
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       start = args;
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       end   = start;
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CommandDef  cmd = main_commands;
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* without arguments, simply dump all commands */
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args == NULL) {
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "Android console command help:\r\n\r\n" );
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for ( ; cmd->names != NULL; cmd++ ) {
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "    %-15s  %s\r\n", cmd->names, cmd->abstract );
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "\r\ntry 'help <command>' for command-specific help\r\n" );
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* with an argument, find the corresponding command */
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (;;) {
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        CommandDef  subcmd;
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        line    = args;
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        subcmd  = find_command( line, cmd, &end, &args );
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (subcmd == NULL) {
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "try one of these instead:\r\n\r\n" );
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for ( ; cmd->names != NULL; cmd++ ) {
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client, "    %.*s %s\r\n",
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              end - start, start, cmd->names );
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "\r\nKO: unknown command\r\n" );
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( !args || !subcmd->subcommands ) {
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dump_help( client, subcmd, start );
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cmd = subcmd->subcommands;
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_client_read_byte( ControlClient  client, unsigned char  ch )
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ch == '\r')
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* filter them out */
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else if (ch == '\n')
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->buff[ client->buff_len ] = 0;
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_client_do_command( client );
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (client->finished)
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->buff_len = 0;
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (client->buff_len >= sizeof(client->buff)-1)
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            client->buff_len = 0;
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->buff[ client->buff_len++ ] = ch;
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_client_read( void*  _client )
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlClient  client = _client;
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned char  buf[4096];
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int            size;
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D(( "in control_client read: " ));
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    size = socket_recv( client->sock, buf, sizeof(buf) );
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (size < 0) {
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "size < 0, exiting with %d: %s\n", errno, errno_str ));
533d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine        if (errno != EWOULDBLOCK && errno != EAGAIN)
534d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine            control_client_destroy( client );
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (size == 0) {
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* end of connection */
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "end of connection detected !!\n" ));
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_client_destroy( client );
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  nn;
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  if DEBUG
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char  temp[16];
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int   count = size > sizeof(temp)-1 ? sizeof(temp)-1 : size;
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; nn < count; nn++) {
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int  c = buf[nn];
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (c == '\n')
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        temp[nn] = '!';
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else if (c < 32)
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        temp[nn] = '.';
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    temp[nn] = (char)c;
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        temp[nn] = 0;
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "received %d bytes: %s\n", size, temp ));
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  endif
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "received %.*s\n", size, buf ));
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; nn < size; nn++) {
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_client_read_byte( client, buf[nn] );
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (client->finished) {
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_client_destroy(client);
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* this function is called on each new client connection */
5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_global_accept( void*  _global )
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlGlobal       global = _global;
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlClient       client;
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Socket              fd;
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
58380bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    D(( "control_global_accept: just in (fd=%d)\n", global->listen_fd ));
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for(;;) {
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        fd = socket_accept( global->listen_fd, NULL );
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (fd < 0 && errno != EINTR) {
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            D(( "problem in accept: %d: %s\n", errno, errno_str ));
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            perror("accept");
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else if (fd >= 0) {
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "relooping in accept()\n" ));
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_xreuseaddr( fd );
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D(( "control_global_accept: creating new client\n" ));
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    client = control_client_create( fd, global );
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (client) {
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "control_global_accept: new client %p\n", client ));
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "Android Console: type 'help' for a list of commands\r\n" );
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "OK\r\n" );
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_global_init( ControlGlobal  global,
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     int            control_port )
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Socket  fd;
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int     ret;
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SockAddress  sockaddr;
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memset( global, 0, sizeof(*global) );
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fd = socket_create_inet( SOCKET_STREAM );
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (fd < 0) {
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        perror("socket");
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_xreuseaddr( fd );
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sock_address_init_inet( &sockaddr, SOCK_ADDRESS_INET_LOOPBACK, control_port );
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = socket_bind(fd, &sockaddr );
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) {
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        perror("bind");
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_close( fd );
6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = socket_listen(fd, 0);
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) {
6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        perror("listen");
6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_close( fd );
6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_nonblock(fd);
6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    global->listen_fd = fd;
6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_set_fd_handler( fd, control_global_accept, NULL, global );
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_quit( ControlClient  client, char*  args )
6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    client->finished = 1;
6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                        N E T W O R K   S E T T I N G S                          ******/
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_network_status( ControlClient  client, char*  args )
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "Current network status:\r\n" );
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "  download speed:   %8d bits/s (%.1f KB/s)\r\n",
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   (long)qemu_net_download_speed, qemu_net_download_speed/8192. );
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "  upload speed:     %8d bits/s (%.1f KB/s)\r\n",
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   (long)qemu_net_upload_speed, qemu_net_upload_speed/8192. );
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "  minimum latency:  %ld ms\r\n", qemu_net_min_latency );
6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "  maximum latency:  %ld ms\r\n", qemu_net_max_latency );
6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdump_network_speeds( ControlClient  client )
6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const NetworkSpeed*  speed = android_netspeeds;
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char* const  format = "  %-8s %s\r\n";
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( ; speed->name; speed++ ) {
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, format, speed->name, speed->display );
6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, format, "<num>", "selects both upload and download speed" );
6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, format, "<up>:<down>", "select individual upload/download speeds" );
6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_network_speed( ControlClient  client, char*  args )
6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !args ) {
7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing <speed> argument, see 'help network speed'\r\n" );
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( android_parse_network_speed( args ) < 0 ) {
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: invalid <speed> argument, see 'help network speed' for valid values\r\n" );
7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    netshaper_set_rate( slirp_shaper_in,  qemu_net_download_speed );
7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    netshaper_set_rate( slirp_shaper_out, qemu_net_upload_speed );
7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (android_modem) {
71371bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine        amodem_set_data_network_type( android_modem,
7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                    android_parse_network_type( args ) );
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdescribe_network_speed( ControlClient  client )
7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client,
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   "'network speed <speed>' allows you to dynamically change the speed of the emulated\r\n"
7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   "network on the device, where <speed> is one of the following:\r\n\r\n" );
7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dump_network_speeds( client );
7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_network_delay( ControlClient  client, char*  args )
7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !args ) {
7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing <delay> argument, see 'help network delay'\r\n" );
7338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( android_parse_network_latency( args ) < 0 ) {
7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: invalid <delay> argument, see 'help network delay' for valid values\r\n" );
7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    netdelay_set_latency( slirp_delay_in, qemu_net_min_latency, qemu_net_max_latency );
7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdescribe_network_delay( ControlClient  client )
7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client,
7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   "'network delay <latency>' allows you to dynamically change the latency of the emulated\r\n"
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   "network on the device, where <latency> is one of the following:\r\n\r\n" );
7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: TODO */
7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_network_capture_start( ControlClient  client, char*  args )
7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !args ) {
7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing <file> argument, see 'help network capture start'\r\n" );
7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( qemu_tcpdump_start(args) < 0) {
7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: could not start capture: %s", strerror(errno) );
7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_network_capture_stop( ControlClient  client, char*  args )
7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* no need to return an error here */
7708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_tcpdump_stop();
7718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
7728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  network_capture_commands[] =
7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "start", "start network capture",
7778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "'network capture start <file>' starts a new capture of network packets\r\n"
7788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "into a specific <file>. This will stop any capture already in progress.\r\n"
7798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "the capture file can later be analyzed by tools like WireShark. It uses\r\n"
7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "the libpcap file format.\r\n\r\n"
7818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "you can stop the capture anytime with 'network capture stop'\r\n", NULL,
7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      do_network_capture_start, NULL },
7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "stop", "stop network capture",
7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "'network capture stop' stops a currently running packet capture, if any.\r\n"
7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "you can start one with 'network capture start <file>'\r\n", NULL,
7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      do_network_capture_stop, NULL },
7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  network_commands[] =
7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "status", "dump network status", NULL, NULL,
7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       do_network_status, NULL },
7968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "speed", "change network speed", NULL, describe_network_speed,
7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      do_network_speed, NULL },
7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "delay", "change network latency", NULL, describe_network_delay,
8018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       do_network_delay, NULL },
8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "capture", "dump network packets to file",
8048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows to start/stop capture of network packets to a file for later analysis\r\n", NULL,
8058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, network_capture_commands },
8068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
8088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
8098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
8128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
8138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                       P O R T   R E D I R E C T I O N S                         ******/
8148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
8158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
8168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
8178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
8198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_redir_list( ControlClient  client, char*  args )
8208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlGlobal  global = client->global;
8228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (global->num_redirs == 0)
8248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "no active redirections\r\n" );
8258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
8268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  nn;
8278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; nn < global->num_redirs; nn++) {
8288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            Redir  redir = &global->redirs[nn];
8298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "%s:%-5d => %-5d\r\n",
8308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          redir->host_udp ? "udp" : "tcp",
8318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          redir->host_port,
8328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          redir->guest_port );
8338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
8348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
8368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* parse a protocol:port specification */
8398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
8408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectredir_parse_proto_port( char*  args, int  *pport, int  *pproto )
8418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  proto = -1;
8438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  len   = 0;
8448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*  end;
8458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !memcmp( args, "tcp:", 4 ) ) {
8478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        proto = 0;
8488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len   = 4;
8498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else if ( !memcmp( args, "udp:", 4 ) ) {
8518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        proto = 1;
8528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len   = 4;
8538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
8558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
8568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    args   += len;
8588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pproto = proto;
8598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pport  = strtol( args, &end, 10 );
8608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (end == args)
8618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
8628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len += end - args;
8648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return len;
8658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
8688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectredir_parse_guest_port( char*  arg, int  *pport )
8698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*  end;
8718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pport = strtoul( arg, &end, 10 );
8738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (end == arg)
8748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
8758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return end - arg;
8778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic Redir
8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectredir_find( ControlGlobal  global, int  port, int  isudp )
8818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
8838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < global->num_redirs; nn++) {
8858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        Redir  redir = &global->redirs[nn];
8868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (redir->host_port == port && redir->host_udp == isudp)
8888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return redir;
8898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
8918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
8958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_redir_add( ControlClient  client, char*  args )
8968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       len, host_proto, host_port, guest_port;
8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t  guest_ip;
8998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Redir     redir;
9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !args )
9028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto BadFormat;
9038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!slirp_is_inited()) {
9055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        control_write( client, "KO: network emulation disabled\r\n");
9065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -1;
9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = redir_parse_proto_port( args, &host_port, &host_proto );
9108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len == 0 || args[len] != ':')
9118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto BadFormat;
9128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    args += len + 1;
9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = redir_parse_guest_port( args, &guest_port );
9158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len == 0 || args[len] != 0)
9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto BadFormat;
9178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir = redir_find( client->global, host_port, host_proto );
9198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( redir != NULL ) {
9208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: host port already active, use 'redir del' to remove first\r\n" );
9218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9247d9a2705e7ae6d8c4b1d9d5b4e2a67ab88c19044David Turner    if (inet_strtoip("10.0.2.15", &guest_ip) < 0) {
9258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: unexpected internal failure when resolving 10.0.2.15\r\n" );
9268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D(("pattern hport=%d gport=%d proto=%d\n", host_port, guest_port, host_proto ));
9308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( control_global_add_redir( client->global, host_port, host_proto,
9318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                   guest_ip, guest_port ) < 0 )
9328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
9338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: not enough memory to allocate redirection\r\n" );
9348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (slirp_redir(host_proto, host_port, guest_ip, guest_port) < 0) {
9388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: can't setup redirection, port probably used by another program on host\r\n" );
9398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_global_del_redir( client->global, host_port, host_proto );
9408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
9448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectBadFormat:
9468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: bad redirection format, try (tcp|udp):hostport:guestport\r\n", -1 );
9478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
9488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
9528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_redir_del( ControlClient  client, char*  args )
9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int    len, proto, port;
9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Redir  redir;
9568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !args )
9588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto BadFormat;
9598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = redir_parse_proto_port( args, &port, &proto );
9608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( len == 0 || args[len] != 0 )
9618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto BadFormat;
9628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir = redir_find( client->global, port, proto );
9648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (redir == NULL) {
9658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: can't remove unknown redirection (%s:%d)\r\n",
9668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        proto ? "udp" : "tcp", port );
9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    slirp_unredir( redir->host_udp, redir->host_port );
9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_global_del_redir( client->global, port, proto );\
9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectBadFormat:
9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: bad redirection format, try (tcp|udp):hostport\r\n" );
9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  redir_commands[] =
9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "list", "list current redirections",
9838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "list current port redirections. use 'redir add' and 'redir del' to add and remove them\r\n", NULL,
9848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_redir_list, NULL },
9858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "add",  "add new redirection",
9878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "add a new port redirection, arguments must be:\r\n\r\n"
9888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "  redir add <protocol>:<host-port>:<guest-port>\r\n\r\n"
9898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "where:   <protocol>     is either 'tcp' or 'udp'\r\n"
9908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "         <host-port>    a number indicating which port on the host to open\r\n"
9918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "         <guest-port>   a number indicating which port to route to on the device\r\n"
9928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "\r\nas an example, 'redir  tcp:5000:6000' will allow any packets sent to\r\n"
9938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "the host's TCP port 5000 to be routed to TCP port 6000 of the emulated device\r\n", NULL,
9948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_redir_add, NULL },
9958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "del",  "remove existing redirection",
9978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "remove a port redirecion that was created with 'redir add', arguments must be:\r\n\r\n"
9988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "  redir  del <protocol>:<host-port>\r\n\r\n"
9998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "see the 'help redir add' for the meaning of <protocol> and <host-port>\r\n", NULL,
10008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_redir_del, NULL },
10018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
10038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
10048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
10088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
10098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
10101a000857bb7eef298efa787699050884f92311feJaime Lopez/*****                          C D M A   M O D E M                                    ******/
10111a000857bb7eef298efa787699050884f92311feJaime Lopez/*****                                                                                 ******/
10121a000857bb7eef298efa787699050884f92311feJaime Lopez/********************************************************************************************/
10131a000857bb7eef298efa787699050884f92311feJaime Lopez/********************************************************************************************/
10141a000857bb7eef298efa787699050884f92311feJaime Lopez
10151a000857bb7eef298efa787699050884f92311feJaime Lopezstatic const struct {
10161a000857bb7eef298efa787699050884f92311feJaime Lopez    const char *            name;
10171a000857bb7eef298efa787699050884f92311feJaime Lopez    const char *            display;
10181a000857bb7eef298efa787699050884f92311feJaime Lopez    ACdmaSubscriptionSource source;
10191a000857bb7eef298efa787699050884f92311feJaime Lopez} _cdma_subscription_sources[] = {
10201a000857bb7eef298efa787699050884f92311feJaime Lopez    { "nv",            "Read subscription from non-volatile RAM", A_SUBSCRIPTION_NVRAM },
10211a000857bb7eef298efa787699050884f92311feJaime Lopez    { "ruim",          "Read subscription from RUIM", A_SUBSCRIPTION_RUIM },
10221a000857bb7eef298efa787699050884f92311feJaime Lopez};
10231a000857bb7eef298efa787699050884f92311feJaime Lopez
10241a000857bb7eef298efa787699050884f92311feJaime Lopezstatic void
10251a000857bb7eef298efa787699050884f92311feJaime Lopezdump_subscription_sources( ControlClient client )
10261a000857bb7eef298efa787699050884f92311feJaime Lopez{
10271a000857bb7eef298efa787699050884f92311feJaime Lopez    int i;
10281a000857bb7eef298efa787699050884f92311feJaime Lopez    for (i = 0;
10291a000857bb7eef298efa787699050884f92311feJaime Lopez         i < sizeof(_cdma_subscription_sources) / sizeof(_cdma_subscription_sources[0]);
10301a000857bb7eef298efa787699050884f92311feJaime Lopez         i++) {
10311a000857bb7eef298efa787699050884f92311feJaime Lopez        control_write( client, "    %s: %s\r\n",
10321a000857bb7eef298efa787699050884f92311feJaime Lopez                       _cdma_subscription_sources[i].name,
10331a000857bb7eef298efa787699050884f92311feJaime Lopez                       _cdma_subscription_sources[i].display );
10341a000857bb7eef298efa787699050884f92311feJaime Lopez    }
10351a000857bb7eef298efa787699050884f92311feJaime Lopez}
10361a000857bb7eef298efa787699050884f92311feJaime Lopez
10371a000857bb7eef298efa787699050884f92311feJaime Lopezstatic void
10381a000857bb7eef298efa787699050884f92311feJaime Lopezdescribe_subscription_source( ControlClient client )
10391a000857bb7eef298efa787699050884f92311feJaime Lopez{
10401a000857bb7eef298efa787699050884f92311feJaime Lopez    control_write( client,
10411a000857bb7eef298efa787699050884f92311feJaime Lopez                   "'cdma ssource <ssource>' allows you to specify where to read the subscription from\r\n" );
10421a000857bb7eef298efa787699050884f92311feJaime Lopez    dump_subscription_sources( client );
10431a000857bb7eef298efa787699050884f92311feJaime Lopez}
10441a000857bb7eef298efa787699050884f92311feJaime Lopez
10451a000857bb7eef298efa787699050884f92311feJaime Lopezstatic int
10461a000857bb7eef298efa787699050884f92311feJaime Lopezdo_cdma_ssource( ControlClient  client, char*  args )
10471a000857bb7eef298efa787699050884f92311feJaime Lopez{
10481a000857bb7eef298efa787699050884f92311feJaime Lopez    int nn;
10491a000857bb7eef298efa787699050884f92311feJaime Lopez    if (!args) {
10501a000857bb7eef298efa787699050884f92311feJaime Lopez        control_write( client, "KO: missing argument, try 'cdma ssource <source>'\r\n" );
10511a000857bb7eef298efa787699050884f92311feJaime Lopez        return -1;
10521a000857bb7eef298efa787699050884f92311feJaime Lopez    }
10531a000857bb7eef298efa787699050884f92311feJaime Lopez
10541a000857bb7eef298efa787699050884f92311feJaime Lopez    for (nn = 0; ; nn++) {
10551a000857bb7eef298efa787699050884f92311feJaime Lopez        const char*         name    = _cdma_subscription_sources[nn].name;
10561a000857bb7eef298efa787699050884f92311feJaime Lopez        ACdmaSubscriptionSource ssource = _cdma_subscription_sources[nn].source;
10571a000857bb7eef298efa787699050884f92311feJaime Lopez
10581a000857bb7eef298efa787699050884f92311feJaime Lopez        if (!name)
10591a000857bb7eef298efa787699050884f92311feJaime Lopez            break;
10601a000857bb7eef298efa787699050884f92311feJaime Lopez
10611a000857bb7eef298efa787699050884f92311feJaime Lopez        if (!strcasecmp( args, name )) {
10621a000857bb7eef298efa787699050884f92311feJaime Lopez            amodem_set_cdma_subscription_source( android_modem, ssource );
10631a000857bb7eef298efa787699050884f92311feJaime Lopez            return 0;
10641a000857bb7eef298efa787699050884f92311feJaime Lopez        }
10651a000857bb7eef298efa787699050884f92311feJaime Lopez    }
10661a000857bb7eef298efa787699050884f92311feJaime Lopez    control_write( client, "KO: Don't know source %s\r\n", args );
10671a000857bb7eef298efa787699050884f92311feJaime Lopez    return -1;
10681a000857bb7eef298efa787699050884f92311feJaime Lopez}
10691a000857bb7eef298efa787699050884f92311feJaime Lopez
10701a000857bb7eef298efa787699050884f92311feJaime Lopezstatic int
10711a000857bb7eef298efa787699050884f92311feJaime Lopezdo_cdma_prl_version( ControlClient client, char * args )
10721a000857bb7eef298efa787699050884f92311feJaime Lopez{
10731a000857bb7eef298efa787699050884f92311feJaime Lopez    int version = 0;
10741a000857bb7eef298efa787699050884f92311feJaime Lopez    char *endptr;
10751a000857bb7eef298efa787699050884f92311feJaime Lopez
10761a000857bb7eef298efa787699050884f92311feJaime Lopez    if (!args) {
10771a000857bb7eef298efa787699050884f92311feJaime Lopez        control_write( client, "KO: missing argument, try 'cdma prl_version <version>'\r\n");
10781a000857bb7eef298efa787699050884f92311feJaime Lopez        return -1;
10791a000857bb7eef298efa787699050884f92311feJaime Lopez    }
10801a000857bb7eef298efa787699050884f92311feJaime Lopez
10811a000857bb7eef298efa787699050884f92311feJaime Lopez    version = strtol(args, &endptr, 0);
10821a000857bb7eef298efa787699050884f92311feJaime Lopez    if (endptr != args) {
10831a000857bb7eef298efa787699050884f92311feJaime Lopez        amodem_set_cdma_prl_version( android_modem, version );
10841a000857bb7eef298efa787699050884f92311feJaime Lopez    }
108580bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    return 0;
10861a000857bb7eef298efa787699050884f92311feJaime Lopez}
10871a000857bb7eef298efa787699050884f92311feJaime Lopez/********************************************************************************************/
10881a000857bb7eef298efa787699050884f92311feJaime Lopez/********************************************************************************************/
10891a000857bb7eef298efa787699050884f92311feJaime Lopez/*****                                                                                 ******/
10908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                           G S M   M O D E M                                     ******/
10918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
10928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
10938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
10948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const struct {
10968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*         name;
10978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*         display;
10988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ARegistrationState  state;
10998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} _gsm_states[] = {
11008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "unregistered",  "no network available", A_REGISTRATION_UNREGISTERED },
11018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "home",          "on local network, non-roaming", A_REGISTRATION_HOME },
11028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "roaming",       "on roaming network", A_REGISTRATION_ROAMING },
11038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "searching",     "searching networks", A_REGISTRATION_SEARCHING },
11048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "denied",        "emergency calls only", A_REGISTRATION_DENIED },
11058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "off",           "same as 'unregistered'", A_REGISTRATION_UNREGISTERED },
11068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "on",            "same as 'home'", A_REGISTRATION_HOME },
11078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, A_REGISTRATION_UNREGISTERED }
11088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
11098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const char*
11118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_state_to_string( ARegistrationState  state )
11128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; _gsm_states[nn].name != NULL; nn++) {
11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (state == _gsm_states[nn].state)
11168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return _gsm_states[nn].name;
11178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return "<unknown>";
11198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_status( ControlClient  client, char*  args )
11238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: no argument required\r\n" );
11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_modem) {
11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: modem emulation not running\r\n" );
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "gsm voice state: %s\r\n",
11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   gsm_state_to_string(
11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       amodem_get_voice_registration(android_modem) ) );
11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "gsm data state:  %s\r\n",
11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   gsm_state_to_string(
11378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       amodem_get_data_registration(android_modem) ) );
11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecthelp_gsm_data( ControlClient  client )
11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client,
11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "the 'gsm data <state>' allows you to change the state of your GPRS connection\r\n"
11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "valid values for <state> are the following:\r\n\r\n" );
11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; ; nn++) {
11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         name    = _gsm_states[nn].name;
11518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         display = _gsm_states[nn].display;
11528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!name)
11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
11558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "  %-15s %s\r\n", name, display );
11578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "\r\n" );
11598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
11638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_data( ControlClient  client, char*  args )
11648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
11668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
11688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm data <state>'\r\n" );
11698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
11708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; ; nn++) {
11738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         name    = _gsm_states[nn].name;
11748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ARegistrationState  state   = _gsm_states[nn].state;
11758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!name)
11778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
11788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( !strcmp( args, name ) ) {
11808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!android_modem) {
11818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client, "KO: modem emulation not running\r\n" );
11828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return -1;
11838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
11848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            amodem_set_data_registration( android_modem, state );
11858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            qemu_net_disable = (state != A_REGISTRATION_HOME    &&
11868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                state != A_REGISTRATION_ROAMING );
11878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
11888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
11898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: bad GSM data state name, try 'help gsm data' for list of valid values\r\n" );
11918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
11928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
11958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecthelp_gsm_voice( ControlClient  client )
11968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
11988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client,
11998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "the 'gsm voice <state>' allows you to change the state of your GPRS connection\r\n"
12008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "valid values for <state> are the following:\r\n\r\n" );
12018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; ; nn++) {
12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         name    = _gsm_states[nn].name;
12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         display = _gsm_states[nn].display;
12048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!name)
12068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
12078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "  %-15s %s\r\n", name, display );
12098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "\r\n" );
12118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
12158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_voice( ControlClient  client, char*  args )
12168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
12188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
12208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm voice <state>'\r\n" );
12218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; ; nn++) {
12258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         name    = _gsm_states[nn].name;
12268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ARegistrationState  state   = _gsm_states[nn].state;
12278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!name)
12298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
12308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( !strcmp( args, name ) ) {
12328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!android_modem) {
12338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client, "KO: modem emulation not running\r\n" );
12348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return -1;
12358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
12368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            amodem_set_voice_registration( android_modem, state );
12378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
12388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
12398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: bad GSM data state name, try 'help gsm voice' for list of valid values\r\n" );
12418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
12428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
12468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_check_number( char*  args )
12478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
12498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; args[nn] != 0; nn++) {
12518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = args[nn];
12528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( !isdigit(c) && c != '+' && c != '#' ) {
12538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
12548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
12558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (nn == 0)
12578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
12608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
12638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_call( ControlClient  client, char*  args )
12648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* check that we have a phone number made of digits */
12668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
12678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm call <phonenumber>'\r\n" );
12688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (gsm_check_number(args)) {
12728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: bad phone number format, use digits, # and + only\r\n" );
12738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_modem) {
12778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: modem emulation not running\r\n" );
12788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    amodem_add_inbound_call( android_modem, args );
12818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
12828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
12858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_cancel( ControlClient  client, char*  args )
12868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
12888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm call <phonenumber>'\r\n" );
12898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (gsm_check_number(args)) {
12928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: bad phone number format, use digits, # and + only\r\n" );
12938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_modem) {
12968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: modem emulation not running\r\n" );
12978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( amodem_disconnect_call( android_modem, args ) < 0 ) {
13008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: could not cancel this number\r\n" );
13018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
13048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const char*
13088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcall_state_to_string( ACallState  state )
13098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (state) {
13118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case A_CALL_ACTIVE:   return "active";
13128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case A_CALL_HELD:     return "held";
13138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case A_CALL_ALERTING: return "ringing";
13148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case A_CALL_WAITING:  return "waiting";
13158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case A_CALL_INCOMING: return "incoming";
13168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default: return "unknown";
13178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
13218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_list( ControlClient  client, char*  args )
13228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* check that we have a phone number made of digits */
13248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   count = amodem_get_call_count( android_modem );
13258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   nn;
13268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < count; nn++) {
13278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ACall        call = amodem_get_call( android_modem, nn );
13288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*  dir;
13298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (call == NULL)
13318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            continue;
13328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (call->dir == A_CALL_OUTBOUND)
13348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dir = "outbound to ";
13358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         else
13368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dir = "inbound from";
13378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "%s %-10s : %s\r\n", dir,
13398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       call->number, call_state_to_string(call->state) );
13408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
13428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
13458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_busy( ControlClient  client, char*  args )
13468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ACall  call;
13488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
13508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm busy <phonenumber>'\r\n" );
13518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    call = amodem_find_call_by_number( android_modem, args );
13548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (call == NULL || call->dir != A_CALL_OUTBOUND) {
13558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: no current outbound call to number '%s' (call %p)\r\n", args, call );
13568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( amodem_disconnect_call( android_modem, args ) < 0 ) {
13598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: could not cancel this number\r\n" );
13608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
13638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
13668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_hold( ControlClient  client, char*  args )
13678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ACall  call;
13698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
13718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm out hold <phonenumber>'\r\n" );
13728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    call = amodem_find_call_by_number( android_modem, args );
13758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (call == NULL) {
13768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: no current call to/from number '%s'\r\n", args );
13778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( amodem_update_call( android_modem, args, A_CALL_HELD ) < 0 ) {
13808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: could put this call on hold\r\n" );
13818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
13848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
13888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_accept( ControlClient  client, char*  args )
13898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ACall  call;
13918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
13938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm accept <phonenumber>'\r\n" );
13948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    call = amodem_find_call_by_number( android_modem, args );
13978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (call == NULL) {
13988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: no current call to/from number '%s'\r\n", args );
13998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( amodem_update_call( android_modem, args, A_CALL_ACTIVE ) < 0 ) {
14028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: could not activate this call\r\n" );
14038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
14068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14084c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstockstatic int
14094c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstockdo_gsm_signal( ControlClient  client, char*  args )
14104c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock{
14114c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      enum { SIGNAL_RSSI = 0, SIGNAL_BER, NUM_SIGNAL_PARAMS };
14124c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      char*   p = args;
14134c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      int     top_param = -1;
14144c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      int     params[ NUM_SIGNAL_PARAMS ];
14154c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14164c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      static  int  last_ber = 99;
14174c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14184c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      if (!p)
14194c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          p = "";
14204c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14214c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      /* tokenize */
14224c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      while (*p) {
14234c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          char*   end;
14244c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          int  val = strtol( p, &end, 10 );
14254c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14264c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          if (end == p) {
14274c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock              control_write( client, "KO: argument '%s' is not a number\n", p );
14284c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock              return -1;
14294c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          }
14304c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14314c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          params[++top_param] = val;
14324c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          if (top_param + 1 == NUM_SIGNAL_PARAMS)
14334c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock              break;
14344c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14354c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          p = end;
14364c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          while (*p && (p[0] == ' ' || p[0] == '\t'))
14374c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock              p += 1;
14384c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      }
14394c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14404c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      /* sanity check */
14414c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      if (top_param < SIGNAL_RSSI) {
14424c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          control_write( client, "KO: not enough arguments: see 'help gsm signal' for details\r\n" );
14434c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          return -1;
14444c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      }
14454c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14464c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      int rssi = params[SIGNAL_RSSI];
14474c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      if ((rssi < 0 || rssi > 31) && rssi != 99) {
14484c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          control_write( client, "KO: invalid RSSI - must be 0..31 or 99\r\n");
14494c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          return -1;
14504c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      }
14514c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14524c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      /* check ber is 0..7 or 99 */
14534c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      if (top_param >= SIGNAL_BER) {
14544c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          int ber = params[SIGNAL_BER];
14554c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          if ((ber < 0 || ber > 7) && ber != 99) {
14564c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock              control_write( client, "KO: invalid BER - must be 0..7 or 99\r\n");
14574c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock              return -1;
14584c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          }
14594c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          last_ber = ber;
14604c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      }
14614c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14624c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      amodem_set_signal_strength( android_modem, rssi, last_ber );
14634c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14644c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      return 0;
14654c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock  }
14664c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
14698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  gsm_in_commands[] =
14708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "new", "create a new 'waiting' inbound call",
14728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm in create <phonenumber>' creates a new inbound phone call, placed in\r\n"
14738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "the 'waiting' state by default, until the system answers/holds/closes it\r\n", NULL
14748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_in_create, NULL },
14758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "hold", "change the state of an oubtound call to 'held'",
14778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "change the state of an outbound call to 'held'. this is only possible\r\n"
14788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "if the call in the 'waiting' or 'active' state\r\n", NULL,
14798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_out_hold, NULL },
14808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "accept", "change the state of an outbound call to 'active'",
14828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "change the state of an outbound call to 'active'. this is only possible\r\n"
14838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "if the call is in the 'waiting' or 'held' state\r\n", NULL,
14848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_out_accept, NULL },
14858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
14878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
14888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
14898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14911a000857bb7eef298efa787699050884f92311feJaime Lopezstatic const CommandDefRec  cdma_commands[] =
14921a000857bb7eef298efa787699050884f92311feJaime Lopez{
14931a000857bb7eef298efa787699050884f92311feJaime Lopez    { "ssource", "Set the current CDMA subscription source",
14941a000857bb7eef298efa787699050884f92311feJaime Lopez      NULL, describe_subscription_source,
14951a000857bb7eef298efa787699050884f92311feJaime Lopez      do_cdma_ssource, NULL },
149680bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    { "prl_version", "Dump the current PRL version",
149780bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner      NULL, NULL,
149880bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner      do_cdma_prl_version, NULL },
14991a000857bb7eef298efa787699050884f92311feJaime Lopez};
15001a000857bb7eef298efa787699050884f92311feJaime Lopez
15018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  gsm_commands[] =
15028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "list", "list current phone calls",
15048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm list' lists all inbound and outbound calls and their state\r\n", NULL,
15058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_list, NULL },
15068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "call", "create inbound phone call",
15088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm call <phonenumber>' allows you to simulate a new inbound call\r\n", NULL,
15098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_call, NULL },
15108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "busy", "close waiting outbound call as busy",
15128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm busy <remoteNumber>' closes an outbound call, reporting\r\n"
15138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "the remote phone as busy. only possible if the call is 'waiting'.\r\n", NULL,
15148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_busy, NULL },
15158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "hold", "change the state of an oubtound call to 'held'",
15178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm hold <remoteNumber>' change the state of a call to 'held'. this is only possible\r\n"
15188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "if the call in the 'waiting' or 'active' state\r\n", NULL,
15198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_hold, NULL },
15208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "accept", "change the state of an outbound call to 'active'",
15228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm accept <remoteNumber>' change the state of a call to 'active'. this is only possible\r\n"
15238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "if the call is in the 'waiting' or 'held' state\r\n", NULL,
15248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_accept, NULL },
15258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "cancel", "disconnect an inbound or outbound phone call",
15278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm cancel <phonenumber>' allows you to simulate the end of an inbound or outbound call\r\n", NULL,
15288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_cancel, NULL },
15298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "data", "modify data connection state", NULL, help_gsm_data,
15318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_data, NULL },
15328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "voice", "modify voice connection state", NULL, help_gsm_voice,
15348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_voice, NULL },
15358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "status", "display GSM status",
15378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm status' displays the current state of the GSM emulation\r\n", NULL,
15388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_status, NULL },
15398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15404c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock    { "signal", "set sets the rssi and ber",
15414c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock    "'gsm signal <rssi> [<ber>]' changes the reported strength and error rate on next (15s) update.\r\n"
15424c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock    "rssi range is 0..31 and 99 for unknown\r\n"
15434c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock    "ber range is 0..7 percent and 99 for unknown\r\n",
15444c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock    NULL, do_gsm_signal, NULL },
15454c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
15468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
15478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
15488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
15508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
15518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
15528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                           S M S   C O M M A N D                                 ******/
15538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
15548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
15558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
15568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
15588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_sms_send( ControlClient  client, char*  args )
15598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*          p;
15618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int            textlen;
15628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsAddressRec  sender;
15638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsPDU*        pdus;
15648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int            nn;
15658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* check that we have a phone number made of digits */
15678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
15688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    MissingArgument:
15698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'sms send <phonenumber> <text message>'\r\n" );
15708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
15718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = strchr( args, ' ' );
15738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!p) {
15748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto MissingArgument;
15758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( sms_address_from_str( &sender, args, p - args ) < 0 ) {
15788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: bad phone number format, must be [+](0-9)*\r\n" );
15798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
15808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* un-secape message text into proper utf-8 (conversion happens in-site) */
15848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p      += 1;
15858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    textlen = strlen(p);
15868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    textlen = sms_utf8_from_message_str( p, textlen, (unsigned char*)p, textlen );
15878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (textlen < 0) {
15888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "message must be utf8 and can use the following escapes:\r\n"
15898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\n      for a newline\r\n"
15908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\xNN    where NN are two hexadecimal numbers\r\n"
15918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\uNNNN  where NNNN are four hexadecimal numbers\r\n"
15928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\\\     to send a '\\' character\r\n\r\n"
15938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    anything else is an error\r\n"
15948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "KO: badly formatted text\r\n" );
15958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
15968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_modem) {
15998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: modem emulation not running\r\n" );
16008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
16018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* create a list of SMS PDUs, then send them */
16048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pdus = smspdu_create_deliver_utf8( (cbytes_t)p, textlen, &sender, NULL );
16058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (pdus == NULL) {
16068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: internal error when creating SMS-DELIVER PDUs\n" );
16078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
16088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; pdus[nn] != NULL; nn++)
16118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        amodem_receive_sms( android_modem, pdus[nn] );
16128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    smspdu_free_list( pdus );
16148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
16158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
16188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_sms_sendpdu( ControlClient  client, char*  args )
16198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsPDU  pdu;
16218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* check that we have a phone number made of digits */
16238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
16248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'sms sendpdu <hexstring>'\r\n" );
16258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
16268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_modem) {
16298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: modem emulation not running\r\n" );
16308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
16318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pdu = smspdu_create_from_hex( args, strlen(args) );
16348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (pdu == NULL) {
16358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: badly formatted <hexstring>\r\n" );
16368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
16378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    amodem_receive_sms( android_modem, pdu );
16408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    smspdu_free( pdu );
16418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
16428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  sms_commands[] =
16458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "send", "send inbound SMS text message",
16478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'sms send <phonenumber> <message>' allows you to simulate a new inbound sms message\r\n", NULL,
16488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_sms_send, NULL },
16498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "pdu", "send inbound SMS PDU",
16518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'sms pdu <hexstring>' allows you to simulate a new inbound sms PDU\r\n"
16528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "(used internally when one emulator sends SMS messages to another instance).\r\n"
16538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "you probably don't want to play with this at all\r\n", NULL,
16548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_sms_sendpdu, NULL },
16558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
16578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
16588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
16608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_control_write(void* data, const char* string)
16618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write((ControlClient)data, string);
16638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
16668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_power_display( ControlClient client, char*  args )
16678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    goldfish_battery_display(do_control_write, client);
16698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
16708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
16738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_ac_state( ControlClient  client, char*  args )
16748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
16768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "on") == 0) {
16778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(1, POWER_SUPPLY_PROP_ONLINE, 1);
16788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "off") == 0) {
16818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(1, POWER_SUPPLY_PROP_ONLINE, 0);
16828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: Usage: \"ac on\" or \"ac off\"\n" );
16878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
16888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
16918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_battery_status( ControlClient  client, char*  args )
16928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
16948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "unknown") == 0) {
16958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_UNKNOWN);
16968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "charging") == 0) {
16998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_CHARGING);
17008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "discharging") == 0) {
17038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_DISCHARGING);
17048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "not-charging") == 0) {
17078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_NOT_CHARGING);
17088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "full") == 0) {
17118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_FULL);
17128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: Usage: \"status unknown|charging|discharging|not-charging|full\"\n" );
17178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
17188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
17218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_battery_present( ControlClient  client, char*  args )
17228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
17248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "true") == 0) {
17258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_PRESENT, 1);
17268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "false") == 0) {
17298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_PRESENT, 0);
17308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: Usage: \"present true\" or \"present false\"\n" );
17358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
17368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
17398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_battery_health( ControlClient  client, char*  args )
17408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
17428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "unknown") == 0) {
17438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_UNKNOWN);
17448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "good") == 0) {
17478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_GOOD);
17488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "overheat") == 0) {
17518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_OVERHEAT);
17528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "dead") == 0) {
17558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_DEAD);
17568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "overvoltage") == 0) {
17598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_OVERVOLTAGE);
17608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "failure") == 0) {
17638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_UNSPEC_FAILURE);
17648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: Usage: \"health unknown|good|overheat|dead|overvoltage|failure\"\n" );
17698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
17708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
17738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_battery_capacity( ControlClient  client, char*  args )
17748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
17768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int capacity;
17778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (sscanf(args, "%d", &capacity) == 1 && capacity >= 0 && capacity <= 100) {
17798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_CAPACITY, capacity);
17808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: Usage: \"capacity <percentage>\"\n" );
17858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
17868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  power_commands[] =
17908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "display", "display battery and charger state",
17928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "display battery and charger state\r\n", NULL,
17938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_power_display, NULL },
17948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "ac", "set AC charging state",
17968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'ac on|off' allows you to set the AC charging state to on or off\r\n", NULL,
17978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_ac_state, NULL },
17988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "status", "set battery status",
18008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'status unknown|charging|discharging|not-charging|full' allows you to set battery status\r\n", NULL,
18018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_battery_status, NULL },
18028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "present", "set battery present state",
18048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'present true|false' allows you to set battery present state to true or false\r\n", NULL,
18058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_battery_present, NULL },
18068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "health", "set battery health state",
18088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'health unknown|good|overheat|dead|overvoltage|failure' allows you to set battery health state\r\n", NULL,
18098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_battery_health, NULL },
18108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "capacity", "set battery capacity state",
18128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'capacity <percentage>' allows you to set battery capacity to a value 0 - 100\r\n", NULL,
18138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_battery_capacity, NULL },
18148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
18168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
18178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
18198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
18208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
18218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                         E  V  E  N  T   C O M M A N D S                         ******/
18228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
18238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
18248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
18258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
18288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_event_send( ControlClient  client, char*  args )
18298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*   p;
18318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
18338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: Usage: event send <type>:<code>:<value> ...\r\n" );
18348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
18358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = args;
18388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (*p) {
18398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char*  q;
18408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int    type, code, value, ret;
18418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p += strspn( args, " \t" );  /* skip spaces */
18438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (*p == 0)
18448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        q  = p + strcspn( p, " \t" );
18478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (q == p)
18498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ret = android_event_from_str( p, &type, &code, &value );
18528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ret < 0) {
18538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (ret == -1) {
18548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client,
18558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               "KO: invalid event type in '%.*s', try 'event list types' for valid values\r\n",
18568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               q-p, p );
18578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else if (ret == -2) {
18588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client,
18598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               "KO: invalid event code in '%.*s', try 'event list codes <type>' for valid values\r\n",
18608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               q-p, p );
18618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            } else {
18628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client,
18638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               "KO: invalid event value in '%.*s', must be an integer\r\n",
18648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                               q-p, p);
18658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
18668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
18678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
18688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
186934f2974ce7ec7c71beb47b5daf9089d5c8c40c79David 'Digit' Turner        user_event_generic( type, code, value );
18708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = q;
18718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
18738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
18768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_event_types( ControlClient  client, char*  args )
18778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  count = android_event_get_type_count();
18798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
18808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "event <type> can be an integer or one of the following aliases\r\n" );
18828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < count; nn++) {
18838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char  tmp[16];
18848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char* p = tmp;
18858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char* end = p + sizeof(tmp);
18868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int   count2 = android_event_get_code_count( nn );;
18878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = android_event_bufprint_type_str( p, end, nn );
18898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "    %-8s", tmp );
18918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (count2 > 0)
18928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "  (%d code aliases)", count2 );
18938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "\r\n" );
18958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
18978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
19008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_event_codes( ControlClient  client, char*  args )
19018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
19028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  count;
19038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn, type, dummy;
19048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
19068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: argument missing, try 'event codes <type>'\r\n" );
19078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
19088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( android_event_from_str( args, &type, &dummy, &dummy ) < 0 ) {
19118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: bad argument, see 'event types' for valid values\r\n" );
19128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
19138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    count = android_event_get_code_count( type );
19168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (count == 0) {
19178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "no code aliases defined for this type\r\n" );
19188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
19198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "type '%s' accepts the following <code> aliases:\r\n",
19208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       args );
19218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; nn < count; nn++) {
19228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            char  temp[20], *p = temp, *end = p + sizeof(temp);
19238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            android_event_bufprint_code_str( p, end, type, nn );
19248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "    %-12s\r\n", temp );
19258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
19268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
19298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
19308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic __inline__ int
19328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectutf8_next( unsigned char* *pp, unsigned char*  end )
19338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
19348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned char*  p      = *pp;
19358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int             result = -1;
19368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (p < end) {
19388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c= *p++;
19398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c >= 128) {
19408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ((c & 0xe0) == 0xc0)
19418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c &= 0x1f;
19428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else if ((c & 0xf0) == 0xe0)
19438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c &= 0x0f;
19448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
19458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c &= 0x07;
19468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            while (p < end && (p[0] & 0xc0) == 0x80) {
19488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                c = (c << 6) | (p[0] & 0x3f);
19498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
19508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
19518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result = c;
19528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *pp    = p;
19538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
19558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
19568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
19588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_event_text( ControlClient  client, char*  args )
19598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
196071bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine    AKeycodeBuffer keycodes;
19618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned char*  p   = (unsigned char*) args;
19628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned char*  end = p + strlen(args);
19638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int             textlen;
196471bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine    const AKeyCharmap* charmap;
19658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
19678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: argument missing, try 'event text <message>'\r\n" );
19688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
19698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
197071bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine
197171bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine    /* Get default charmap. */
197243552dc4fa64aad0c9fdb8f4c92ae7ac79406596Vladimir Chtchetkine    charmap = android_get_default_charmap();
197371bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine    if (charmap == NULL) {
197471bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine        control_write( client, "KO: no character map active in current device layout/config\r\n" );
19758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
19768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
197871bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine    keycodes.keycode_count = 0;
197971bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine
19808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* un-secape message text into proper utf-8 (conversion happens in-site) */
19818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    textlen = strlen((char*)p);
19828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    textlen = sms_utf8_from_message_str( args, textlen, (unsigned char*)p, textlen );
19838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (textlen < 0) {
19848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "message must be utf8 and can use the following escapes:\r\n"
19858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\n      for a newline\r\n"
19868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\xNN    where NN are two hexadecimal numbers\r\n"
19878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\uNNNN  where NNNN are four hexadecimal numbers\r\n"
19888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\\\     to send a '\\' character\r\n\r\n"
19898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    anything else is an error\r\n"
19908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "KO: badly formatted text\r\n" );
19918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
19928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
19938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    end = p + textlen;
19958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (p < end) {
19968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = utf8_next( &p, end );
19978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c <= 0)
19988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
200071bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine        android_charmap_reverse_map_unicode( NULL, (unsigned)c, 1, &keycodes );
200171bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine        android_charmap_reverse_map_unicode( NULL, (unsigned)c, 0, &keycodes );
200271bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine        android_keycodes_flush( &keycodes );
20038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
20048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
20068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
20078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  event_commands[] =
20098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
20108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "send", "send a series of events to the kernel",
20118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'event send <type>:<code>:<value> ...' allows your to send one or more hardware events\r\n"
20128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "to the Android kernel. you can use text names or integers for <type> and <code>\r\n", NULL,
20138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_event_send, NULL },
20148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "types", "list all <type> aliases",
20168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'event types' list all <type> string aliases supported by the 'event' subcommands\r\n",
20178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_event_types, NULL },
20188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "codes", "list all <code> aliases for a given <type>",
20208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'event codes <type>' lists all <code> string aliases for a given event <type>\r\n",
20218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_event_codes, NULL },
20228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "text", "simulate keystrokes from a given text",
20248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'event text <message>' allows you to simulate keypresses to generate a given text\r\n"
20258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "message. <message> must be an utf-8 string. Unicode points will be reverse-mapped\r\n"
20268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "according to the current device keyboard. unsupported characters will be discarded\r\n"
20278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "silently\r\n", NULL, do_event_text, NULL },
20288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
20308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
20318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20322ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije#if CONFIG_ANDROID_SNAPSHOTS
20332ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20342ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20352ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/********************************************************************************************/
20362ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/********************************************************************************************/
20372ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/*****                                                                                 ******/
20382ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/*****                      S N A P S H O T   C O M M A N D S                          ******/
20392ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/*****                                                                                 ******/
20402ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/********************************************************************************************/
20412ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/********************************************************************************************/
20422ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20432ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int
20442ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijecontrol_write_out_cb(void* opaque, const char* fmt, va_list ap)
20452ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
20462ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ControlClient client = opaque;
20472ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    int ret = control_vwrite(client, fmt, ap);
20482ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret;
20492ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
20502ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20512ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int
20522ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijecontrol_write_err_cb(void* opaque, const char* fmt, va_list ap)
20532ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
20542ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    int ret = 0;
20552ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ControlClient client = opaque;
20562ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ret += control_write(client, "KO: ");
20572ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ret += control_vwrite(client, fmt, ap);
20582ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret;
20592ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
20602ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20612ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int
20622ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijedo_snapshot_list( ControlClient  client, char*  args )
20632ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
20642ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    int ret;
20652ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    OutputChannel *out = output_channel_alloc(client, control_write_out_cb);
20662ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    OutputChannel *err = output_channel_alloc(client, control_write_err_cb);
20672ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    do_info_snapshots_oc(out, err);
20682ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ret = output_channel_written(err);
20692ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    output_channel_free(out);
20702ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    output_channel_free(err);
20712ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20722ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret > 0;
20732ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
20742ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20752ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int
20762ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijedo_snapshot_save( ControlClient  client, char*  args )
20772ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
20782ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    int ret;
20792ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    OutputChannel *err = output_channel_alloc(client, control_write_err_cb);
20802ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    do_savevm_oc(err, args);
20812ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ret = output_channel_written(err);
20822ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    output_channel_free(err);
20832ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20842ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret > 0; // no output on error channel indicates success
20852ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
20862ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20872ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int
20882ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijedo_snapshot_load( ControlClient  client, char*  args )
20892ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
20902ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    int ret;
20912ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    OutputChannel *err = output_channel_alloc(client, control_write_err_cb);
20922ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    do_loadvm_oc(err, args);
20932ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ret = output_channel_written(err);
20942ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    output_channel_free(err);
20952ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20962ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret > 0;
20972ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
20982ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20992ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int
21002ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijedo_snapshot_del( ControlClient  client, char*  args )
21012ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
21022ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    int ret;
21032ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    OutputChannel *err = output_channel_alloc(client, control_write_err_cb);
21042ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    do_delvm_oc(err, args);
21052ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ret = output_channel_written(err);
21062ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    output_channel_free(err);
21072ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
21082ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret > 0;
21092ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
21102ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
21112ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic const CommandDefRec  snapshot_commands[] =
21122ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
21132ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { "list", "list available state snapshots",
21142ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "'avd snapshot list' will show a list of all state snapshots that can be loaded\r\n",
21152ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    NULL, do_snapshot_list, NULL },
21162ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
21172ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { "save", "save state snapshot",
21182ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "'avd snapshot save <name>' will save the current (run-time) state to a snapshot with the given name\r\n",
21192ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    NULL, do_snapshot_save, NULL },
21202ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
21212ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { "load", "load state snapshot",
21222ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "'avd snapshot load <name>' will load the state snapshot of the given name\r\n",
21232ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    NULL, do_snapshot_load, NULL },
21242ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
21252ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { "del", "delete state snapshot",
21262ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "'avd snapshot del <name>' will delete the state snapshot with the given name\r\n",
21272ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    NULL, do_snapshot_del, NULL },
21282ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
21292ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { NULL, NULL, NULL, NULL, NULL, NULL }
21302ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije};
21312ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
21322ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
21332ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije#endif
21342ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
21358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
21378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
21388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
21398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                               V M   C O M M A N D S                             ******/
21408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
21418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
21428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
21438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
21458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_avd_stop( ControlClient  client, char*  args )
21468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
21478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!vm_running) {
21488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: virtual device already stopped\r\n" );
21498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
21508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
21518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    vm_stop(EXCP_INTERRUPT);
21528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
21538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
21548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
21568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_avd_start( ControlClient  client, char*  args )
21578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
21588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (vm_running) {
21598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: virtual device already running\r\n" );
21608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
21618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
21628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    vm_start();
21638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
21648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
21658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
21678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_avd_status( ControlClient  client, char*  args )
21688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
21698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "virtual device is %s\r\n", vm_running ? "running" : "stopped" );
21708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
21718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
21728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
21748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_avd_name( ControlClient  client, char*  args )
21758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
217690c6235ce7bdc6f7afbcfe56ea6f2c3d2b128447Vladimir Chtchetkine    control_write( client, "%s\r\n", android_op_avd_name);
21778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
21788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
21798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  vm_commands[] =
21818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
21828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "stop", "stop the virtual device",
21838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'avd stop' stops the virtual device immediately, use 'avd start' to continue execution\r\n",
21848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_avd_stop, NULL },
21858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "start", "start/restart the virtual device",
21878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'avd start' will start or continue the virtual device, use 'avd stop' to stop it\r\n",
21888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_avd_start, NULL },
21898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "status", "query virtual device status",
21912ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "'avd status' will indicate whether the virtual device is running or not\r\n",
21928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_avd_status, NULL },
21938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "name", "query virtual device name",
21958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'avd name' will return the name of this virtual device\r\n",
21968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_avd_name, NULL },
21978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21982ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije#if CONFIG_ANDROID_SNAPSHOTS
21992ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { "snapshot", "state snapshot commands",
22002ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "allows you to save and restore the virtual device state in snapshots\r\n",
22012ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    NULL, NULL, snapshot_commands },
22022ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije#endif
22032ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
22048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
22058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
22068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
22088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
22098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
22108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                             G E O   C O M M A N D S                             ******/
22118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
22128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
22138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
22148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
22168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_geo_nmea( ControlClient  client, char*  args )
22178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
22188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
22198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: NMEA sentence missing, try 'help geo nmea'\r\n" );
22208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
22218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
22228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_gps_cs) {
22238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: no GPS emulation in this virtual device\r\n" );
22248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
22258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
22268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    android_gps_send_nmea( args );
22278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
22288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
22298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
22318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_geo_fix( ControlClient  client, char*  args )
22328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
22334afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock    // GEO_SAT2 provides bug backwards compatibility.
22344afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock    enum { GEO_LONG = 0, GEO_LAT, GEO_ALT, GEO_SAT, GEO_SAT2, NUM_GEO_PARAMS };
22358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*   p = args;
22364afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock    int     top_param = -1;
22374afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock    double  params[ NUM_GEO_PARAMS ];
2238657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner    int     n_satellites = 1;
22398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static  int     last_time = 0;
22418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static  double  last_altitude = 0.;
22428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!p)
22448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = "";
22458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* tokenize */
22478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (*p) {
22488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char*   end;
22498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        double  val = strtod( p, &end );
22508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (end == p) {
22528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "KO: argument '%s' is not a number\n", p );
22538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
22548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
22558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22564afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock        params[++top_param] = val;
22574afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock        if (top_param + 1 == NUM_GEO_PARAMS)
22588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = end;
22618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (*p && (p[0] == ' ' || p[0] == '\t'))
22628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p += 1;
22638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
22648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* sanity check */
22664afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock    if (top_param < GEO_LAT) {
22678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: not enough arguments: see 'help geo fix' for details\r\n" );
22688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
22698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
22708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22714afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock    /* check number of satellites, must be integer between 1 and 12 */
22724afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock    if (top_param >= GEO_SAT) {
22734afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock        int sat_index = (top_param >= GEO_SAT2) ? GEO_SAT2 : GEO_SAT;
22744afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock        n_satellites = (int) params[sat_index];
22754afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock        if (n_satellites != params[sat_index]
22764afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock            || n_satellites < 1 || n_satellites > 12) {
2277657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner            control_write( client, "KO: invalid number of satellites. Must be an integer between 1 and 12\r\n");
2278657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner            return -1;
2279657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        }
2280657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner    }
2281657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner
22828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* generate an NMEA sentence for this fix */
22838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
22848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        STRALLOC_DEFINE(s);
22858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        double   val;
22868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int      deg, min;
22878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char     hemi;
22888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2289657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        /* format overview:
2290657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    time of fix      123519     12:35:19 UTC
2291657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    latitude         4807.038   48 degrees, 07.038 minutes
2292657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    north/south      N or S
2293657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    longitude        01131.000  11 degrees, 31. minutes
2294657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    east/west        E or W
2295657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    fix quality      1          standard GPS fix
2296657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    satellites       1 to 12    number of satellites being tracked
2297657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    HDOP             <dontcare> horizontal dilution
2298657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    altitude         546.       altitude above sea-level
2299657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    altitude units   M          to indicate meters
2300657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    diff             <dontcare> height of sea-level above ellipsoid
2301657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    diff units       M          to indicate meters (should be <dontcare>)
2302657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    dgps age         <dontcare> time in seconds since last DGPS fix
2303657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    dgps sid         <dontcare> DGPS station id
2304657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         */
2305657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner
23068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* first, the time */
23078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stralloc_add_format( s, "$GPGGA,%06d", last_time );
23088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        last_time ++;
23098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* then the latitude */
23118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hemi = 'N';
23124afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock        val  = params[GEO_LAT];
23138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (val < 0) {
23148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            hemi = 'S';
23158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val  = -val;
23168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
23178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        deg = (int) val;
2318657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        val = 60*(val - deg);
2319657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        min = (int) val;
2320631f2555ed2b50a07ea19eaefa495a028ab1991aDavid 'Digit' Turner        val = 10000*(val - min);
2321657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        stralloc_add_format( s, ",%02d%02d.%04d,%c", deg, min, (int)val, hemi );
23228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* the longitude */
23248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hemi = 'E';
23254afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock        val  = params[GEO_LONG];
23268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (val < 0) {
23278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            hemi = 'W';
23288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val  = -val;
23298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
23308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        deg = (int) val;
2331657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        val = 60*(val - deg);
2332657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        min = (int) val;
2333631f2555ed2b50a07ea19eaefa495a028ab1991aDavid 'Digit' Turner        val = 10000*(val - min);
2334657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        stralloc_add_format( s, ",%02d%02d.%04d,%c", deg, min, (int)val, hemi );
23358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2336657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        /* bogus fix quality, satellite count and dilution */
2337657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        stralloc_add_format( s, ",1,%02d,", n_satellites );
23388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2339657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        /* optional altitude + bogus diff */
23404afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock        if (top_param >= GEO_ALT) {
23414afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock            stralloc_add_format( s, ",%.1g,M,0.,M", params[GEO_ALT] );
23424afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock            last_altitude = params[GEO_ALT];
23438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
2344657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner            stralloc_add_str( s, ",,,," );
23458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
23468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* bogus rest and checksum */
23478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stralloc_add_str( s, ",,,*47" );
23488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* send it, then free */
23508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        android_gps_send_nmea( stralloc_cstr(s) );
23518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stralloc_reset( s );
23528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
23538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
23548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  geo_commands[] =
23578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "nmea", "send an GPS NMEA sentence",
23598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'geo nema <sentence>' sends a NMEA 0183 sentence to the emulated device, as\r\n"
23608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "if it came from an emulated GPS modem. <sentence> must begin with '$GP'. only\r\n"
23618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'$GPGGA' and '$GPRCM' sentences are supported at the moment.\r\n",
23628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_geo_nmea, NULL },
23638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "fix", "send a simple GPS fix",
23654afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock    "'geo fix <longitude> <latitude> [<altitude> [<satellites>]]'\r\n"
23664afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock    " allows you to send a simple GPS fix to the emulated system.\r\n"
23674afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock    " The parameters are:\r\n\r\n"
23688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "  <longitude>   longitude, in decimal degrees\r\n"
23698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "  <latitude>    latitude, in decimal degrees\r\n"
23708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "  <altitude>    optional altitude in meters\r\n"
2371657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner    "  <satellites>  number of satellites being tracked (1-12)\r\n"
23728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "\r\n",
23738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_geo_fix, NULL },
23748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
23768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
23778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
23808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
23818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
23828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                           M A I N   C O M M A N D S                             ******/
23838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
23848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
23858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
23868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
23888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_window_scale( ControlClient  client, char*  args )
23898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    double  scale;
23918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int     is_dpi = 0;
23928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*   end;
23938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
23958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: argument missing, try 'window scale <scale>'\r\n" );
23968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
23978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
23988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    scale = strtol( args, &end, 10 );
24008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (end > args && !memcmp( end, "dpi", 4 )) {
24018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        is_dpi = 1;
24028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
24048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        scale = strtod( args, &end );
24058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (end == args || end[0]) {
24068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "KO: argument <scale> must be a real number, or an integer followed by 'dpi'\r\n" );
24078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
24088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
24098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
24108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24112fa5173bd1ce7341c50adac676a317945f0969c7Vladimir Chtchetkine    android_ui_set_window_scale( scale, is_dpi );
24128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
24138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
24148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  window_commands[] =
24168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
24178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "scale", "change the window scale",
24188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'window scale <scale>' allows you to change the scale of the emulator window at runtime\r\n"
24198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "<scale> must be either a real number between 0.1 and 3.0, or an integer followed by\r\n"
24208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "the 'dpi' prefix (as in '120dpi')\r\n",
24218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_window_scale, NULL },
24228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
24248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
24258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
24278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
24288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
2429e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/*****                           Q E M U   C O M M A N D S                             ******/
2430e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/*****                                                                                 ******/
2431e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/********************************************************************************************/
2432e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/********************************************************************************************/
2433e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2434e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnerstatic int
2435e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnerdo_qemu_monitor( ControlClient client, char* args )
2436e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner{
2437e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    char             socketname[32];
2438e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    int              fd;
2439e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    CharDriverState* cs;
2440e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2441e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    if (args != NULL) {
2442e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner        control_write( client, "KO: no argument for 'qemu monitor'\r\n" );
2443e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner        return -1;
2444e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    }
2445e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    /* Detach the client socket, and re-attach it to a monitor */
2446e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    fd = control_client_detach(client);
2447e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    snprintf(socketname, sizeof socketname, "tcp:socket=%d", fd);
2448e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    cs = qemu_chr_open("monitor", socketname, NULL);
2449e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    if (cs == NULL) {
2450e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner        control_client_reattach(client, fd);
2451e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner        control_write( client, "KO: internal error: could not detach from console !\r\n" );
2452e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner        return -1;
2453e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    }
2454e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    monitor_init(cs, MONITOR_USE_READLINE|MONITOR_QUIT_DOESNT_EXIT);
2455e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    control_client_destroy(client);
2456e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    return 0;
2457e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner}
2458e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2459e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#ifdef CONFIG_STANDALONE_CORE
2460d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine/* UI settings, passed to the core via -ui-settings command line parameter. */
2461d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkineextern char* android_op_ui_settings;
2462d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine
2463d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkinestatic int
2464d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkinedo_attach_ui( ControlClient client, char* args )
2465d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine{
2466d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    // Make sure that there are no UI already attached to this console.
2467d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    if (attached_ui_client != NULL) {
2468d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine        control_write( client, "KO: Another UI is attached to this core!\r\n" );
2469d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine        control_client_destroy(client);
2470d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine        return -1;
2471d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    }
2472d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine
2473d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    attached_ui_client = client;
2474d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine
2475d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    if (android_op_ui_settings != NULL) {
2476d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine        // Reply "OK" with the saved -ui-settings property.
2477d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine        char reply_buf[4096];
2478d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine        snprintf(reply_buf, sizeof(reply_buf), "OK: %s\r\n", android_op_ui_settings);
2479d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine        control_write( client, reply_buf);
2480d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    } else {
2481d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine        control_write( client, "OK\r\n");
2482d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    }
2483d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine
2484d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    return 0;
2485d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine}
2486d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine
2487e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine/* Core display instance. */
2488e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkineextern CoreDisplay core_display;
2489e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine
2490e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkinestatic int
2491e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkinedo_create_framebuffer_service( ControlClient client, char* args )
2492e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine{
2493e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    CoreFramebuffer* core_fb;
2494e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    const char* protocol = "-raw";   // Default framebuffer exchange protocol.
2495e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine
2496e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    // Protocol type is defined by the arguments passed with the stream switch
2497e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    // command.
2498e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    if (args != NULL && *args != '\0') {
2499e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        size_t token_len;
2500e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        const char* param_end = strchr(args, ' ');
2501e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        if (param_end == NULL) {
2502e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine            param_end = args + strlen(args);
2503e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        }
2504e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        token_len = param_end - args;
2505e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        protocol = args;
2506e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine
2507e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        // Make sure that this is one of the supported protocols.
2508e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        if (strncmp(protocol, "-raw", token_len) &&
2509e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine            strncmp(protocol, "-shared", token_len)) {
2510e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine            derror("Invalid framebuffer parameter %s\n", protocol);
2511e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine            control_write( client, "KO: Invalid parameter\r\n" );
2512e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine            control_client_destroy(client);
2513e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine            return -1;
2514e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        }
2515e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    }
2516e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine
2517e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    // Make sure that there are no framebuffer client already existing.
2518e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    if (framebuffer_client != NULL) {
2519e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        control_write( client, "KO: Another framebuffer service is already existing!\r\n" );
2520e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        control_client_destroy(client);
2521e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        return -1;
2522e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    }
2523e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine
25248acf4e2237c2969647f47008344e44918bb30acbVladimir Chtchetkine    core_fb = corefb_create(client->sock, protocol, coredisplay_get_framebuffer());
2525e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    if (!coredisplay_attach_fb_service(core_fb)) {
25268acf4e2237c2969647f47008344e44918bb30acbVladimir Chtchetkine        char reply_buf[4096];
2527e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        framebuffer_client = client;
25288acf4e2237c2969647f47008344e44918bb30acbVladimir Chtchetkine        // Reply "OK" with the framebuffer's bits per pixel
25298acf4e2237c2969647f47008344e44918bb30acbVladimir Chtchetkine        snprintf(reply_buf, sizeof(reply_buf), "OK: -bitsperpixel=%d\r\n",
25308acf4e2237c2969647f47008344e44918bb30acbVladimir Chtchetkine                 corefb_get_bits_per_pixel(core_fb));
25318acf4e2237c2969647f47008344e44918bb30acbVladimir Chtchetkine        control_write( client, reply_buf);
2532e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    } else {
2533e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        control_write( client, "KO\r\n" );
2534e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        control_client_destroy(client);
2535e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        return -1;
2536e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    }
2537e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine
2538e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    return 0;
2539e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine}
2540e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#endif  // CONFIG_STANDALONE_CORE
2541e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine
2542e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnerstatic const CommandDefRec  qemu_commands[] =
2543e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner{
2544e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    { "monitor", "enter QEMU monitor",
2545e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    "Enter the QEMU virtual machine monitor\r\n",
2546e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    NULL, do_qemu_monitor, NULL },
2547e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2548e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#ifdef CONFIG_STANDALONE_CORE
2549d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    { "attach UI", "attach UI to the core",
2550d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    "Attach UI to the core\r\n",
2551d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    NULL, do_attach_ui, NULL },
2552d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine
2553e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    { "framebuffer", "create framebuffer service",
2554e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    "Create framebuffer service\r\n",
2555e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    NULL, do_create_framebuffer_service, NULL },
2556e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#endif  // CONFIG_STANDALONE_CORE
2557e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine
2558e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    { NULL, NULL, NULL, NULL, NULL, NULL }
2559e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner};
2560e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2561e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2562e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/********************************************************************************************/
2563e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/********************************************************************************************/
2564e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/*****                                                                                 ******/
25658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                           M A I N   C O M M A N D S                             ******/
25668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
25678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
25688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
25698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
25718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_kill( ControlClient  client, char*  args )
25728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2573d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    control_write( client, "OK: killing emulator, bye bye\r\n" );
2574d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    exit(0);
25758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
25768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec   main_commands[] =
25788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "help|h|?", "print a list of commands", NULL, NULL, do_help, NULL },
25808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "event", "simulate hardware events",
25828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "allows you to send fake hardware events to the kernel\r\n", NULL,
25838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, event_commands },
25848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "geo", "Geo-location commands",
25868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows you to change Geo-related settings, or to send GPS NMEA sentences\r\n", NULL,
25878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, geo_commands },
25888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "gsm", "GSM related commands",
25908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows you to change GSM-related settings, or to make a new inbound phone call\r\n", NULL,
25918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, gsm_commands },
25928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25931a000857bb7eef298efa787699050884f92311feJaime Lopez    { "cdma", "CDMA related commands",
25941a000857bb7eef298efa787699050884f92311feJaime Lopez      "allows you to change CDMA-related settings\r\n", NULL,
25951a000857bb7eef298efa787699050884f92311feJaime Lopez      NULL, cdma_commands },
25961a000857bb7eef298efa787699050884f92311feJaime Lopez
25978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "kill", "kill the emulator instance", NULL, NULL,
2598d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine      do_kill, NULL },
25998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "network", "manage network settings",
26018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows you to manage the settings related to the network data connection of the\r\n"
26028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "emulated device.\r\n", NULL,
26038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, network_commands },
26048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "power", "power related commands",
26068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows to change battery and AC power status\r\n", NULL,
26078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, power_commands },
26088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "quit|exit", "quit control session", NULL, NULL,
26108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      do_quit, NULL },
26118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "redir",    "manage port redirections",
26138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows you to add, list and remove UDP and/or PORT redirection from the host to the device\r\n"
26148b23a6c7e1aee255004dd19098d4c2462b61b849The 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"
26158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "to TCP port 6000 of the emulated device\r\n", NULL,
26168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, redir_commands },
26178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "sms", "SMS related commands",
26198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows you to simulate an inbound SMS\r\n", NULL,
26208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, sms_commands },
26218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26222ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { "avd", "control virtual device execution",
26232ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "allows you to control (e.g. start/stop) the execution of the virtual device\r\n", NULL,
26248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, vm_commands },
26258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "window", "manage emulator window",
26278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "allows you to modify the emulator window\r\n", NULL,
26288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, window_commands },
26298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2630e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    { "qemu", "QEMU-specific commands",
2631e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    "allows to connect to the QEMU virtual machine monitor\r\n", NULL,
2632e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    NULL, qemu_commands },
2633e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
26348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
26358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
26368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic ControlGlobalRec  _g_global;
26398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
26418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_console_start( int  port )
26428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
26438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return control_global_init( &_g_global, port );
26448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2645