r2337 - in trunk/src/host/qemu-neo1973: . gnokiigsm hw

andrew at sita.openmoko.org andrew at sita.openmoko.org
Sat Jun 23 17:16:24 CEST 2007


Author: andrew
Date: 2007-06-23 17:16:21 +0200 (Sat, 23 Jun 2007)
New Revision: 2337

Modified:
   trunk/src/host/qemu-neo1973/gnokiigsm/at-emulator.c
   trunk/src/host/qemu-neo1973/gnokiigsm/at-emulator.h
   trunk/src/host/qemu-neo1973/gnokiigsm/datapump.c
   trunk/src/host/qemu-neo1973/hw/modem.c
   trunk/src/host/qemu-neo1973/monitor.c
   trunk/src/host/qemu-neo1973/vl.c
   trunk/src/host/qemu-neo1973/vl.h
Log:
Simulate incoming calls.
Implement TI's undocumented %CPI and +CLIP based on gsmd code.
Report variable CSQ values.


Modified: trunk/src/host/qemu-neo1973/gnokiigsm/at-emulator.c
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/at-emulator.c	2007-06-23 01:01:43 UTC (rev 2336)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/at-emulator.c	2007-06-23 15:16:21 UTC (rev 2337)
@@ -227,6 +227,12 @@
 		break;
 	case GN_CALL_LocalHangup:
 	case GN_CALL_RemoteHangup:
+		if (IncomingCallNo > 0) {
+			gn_atem_cpi(GSMD_CALLPROG_DISCONNECT,
+					GSMD_CALL_DIR_MT, 0);
+			gn_atem_cpi(GSMD_CALLPROG_RELEASE,
+					GSMD_CALL_DIR_MT, 0);
+		}
 		IncomingCallNo = -1;
 		break;
 	default:
