Add 'gsm signal' command, to set rssi and ber

Change-Id: I24d4738f6e5135437af25d22e2fa68617f5632fa
diff --git a/android/console.c b/android/console.c
index 5e37060..68b9480 100644
--- a/android/console.c
+++ b/android/console.c
@@ -1385,6 +1385,65 @@
     return 0;
 }
 
+static int
+do_gsm_signal( ControlClient  client, char*  args )
+{
+      enum { SIGNAL_RSSI = 0, SIGNAL_BER, NUM_SIGNAL_PARAMS };
+      char*   p = args;
+      int     top_param = -1;
+      int     params[ NUM_SIGNAL_PARAMS ];
+
+      static  int  last_ber = 99;
+
+      if (!p)
+          p = "";
+
+      /* tokenize */
+      while (*p) {
+          char*   end;
+          int  val = strtol( p, &end, 10 );
+
+          if (end == p) {
+              control_write( client, "KO: argument '%s' is not a number\n", p );
+              return -1;
+          }
+
+          params[++top_param] = val;
+          if (top_param + 1 == NUM_SIGNAL_PARAMS)
+              break;
+
+          p = end;
+          while (*p && (p[0] == ' ' || p[0] == '\t'))
+              p += 1;
+      }
+
+      /* sanity check */
+      if (top_param < SIGNAL_RSSI) {
+          control_write( client, "KO: not enough arguments: see 'help gsm signal' for details\r\n" );
+          return -1;
+      }
+
+      int rssi = params[SIGNAL_RSSI];
+      if ((rssi < 0 || rssi > 31) && rssi != 99) {
+          control_write( client, "KO: invalid RSSI - must be 0..31 or 99\r\n");
+          return -1;
+      }
+
+      /* check ber is 0..7 or 99 */
+      if (top_param >= SIGNAL_BER) {
+          int ber = params[SIGNAL_BER];
+          if ((ber < 0 || ber > 7) && ber != 99) {
+              control_write( client, "KO: invalid BER - must be 0..7 or 99\r\n");
+              return -1;
+          }
+          last_ber = ber;
+      }
+
+      amodem_set_signal_strength( android_modem, rssi, last_ber );
+
+      return 0;
+  }
+
 
 #if 0
 static const CommandDefRec  gsm_in_commands[] =
@@ -1458,6 +1517,12 @@
     "'gsm status' displays the current state of the GSM emulation\r\n", NULL,
     do_gsm_status, NULL },
 
+    { "signal", "set sets the rssi and ber",
+    "'gsm signal <rssi> [<ber>]' changes the reported strength and error rate on next (15s) update.\r\n"
+    "rssi range is 0..31 and 99 for unknown\r\n"
+    "ber range is 0..7 percent and 99 for unknown\r\n",
+    NULL, do_gsm_signal, NULL },
+
     { NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
diff --git a/telephony/android_modem.c b/telephony/android_modem.c
index 009b5af..dd9f78d 100644
--- a/telephony/android_modem.c
+++ b/telephony/android_modem.c
@@ -235,6 +235,9 @@
     int           cell_id;
     int           base_port;
 
+    int           rssi;
+    int           ber;
+
     /* SMS */
     int           wait_sms;
 
@@ -465,6 +468,9 @@
     modem->radio_state = A_RADIO_STATE_OFF;
     modem->wait_sms    = 0;
 
+    modem->rssi= 7;    // Two signal strength bars
+    modem->ber = 99;   // Means 'unknown'
+
     modem->oper_name_index     = amodem_nvram_get_int(modem, NV_OPER_NAME_INDEX, 2);
     modem->oper_selection_mode = amodem_nvram_get_int(modem, NV_SELECTION_MODE, A_SELECTION_AUTOMATIC);
     modem->oper_index          = amodem_nvram_get_int(modem, NV_OPER_INDEX, 0);
@@ -877,6 +883,12 @@
     return  NULL;
 }
 
+void
+amodem_set_signal_strength( AModem modem, int rssi, int ber )
+{
+    modem->rssi = rssi;
+    modem->ber = ber;
+}
 
 static void
 acall_set_state( AVoiceCall    call, ACallState  state )
@@ -2135,7 +2147,6 @@
 static const char*
 handleSignalStrength( const char*  cmd, AModem  modem )
 {
-   /* XXX: TODO: implement variable signal strength and error rates */
     amodem_begin_line( modem );
 #if CONFIG_ANDROID_SNAPSHOTS
     /* Sneak time updates into the SignalStrength request, because it's periodic.
@@ -2149,7 +2160,12 @@
 #endif
     // rssi = 0 (<-113dBm) 1 (<-111) 2-30 (<-109--53) 31 (>=-51) 99 (?!)
     // ber (bit error rate) - always 99 (unknown), apparently.
-    amodem_add_line( modem, "+CSQ: %i,99\r\n", 27 );
+    // TODO: return 99 if modem->radio_state==A_RADIO_STATE_OFF, once radio_state is in snapshot.
+    int rssi = modem->rssi;
+    int ber = modem->ber;
+    rssi = (0 > rssi && rssi > 31) ? 99 : rssi ;
+    ber = (0 > ber && ber > 7 ) ? 99 : ber;
+    amodem_add_line( modem, "+CSQ: %i,%i\r\n", rssi, ber );
     return amodem_end_line( modem );
 }
 
diff --git a/telephony/android_modem.h b/telephony/android_modem.h
index 4409a7d..cbe8f46 100644
--- a/telephony/android_modem.h
+++ b/telephony/android_modem.h
@@ -42,6 +42,9 @@
 extern ARadioState  amodem_get_radio_state( AModem modem );
 extern void         amodem_set_radio_state( AModem modem, ARadioState  state );
 
+/* Set the received signal strength indicator and bit error rate */
+extern void         amodem_set_signal_strength( AModem modem, int rssi, int ber );
+
 /** SIM CARD STATUS
  **/
 extern ASimCard    amodem_get_sim( AModem  modem );