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
24cc330d4169441727fecf1da08aee806fc021c4e2David 'Digit' Turner#include "android/sockets.h"
25e7216d82dbaa19892ad62b07402d512234559a6eDavid 'Digit' Turner#include "sysemu/char.h"
2634c48ff1e3ad5cd2084ca40188754d45f423750bDavid 'Digit' Turner#include "sysemu/sysemu.h"
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/android.h"
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "cpu.h"
29f5bc01c356e1fa924ed07aadf589b3663873593eDavid 'Digit' Turner#include "hw/android/goldfish/device.h"
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "hw/power_supply.h"
31cc330d4169441727fecf1da08aee806fc021c4e2David 'Digit' Turner#include "android/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"
37af81d7432594d8459c4fb9f76c5e8a981f69a94cDavid 'Digit' Turner#include "android/utils/eintr_wrapper.h"
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/utils/stralloc.h"
392ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije#include "android/config/config.h"
406e2eb78f2b52b6fff73a72995bc4356d6e67e773David 'Digit' Turner#include "android/tcpdump.h"
41cc330d4169441727fecf1da08aee806fc021c4e2David 'Digit' Turner#include "net/net.h"
426af6765e2f3bc930d0dce21d752bea570a1b1362David 'Digit' Turner#include "monitor/monitor.h"
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdlib.h>
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdio.h>
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdarg.h>
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <string.h>
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <unistd.h>
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <fcntl.h>
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/hw-events.h"
51d4e803c5e928790b14704ae7f0b048da7ba47fabDavid 'Digit' Turner#include "android/user-events.h"
52736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan#include "android/hw-sensors.h"
5371bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine#include "android/keycode-array.h"
5471bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine#include "android/charmap.h"
55e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#include "android/display-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
61496168ed6e29479bcc2c5cac2ade6f045013a59cDavid 'Digit' Turnerextern void android_emulator_set_window_scale(double, int);
62496168ed6e29479bcc2c5cac2ade6f045013a59cDavid 'Digit' Turner
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  DEBUG  1
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 1
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  D_ACTIVE   VERBOSE_CHECK(console)
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  D_ACTIVE   DEBUG
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if DEBUG
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  D(x)   do { if (D_ACTIVE) ( printf x , fflush(stdout) ); } while (0)
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  define  D(x)   do{}while(0)
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct ControlGlobalRec_*  ControlGlobal;
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct ControlClientRec_*  ControlClient;
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct {
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int           host_port;
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int           host_udp;
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned int  guest_ip;
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int           guest_port;
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} RedirRec, *Redir;
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
89e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnertypedef int Socket;
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct ControlClientRec_
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    struct ControlClientRec_*  next;       /* next client in list           */
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Socket                     sock;       /* socket used for communication */
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlGlobal              global;
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char                       finished;
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char                       buff[ 4096 ];
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int                        buff_len;
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} ControlClientRec;
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct ControlGlobalRec_
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* listening socket */
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Socket    listen_fd;
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* the list of current clients */
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlClient   clients;
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* the list of redirections currently active */
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Redir     redirs;
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       num_redirs;
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       max_redirs;
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} ControlGlobalRec;
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
118e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#ifdef CONFIG_STANDALONE_CORE
119d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine/* UI client currently attached to the core. */
120d87b080495e71ada650b165a1f06616b433e6073Vladimir ChtchetkineControlClient attached_ui_client = NULL;
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1229411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine/* User events service client. */
1239411a562e1ab772732a4d5147c9103a638837c82Vladimir ChtchetkineControlClient user_events_client = NULL;
1249411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine
1256b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine/* UI control service client (UI -> Core). */
1266b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir ChtchetkineControlClient ui_core_ctl_client = NULL;
1276b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine
1286b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine/* UI control service (UI -> Core. */
1296b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine// CoreUICtl* ui_core_ctl = NULL;
1306b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine
1316b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine/* UI control service client (Core-> UI). */
1326b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir ChtchetkineControlClient core_ui_ctl_client = NULL;
133e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#endif  // CONFIG_STANDALONE_CORE
134e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_global_add_redir( ControlGlobal  global,
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int            host_port,
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int            host_udp,
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          unsigned int   guest_ip,
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int            guest_port )
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Redir  redir;
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (global->num_redirs >= global->max_redirs)
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  old_max = global->max_redirs;
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  new_max = old_max + (old_max >> 1) + 4;
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        Redir  new_redirs = realloc( global->redirs, new_max*sizeof(global->redirs[0]) );
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (new_redirs == NULL)
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        global->redirs     = new_redirs;
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        global->max_redirs = new_max;
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir = &global->redirs[ global->num_redirs++ ];
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir->host_port  = host_port;
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir->host_udp   = host_udp;
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir->guest_ip   = guest_ip;
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir->guest_port = guest_port;
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_global_del_redir( ControlGlobal  global,
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int            host_port,
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          int            host_udp )
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < global->num_redirs; nn++)
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        Redir  redir = &global->redirs[nn];
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( redir->host_port == host_port &&
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             redir->host_udp  == host_udp  )
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        {
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            memmove( redir, redir + 1, ((global->num_redirs - nn)-1)*sizeof(*redir) );
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            global->num_redirs -= 1;
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* we didn't find it */
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
190e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/* Detach the socket descriptor from a given ControlClient
191e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner * and return its value. This is useful either when destroying
192e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner * the client, or redirecting the socket to another service.
193e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner *
194e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner * NOTE: this does not close the socket.
195e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner */
196e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnerstatic int
197e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnercontrol_client_detach( ControlClient  client )
198e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner{
199e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    int  result;
200e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
201e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    if (client->sock < 0)
202e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner        return -1;
203e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
204e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    qemu_set_fd_handler( client->sock, NULL, NULL, NULL );
205e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    result = client->sock;
206e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    client->sock = -1;
207e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
208e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    return result;
209e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner}
210e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
211e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnerstatic void  control_client_read( void*  _client );  /* forward */
212e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_client_destroy( ControlClient  client )
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlGlobal  global = client->global;
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlClient  *pnode = &global->clients;
218e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    int            sock;
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D(( "destroying control client %p\n", client ));
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
222e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#ifdef CONFIG_STANDALONE_CORE
223d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    if (client == attached_ui_client) {
22485276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine        attachUiProxy_destroy();
225d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine        attached_ui_client = NULL;
226d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    }
227d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine
2289411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine    if (client == user_events_client) {
229250b2e00af04f8407dea564e643dad4ef08b8a88Vladimir Chtchetkine        userEventsImpl_destroy();
2309411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine        user_events_client = NULL;
2319411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine    }
2326b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine
2336b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    if (client == ui_core_ctl_client) {
234777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        coreCmdImpl_destroy();
2356b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        ui_core_ctl_client = NULL;
2366b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    }
2376b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine
2386b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    if (client == core_ui_ctl_client) {
239777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        uiCmdProxy_destroy();
2406b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        core_ui_ctl_client = NULL;
2416b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    }
242e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#endif  // CONFIG_STANDALONE_CORE
243e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine
244e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    sock = control_client_detach( client );
245e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    if (sock >= 0)
246e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner        socket_close(sock);
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( ;; ) {
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ControlClient  node = *pnode;
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( node == NULL )
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( node == client ) {
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            *pnode     = node->next;
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            node->next = NULL;
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        pnode = &node->next;
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    free( client );
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void  control_control_write( ControlClient  client, const char*  buff, int  len )
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int ret;
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len < 0)
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len = strlen(buff);
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (len > 0) {
273af81d7432594d8459c4fb9f76c5e8a981f69a94cDavid 'Digit' Turner        ret = HANDLE_EINTR(socket_send( client->sock, buff, len));
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (ret < 0) {
275af81d7432594d8459c4fb9f76c5e8a981f69a94cDavid 'Digit' Turner            if (errno != EWOULDBLOCK && errno != EAGAIN)
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            buff += ret;
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            len  -= ret;
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2842ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int  control_vwrite( ControlClient  client, const char*  format, va_list args )
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static char  temp[1024];
2872ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    int ret = vsnprintf( temp, sizeof(temp), format, args );
2882ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    temp[ sizeof(temp)-1 ] = 0;
2892ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    control_control_write( client, temp, -1 );
2902ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
2912ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret;
2922ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2942ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int  control_write( ControlClient  client, const char*  format, ... )
2952ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
2962ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    int ret;
2972ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    va_list      args;
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_start(args, format);
2992ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ret = control_vwrite(client, format, args);
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_end(args);
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3022ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret;
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic ControlClient
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_client_create( Socket         socket,
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       ControlGlobal  global )
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlClient  client = calloc( sizeof(*client), 1 );
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (client) {
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_set_nodelay( socket );
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_set_nonblock( socket );
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->finished = 0;
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->global  = global;
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->sock    = socket;
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->next    = global->clients;
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        global->clients = client;
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        qemu_set_fd_handler( socket, control_client_read, NULL, client );
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return client;
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef const struct CommandDefRec_  *CommandDef;
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct CommandDefRec_ {
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*  names;
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*  abstract;
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*  description;
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    void        (*descriptor)( ControlClient  client );
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int         (*handler)( ControlClient  client, char* args );
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CommandDef   subcommands;   /* if handler is NULL */
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} CommandDefRec;
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec   main_commands[];  /* forward */
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic CommandDef
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectfind_command( char*  input, CommandDef  commands, char*  *pend, char*  *pargs )
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int    nn;
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*  args = strchr(input, ' ');
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args != NULL) {
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (*args == ' ')
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            args++;
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (args[0] == 0)
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            args = NULL;
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; commands[nn].names != NULL; nn++)
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*  name = commands[nn].names;
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*  sep;
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        do {
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int  len, c;
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sep = strchr( name, '|' );
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (sep)
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                len = sep - name;
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                len = strlen(name);
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            c = input[len];
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if ( !memcmp( name, input, len ) && (c == ' ' || c == 0) ) {
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                *pend  = input + len;
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                *pargs = args;
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return &commands[nn];
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (sep)
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                name = sep + 1;
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } while (sep != NULL && *name);
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* NOTE: don't touch *pend and *pargs if no command is found */
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdump_help( ControlClient  client,
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           CommandDef     cmd,
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           const char*    prefix )
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cmd->description) {
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "%s", cmd->description );
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else if (cmd->descriptor) {
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cmd->descriptor( client );
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "%s\r\n", cmd->abstract );
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cmd->subcommands) {
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cmd = cmd->subcommands;
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "\r\navailable sub-commands:\r\n" );
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for ( ; cmd->names != NULL; cmd++ ) {
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "   %s %-15s  %s\r\n", prefix, cmd->names, cmd->abstract );
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "\r\n" );
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_client_do_command( ControlClient  client )
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       line     = client->buff;
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       args     = NULL;
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CommandDef  commands = main_commands;
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       cmdend   = client->buff;
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CommandDef  cmd      = find_command( line, commands, &cmdend, &args );
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (cmd == NULL) {
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: unknown command, try 'help'\r\n" );
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (;;) {
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        CommandDef  subcmd;
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (cmd->handler) {
424d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine            if ( !cmd->handler( client, args ) ) {
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client, "OK\r\n" );
426d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine            }
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* no handler means we should have sub-commands */
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (cmd->subcommands == NULL) {
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "KO: internal error: buggy command table for '%.*s'\r\n",
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                           cmdend - client->buff, client->buff );
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* we need a sub-command here */
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( !args ) {
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dump_help( client, cmd, "" );
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "KO: missing sub-command\r\n" );
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        line     = args;
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        commands = cmd->subcommands;
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        subcmd   = find_command( line, commands, &cmdend, &args );
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (subcmd == NULL) {
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dump_help( client, cmd, "" );
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "KO:  bad sub-command\r\n" );
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cmd = subcmd;
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* implement the 'help' command */
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_help( ControlClient  client, char*  args )
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       line;
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       start = args;
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*       end   = start;
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    CommandDef  cmd = main_commands;
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* without arguments, simply dump all commands */
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args == NULL) {
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "Android console command help:\r\n\r\n" );
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for ( ; cmd->names != NULL; cmd++ ) {
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "    %-15s  %s\r\n", cmd->names, cmd->abstract );
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "\r\ntry 'help <command>' for command-specific help\r\n" );
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* with an argument, find the corresponding command */
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (;;) {
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        CommandDef  subcmd;
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        line    = args;
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        subcmd  = find_command( line, cmd, &end, &args );
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (subcmd == NULL) {
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "try one of these instead:\r\n\r\n" );
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for ( ; cmd->names != NULL; cmd++ ) {
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client, "    %.*s %s\r\n",
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                              end - start, start, cmd->names );
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "\r\nKO: unknown command\r\n" );
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( !args || !subcmd->subcommands ) {
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dump_help( client, subcmd, start );
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        cmd = subcmd->subcommands;
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_client_read_byte( ControlClient  client, unsigned char  ch )
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ch == '\r')
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* filter them out */
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else if (ch == '\n')
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->buff[ client->buff_len ] = 0;
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_client_do_command( client );
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (client->finished)
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->buff_len = 0;
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (client->buff_len >= sizeof(client->buff)-1)
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            client->buff_len = 0;
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        client->buff[ client->buff_len++ ] = ch;
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_client_read( void*  _client )
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlClient  client = _client;
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned char  buf[4096];
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int            size;
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D(( "in control_client read: " ));
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    size = socket_recv( client->sock, buf, sizeof(buf) );
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (size < 0) {
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "size < 0, exiting with %d: %s\n", errno, errno_str ));
536d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine        if (errno != EWOULDBLOCK && errno != EAGAIN)
537d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine            control_client_destroy( client );
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (size == 0) {
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* end of connection */
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "end of connection detected !!\n" ));
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_client_destroy( client );
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  nn;
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef _WIN32
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  if DEBUG
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char  temp[16];
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int   count = size > sizeof(temp)-1 ? sizeof(temp)-1 : size;
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; nn < count; nn++) {
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                int  c = buf[nn];
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                if (c == '\n')
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        temp[nn] = '!';
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else if (c < 32)
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        temp[nn] = '.';
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                else
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                    temp[nn] = (char)c;
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        temp[nn] = 0;
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "received %d bytes: %s\n", size, temp ));
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#  endif
5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "received %.*s\n", size, buf ));
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; nn < size; nn++) {
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_client_read_byte( client, buf[nn] );
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (client->finished) {
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_client_destroy(client);
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return;
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* this function is called on each new client connection */
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_global_accept( void*  _global )
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlGlobal       global = _global;
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlClient       client;
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Socket              fd;
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
58680bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    D(( "control_global_accept: just in (fd=%d)\n", global->listen_fd ));
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
588af81d7432594d8459c4fb9f76c5e8a981f69a94cDavid 'Digit' Turner    fd = HANDLE_EINTR(socket_accept(global->listen_fd, NULL));
589af81d7432594d8459c4fb9f76c5e8a981f69a94cDavid 'Digit' Turner    if (fd < 0) {
590af81d7432594d8459c4fb9f76c5e8a981f69a94cDavid 'Digit' Turner        D(( "problem in accept: %d: %s\n", errno, errno_str ));
591af81d7432594d8459c4fb9f76c5e8a981f69a94cDavid 'Digit' Turner        perror("accept");
592af81d7432594d8459c4fb9f76c5e8a981f69a94cDavid 'Digit' Turner        return;
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_xreuseaddr( fd );
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D(( "control_global_accept: creating new client\n" ));
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    client = control_client_create( fd, global );
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (client) {
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        D(( "control_global_accept: new client %p\n", client ));
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "Android Console: type 'help' for a list of commands\r\n" );
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "OK\r\n" );
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_global_init( ControlGlobal  global,
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     int            control_port )
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Socket  fd;
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int     ret;
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SockAddress  sockaddr;
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memset( global, 0, sizeof(*global) );
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fd = socket_create_inet( SOCKET_STREAM );
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (fd < 0) {
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        perror("socket");
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_xreuseaddr( fd );
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sock_address_init_inet( &sockaddr, SOCK_ADDRESS_INET_LOOPBACK, control_port );
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = socket_bind(fd, &sockaddr );
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) {
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        perror("bind");
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_close( fd );
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ret = socket_listen(fd, 0);
6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (ret < 0) {
6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        perror("listen");
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_close( fd );
6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_nonblock(fd);
6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    global->listen_fd = fd;
6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_set_fd_handler( fd, control_global_accept, NULL, global );
6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_quit( ControlClient  client, char*  args )
6538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    client->finished = 1;
6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                        N E T W O R K   S E T T I N G S                          ******/
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_network_status( ControlClient  client, char*  args )
6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "Current network status:\r\n" );
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "  download speed:   %8d bits/s (%.1f KB/s)\r\n",
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   (long)qemu_net_download_speed, qemu_net_download_speed/8192. );
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "  upload speed:     %8d bits/s (%.1f KB/s)\r\n",
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   (long)qemu_net_upload_speed, qemu_net_upload_speed/8192. );
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "  minimum latency:  %ld ms\r\n", qemu_net_min_latency );
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "  maximum latency:  %ld ms\r\n", qemu_net_max_latency );
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdump_network_speeds( ControlClient  client )
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const NetworkSpeed*  speed = android_netspeeds;
6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char* const  format = "  %-8s %s\r\n";
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( ; speed->name; speed++ ) {
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, format, speed->name, speed->display );
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, format, "<num>", "selects both upload and download speed" );
6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, format, "<up>:<down>", "select individual upload/download speeds" );
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_network_speed( ControlClient  client, char*  args )
6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !args ) {
6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing <speed> argument, see 'help network speed'\r\n" );
7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( android_parse_network_speed( args ) < 0 ) {
7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: invalid <speed> argument, see 'help network speed' for valid values\r\n" );
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    netshaper_set_rate( slirp_shaper_in,  qemu_net_download_speed );
7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    netshaper_set_rate( slirp_shaper_out, qemu_net_upload_speed );
7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (android_modem) {
71171bb14f826775867d16e7d382cfdc48e6ca46ccbVladimir Chtchetkine        amodem_set_data_network_type( android_modem,
7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                    android_parse_network_type( args ) );
7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdescribe_network_speed( ControlClient  client )
7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client,
7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   "'network speed <speed>' allows you to dynamically change the speed of the emulated\r\n"
7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   "network on the device, where <speed> is one of the following:\r\n\r\n" );
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    dump_network_speeds( client );
7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_network_delay( ControlClient  client, char*  args )
7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !args ) {
7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing <delay> argument, see 'help network delay'\r\n" );
7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( android_parse_network_latency( args ) < 0 ) {
7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: invalid <delay> argument, see 'help network delay' for valid values\r\n" );
7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    netdelay_set_latency( slirp_delay_in, qemu_net_min_latency, qemu_net_max_latency );
7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdescribe_network_delay( ControlClient  client )
7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client,
7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   "'network delay <latency>' allows you to dynamically change the latency of the emulated\r\n"
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   "network on the device, where <latency> is one of the following:\r\n\r\n" );
7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* XXX: TODO */
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_network_capture_start( ControlClient  client, char*  args )
7528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !args ) {
7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing <file> argument, see 'help network capture start'\r\n" );
7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( qemu_tcpdump_start(args) < 0) {
7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: could not start capture: %s", strerror(errno) );
7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_network_capture_stop( ControlClient  client, char*  args )
7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* no need to return an error here */
7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    qemu_tcpdump_stop();
7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
7708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  network_capture_commands[] =
7738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "start", "start network capture",
7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "'network capture start <file>' starts a new capture of network packets\r\n"
7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "into a specific <file>. This will stop any capture already in progress.\r\n"
7778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "the capture file can later be analyzed by tools like WireShark. It uses\r\n"
7788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "the libpcap file format.\r\n\r\n"
7798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "you can stop the capture anytime with 'network capture stop'\r\n", NULL,
7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      do_network_capture_start, NULL },
7818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "stop", "stop network capture",
7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "'network capture stop' stops a currently running packet capture, if any.\r\n"
7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "you can start one with 'network capture start <file>'\r\n", NULL,
7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      do_network_capture_stop, NULL },
7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  network_commands[] =
7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "status", "dump network status", NULL, NULL,
7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       do_network_status, NULL },
7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "speed", "change network speed", NULL, describe_network_speed,
7968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      do_network_speed, NULL },
7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "delay", "change network latency", NULL, describe_network_delay,
7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       do_network_delay, NULL },
8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "capture", "dump network packets to file",
8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows to start/stop capture of network packets to a file for later analysis\r\n", NULL,
8038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, network_capture_commands },
8048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
8068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
8078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
8098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                       P O R T   R E D I R E C T I O N S                         ******/
8128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
8138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
8148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
8158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
8178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_redir_list( ControlClient  client, char*  args )
8188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ControlGlobal  global = client->global;
8208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (global->num_redirs == 0)
8228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "no active redirections\r\n" );
8238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
8248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  nn;
8258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        for (nn = 0; nn < global->num_redirs; nn++) {
8268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            Redir  redir = &global->redirs[nn];
8278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "%s:%-5d => %-5d\r\n",
8288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          redir->host_udp ? "udp" : "tcp",
8298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          redir->host_port,
8308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                          redir->guest_port );
8318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
8328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
8348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* parse a protocol:port specification */
8378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
8388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectredir_parse_proto_port( char*  args, int  *pport, int  *pproto )
8398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  proto = -1;
8418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  len   = 0;
8428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*  end;
8438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !memcmp( args, "tcp:", 4 ) ) {
8458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        proto = 0;
8468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len   = 4;
8478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else if ( !memcmp( args, "udp:", 4 ) ) {
8498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        proto = 1;
8508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        len   = 4;
8518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else
8538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
8548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    args   += len;
8568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pproto = proto;
8578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pport  = strtol( args, &end, 10 );
8588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (end == args)
8598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
8608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len += end - args;
8628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return len;
8638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
8668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectredir_parse_guest_port( char*  arg, int  *pport )
8678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*  end;
8698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *pport = strtoul( arg, &end, 10 );
8718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (end == arg)
8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 0;
8738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return end - arg;
8758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic Redir
8788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectredir_find( ControlGlobal  global, int  port, int  isudp )
8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
8818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < global->num_redirs; nn++) {
8838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        Redir  redir = &global->redirs[nn];
8848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (redir->host_port == port && redir->host_udp == isudp)
8868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return redir;
8878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
8888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return NULL;
8898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
8938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_redir_add( ControlClient  client, char*  args )
8948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int       len, host_proto, host_port, guest_port;
8968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    uint32_t  guest_ip;
8978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Redir     redir;
8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !args )
9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto BadFormat;
9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner    if (!slirp_is_inited()) {
9035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        control_write( client, "KO: network emulation disabled\r\n");
9045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner        return -1;
9058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = redir_parse_proto_port( args, &host_port, &host_proto );
9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len == 0 || args[len] != ':')
9098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto BadFormat;
9108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    args += len + 1;
9128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = redir_parse_guest_port( args, &guest_port );
9138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (len == 0 || args[len] != 0)
9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto BadFormat;
9158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir = redir_find( client->global, host_port, host_proto );
9178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( redir != NULL ) {
9188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: host port already active, use 'redir del' to remove first\r\n" );
9198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9227d9a2705e7ae6d8c4b1d9d5b4e2a67ab88c19044David Turner    if (inet_strtoip("10.0.2.15", &guest_ip) < 0) {
9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: unexpected internal failure when resolving 10.0.2.15\r\n" );
9248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    D(("pattern hport=%d gport=%d proto=%d\n", host_port, guest_port, host_proto ));
9288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( control_global_add_redir( client->global, host_port, host_proto,
9298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                   guest_ip, guest_port ) < 0 )
9308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
9318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: not enough memory to allocate redirection\r\n" );
9328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (slirp_redir(host_proto, host_port, guest_ip, guest_port) < 0) {
9368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: can't setup redirection, port probably used by another program on host\r\n" );
9378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_global_del_redir( client->global, host_port, host_proto );
9388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
9428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectBadFormat:
9448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: bad redirection format, try (tcp|udp):hostport:guestport\r\n", -1 );
9458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
9468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
9508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_redir_del( ControlClient  client, char*  args )
9518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int    len, proto, port;
9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    Redir  redir;
9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( !args )
9568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto BadFormat;
9578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    len = redir_parse_proto_port( args, &port, &proto );
9588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( len == 0 || args[len] != 0 )
9598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto BadFormat;
9608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    redir = redir_find( client->global, port, proto );
9628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (redir == NULL) {
9638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: can't remove unknown redirection (%s:%d)\r\n",
9648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                        proto ? "udp" : "tcp", port );
9658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
9668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    slirp_unredir( redir->host_udp, redir->host_port );
9698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_global_del_redir( client->global, port, proto );\
9708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectBadFormat:
9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: bad redirection format, try (tcp|udp):hostport\r\n" );
9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  redir_commands[] =
9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "list", "list current redirections",
9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "list current port redirections. use 'redir add' and 'redir del' to add and remove them\r\n", NULL,
9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_redir_list, NULL },
9838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "add",  "add new redirection",
9858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "add a new port redirection, arguments must be:\r\n\r\n"
9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "  redir add <protocol>:<host-port>:<guest-port>\r\n\r\n"
9878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "where:   <protocol>     is either 'tcp' or 'udp'\r\n"
9888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "         <host-port>    a number indicating which port on the host to open\r\n"
9898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "         <guest-port>   a number indicating which port to route to on the device\r\n"
9908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "\r\nas an example, 'redir  tcp:5000:6000' will allow any packets sent to\r\n"
9918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "the host's TCP port 5000 to be routed to TCP port 6000 of the emulated device\r\n", NULL,
9928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_redir_add, NULL },
9938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "del",  "remove existing redirection",
9958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "remove a port redirecion that was created with 'redir add', arguments must be:\r\n\r\n"
9968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "  redir  del <protocol>:<host-port>\r\n\r\n"
9978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "see the 'help redir add' for the meaning of <protocol> and <host-port>\r\n", NULL,
9988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_redir_del, NULL },
9998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
10018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
10028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
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/*****                                                                                 ******/
10081a000857bb7eef298efa787699050884f92311feJaime Lopez/*****                          C D M A   M O D E M                                    ******/
10091a000857bb7eef298efa787699050884f92311feJaime Lopez/*****                                                                                 ******/
10101a000857bb7eef298efa787699050884f92311feJaime Lopez/********************************************************************************************/
10111a000857bb7eef298efa787699050884f92311feJaime Lopez/********************************************************************************************/
10121a000857bb7eef298efa787699050884f92311feJaime Lopez
10131a000857bb7eef298efa787699050884f92311feJaime Lopezstatic const struct {
10141a000857bb7eef298efa787699050884f92311feJaime Lopez    const char *            name;
10151a000857bb7eef298efa787699050884f92311feJaime Lopez    const char *            display;
10161a000857bb7eef298efa787699050884f92311feJaime Lopez    ACdmaSubscriptionSource source;
10171a000857bb7eef298efa787699050884f92311feJaime Lopez} _cdma_subscription_sources[] = {
10181a000857bb7eef298efa787699050884f92311feJaime Lopez    { "nv",            "Read subscription from non-volatile RAM", A_SUBSCRIPTION_NVRAM },
10191a000857bb7eef298efa787699050884f92311feJaime Lopez    { "ruim",          "Read subscription from RUIM", A_SUBSCRIPTION_RUIM },
10201a000857bb7eef298efa787699050884f92311feJaime Lopez};
10211a000857bb7eef298efa787699050884f92311feJaime Lopez
10221a000857bb7eef298efa787699050884f92311feJaime Lopezstatic void
10231a000857bb7eef298efa787699050884f92311feJaime Lopezdump_subscription_sources( ControlClient client )
10241a000857bb7eef298efa787699050884f92311feJaime Lopez{
10251a000857bb7eef298efa787699050884f92311feJaime Lopez    int i;
10261a000857bb7eef298efa787699050884f92311feJaime Lopez    for (i = 0;
10271a000857bb7eef298efa787699050884f92311feJaime Lopez         i < sizeof(_cdma_subscription_sources) / sizeof(_cdma_subscription_sources[0]);
10281a000857bb7eef298efa787699050884f92311feJaime Lopez         i++) {
10291a000857bb7eef298efa787699050884f92311feJaime Lopez        control_write( client, "    %s: %s\r\n",
10301a000857bb7eef298efa787699050884f92311feJaime Lopez                       _cdma_subscription_sources[i].name,
10311a000857bb7eef298efa787699050884f92311feJaime Lopez                       _cdma_subscription_sources[i].display );
10321a000857bb7eef298efa787699050884f92311feJaime Lopez    }
10331a000857bb7eef298efa787699050884f92311feJaime Lopez}
10341a000857bb7eef298efa787699050884f92311feJaime Lopez
10351a000857bb7eef298efa787699050884f92311feJaime Lopezstatic void
10361a000857bb7eef298efa787699050884f92311feJaime Lopezdescribe_subscription_source( ControlClient client )
10371a000857bb7eef298efa787699050884f92311feJaime Lopez{
10381a000857bb7eef298efa787699050884f92311feJaime Lopez    control_write( client,
10391a000857bb7eef298efa787699050884f92311feJaime Lopez                   "'cdma ssource <ssource>' allows you to specify where to read the subscription from\r\n" );
10401a000857bb7eef298efa787699050884f92311feJaime Lopez    dump_subscription_sources( client );
10411a000857bb7eef298efa787699050884f92311feJaime Lopez}
10421a000857bb7eef298efa787699050884f92311feJaime Lopez
10431a000857bb7eef298efa787699050884f92311feJaime Lopezstatic int
10441a000857bb7eef298efa787699050884f92311feJaime Lopezdo_cdma_ssource( ControlClient  client, char*  args )
10451a000857bb7eef298efa787699050884f92311feJaime Lopez{
10461a000857bb7eef298efa787699050884f92311feJaime Lopez    int nn;
10471a000857bb7eef298efa787699050884f92311feJaime Lopez    if (!args) {
10481a000857bb7eef298efa787699050884f92311feJaime Lopez        control_write( client, "KO: missing argument, try 'cdma ssource <source>'\r\n" );
10491a000857bb7eef298efa787699050884f92311feJaime Lopez        return -1;
10501a000857bb7eef298efa787699050884f92311feJaime Lopez    }
10511a000857bb7eef298efa787699050884f92311feJaime Lopez
10521a000857bb7eef298efa787699050884f92311feJaime Lopez    for (nn = 0; ; nn++) {
10531a000857bb7eef298efa787699050884f92311feJaime Lopez        const char*         name    = _cdma_subscription_sources[nn].name;
10541a000857bb7eef298efa787699050884f92311feJaime Lopez        ACdmaSubscriptionSource ssource = _cdma_subscription_sources[nn].source;
10551a000857bb7eef298efa787699050884f92311feJaime Lopez
10561a000857bb7eef298efa787699050884f92311feJaime Lopez        if (!name)
10571a000857bb7eef298efa787699050884f92311feJaime Lopez            break;
10581a000857bb7eef298efa787699050884f92311feJaime Lopez
10591a000857bb7eef298efa787699050884f92311feJaime Lopez        if (!strcasecmp( args, name )) {
10601a000857bb7eef298efa787699050884f92311feJaime Lopez            amodem_set_cdma_subscription_source( android_modem, ssource );
10611a000857bb7eef298efa787699050884f92311feJaime Lopez            return 0;
10621a000857bb7eef298efa787699050884f92311feJaime Lopez        }
10631a000857bb7eef298efa787699050884f92311feJaime Lopez    }
10641a000857bb7eef298efa787699050884f92311feJaime Lopez    control_write( client, "KO: Don't know source %s\r\n", args );
10651a000857bb7eef298efa787699050884f92311feJaime Lopez    return -1;
10661a000857bb7eef298efa787699050884f92311feJaime Lopez}
10671a000857bb7eef298efa787699050884f92311feJaime Lopez
10681a000857bb7eef298efa787699050884f92311feJaime Lopezstatic int
10691a000857bb7eef298efa787699050884f92311feJaime Lopezdo_cdma_prl_version( ControlClient client, char * args )
10701a000857bb7eef298efa787699050884f92311feJaime Lopez{
10711a000857bb7eef298efa787699050884f92311feJaime Lopez    int version = 0;
10721a000857bb7eef298efa787699050884f92311feJaime Lopez    char *endptr;
10731a000857bb7eef298efa787699050884f92311feJaime Lopez
10741a000857bb7eef298efa787699050884f92311feJaime Lopez    if (!args) {
10751a000857bb7eef298efa787699050884f92311feJaime Lopez        control_write( client, "KO: missing argument, try 'cdma prl_version <version>'\r\n");
10761a000857bb7eef298efa787699050884f92311feJaime Lopez        return -1;
10771a000857bb7eef298efa787699050884f92311feJaime Lopez    }
10781a000857bb7eef298efa787699050884f92311feJaime Lopez
10791a000857bb7eef298efa787699050884f92311feJaime Lopez    version = strtol(args, &endptr, 0);
10801a000857bb7eef298efa787699050884f92311feJaime Lopez    if (endptr != args) {
10811a000857bb7eef298efa787699050884f92311feJaime Lopez        amodem_set_cdma_prl_version( android_modem, version );
10821a000857bb7eef298efa787699050884f92311feJaime Lopez    }
108380bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    return 0;
10841a000857bb7eef298efa787699050884f92311feJaime Lopez}
10851a000857bb7eef298efa787699050884f92311feJaime Lopez/********************************************************************************************/
10861a000857bb7eef298efa787699050884f92311feJaime Lopez/********************************************************************************************/
10871a000857bb7eef298efa787699050884f92311feJaime Lopez/*****                                                                                 ******/
10888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                           G S M   M O D E M                                     ******/
10898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
10908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
10918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
10928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const struct {
10948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*         name;
10958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*         display;
10968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ARegistrationState  state;
10978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} _gsm_states[] = {
10988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "unregistered",  "no network available", A_REGISTRATION_UNREGISTERED },
10998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "home",          "on local network, non-roaming", A_REGISTRATION_HOME },
11008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "roaming",       "on roaming network", A_REGISTRATION_ROAMING },
11018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "searching",     "searching networks", A_REGISTRATION_SEARCHING },
11028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "denied",        "emergency calls only", A_REGISTRATION_DENIED },
11038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "off",           "same as 'unregistered'", A_REGISTRATION_UNREGISTERED },
11048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "on",            "same as 'home'", A_REGISTRATION_HOME },
11058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, A_REGISTRATION_UNREGISTERED }
11068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
11078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const char*
11098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_state_to_string( ARegistrationState  state )
11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
11128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; _gsm_states[nn].name != NULL; nn++) {
11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (state == _gsm_states[nn].state)
11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return _gsm_states[nn].name;
11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return "<unknown>";
11178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
11208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_status( ControlClient  client, char*  args )
11218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
11238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: no argument required\r\n" );
11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_modem) {
11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: modem emulation not running\r\n" );
11288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "gsm voice state: %s\r\n",
11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   gsm_state_to_string(
11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       amodem_get_voice_registration(android_modem) ) );
11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "gsm data state:  %s\r\n",
11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   gsm_state_to_string(
11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       amodem_get_data_registration(android_modem) ) );
11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
11378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecthelp_gsm_data( ControlClient  client )
11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client,
11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "the 'gsm data <state>' allows you to change the state of your GPRS connection\r\n"
11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "valid values for <state> are the following:\r\n\r\n" );
11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; ; nn++) {
11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         name    = _gsm_states[nn].name;
11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         display = _gsm_states[nn].display;
11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!name)
11528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "  %-15s %s\r\n", name, display );
11558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "\r\n" );
11578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
11618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_data( ControlClient  client, char*  args )
11628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
11648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
11668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm data <state>'\r\n" );
11678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
11688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; ; nn++) {
11718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         name    = _gsm_states[nn].name;
11728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ARegistrationState  state   = _gsm_states[nn].state;
11738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!name)
11758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
11768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( !strcmp( args, name ) ) {
11788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!android_modem) {
11798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client, "KO: modem emulation not running\r\n" );
11808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return -1;
11818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
11828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            amodem_set_data_registration( android_modem, state );
11838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            qemu_net_disable = (state != A_REGISTRATION_HOME    &&
11848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                state != A_REGISTRATION_ROAMING );
11858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
11868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
11878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
11888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: bad GSM data state name, try 'help gsm data' for list of valid values\r\n" );
11898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
11908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
11938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecthelp_gsm_voice( ControlClient  client )
11948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
11968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client,
11978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "the 'gsm voice <state>' allows you to change the state of your GPRS connection\r\n"
11988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "valid values for <state> are the following:\r\n\r\n" );
11998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; ; nn++) {
12008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         name    = _gsm_states[nn].name;
12018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         display = _gsm_states[nn].display;
12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!name)
12048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
12058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "  %-15s %s\r\n", name, display );
12078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "\r\n" );
12098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
12138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_voice( ControlClient  client, char*  args )
12148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
12168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
12188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm voice <state>'\r\n" );
12198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; ; nn++) {
12238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*         name    = _gsm_states[nn].name;
12248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ARegistrationState  state   = _gsm_states[nn].state;
12258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (!name)
12278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
12288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( !strcmp( args, name ) ) {
12308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (!android_modem) {
12318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                control_write( client, "KO: modem emulation not running\r\n" );
12328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return -1;
12338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
12348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            amodem_set_voice_registration( android_modem, state );
12358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
12368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
12378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: bad GSM data state name, try 'help gsm voice' for list of valid values\r\n" );
12398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
12408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
12448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectgsm_check_number( char*  args )
12458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  nn;
12478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; args[nn] != 0; nn++) {
12498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  c = args[nn];
12508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( !isdigit(c) && c != '+' && c != '#' ) {
12518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
12528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
12538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (nn == 0)
12558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
12588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
12618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_call( ControlClient  client, char*  args )
12628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* check that we have a phone number made of digits */
12648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
12658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm call <phonenumber>'\r\n" );
12668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (gsm_check_number(args)) {
12708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: bad phone number format, use digits, # and + only\r\n" );
12718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_modem) {
12758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: modem emulation not running\r\n" );
12768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    amodem_add_inbound_call( android_modem, args );
12798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
12808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
12818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
12838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_cancel( ControlClient  client, char*  args )
12848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
12868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm call <phonenumber>'\r\n" );
12878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (gsm_check_number(args)) {
12908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: bad phone number format, use digits, # and + only\r\n" );
12918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_modem) {
12948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: modem emulation not running\r\n" );
12958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
12968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
12978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( amodem_disconnect_call( android_modem, args ) < 0 ) {
12988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: could not cancel this number\r\n" );
12998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
13028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const char*
13068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcall_state_to_string( ACallState  state )
13078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    switch (state) {
13098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case A_CALL_ACTIVE:   return "active";
13108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case A_CALL_HELD:     return "held";
13118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case A_CALL_ALERTING: return "ringing";
13128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case A_CALL_WAITING:  return "waiting";
13138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        case A_CALL_INCOMING: return "incoming";
13148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        default: return "unknown";
13158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
13198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_list( ControlClient  client, char*  args )
13208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* check that we have a phone number made of digits */
13228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   count = amodem_get_call_count( android_modem );
13238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   nn;
13248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; nn < count; nn++) {
13258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ACall        call = amodem_get_call( android_modem, nn );
13268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        const char*  dir;
13278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (call == NULL)
13298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            continue;
13308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (call->dir == A_CALL_OUTBOUND)
13328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dir = "outbound to ";
13338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         else
13348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dir = "inbound from";
13358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "%s %-10s : %s\r\n", dir,
13378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       call->number, call_state_to_string(call->state) );
13388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
13408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
13438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_busy( ControlClient  client, char*  args )
13448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ACall  call;
13468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
13488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm busy <phonenumber>'\r\n" );
13498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    call = amodem_find_call_by_number( android_modem, args );
13528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (call == NULL || call->dir != A_CALL_OUTBOUND) {
13538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: no current outbound call to number '%s' (call %p)\r\n", args, call );
13548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( amodem_disconnect_call( android_modem, args ) < 0 ) {
13578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: could not cancel this number\r\n" );
13588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
13618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
13648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_hold( ControlClient  client, char*  args )
13658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ACall  call;
13678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
13698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm out hold <phonenumber>'\r\n" );
13708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    call = amodem_find_call_by_number( android_modem, args );
13738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (call == NULL) {
13748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: no current call to/from number '%s'\r\n", args );
13758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( amodem_update_call( android_modem, args, A_CALL_HELD ) < 0 ) {
13788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: could put this call on hold\r\n" );
13798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
13828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
13868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_gsm_accept( ControlClient  client, char*  args )
13878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ACall  call;
13898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
13918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'gsm accept <phonenumber>'\r\n" );
13928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    call = amodem_find_call_by_number( android_modem, args );
13958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (call == NULL) {
13968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: no current call to/from number '%s'\r\n", args );
13978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
13988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
13998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( amodem_update_call( android_modem, args, A_CALL_ACTIVE ) < 0 ) {
14008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: could not activate this call\r\n" );
14018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
14028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
14038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
14048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14064c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstockstatic int
14074c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstockdo_gsm_signal( ControlClient  client, char*  args )
14084c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock{
14094c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      enum { SIGNAL_RSSI = 0, SIGNAL_BER, NUM_SIGNAL_PARAMS };
14104c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      char*   p = args;
14114c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      int     top_param = -1;
14124c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      int     params[ NUM_SIGNAL_PARAMS ];
14134c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14144c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      static  int  last_ber = 99;
14154c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14164c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      if (!p)
14174c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          p = "";
14184c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14194c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      /* tokenize */
14204c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      while (*p) {
14214c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          char*   end;
14224c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          int  val = strtol( p, &end, 10 );
14234c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14244c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          if (end == p) {
14254c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock              control_write( client, "KO: argument '%s' is not a number\n", p );
14264c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock              return -1;
14274c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          }
14284c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14294c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          params[++top_param] = val;
14304c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          if (top_param + 1 == NUM_SIGNAL_PARAMS)
14314c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock              break;
14324c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14334c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          p = end;
14344c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          while (*p && (p[0] == ' ' || p[0] == '\t'))
14354c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock              p += 1;
14364c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      }
14374c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14384c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      /* sanity check */
14394c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      if (top_param < SIGNAL_RSSI) {
14404c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          control_write( client, "KO: not enough arguments: see 'help gsm signal' for details\r\n" );
14414c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          return -1;
14424c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      }
14434c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14444c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      int rssi = params[SIGNAL_RSSI];
14454c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      if ((rssi < 0 || rssi > 31) && rssi != 99) {
14464c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          control_write( client, "KO: invalid RSSI - must be 0..31 or 99\r\n");
14474c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          return -1;
14484c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      }
14494c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14504c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      /* check ber is 0..7 or 99 */
14514c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      if (top_param >= SIGNAL_BER) {
14524c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          int ber = params[SIGNAL_BER];
14534c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          if ((ber < 0 || ber > 7) && ber != 99) {
14544c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock              control_write( client, "KO: invalid BER - must be 0..7 or 99\r\n");
14554c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock              return -1;
14564c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          }
14574c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock          last_ber = ber;
14584c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      }
14594c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14604c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      amodem_set_signal_strength( android_modem, rssi, last_ber );
14614c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14624c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock      return 0;
14634c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock  }
14644c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
14658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if 0
14678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  gsm_in_commands[] =
14688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "new", "create a new 'waiting' inbound call",
14708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm in create <phonenumber>' creates a new inbound phone call, placed in\r\n"
14718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "the 'waiting' state by default, until the system answers/holds/closes it\r\n", NULL
14728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_in_create, NULL },
14738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "hold", "change the state of an oubtound call to 'held'",
14758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "change the state of an outbound call to 'held'. this is only possible\r\n"
14768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "if the call in the 'waiting' or 'active' state\r\n", NULL,
14778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_out_hold, NULL },
14788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "accept", "change the state of an outbound call to 'active'",
14808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "change the state of an outbound call to 'active'. this is only possible\r\n"
14818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "if the call is in the 'waiting' or 'held' state\r\n", NULL,
14828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_out_accept, NULL },
14838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
14858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
14868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
14878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14891a000857bb7eef298efa787699050884f92311feJaime Lopezstatic const CommandDefRec  cdma_commands[] =
14901a000857bb7eef298efa787699050884f92311feJaime Lopez{
14911a000857bb7eef298efa787699050884f92311feJaime Lopez    { "ssource", "Set the current CDMA subscription source",
14921a000857bb7eef298efa787699050884f92311feJaime Lopez      NULL, describe_subscription_source,
14931a000857bb7eef298efa787699050884f92311feJaime Lopez      do_cdma_ssource, NULL },
149480bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner    { "prl_version", "Dump the current PRL version",
149580bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner      NULL, NULL,
149680bc5c8c7b9c50e8f302c22c2fba42dd6e8aa2dfDavid 'Digit' Turner      do_cdma_prl_version, NULL },
14971a000857bb7eef298efa787699050884f92311feJaime Lopez};
14981a000857bb7eef298efa787699050884f92311feJaime Lopez
14998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  gsm_commands[] =
15008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "list", "list current phone calls",
15028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm list' lists all inbound and outbound calls and their state\r\n", NULL,
15038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_list, NULL },
15048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "call", "create inbound phone call",
15068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm call <phonenumber>' allows you to simulate a new inbound call\r\n", NULL,
15078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_call, NULL },
15088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "busy", "close waiting outbound call as busy",
15108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm busy <remoteNumber>' closes an outbound call, reporting\r\n"
15118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "the remote phone as busy. only possible if the call is 'waiting'.\r\n", NULL,
15128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_busy, NULL },
15138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "hold", "change the state of an oubtound call to 'held'",
15158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm hold <remoteNumber>' change the state of a call to 'held'. this is only possible\r\n"
15168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "if the call in the 'waiting' or 'active' state\r\n", NULL,
15178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_hold, NULL },
15188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "accept", "change the state of an outbound call to 'active'",
15208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm accept <remoteNumber>' change the state of a call to 'active'. this is only possible\r\n"
15218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "if the call is in the 'waiting' or 'held' state\r\n", NULL,
15228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_accept, NULL },
15238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "cancel", "disconnect an inbound or outbound phone call",
15258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm cancel <phonenumber>' allows you to simulate the end of an inbound or outbound call\r\n", NULL,
15268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_cancel, NULL },
15278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "data", "modify data connection state", NULL, help_gsm_data,
15298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_data, NULL },
15308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "voice", "modify voice connection state", NULL, help_gsm_voice,
15328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_voice, NULL },
15338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "status", "display GSM status",
15358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'gsm status' displays the current state of the GSM emulation\r\n", NULL,
15368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_gsm_status, NULL },
15378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15384c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock    { "signal", "set sets the rssi and ber",
15394c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock    "'gsm signal <rssi> [<ber>]' changes the reported strength and error rate on next (15s) update.\r\n"
15404c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock    "rssi range is 0..31 and 99 for unknown\r\n"
15414c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock    "ber range is 0..7 percent and 99 for unknown\r\n",
15424c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock    NULL, do_gsm_signal, NULL },
15434c6b10a4f385c04dbd7226e10a86a1f5cbd34f2aTim Baverstock
15448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
15458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
15468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
15488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
15498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
15508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                           S M S   C O M M A N D                                 ******/
15518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
15528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
15538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
15548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
15568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_sms_send( ControlClient  client, char*  args )
15578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*          p;
15598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int            textlen;
15608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsAddressRec  sender;
15618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsPDU*        pdus;
15628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int            nn;
15638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* check that we have a phone number made of digits */
15658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
15668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    MissingArgument:
15678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'sms send <phonenumber> <text message>'\r\n" );
15688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
15698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = strchr( args, ' ' );
15718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!p) {
15728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto MissingArgument;
15738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if ( sms_address_from_str( &sender, args, p - args ) < 0 ) {
15768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: bad phone number format, must be [+](0-9)*\r\n" );
15778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
15788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* un-secape message text into proper utf-8 (conversion happens in-site) */
15828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p      += 1;
15838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    textlen = strlen(p);
15848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    textlen = sms_utf8_from_message_str( p, textlen, (unsigned char*)p, textlen );
15858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (textlen < 0) {
15868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "message must be utf8 and can use the following escapes:\r\n"
15878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\n      for a newline\r\n"
15888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\xNN    where NN are two hexadecimal numbers\r\n"
15898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\uNNNN  where NNNN are four hexadecimal numbers\r\n"
15908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    \\\\     to send a '\\' character\r\n\r\n"
15918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "    anything else is an error\r\n"
15928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       "KO: badly formatted text\r\n" );
15938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
15948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
15958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_modem) {
15978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: modem emulation not running\r\n" );
15988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
15998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* create a list of SMS PDUs, then send them */
16028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pdus = smspdu_create_deliver_utf8( (cbytes_t)p, textlen, &sender, NULL );
16038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (pdus == NULL) {
16048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: internal error when creating SMS-DELIVER PDUs\n" );
16058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
16068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (nn = 0; pdus[nn] != NULL; nn++)
16098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        amodem_receive_sms( android_modem, pdus[nn] );
16108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    smspdu_free_list( pdus );
16128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
16138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
16168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_sms_sendpdu( ControlClient  client, char*  args )
16178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    SmsPDU  pdu;
16198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* check that we have a phone number made of digits */
16218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
16228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: missing argument, try 'sms sendpdu <hexstring>'\r\n" );
16238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
16248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_modem) {
16278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: modem emulation not running\r\n" );
16288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
16298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    pdu = smspdu_create_from_hex( args, strlen(args) );
16328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (pdu == NULL) {
16338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: badly formatted <hexstring>\r\n" );
16348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
16358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    amodem_receive_sms( android_modem, pdu );
16388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    smspdu_free( pdu );
16398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
16408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  sms_commands[] =
16438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "send", "send inbound SMS text message",
16458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'sms send <phonenumber> <message>' allows you to simulate a new inbound sms message\r\n", NULL,
16468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_sms_send, NULL },
16478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "pdu", "send inbound SMS PDU",
16498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'sms pdu <hexstring>' allows you to simulate a new inbound sms PDU\r\n"
16508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "(used internally when one emulator sends SMS messages to another instance).\r\n"
16518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "you probably don't want to play with this at all\r\n", NULL,
16528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_sms_sendpdu, NULL },
16538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
16558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
16568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
16588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_control_write(void* data, const char* string)
16598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write((ControlClient)data, string);
16618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
16648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_power_display( ControlClient client, char*  args )
16658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    goldfish_battery_display(do_control_write, client);
16678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
16688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
16718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_ac_state( ControlClient  client, char*  args )
16728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
16748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "on") == 0) {
16758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(1, POWER_SUPPLY_PROP_ONLINE, 1);
16768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "off") == 0) {
16798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(1, POWER_SUPPLY_PROP_ONLINE, 0);
16808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
16838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: Usage: \"ac on\" or \"ac off\"\n" );
16858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
16868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
16898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_battery_status( ControlClient  client, char*  args )
16908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
16928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "unknown") == 0) {
16938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_UNKNOWN);
16948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
16968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "charging") == 0) {
16978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_CHARGING);
16988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
16998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "discharging") == 0) {
17018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_DISCHARGING);
17028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "not-charging") == 0) {
17058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_NOT_CHARGING);
17068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "full") == 0) {
17098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_STATUS, POWER_SUPPLY_STATUS_FULL);
17108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: Usage: \"status unknown|charging|discharging|not-charging|full\"\n" );
17158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
17168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
17198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_battery_present( ControlClient  client, char*  args )
17208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
17228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "true") == 0) {
17238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_PRESENT, 1);
17248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "false") == 0) {
17278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_PRESENT, 0);
17288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: Usage: \"present true\" or \"present false\"\n" );
17338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
17348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
17378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_battery_health( ControlClient  client, char*  args )
17388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
17408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "unknown") == 0) {
17418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_UNKNOWN);
17428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "good") == 0) {
17458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_GOOD);
17468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "overheat") == 0) {
17498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_OVERHEAT);
17508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "dead") == 0) {
17538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_DEAD);
17548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "overvoltage") == 0) {
17578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_OVERVOLTAGE);
17588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (strcasecmp(args, "failure") == 0) {
17618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_HEALTH, POWER_SUPPLY_HEALTH_UNSPEC_FAILURE);
17628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: Usage: \"health unknown|good|overheat|dead|overvoltage|failure\"\n" );
17678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
17688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
17718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_battery_capacity( ControlClient  client, char*  args )
17728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (args) {
17748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int capacity;
17758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (sscanf(args, "%d", &capacity) == 1 && capacity >= 0 && capacity <= 100) {
17778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            goldfish_battery_set_prop(0, POWER_SUPPLY_PROP_CAPACITY, capacity);
17788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
17798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
17808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
17818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "KO: Usage: \"capacity <percentage>\"\n" );
17838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
17848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  power_commands[] =
17888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "display", "display battery and charger state",
17908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "display battery and charger state\r\n", NULL,
17918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_power_display, NULL },
17928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "ac", "set AC charging state",
17948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'ac on|off' allows you to set the AC charging state to on or off\r\n", NULL,
17958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_ac_state, NULL },
17968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "status", "set battery status",
17988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'status unknown|charging|discharging|not-charging|full' allows you to set battery status\r\n", NULL,
17998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_battery_status, NULL },
18008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "present", "set battery present state",
18028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'present true|false' allows you to set battery present state to true or false\r\n", NULL,
18038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_battery_present, NULL },
18048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "health", "set battery health state",
18068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'health unknown|good|overheat|dead|overvoltage|failure' allows you to set battery health state\r\n", NULL,
18078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_battery_health, NULL },
18088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "capacity", "set battery capacity state",
18108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'capacity <percentage>' allows you to set battery capacity to a value 0 - 100\r\n", NULL,
18118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    do_battery_capacity, NULL },
18128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
18148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
18158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
18178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
18188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
18198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                         E  V  E  N  T   C O M M A N D S                         ******/
18208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
18218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
18228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
18238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
18268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_event_send( ControlClient  client, char*  args )
18278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*   p;
18298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
18318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: Usage: event send <type>:<code>:<value> ...\r\n" );
18328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
18338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
18348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    p = args;
18368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (*p) {
18378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char*  q;
183888935f701f51d84ed536cb55cc7b2ba391d7597eDavid 'Digit' Turner        char   temp[128];
18398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int    type, code, value, ret;
18408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
184188935f701f51d84ed536cb55cc7b2ba391d7597eDavid 'Digit' Turner        p += strspn( p, " \t" );  /* skip spaces */
18428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (*p == 0)
18438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        q  = p + strcspn( p, " \t" );
18468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (q == p)
18488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
18498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1850c7389bd69e570a2c8432b37399aff1976b021f0fAndrew Hsieh        snprintf(temp, sizeof temp, "%.*s", (int)(intptr_t)(q-p), p);
185188935f701f51d84ed536cb55cc7b2ba391d7597eDavid 'Digit' Turner        ret = android_event_from_str( temp, &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
19710158ea3220978ecc0fa1738e4a0bdae83fa36175David 'Digit' Turner    /* Get active charmap. */
19720158ea3220978ecc0fa1738e4a0bdae83fa36175David 'Digit' Turner    charmap = android_get_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
20332ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/********************************************************************************************/
20342ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/********************************************************************************************/
20352ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/*****                                                                                 ******/
20362ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/*****                      S N A P S H O T   C O M M A N D S                          ******/
20372ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/*****                                                                                 ******/
20382ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/********************************************************************************************/
20392ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije/********************************************************************************************/
20402ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20412ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int
204295a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turnercontrol_write_out_cb(void* opaque, const char* str, int strsize)
20432ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
20442ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ControlClient client = opaque;
204595a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    control_control_write(client, str, strsize);
204695a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    return strsize;
20472ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
20482ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20492ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int
205095a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turnercontrol_write_err_cb(void* opaque, const char* str, int strsize)
20512ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
20522ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    int ret = 0;
20532ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ControlClient client = opaque;
20542ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    ret += control_write(client, "KO: ");
205595a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    control_control_write(client, str, strsize);
205695a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    return ret + strsize;
20572ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
20582ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20592ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int
20602ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijedo_snapshot_list( ControlClient  client, char*  args )
20612ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
206295a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    int64_t ret;
206395a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    Monitor *out = monitor_fake_new(client, control_write_out_cb);
206495a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    Monitor *err = monitor_fake_new(client, control_write_err_cb);
206595a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    do_info_snapshots(out, err);
206695a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    ret = monitor_fake_get_bytes(err);
206795a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    monitor_fake_free(err);
206895a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    monitor_fake_free(out);
20692ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20702ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret > 0;
20712ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
20722ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20732ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int
20742ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijedo_snapshot_save( ControlClient  client, char*  args )
20752ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
207695a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    int64_t ret;
20779fb360ec4c47d750711c8f1776c180e3802b0aabDavid 'Digit' Turner
20789fb360ec4c47d750711c8f1776c180e3802b0aabDavid 'Digit' Turner    if (args == NULL) {
20799fb360ec4c47d750711c8f1776c180e3802b0aabDavid 'Digit' Turner        control_write(client, "KO: argument missing, try 'avd snapshot save <name>'\r\n");
20809fb360ec4c47d750711c8f1776c180e3802b0aabDavid 'Digit' Turner        return -1;
20819fb360ec4c47d750711c8f1776c180e3802b0aabDavid 'Digit' Turner    }
20829fb360ec4c47d750711c8f1776c180e3802b0aabDavid 'Digit' Turner
208395a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    Monitor *err = monitor_fake_new(client, control_write_err_cb);
208495a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    do_savevm(err, args);
208595a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    ret = monitor_fake_get_bytes(err);
208695a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    monitor_fake_free(err);
20872ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20882ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret > 0; // no output on error channel indicates success
20892ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
20902ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
20912ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int
20922ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijedo_snapshot_load( ControlClient  client, char*  args )
20932ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
209495a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    int64_t ret;
20959fb360ec4c47d750711c8f1776c180e3802b0aabDavid 'Digit' Turner
20969fb360ec4c47d750711c8f1776c180e3802b0aabDavid 'Digit' Turner    if (args == NULL) {
20979fb360ec4c47d750711c8f1776c180e3802b0aabDavid 'Digit' Turner        control_write(client, "KO: argument missing, try 'avd snapshot load <name>'\r\n");
20989fb360ec4c47d750711c8f1776c180e3802b0aabDavid 'Digit' Turner        return -1;
20999fb360ec4c47d750711c8f1776c180e3802b0aabDavid 'Digit' Turner    }
21009fb360ec4c47d750711c8f1776c180e3802b0aabDavid 'Digit' Turner
210195a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    Monitor *err = monitor_fake_new(client, control_write_err_cb);
210295a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    do_loadvm(err, args);
210395a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    ret = monitor_fake_get_bytes(err);
210495a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    monitor_fake_free(err);
21052ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
21062ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret > 0;
21072ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
21082ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
21092ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic int
21102ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijedo_snapshot_del( ControlClient  client, char*  args )
21112ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
211295a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    int64_t ret;
21139fb360ec4c47d750711c8f1776c180e3802b0aabDavid 'Digit' Turner
21149fb360ec4c47d750711c8f1776c180e3802b0aabDavid 'Digit' Turner    if (args == NULL) {
21159fb360ec4c47d750711c8f1776c180e3802b0aabDavid 'Digit' Turner        control_write(client, "KO: argument missing, try 'avd snapshot del <name>'\r\n");
21169fb360ec4c47d750711c8f1776c180e3802b0aabDavid 'Digit' Turner        return -1;
21179fb360ec4c47d750711c8f1776c180e3802b0aabDavid 'Digit' Turner    }
21189fb360ec4c47d750711c8f1776c180e3802b0aabDavid 'Digit' Turner
211995a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    Monitor *err = monitor_fake_new(client, control_write_err_cb);
212095a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    do_delvm(err, args);
212195a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    ret = monitor_fake_get_bytes(err);
212295a83ce7ee413954ba6325584ea659c6685edfd5David 'Digit' Turner    monitor_fake_free(err);
21232ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
21242ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    return ret > 0;
21252ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije}
21262ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
21272ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thijestatic const CommandDefRec  snapshot_commands[] =
21282ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije{
21292ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { "list", "list available state snapshots",
21302ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "'avd snapshot list' will show a list of all state snapshots that can be loaded\r\n",
21312ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    NULL, do_snapshot_list, NULL },
21322ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
21332ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { "save", "save state snapshot",
21342ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "'avd snapshot save <name>' will save the current (run-time) state to a snapshot with the given name\r\n",
21352ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    NULL, do_snapshot_save, NULL },
21362ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
21372ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { "load", "load state snapshot",
21382ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "'avd snapshot load <name>' will load the state snapshot of the given name\r\n",
21392ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    NULL, do_snapshot_load, NULL },
21402ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
21412ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { "del", "delete state snapshot",
21422ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "'avd snapshot del <name>' will delete the state snapshot with the given name\r\n",
21432ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    NULL, do_snapshot_del, NULL },
21442ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
21452ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { NULL, NULL, NULL, NULL, NULL, NULL }
21462ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije};
21472ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
21482ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
21498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
21518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
21528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
21538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                               V M   C O M M A N D S                             ******/
21548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
21558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
21568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
21578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
21598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_avd_stop( ControlClient  client, char*  args )
21608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
21618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!vm_running) {
21628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: virtual device already stopped\r\n" );
21638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
21648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
21658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    vm_stop(EXCP_INTERRUPT);
21668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
21678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
21688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
21708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_avd_start( ControlClient  client, char*  args )
21718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
21728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (vm_running) {
21738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: virtual device already running\r\n" );
21748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
21758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
21768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    vm_start();
21778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
21788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
21798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
21818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_avd_status( ControlClient  client, char*  args )
21828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
21838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    control_write( client, "virtual device is %s\r\n", vm_running ? "running" : "stopped" );
21848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
21858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
21868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
21888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_avd_name( ControlClient  client, char*  args )
21898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2190ec6cedb56251ce3d5703c43c352d373c0baaa76dDavid 'Digit' Turner    control_write( client, "%s\r\n", android_hw->avd_name);
21918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
21928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
21938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  vm_commands[] =
21958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
21968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "stop", "stop the virtual device",
21978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'avd stop' stops the virtual device immediately, use 'avd start' to continue execution\r\n",
21988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_avd_stop, NULL },
21998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "start", "start/restart the virtual device",
22018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'avd start' will start or continue the virtual device, use 'avd stop' to stop it\r\n",
22028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_avd_start, NULL },
22038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "status", "query virtual device status",
22052ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "'avd status' will indicate whether the virtual device is running or not\r\n",
22068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_avd_status, NULL },
22078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "name", "query virtual device name",
22098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'avd name' will return the name of this virtual device\r\n",
22108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_avd_name, NULL },
22118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22122ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { "snapshot", "state snapshot commands",
22132ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "allows you to save and restore the virtual device state in snapshots\r\n",
22142ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    NULL, NULL, snapshot_commands },
22152ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije
22168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
22178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
22188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
22208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
22218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
22228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                             G E O   C O M M A N D S                             ******/
22238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
22248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
22258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
22268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
22288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_geo_nmea( ControlClient  client, char*  args )
22298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
22308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
22318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: NMEA sentence missing, try 'help geo nmea'\r\n" );
22328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
22338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
22348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!android_gps_cs) {
22358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: no GPS emulation in this virtual device\r\n" );
22368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
22378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
22388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    android_gps_send_nmea( args );
22398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
22408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
22418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
22438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_geo_fix( ControlClient  client, char*  args )
22448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
22454afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock    // GEO_SAT2 provides bug backwards compatibility.
22464afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock    enum { GEO_LONG = 0, GEO_LAT, GEO_ALT, GEO_SAT, GEO_SAT2, NUM_GEO_PARAMS };
22478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*   p = args;
22484afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock    int     top_param = -1;
22494afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock    double  params[ NUM_GEO_PARAMS ];
2250657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner    int     n_satellites = 1;
22518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2252a2c14f947951612b45024095afd2210aa7368773David 'Digit' Turner    static  int last_time = 0;
22538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!p)
22558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = "";
22568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* tokenize */
22588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (*p) {
22598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char*   end;
22608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        double  val = strtod( p, &end );
22618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (end == p) {
22638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "KO: argument '%s' is not a number\n", p );
22648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
22658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
22668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22674afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock        params[++top_param] = val;
22684afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock        if (top_param + 1 == NUM_GEO_PARAMS)
22698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        p = end;
22728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        while (*p && (p[0] == ' ' || p[0] == '\t'))
22738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p += 1;
22748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
22758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* sanity check */
22774afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock    if (top_param < GEO_LAT) {
22788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: not enough arguments: see 'help geo fix' for details\r\n" );
22798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
22808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
22818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22824afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock    /* check number of satellites, must be integer between 1 and 12 */
22834afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock    if (top_param >= GEO_SAT) {
22844afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock        int sat_index = (top_param >= GEO_SAT2) ? GEO_SAT2 : GEO_SAT;
22854afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock        n_satellites = (int) params[sat_index];
22864afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock        if (n_satellites != params[sat_index]
22874afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock            || n_satellites < 1 || n_satellites > 12) {
2288657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner            control_write( client, "KO: invalid number of satellites. Must be an integer between 1 and 12\r\n");
2289657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner            return -1;
2290657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        }
2291657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner    }
2292657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner
22938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* generate an NMEA sentence for this fix */
22948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
22958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        STRALLOC_DEFINE(s);
22968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        double   val;
22978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int      deg, min;
22988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char     hemi;
22998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2300657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        /* format overview:
2301657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    time of fix      123519     12:35:19 UTC
2302657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    latitude         4807.038   48 degrees, 07.038 minutes
2303657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    north/south      N or S
2304657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    longitude        01131.000  11 degrees, 31. minutes
2305657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    east/west        E or W
2306657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    fix quality      1          standard GPS fix
2307657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    satellites       1 to 12    number of satellites being tracked
2308657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    HDOP             <dontcare> horizontal dilution
2309657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    altitude         546.       altitude above sea-level
2310657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    altitude units   M          to indicate meters
2311657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    diff             <dontcare> height of sea-level above ellipsoid
2312657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    diff units       M          to indicate meters (should be <dontcare>)
2313657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    dgps age         <dontcare> time in seconds since last DGPS fix
2314657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         *    dgps sid         <dontcare> DGPS station id
2315657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner         */
2316657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner
23178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* first, the time */
23188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stralloc_add_format( s, "$GPGGA,%06d", last_time );
23198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        last_time ++;
23208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* then the latitude */
23228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hemi = 'N';
23234afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock        val  = params[GEO_LAT];
23248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (val < 0) {
23258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            hemi = 'S';
23268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val  = -val;
23278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
23288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        deg = (int) val;
2329657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        val = 60*(val - deg);
2330657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        min = (int) val;
2331631f2555ed2b50a07ea19eaefa495a028ab1991aDavid 'Digit' Turner        val = 10000*(val - min);
2332657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        stralloc_add_format( s, ",%02d%02d.%04d,%c", deg, min, (int)val, hemi );
23338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* the longitude */
23358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hemi = 'E';
23364afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock        val  = params[GEO_LONG];
23378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (val < 0) {
23388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            hemi = 'W';
23398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            val  = -val;
23408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
23418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        deg = (int) val;
2342657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        val = 60*(val - deg);
2343657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        min = (int) val;
2344631f2555ed2b50a07ea19eaefa495a028ab1991aDavid 'Digit' Turner        val = 10000*(val - min);
2345657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        stralloc_add_format( s, ",%02d%02d.%04d,%c", deg, min, (int)val, hemi );
23468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2347657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        /* bogus fix quality, satellite count and dilution */
2348657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        stralloc_add_format( s, ",1,%02d,", n_satellites );
23498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2350657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner        /* optional altitude + bogus diff */
23514afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock        if (top_param >= GEO_ALT) {
23524afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock            stralloc_add_format( s, ",%.1g,M,0.,M", params[GEO_ALT] );
23538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        } else {
2354657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner            stralloc_add_str( s, ",,,," );
23558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
23568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* bogus rest and checksum */
23578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stralloc_add_str( s, ",,,*47" );
23588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* send it, then free */
23608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        android_gps_send_nmea( stralloc_cstr(s) );
23618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stralloc_reset( s );
23628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
23638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
23648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
23658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  geo_commands[] =
23678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
23688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "nmea", "send an GPS NMEA sentence",
23698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'geo nema <sentence>' sends a NMEA 0183 sentence to the emulated device, as\r\n"
23708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "if it came from an emulated GPS modem. <sentence> must begin with '$GP'. only\r\n"
23718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'$GPGGA' and '$GPRCM' sentences are supported at the moment.\r\n",
23728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_geo_nmea, NULL },
23738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "fix", "send a simple GPS fix",
23754afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock    "'geo fix <longitude> <latitude> [<altitude> [<satellites>]]'\r\n"
23764afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock    " allows you to send a simple GPS fix to the emulated system.\r\n"
23774afdaf1285ecdcbcfeac6d3e9be0b9b0de0e2b07Tim Baverstock    " The parameters are:\r\n\r\n"
23788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "  <longitude>   longitude, in decimal degrees\r\n"
23798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "  <latitude>    latitude, in decimal degrees\r\n"
23808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "  <altitude>    optional altitude in meters\r\n"
2381657a3521a1f4d354b57f0e524b1cd57bed177bb0David 'Digit' Turner    "  <satellites>  number of satellites being tracked (1-12)\r\n"
23828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "\r\n",
23838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_geo_fix, NULL },
23848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
23868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
23878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
23908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
23918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
2392736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan/*****                        S E N S O R S  C O M M A N D S                           ******/
2393736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan/*****                                                                                 ******/
2394736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan/********************************************************************************************/
2395736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan/********************************************************************************************/
2396736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2397736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan/* For sensors user prompt string size.*/
2398736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan#define SENSORS_INFO_SIZE 150
2399736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2400736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan/* Get sensor data - (a,b,c) from sensor name */
2401736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wanstatic int
2402736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wando_sensors_get( ControlClient client, char* args )
2403736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan{
2404736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    if (! args) {
2405736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        control_write( client, "KO: Usage: \"get <sensorname>\"\n" );
2406736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        return -1;
2407736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    }
2408736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2409736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    int status = SENSOR_STATUS_UNKNOWN;
2410736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    char sensor[strlen(args) + 1];
2411736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    if (1 != sscanf( args, "%s", &sensor[0] ))
2412736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        goto SENSOR_STATUS_ERROR;
2413736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2414736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    int sensor_id = android_sensors_get_id_from_name( sensor );
2415736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    char buffer[SENSORS_INFO_SIZE] = { 0 };
2416736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    float a, b, c;
2417736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2418736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    if (sensor_id < 0) {
2419736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        status = sensor_id;
2420736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        goto SENSOR_STATUS_ERROR;
2421736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    } else {
2422736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        status = android_sensors_get( sensor_id, &a, &b, &c );
2423736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        if (status != SENSOR_STATUS_OK)
2424736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan            goto SENSOR_STATUS_ERROR;
2425736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        snprintf( buffer, sizeof(buffer),
2426736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan                "%s = %g:%g:%g\r\n", sensor, a, b, c );
2427736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        do_control_write( client, buffer );
2428736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        return 0;
2429736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    }
2430736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2431736e01f86f4ec4049bb5795f1ddb979132b05333Tim WanSENSOR_STATUS_ERROR:
2432736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    switch(status) {
2433736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    case SENSOR_STATUS_NO_SERVICE:
2434736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        snprintf( buffer, sizeof(buffer), "KO: No sensor service found!\r\n" );
2435736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        break;
2436736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    case SENSOR_STATUS_DISABLED:
2437736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        snprintf( buffer, sizeof(buffer), "KO: '%s' sensor is disabled.\r\n", sensor );
2438736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        break;
2439736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    case SENSOR_STATUS_UNKNOWN:
2440736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        snprintf( buffer, sizeof(buffer),
2441736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan                "KO: unknown sensor name: %s, run 'sensor status' to get available sensors.\r\n", sensor );
2442736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        break;
2443736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    default:
2444736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        snprintf( buffer, sizeof(buffer), "KO: '%s' sensor: exception happens.\r\n", sensor );
2445736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    }
2446736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    do_control_write( client, buffer );
2447736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    return -1;
2448736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan}
2449736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2450736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan/* set sensor data - (a,b,c) from sensor name */
2451736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wanstatic int
2452736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wando_sensors_set( ControlClient client, char* args )
2453736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan{
2454736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    if (! args) {
2455736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        control_write( client, "KO: Usage: \"set <sensorname> <value-a>[:<value-b>[:<value-c>]]\"\n" );
2456736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        return -1;
2457736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    }
2458736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2459736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    int status;
2460736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    char* sensor;
2461736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    char* value;
2462736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    char* args_dup = strdup( args );
2463736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    if (args_dup == NULL) {
2464736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        control_write( client, "KO: Memory allocation failed.\n" );
2465736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        return -1;
2466736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    }
2467736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    char* p = args_dup;
2468736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2469736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    /* Parsing the args to get sensor name string */
2470736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    while (*p && isspace(*p)) p++;
2471736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    if (*p == 0)
2472736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        goto INPUT_ERROR;
2473736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    sensor = p;
2474736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2475736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    /* Parsing the args to get value string */
2476736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    while (*p && (! isspace(*p))) p++;
2477736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    if (*p == 0 || *(p + 1) == 0/* make sure value isn't NULL */)
2478736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        goto INPUT_ERROR;
2479736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    *p = 0;
2480736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    value = p + 1;
2481736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2482736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    if (! (strlen(sensor) && strlen(value)))
2483736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        goto INPUT_ERROR;
2484736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2485736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    int sensor_id = android_sensors_get_id_from_name( sensor );
2486736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    char buffer[SENSORS_INFO_SIZE] = { 0 };
2487736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2488736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    if (sensor_id < 0) {
2489736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        status = sensor_id;
2490736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        goto SENSOR_STATUS_ERROR;
2491736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    } else {
2492736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        float fvalues[3];
2493736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        status = android_sensors_get( sensor_id, &fvalues[0], &fvalues[1], &fvalues[2] );
2494736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        if (status != SENSOR_STATUS_OK)
2495736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan            goto SENSOR_STATUS_ERROR;
2496736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2497736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        /* Parsing the value part to get the sensor values(a, b, c) */
2498736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        int i;
2499736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        char* pnext;
2500736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        char* pend = value + strlen(value);
2501736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        for (i = 0; i < 3; i++, value = pnext + 1) {
2502736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan            pnext=strchr( value, ':' );
2503736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan            if (pnext) {
2504736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan                *pnext = 0;
2505736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan            } else {
2506736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan                pnext = pend;
2507736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan            }
2508736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2509736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan            if (pnext > value) {
2510736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan                if (1 != sscanf( value,"%g", &fvalues[i] ))
2511736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan                    goto INPUT_ERROR;
2512736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan            }
2513736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        }
2514736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2515736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        status = android_sensors_set( sensor_id, fvalues[0], fvalues[1], fvalues[2] );
2516736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        if (status != SENSOR_STATUS_OK)
2517736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan            goto SENSOR_STATUS_ERROR;
2518736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2519736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        free( args_dup );
2520736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        return 0;
2521736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    }
2522736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2523736e01f86f4ec4049bb5795f1ddb979132b05333Tim WanSENSOR_STATUS_ERROR:
2524736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    switch(status) {
2525736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    case SENSOR_STATUS_NO_SERVICE:
2526736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        snprintf( buffer, sizeof(buffer), "KO: No sensor service found!\r\n" );
2527736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        break;
2528736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    case SENSOR_STATUS_DISABLED:
2529736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        snprintf( buffer, sizeof(buffer), "KO: '%s' sensor is disabled.\r\n", sensor );
2530736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        break;
2531736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    case SENSOR_STATUS_UNKNOWN:
2532736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        snprintf( buffer, sizeof(buffer),
2533736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan                "KO: unknown sensor name: %s, run 'sensor status' to get available sensors.\r\n", sensor );
2534736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        break;
2535736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    default:
2536736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        snprintf( buffer, sizeof(buffer), "KO: '%s' sensor: exception happens.\r\n", sensor );
2537736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    }
2538736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    do_control_write( client, buffer );
2539736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    free( args_dup );
2540736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    return -1;
2541736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2542736e01f86f4ec4049bb5795f1ddb979132b05333Tim WanINPUT_ERROR:
2543736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    control_write( client, "KO: Usage: \"set <sensorname> <value-a>[:<value-b>[:<value-c>]]\"\n" );
2544736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    free( args_dup );
2545736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    return -1;
2546736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan}
2547736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2548736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan/* get all available sensor names and enable status respectively. */
2549736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wanstatic int
2550736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wando_sensors_status( ControlClient client, char* args )
2551736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan{
2552736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    uint8_t id, status;
2553736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    char buffer[SENSORS_INFO_SIZE] = { 0 };
2554736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2555736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    for(id = 0; id < MAX_SENSORS; id++) {
2556736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        status = android_sensors_get_sensor_status( id );
2557736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        snprintf( buffer, sizeof(buffer), "%s: %s\n",
2558736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan                android_sensors_get_name_from_id(id), (status ? "enabled.":"disabled.") );
2559736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan        control_write( client, buffer );
2560736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    }
2561736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2562736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    return 0;
2563736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan}
2564736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2565736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan/* Sensor commands for get/set sensor values and get available sensor names. */
2566736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wanstatic const CommandDefRec sensor_commands[] =
2567736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan{
2568736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    { "status", "list all sensors and their status.",
2569736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan      "'status': list all sensors and their status.\r\n",
2570736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan      NULL, do_sensors_status, NULL },
2571736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2572736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    { "get", "get sensor values",
2573736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan      "'get <sensorname>' returns the values of a given sensor.\r\n",
2574736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan      NULL, do_sensors_get, NULL },
2575736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2576736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    { "set", "set sensor values",
2577736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan      "'set <sensorname> <value-a>[:<value-b>[:<value-c>]]' set the values of a given sensor.\r\n",
2578736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan      NULL, do_sensors_set, NULL },
2579736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2580736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    { NULL, NULL, NULL, NULL, NULL, NULL }
2581736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan};
2582736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
2583736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan/********************************************************************************************/
2584736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan/********************************************************************************************/
2585736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan/*****                                                                                 ******/
25868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                           M A I N   C O M M A N D S                             ******/
25878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
25888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
25898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
25908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
25928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_window_scale( ControlClient  client, char*  args )
25938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
25948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    double  scale;
25958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int     is_dpi = 0;
25968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char*   end;
25978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!args) {
25998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        control_write( client, "KO: argument missing, try 'window scale <scale>'\r\n" );
26008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
26018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
26028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    scale = strtol( args, &end, 10 );
26048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (end > args && !memcmp( end, "dpi", 4 )) {
26058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        is_dpi = 1;
26068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
26078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    else {
26088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        scale = strtod( args, &end );
26098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (end == args || end[0]) {
26108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            control_write( client, "KO: argument <scale> must be a real number, or an integer followed by 'dpi'\r\n" );
26118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
26128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
26138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
26148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2615496168ed6e29479bcc2c5cac2ade6f045013a59cDavid 'Digit' Turner    android_emulator_set_window_scale(scale, is_dpi);
26168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
26178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
26188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec  window_commands[] =
26208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
26218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "scale", "change the window scale",
26228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "'window scale <scale>' allows you to change the scale of the emulator window at runtime\r\n"
26238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "<scale> must be either a real number between 0.1 and 3.0, or an integer followed by\r\n"
26248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "the 'dpi' prefix (as in '120dpi')\r\n",
26258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, do_window_scale, NULL },
26268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
26288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
26298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
26318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
26328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
2633e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/*****                           Q E M U   C O M M A N D S                             ******/
2634e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/*****                                                                                 ******/
2635e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/********************************************************************************************/
2636e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/********************************************************************************************/
2637e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2638e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnerstatic int
2639e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnerdo_qemu_monitor( ControlClient client, char* args )
2640e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner{
2641aa1180ca05774398245953deb306c0e25829afeeDavid 'Digit' Turner    control_write(client, "KO: QEMU support no longer available\r\n");
2642aa1180ca05774398245953deb306c0e25829afeeDavid 'Digit' Turner    return -1;
2643e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner}
2644e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2645e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#ifdef CONFIG_STANDALONE_CORE
2646d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine/* UI settings, passed to the core via -ui-settings command line parameter. */
2647d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkineextern char* android_op_ui_settings;
2648d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine
2649d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkinestatic int
2650d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkinedo_attach_ui( ControlClient client, char* args )
2651d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine{
2652d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    // Make sure that there are no UI already attached to this console.
2653d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    if (attached_ui_client != NULL) {
2654d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine        control_write( client, "KO: Another UI is attached to this core!\r\n" );
2655d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine        control_client_destroy(client);
2656d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine        return -1;
2657d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    }
2658d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine
265985276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    if (!attachUiProxy_create(client->sock)) {
2660d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine        char reply_buf[4096];
266185276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine        attached_ui_client = client;
266285276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine        // Reply "OK" with the saved -ui-settings property.
2663d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine        snprintf(reply_buf, sizeof(reply_buf), "OK: %s\r\n", android_op_ui_settings);
2664d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine        control_write( client, reply_buf);
2665d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    } else {
266685276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine        control_write( client, "KO\r\n" );
266785276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine        control_client_destroy(client);
266885276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine        return -1;
2669d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    }
2670d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine
2671d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    return 0;
2672d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine}
2673d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine
267485276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkinevoid
267585276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkinedestroy_attach_ui_client(void)
267685276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine{
267785276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    if (attached_ui_client != NULL) {
267885276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine        control_client_destroy(attached_ui_client);
267985276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine    }
268085276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine}
268185276806ec6ac969d7befa2496c1de59adaaac74Vladimir Chtchetkine
2682e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkinestatic int
2683e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkinedo_create_framebuffer_service( ControlClient client, char* args )
2684e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine{
268594a2fba98924c6684650d66409934358cb0c9d09Vladimir Chtchetkine    ProxyFramebuffer* core_fb;
2686e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    const char* protocol = "-raw";   // Default framebuffer exchange protocol.
26877a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner    char reply_buf[64];
2688e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine
2689e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    // Protocol type is defined by the arguments passed with the stream switch
2690e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    // command.
2691e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    if (args != NULL && *args != '\0') {
2692e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        size_t token_len;
2693e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        const char* param_end = strchr(args, ' ');
2694e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        if (param_end == NULL) {
2695e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine            param_end = args + strlen(args);
2696e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        }
2697e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        token_len = param_end - args;
2698e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        protocol = args;
2699e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine
2700e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        // Make sure that this is one of the supported protocols.
2701e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        if (strncmp(protocol, "-raw", token_len) &&
2702e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine            strncmp(protocol, "-shared", token_len)) {
2703e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine            derror("Invalid framebuffer parameter %s\n", protocol);
2704e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine            control_write( client, "KO: Invalid parameter\r\n" );
2705e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine            control_client_destroy(client);
2706e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine            return -1;
2707e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        }
2708e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    }
2709e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine
27107a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner    core_fb = proxyFb_create(client->sock, protocol);
27117a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner    if (core_fb == NULL) {
2712e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        control_write( client, "KO\r\n" );
2713e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        control_client_destroy(client);
2714e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine        return -1;
2715e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    }
2716e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine
27177a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner    // Reply "OK" with the framebuffer's bits per pixel
27187a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner    snprintf(reply_buf, sizeof(reply_buf), "OK: -bitsperpixel=%d\r\n",
27197a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner             proxyFb_get_bits_per_pixel(core_fb));
27207a5ee57895822a769f48ab40e590711a2459e2d1David 'Digit' Turner    control_write( client, reply_buf);
2721e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    return 0;
2722e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine}
27239411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine
27249411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkinestatic int
27259411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkinedo_create_user_events_service( ControlClient client, char* args )
27269411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine{
27276b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    // Make sure that there are no user events client already existing.
27289411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine    if (user_events_client != NULL) {
27299411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine        control_write( client, "KO: Another user events service is already existing!\r\n" );
27309411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine        control_client_destroy(client);
27319411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine        return -1;
27329411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine    }
27339411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine
2734250b2e00af04f8407dea564e643dad4ef08b8a88Vladimir Chtchetkine    if (!userEventsImpl_create(client->sock)) {
27359411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine        char reply_buf[4096];
27369411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine        user_events_client = client;
27379411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine        snprintf(reply_buf, sizeof(reply_buf), "OK\r\n");
27389411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine        control_write( client, reply_buf);
27399411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine    } else {
27409411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine        control_write( client, "KO\r\n" );
27419411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine        control_client_destroy(client);
27429411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine        return -1;
27439411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine    }
27449411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine
27459411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine    return 0;
27469411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine}
27476ee1c4edbd30b7c7aff9d6e13793207278aa1660Vladimir Chtchetkine
27486ee1c4edbd30b7c7aff9d6e13793207278aa1660Vladimir Chtchetkinevoid
2749250b2e00af04f8407dea564e643dad4ef08b8a88Vladimir Chtchetkinedestroy_user_events_client(void)
27506ee1c4edbd30b7c7aff9d6e13793207278aa1660Vladimir Chtchetkine{
27516ee1c4edbd30b7c7aff9d6e13793207278aa1660Vladimir Chtchetkine    if (user_events_client != NULL) {
27526ee1c4edbd30b7c7aff9d6e13793207278aa1660Vladimir Chtchetkine        control_client_destroy(user_events_client);
27536ee1c4edbd30b7c7aff9d6e13793207278aa1660Vladimir Chtchetkine    }
27546ee1c4edbd30b7c7aff9d6e13793207278aa1660Vladimir Chtchetkine}
27556b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine
27566b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkinestatic int
27576b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkinedo_create_ui_core_ctl_service( ControlClient client, char* args )
27586b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine{
27596b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    // Make sure that there are no ui control client already existing.
27606b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    if (ui_core_ctl_client != NULL) {
27616b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        control_write( client, "KO: Another UI control service is already existing!\r\n" );
27626b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        control_client_destroy(client);
27636b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        return -1;
27646b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    }
27656b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine
2766777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    if (!coreCmdImpl_create(client->sock)) {
27676b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        char reply_buf[4096];
27686b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        ui_core_ctl_client = client;
27696b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        snprintf(reply_buf, sizeof(reply_buf), "OK\r\n");
27706b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        control_write( client, reply_buf);
27716b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    } else {
27726b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        control_write( client, "KO\r\n" );
27736b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        control_client_destroy(client);
27746b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        return -1;
27756b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    }
27766b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine
27776b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    return 0;
27786b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine}
27796b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine
27806b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkinevoid
27816b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkinedestroy_ui_core_ctl_client(void)
27826b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine{
27836b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    if (ui_core_ctl_client != NULL) {
27846b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        control_client_destroy(ui_core_ctl_client);
27856b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    }
27866b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine}
27876b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine
2788777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkinevoid
2789777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkinedestroy_corecmd_client(void)
2790777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine{
2791777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    if (ui_core_ctl_client != NULL) {
2792777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        control_client_destroy(ui_core_ctl_client);
2793777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    }
2794777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine}
2795777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
27966b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkinestatic int
27976b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkinedo_create_core_ui_ctl_service( ControlClient client, char* args )
27986b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine{
27996b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    // Make sure that there are no ui control client already existing.
28006b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    if (core_ui_ctl_client != NULL) {
28016b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        control_write( client, "KO: Another UI control service is already existing!\r\n" );
28026b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        control_client_destroy(client);
28036b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        return -1;
28046b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    }
28056b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine
2806777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    if (!uiCmdProxy_create(client->sock)) {
28076b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        char reply_buf[4096];
28086b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        core_ui_ctl_client = client;
28096b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        snprintf(reply_buf, sizeof(reply_buf), "OK\r\n");
28106b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        control_write( client, reply_buf);
28116b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    } else {
28126b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        control_write( client, "KO\r\n" );
28136b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        control_client_destroy(client);
28146b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        return -1;
28156b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    }
28166b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine
28176b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    return 0;
28186b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine}
28196b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine
28206b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkinevoid
28216b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkinedestroy_core_ui_ctl_client(void)
28226b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine{
28236b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    if (core_ui_ctl_client != NULL) {
28246b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine        control_client_destroy(core_ui_ctl_client);
28256b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    }
28266b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine}
2827777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
2828777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkinevoid
2829777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkinedestroy_uicmd_client(void)
2830777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine{
2831777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    if (core_ui_ctl_client != NULL) {
2832777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine        control_client_destroy(core_ui_ctl_client);
2833777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine    }
2834777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine}
2835777eb68eb60cac18f4b62e2e1b14a906875cbe7aVladimir Chtchetkine
2836e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#endif  // CONFIG_STANDALONE_CORE
2837e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine
2838e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turnerstatic const CommandDefRec  qemu_commands[] =
2839e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner{
2840e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    { "monitor", "enter QEMU monitor",
2841e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    "Enter the QEMU virtual machine monitor\r\n",
2842e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    NULL, do_qemu_monitor, NULL },
2843e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2844e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#ifdef CONFIG_STANDALONE_CORE
2845a473d81826d44905bc0d7ec8c9b39aef1cf87fb7Vladimir Chtchetkine    { "attach-UI", "attach UI to the core",
2846d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    "Attach UI to the core\r\n",
2847d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    NULL, do_attach_ui, NULL },
2848d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine
2849e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    { "framebuffer", "create framebuffer service",
2850e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    "Create framebuffer service\r\n",
2851e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine    NULL, do_create_framebuffer_service, NULL },
28529411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine
2853a473d81826d44905bc0d7ec8c9b39aef1cf87fb7Vladimir Chtchetkine    { "user-events", "create user events service",
28549411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine    "Create user events service\r\n",
28559411a562e1ab772732a4d5147c9103a638837c82Vladimir Chtchetkine    NULL, do_create_user_events_service, NULL },
28566b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine
2857a473d81826d44905bc0d7ec8c9b39aef1cf87fb7Vladimir Chtchetkine    { "ui-core-control", "create UI control service",
28586b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    "Create UI control service\r\n",
28596b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    NULL, do_create_ui_core_ctl_service, NULL },
28606b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine
2861a473d81826d44905bc0d7ec8c9b39aef1cf87fb7Vladimir Chtchetkine    { "core-ui-control", "create UI control service",
28626b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    "Create UI control service\r\n",
28636b985d708d64008eee69fe0c3f03c6e3c61e7f73Vladimir Chtchetkine    NULL, do_create_core_ui_ctl_service, NULL },
2864e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine#endif  // CONFIG_STANDALONE_CORE
2865e95660aadc669784406d5f5a867988b8ecc2ed0dVladimir Chtchetkine
2866e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    { NULL, NULL, NULL, NULL, NULL, NULL }
2867e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner};
2868e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2869e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2870e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/********************************************************************************************/
2871e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/********************************************************************************************/
2872e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner/*****                                                                                 ******/
28738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                           M A I N   C O M M A N D S                             ******/
28748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*****                                                                                 ******/
28758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
28768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/********************************************************************************************/
28778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
28788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int
28798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectdo_kill( ControlClient  client, char*  args )
28808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2881d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    control_write( client, "OK: killing emulator, bye bye\r\n" );
2882d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine    exit(0);
28838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
28848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
28858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic const CommandDefRec   main_commands[] =
28868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
28878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "help|h|?", "print a list of commands", NULL, NULL, do_help, NULL },
28888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
28898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "event", "simulate hardware events",
28908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "allows you to send fake hardware events to the kernel\r\n", NULL,
28918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, event_commands },
28928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
28938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "geo", "Geo-location commands",
28948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows you to change Geo-related settings, or to send GPS NMEA sentences\r\n", NULL,
28958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, geo_commands },
28968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
28978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "gsm", "GSM related commands",
28988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows you to change GSM-related settings, or to make a new inbound phone call\r\n", NULL,
28998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, gsm_commands },
29008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29011a000857bb7eef298efa787699050884f92311feJaime Lopez    { "cdma", "CDMA related commands",
29021a000857bb7eef298efa787699050884f92311feJaime Lopez      "allows you to change CDMA-related settings\r\n", NULL,
29031a000857bb7eef298efa787699050884f92311feJaime Lopez      NULL, cdma_commands },
29041a000857bb7eef298efa787699050884f92311feJaime Lopez
29058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "kill", "kill the emulator instance", NULL, NULL,
2906d87b080495e71ada650b165a1f06616b433e6073Vladimir Chtchetkine      do_kill, NULL },
29078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "network", "manage network settings",
29098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows you to manage the settings related to the network data connection of the\r\n"
29108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "emulated device.\r\n", NULL,
29118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, network_commands },
29128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "power", "power related commands",
29148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows to change battery and AC power status\r\n", NULL,
29158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, power_commands },
29168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "quit|exit", "quit control session", NULL, NULL,
29188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      do_quit, NULL },
29198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "redir",    "manage port redirections",
29218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows you to add, list and remove UDP and/or PORT redirection from the host to the device\r\n"
29228b23a6c7e1aee255004dd19098d4c2462b61b849The 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"
29238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "to TCP port 6000 of the emulated device\r\n", NULL,
29248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, redir_commands },
29258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "sms", "SMS related commands",
29278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      "allows you to simulate an inbound SMS\r\n", NULL,
29288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      NULL, sms_commands },
29298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29302ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    { "avd", "control virtual device execution",
29312ff39a367738422c0ca1313cac8ff380e1fdd498Ot ten Thije    "allows you to control (e.g. start/stop) the execution of the virtual device\r\n", NULL,
29328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, vm_commands },
29338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { "window", "manage emulator window",
29358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    "allows you to modify the emulator window\r\n", NULL,
29368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    NULL, window_commands },
29378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2938e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    { "qemu", "QEMU-specific commands",
2939e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    "allows to connect to the QEMU virtual machine monitor\r\n", NULL,
2940e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner    NULL, qemu_commands },
2941e92bc56ef89ab8b51c4c89d4d9779b64e9491b9bDavid 'Digit' Turner
2942736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan    { "sensor", "manage emulator sensors",
2943736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan      "allows you to request the emulator sensors\r\n", NULL,
2944736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan      NULL, sensor_commands },
2945736e01f86f4ec4049bb5795f1ddb979132b05333Tim Wan
29468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    { NULL, NULL, NULL, NULL, NULL, NULL }
29478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project};
29488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic ControlGlobalRec  _g_global;
29518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
29528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
29538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectcontrol_console_start( int  port )
29548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
29558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return control_global_init( &_g_global, port );
29568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2957