@@ -365,6 +371,10 @@
 {
 	char	buffer[MAX_LINE_LENGTH], **strval;
 	int	len;
+
+	if (*val == 0)
+		strcpy(val, op->default_val);
+
 	if ((*buf)[0] == 0 || ((*buf)[0] == '?' && (*buf)[1] == 0)) {
 		*buf += strlen(*buf);
 		gsprintf(buffer, MAX_LINE_LENGTH, "%s: %s\r\n", op->op, val);
@@ -838,6 +848,22 @@
 	return (false);
 }
 
+void	gn_atem_cpi(enum gsmd_call_progress msg,
+		enum gsmd_call_direction dir, int inband)
+{
+	char *buffer;
+
+	if (data.cpi[0] < '1')
+		return;
+
+	/* Format: %CPI: <cId>,<msgType>,<ibt>,<tch>,<dir>,[<mode>],
+	 * [<number>],[<type>],[<alpha>],[<cause>],<line> */
+	asprintf(&buffer, "%%CPI: %i,%i,0,%i,%i,0,,,,,0\r\n",
+			data.call_info->call_id, msg, inband, dir);
+	gn_atem_string_out(buffer);
+	free(buffer);
+}
+
 static struct gn_atem_op gn_atem_op_cpi = {
 	.op		= "%CPI",
 	.writable	= 1,
@@ -919,6 +945,8 @@
 			if (gn_sm_functions(GN_OP_MakeCall, &data, sm) != GN_ERR_NONE) {
 				CommandMode = true;
 				dp_CallPassup(GN_CALL_RemoteHangup, NULL, NULL);
+				data.call_notification = gn_atem_call_passup;
+				gn_sm_functions(GN_OP_SetCallNotification, &data, sm);
 			} else {
 				IncomingCallNo = data.call_info->call_id;
 				gn_sm_loop(10, sm);
@@ -931,6 +959,12 @@
 			switch (gn_atem_num_get(&buf)) {
 			case -1:
 			case 0:	/* hook off the phone */
+				if (IncomingCallNo > 0) {
+					gn_atem_cpi(GSMD_CALLPROG_DISCONNECT,
+							GSMD_CALL_DIR_MT, 0);
+					gn_atem_cpi(GSMD_CALLPROG_RELEASE,
+							GSMD_CALL_DIR_MT, 0);
+				}
 				gn_atem_hangup_phone();
 				break;
 			case 1:	/* hook on the phone */
@@ -1890,14 +1924,21 @@
 				break;
 
 		        case MR_RING:
+				gn_atem_cpi(GSMD_CALLPROG_SETUP,
+						GSMD_CALL_DIR_MT, 0);
+				gn_atem_cpi(GSMD_CALLPROG_SETUP,
+						GSMD_CALL_DIR_MT, 1);
 				if (!strcmp(data.crc, "1"))
 					gn_atem_string_out(
 							"+CRING: VOICE\r\n");
 				else
 					gn_atem_string_out("RING\r\n");
+				/* XXX: Standard format is "313373",145 */
 				if (!strcmp(data.clip, "1,1"))
-					gn_atem_string_out("+CLIP: "
-							"\"313373\",0\r\n");
+					gn_atem_string_out("+CLIP: \"313373\""
+							",145,,,,1\r\n");
+				gn_atem_cpi(GSMD_CALLPROG_SYNC,
+						GSMD_CALL_DIR_MT, 1);
 				break;
 
 			default:

Modified: trunk/src/host/qemu-neo1973/gnokiigsm/at-emulator.h
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/at-emulator.h	2007-06-23 01:01:43 UTC (rev 2336)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/at-emulator.h	2007-06-23 15:16:21 UTC (rev 2337)
@@ -34,6 +34,28 @@
 #include "compat.h"
 #include "gnokii.h"
 
+/* XXX: The values >6 are TI-specific */
+enum gsmd_call_progress {
+	GSMD_CALLPROG_SETUP		= 0,
+	GSMD_CALLPROG_DISCONNECT	= 1,
+	GSMD_CALLPROG_ALERT		= 2,
+	GSMD_CALLPROG_CALL_PROCEED	= 3,
+	GSMD_CALLPROG_SYNC		= 4,
+	GSMD_CALLPROG_PROGRESS		= 5,
+	GSMD_CALLPROG_CONNECTED		= 6,
+	GSMD_CALLPROG_RELEASE		= 7,
+	GSMD_CALLPROG_REJECT		= 8,
+	GSMD_CALLPROG_UNKNOWN		= 9,
+	__NUM_GSMD_CALLPROG
+};
+
+enum gsmd_call_direction {
+	GSMD_CALL_DIR_MO	= 0,	/* Mobile Originated (Outgoing) */
+	GSMD_CALL_DIR_MT	= 1,	/* Mobile Terminated (Incoming) */
+	GSMD_CALL_DIR_CCBS	= 2,	/* network initiated MO */
+	GSMD_CALL_DIR_MO_REDIAL	= 3,	/* Mobile Originated Redial */
+};
+
 	/* Prototypes */
 bool	gn_atem_initialise(struct gn_statemachine *sm);
 void	gn_atem_incoming_data_handle(const char *buffer, int length);
@@ -47,9 +69,12 @@
 bool	gn_atem_command_percent(char **buf);
 int	gn_atem_num_get(char **p);
 void	gn_atem_modem_result(int code);
-void    gn_atem_call_passup(gn_call_status call_status, gn_call_info *call_info, struct gn_statemachine *state);
+void    gn_atem_call_passup(gn_call_status call_status,
+		gn_call_info *call_info, struct gn_statemachine *state);
 void	gn_atem_cid_out(gn_call_info *callinfo);
 bool	gn_atem_command_diesis(char **buf);
+void	gn_atem_cpi(enum gsmd_call_progress msg, enum gsmd_call_direction dir,
+		int inband);
 
 	/* Global variables */
 extern bool gn_atem_initialised;

Modified: trunk/src/host/qemu-neo1973/gnokiigsm/datapump.c
===================================================================
--- trunk/src/host/qemu-neo1973/gnokiigsm/datapump.c	2007-06-23 01:01:43 UTC (rev 2336)
+++ trunk/src/host/qemu-neo1973/gnokiigsm/datapump.c	2007-06-23 15:16:21 UTC (rev 2337)
@@ -75,6 +75,8 @@
 	gn_sm_functions(GN_OP_SetRLPRXCallback, &data, sm);
 
 	CommandMode = true;
+	data.call_notification = gn_atem_call_passup;
+	gn_sm_functions(GN_OP_SetCallNotification, &data, sm);
 
 	return true;
 }

Modified: trunk/src/host/qemu-neo1973/hw/modem.c
===================================================================
--- trunk/src/host/qemu-neo1973/hw/modem.c	2007-06-23 01:01:43 UTC (rev 2336)
+++ trunk/src/host/qemu-neo1973/hw/modem.c	2007-06-23 15:16:21 UTC (rev 2337)
@@ -29,6 +29,9 @@
     QEMUTimer *csq_tm;
     QEMUTimer *reg_tm;
     gn_data *reg_data;
+    void (*call_notification)(gn_call_status call_status,
+                    gn_call_info *call_info, struct gn_statemachine *state);
+    int next_call_id;
 };
 
 #define TICALYPSOv3_MANF	"<manufacturer>"
@@ -41,7 +44,7 @@
 #define TICALYPSOv4_REV		"GTA01Bv4"
 #define TICALYPSOv4_IMEI	"354651010000000"
 
-static gn_error modem_ops(gn_operation op, gn_data *data,
+static gn_error modem_gsm_ops(gn_operation op, gn_data *data,
                 struct gn_statemachine *sm)
 {
     struct modem_s *s = (struct modem_s *) sm->info->opaque;
@@ -61,6 +64,14 @@
         fprintf(stderr, "%s: hangup.\n", __FUNCTION__);
         break;
 
+    case GN_OP_AnswerCall:
+        fprintf(stderr, "%s: call answered.\n", __FUNCTION__);
+        if (!s->enable || !s->reg_data || !s->call_notification)
+            break;
+
+        s->call_notification(GN_CALL_RemoteHangup, NULL, &s->state);
+        break;
+
     case GN_OP_GetSMS:
         fprintf(stderr, "%s: SMS number %i requested\n",
                         __FUNCTION__, data->sms->number);
@@ -77,7 +88,7 @@
         return GN_ERR_NOTSUPPORTED;
 
     case GN_OP_GetRFLevel:
-        *data->rf_level = 30.0f;	/* Some -50 dBm */
+        *data->rf_level = 15.0f + ((time(0) & 15) ^ 2);	/* Around -70 dBm */
         break;
 
     case GN_OP_GetImei:
@@ -109,8 +120,13 @@
         qemu_del_timer(s->csq_tm);
         if (data->network_change_notification)
             data->network_change_notification(0, &s->state);
+        s->reg_data = 0;
         break;
 
+    case GN_OP_SetCallNotification:
+        s->call_notification = data->call_notification;
+        break;
+
     default:
         return GN_ERR_NOTSUPPORTED;
     }
@@ -130,7 +146,7 @@
     struct modem_s *s = (struct modem_s *) opaque;
     if (s->reg_data && s->reg_data->signal_quality_notification)
         s->reg_data->signal_quality_notification(&s->state);
-    qemu_mod_timer(s->csq_tm, qemu_get_clock(vm_clock) + ticks_per_sec * 30);
+    qemu_mod_timer(s->csq_tm, qemu_get_clock(vm_clock) + ticks_per_sec * 50);
 }
 
 static void modem_network_register(void *opaque)
@@ -232,6 +248,23 @@
     modem_fifo_wake((struct modem_s *) opaque);
 }
 
+static void modem_ring(void *opaque)
+{
+    struct modem_s *s = (struct modem_s *) opaque;
+    gn_call_info call_info;
+
+    if (!s->enable || !s->reg_data || !s->call_notification)
+        return;
+
+    call_info.type = GN_CALL_Voice;
+    snprintf(call_info.number, sizeof(call_info.number), "6100918");
+    snprintf(call_info.name, sizeof(call_info.name), "Red Riding Hood");
+    call_info.send_number = GN_CALL_Always;
+    call_info.call_id = s->next_call_id ++;
+
+    s->call_notification(GN_CALL_Incoming, &call_info, &s->state);
+}
+
 CharDriverState *modem_init()
 {
     struct modem_s *s = (struct modem_s *)
@@ -243,11 +276,12 @@
 
     s->state.info = &s->info;
     s->info.write = modem_resp;
-    s->info.gn_sm_functions = modem_ops;
+    s->info.gn_sm_functions = modem_gsm_ops;
     s->info.opaque = s;
     s->info.non_at_ok = 1;	/* Return OK on non-AT commands.  */
     s->reg_tm = qemu_new_timer(vm_clock, modem_network_register, s);
     s->csq_tm = qemu_new_timer(vm_clock, modem_csq_report, s);
+    s->next_call_id = 1;
 
     if (!gn_atem_initialise(&s->state))
         goto fail;
@@ -255,6 +289,11 @@
     if (!dp_Initialise())
         goto fail;
 
+    /* If this is the first modem, register it as the one to receive
+     * "modem .." commands.  */
+    modem_ops.opaque = s;
+    modem_ops.ring = modem_ring;
+
     return &s->chr;
 fail:
     fprintf(stderr, "%s: GSM modem initialisation failed\n", __FUNCTION__);

Modified: trunk/src/host/qemu-neo1973/monitor.c
===================================================================
--- trunk/src/host/qemu-neo1973/monitor.c	2007-06-23 01:01:43 UTC (rev 2336)
+++ trunk/src/host/qemu-neo1973/monitor.c	2007-06-23 15:16:21 UTC (rev 2337)
@@ -60,6 +60,7 @@
 
 static term_cmd_t term_cmds[];
 static term_cmd_t info_cmds[];
+static term_cmd_t modem_cmds[];
 
 static char term_outbuf[1024];
 static int term_outbuf_index;
@@ -181,6 +182,8 @@
 {
     if (name && !strcmp(name, "info")) {
         help_cmd1(info_cmds, "info ", NULL);
+    } else if (name && !strcmp(name, "modem")) {
+        help_cmd1(modem_cmds, "modem ", NULL);
     } else {
         help_cmd1(term_cmds, "", name);
         if (name && !strcmp(name, "log")) {
@@ -1198,6 +1201,29 @@
 }
 #endif
 
+static void do_modem(const char *item)
+{
+    term_cmd_t *cmd;
+
+    if (!item)
+        goto help;
+    for(cmd = modem_cmds; cmd->name != NULL; cmd++) {
+        if (compare_cmd(item, cmd->name)) 
+            goto found;
+    }
+ help:
+    help_cmd("modem");
+    return;
+ found:
+    cmd->handler();
+}
+
+static void do_modem_ring(const char *item)
+{
+    if (modem_ops.ring)
+        modem_ops.ring(modem_ops.opaque);
+}
+
 static term_cmd_t term_cmds[] = {
     { "help|?", "s?", do_help, 
       "[cmd]", "show the help" },
@@ -1263,10 +1289,12 @@
       "path [frequency bits channels]",
       "capture audio to a wave file (default frequency=44100 bits=16 channels=2)" },
 #endif
-     { "stopcapture", "i", do_stop_capture,
-       "capture index", "stop capture" },
+    { "stopcapture", "i", do_stop_capture,
+      "capture index", "stop capture" },
     { "memsave", "lis", do_memory_save, 
       "addr size file", "save to disk virtual memory dump starting at 'addr' of size 'size'", },
+    { "modem", "s?", do_modem,
+      "subcommand", "cause various actions in the virtual modem", },
     { NULL, NULL, }, 
 };
 
@@ -1326,6 +1354,12 @@
     { NULL, NULL, },
 };
 
+static term_cmd_t modem_cmds[] = {
+    { "ring", "", do_modem_ring,
+      "", "make the virtual modem output a RING notification" },
+    { NULL, NULL, },
+};
+
 /*******************************************************************/
 
 static const char *pch;
@@ -2430,6 +2464,11 @@
                 for(key = key_defs; key->name != NULL; key++) {
                     cmd_completion(str, key->name);
                 }
+            } else if (!strcmp(cmd->name, "modem")) {
+                completion_index = strlen(str);
+                for(cmd = modem_cmds; cmd->name != NULL; cmd++) {
+                    cmd_completion(str, cmd->name);
+                }
             }
             break;
         default:

Modified: trunk/src/host/qemu-neo1973/vl.c
===================================================================
--- trunk/src/host/qemu-neo1973/vl.c	2007-06-23 01:01:43 UTC (rev 2336)
+++ trunk/src/host/qemu-neo1973/vl.c	2007-06-23 15:16:21 UTC (rev 2337)
@@ -201,6 +201,7 @@
 const char *prom_envs[MAX_PROM_ENVS];
 #endif
 struct bt_piconet_s *local_piconet;
+struct modem_ops_s modem_ops;
 
 /***********************************************************/
 /* x86 ISA bus support */

Modified: trunk/src/host/qemu-neo1973/vl.h
===================================================================
--- trunk/src/host/qemu-neo1973/vl.h	2007-06-23 01:01:43 UTC (rev 2336)
+++ trunk/src/host/qemu-neo1973/vl.h	2007-06-23 15:16:21 UTC (rev 2337)
@@ -1551,6 +1551,10 @@
 /* modem.c */
 CharDriverState *modem_init();
 void modem_enable(CharDriverState *chr, int enable);
+extern struct modem_ops_s {
+    void *opaque;
+    void (*ring)(void *opaque);
+} modem_ops;
 
 /* PCMCIA/Cardbus */
 





More information about the commitlog mailing list