summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2013-01-06 11:59:14 +0100
committerAndreas Eversberg <jolly@eversberg.eu>2013-01-06 11:59:14 +0100
commit47f05aefdf4eac7332aa4aa32238225e1c98aedb (patch)
tree544bb405acc1397038d86d4d26ce3b159ff4b6db
parentf0964c1d6752284f2fb7013f276a31f6aa08f9a2 (diff)
mobile: Add user-user message transmission to call control
If a user-user message is received, it is displayed via VTY. If a user-user message is defined with "call <ms> set-useruser <text>", it will can be transmitted with "call <ms> useruser" while there is an active call. After transmission, the message is cleared. If defined, it will be transmitted with next setup/alerting/connect/disconnect/release message also.
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/gsm48_cc.h2
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/mncc.h1
-rw-r--r--src/host/layer23/src/mobile/mnccms.c96
-rw-r--r--src/host/layer23/src/mobile/vty_interface.c53
4 files changed, 146 insertions, 6 deletions
diff --git a/src/host/layer23/include/osmocom/bb/mobile/gsm48_cc.h b/src/host/layer23/include/osmocom/bb/mobile/gsm48_cc.h
index 282ffe5b..aad6b5e5 100644
--- a/src/host/layer23/include/osmocom/bb/mobile/gsm48_cc.h
+++ b/src/host/layer23/include/osmocom/bb/mobile/gsm48_cc.h
@@ -5,6 +5,8 @@ struct gsm48_cclayer {
struct osmocom_ms *ms;
struct llist_head mncc_upqueue;
+
+ char useruser[129]; /* 128 + EOL */
};
int gsm48_cc_init(struct osmocom_ms *ms);
diff --git a/src/host/layer23/include/osmocom/bb/mobile/mncc.h b/src/host/layer23/include/osmocom/bb/mobile/mncc.h
index cad1883c..645bb264 100644
--- a/src/host/layer23/include/osmocom/bb/mobile/mncc.h
+++ b/src/host/layer23/include/osmocom/bb/mobile/mncc.h
@@ -39,6 +39,7 @@ struct gsm_call {
uint8_t init; /* call initiated, no response yet */
uint8_t hold; /* call on hold */
uint8_t ring; /* call ringing/knocking */
+ uint8_t connect; /* call connected (answered) */
struct osmo_timer_list dtmf_timer;
uint8_t dtmf_state;
diff --git a/src/host/layer23/src/mobile/mnccms.c b/src/host/layer23/src/mobile/mnccms.c
index 75cde8e4..e0e9b26c 100644
--- a/src/host/layer23/src/mobile/mnccms.c
+++ b/src/host/layer23/src/mobile/mnccms.c
@@ -203,6 +203,38 @@ static void mncc_set_bearer(struct osmocom_ms *ms, int8_t speech_ver,
mncc->bearer_cap.mode = 0;
}
+static void display_useruser(struct osmocom_ms *ms, struct gsm_mncc *data)
+{
+ const char *text;
+
+ /* if not user-user message is present, we are done */
+ if (!(data->fields & MNCC_F_USERUSER))
+ return;
+
+ if (data->useruser.proto == 4)
+ text = data->useruser.info;
+ else
+ text = osmo_hexdump((unsigned char *)data->useruser.info,
+ strlen(data->useruser.info));
+
+ vty_notify(ms, "User info: %s\n", text);
+ LOGP(DMNCC, LOGL_INFO, "User info: %s\n", text);
+}
+
+static void include_useruser(struct osmocom_ms *ms, struct gsm_mncc *data)
+{
+ struct gsm48_cclayer *cc = &ms->cclayer;
+
+ if (!cc->useruser[0])
+ return;
+
+ data->fields |= MNCC_F_USERUSER;
+ data->useruser.proto = 4;
+ strncpy(data->useruser.info, cc->useruser,
+ sizeof(data->useruser.info) - 1);
+ cc->useruser[0] = '\0';
+}
+
/*
* MNCCms dummy application
*/
@@ -289,6 +321,7 @@ int mncc_recv_mobile(struct osmocom_ms *ms, int msg_type, void *arg)
memset(&mncc, 0, sizeof(struct gsm_mncc));
mncc.callref = data->callref;
mncc_set_cause(&mncc, GSM48_CAUSE_LOC_USER, cause);
+ include_useruser(ms, &mncc);
return mncc_tx_to_cc(ms, MNCC_REL_REQ, &mncc);
}
@@ -362,6 +395,8 @@ int mncc_recv_mobile(struct osmocom_ms *ms, int msg_type, void *arg)
}
LOGP(DMNCC, LOGL_INFO, "Call has been disconnected "
"(cause %d)\n", data->cause.value);
+ display_useruser(ms, data);
+ call->connect = 0;
if ((data->fields & MNCC_F_PROGRESS)
&& data->progress.descr == 8) {
vty_notify(ms, "Please hang up!\n");
@@ -380,6 +415,7 @@ int mncc_recv_mobile(struct osmocom_ms *ms, int msg_type, void *arg)
vty_notify(ms, "Call has been released\n");
LOGP(DMNCC, LOGL_INFO, "Call has been released (cause %d)\n",
data->cause.value);
+ display_useruser(ms, data);
free_call(call);
break;
case MNCC_PROGRESS_IND:
@@ -417,6 +453,7 @@ int mncc_recv_mobile(struct osmocom_ms *ms, int msg_type, void *arg)
}
LOGP(DMNCC, LOGL_INFO, "Call is in progress (descr=%d)\n",
data->progress.descr);
+ display_useruser(ms, data);
break;
case MNCC_CALL_PROC_IND:
vty_notify(ms, NULL);
@@ -431,17 +468,20 @@ int mncc_recv_mobile(struct osmocom_ms *ms, int msg_type, void *arg)
vty_notify(ms, NULL);
vty_notify(ms, "Call is alerting\n");
LOGP(DMNCC, LOGL_INFO, "Call is alerting\n");
+ display_useruser(ms, data);
break;
case MNCC_SETUP_CNF:
vty_notify(ms, NULL);
vty_notify(ms, "Call is answered\n");
LOGP(DMNCC, LOGL_INFO, "Call is answered\n");
+ display_useruser(ms, data);
break;
case MNCC_SETUP_IND:
vty_notify(ms, NULL);
if (!first_call && !ms->settings.cw) {
vty_notify(ms, "Incoming call rejected while busy\n");
LOGP(DMNCC, LOGL_INFO, "Incoming call but busy\n");
+ display_useruser(ms, data);
cause = GSM48_CC_CAUSE_USER_BUSY;
goto release;
}
@@ -504,6 +544,7 @@ int mncc_recv_mobile(struct osmocom_ms *ms, int msg_type, void *arg)
data->calling.number);
LOGP(DMNCC, LOGL_INFO, "Incoming call (from %s callref %x)\n",
data->calling.number, call->callref);
+ display_useruser(ms, data);
memset(&mncc, 0, sizeof(struct gsm_mncc));
mncc.callref = call->callref;
/* only include bearer cap, if not given in setup
@@ -528,19 +569,23 @@ int mncc_recv_mobile(struct osmocom_ms *ms, int msg_type, void *arg)
LOGP(DMNCC, LOGL_INFO, "Knock!\n");
call->hold = 1;
}
- call->ring = 1;
- memset(&mncc, 0, sizeof(struct gsm_mncc));
- mncc.callref = call->callref;
- mncc_tx_to_cc(ms, MNCC_ALERT_REQ, &mncc);
if (ms->settings.auto_answer) {
LOGP(DMNCC, LOGL_INFO, "Auto-answering call\n");
mncc_answer(ms);
+ } else {
+ call->ring = 1;
+ memset(&mncc, 0, sizeof(struct gsm_mncc));
+ mncc.callref = call->callref;
+ include_useruser(ms, &mncc);
+ mncc_tx_to_cc(ms, MNCC_ALERT_REQ, &mncc);
}
break;
case MNCC_SETUP_COMPL_IND:
vty_notify(ms, NULL);
vty_notify(ms, "Call is connected\n");
LOGP(DMNCC, LOGL_INFO, "Call is connected\n");
+ display_useruser(ms, data);
+ call->connect = 1;
break;
case MNCC_HOLD_CNF:
vty_notify(ms, NULL);
@@ -573,6 +618,10 @@ int mncc_recv_mobile(struct osmocom_ms *ms, int msg_type, void *arg)
case MNCC_STOP_DTMF_RSP:
dtmf_statemachine(call, data);
break;
+ case MNCC_USERINFO_IND:
+ vty_notify(ms, NULL);
+ display_useruser(ms, data);
+ break;
default:
LOGP(DMNCC, LOGL_INFO, "Message 0x%02x unsupported\n",
msg_type);
@@ -638,6 +687,9 @@ int mncc_call(struct osmocom_ms *ms, char *number)
setup.fields |= MNCC_F_CCCAP;
setup.cccap.dtmf = 1;
}
+
+ /* USER-USER (optional) */
+ include_useruser(ms, &setup);
}
return mncc_tx_to_cc(ms, MNCC_SETUP_REQ, &setup);
@@ -661,10 +713,12 @@ int mncc_hangup(struct osmocom_ms *ms)
return -EINVAL;
}
+ found->connect = 0;
memset(&disc, 0, sizeof(struct gsm_mncc));
disc.callref = found->callref;
mncc_set_cause(&disc, GSM48_CAUSE_LOC_USER,
GSM48_CC_CAUSE_NORM_CALL_CLEAR);
+ include_useruser(ms, &disc);
return mncc_tx_to_cc(ms, (call->init) ? MNCC_REL_REQ : MNCC_DISC_REQ,
&disc);
}
@@ -695,9 +749,11 @@ int mncc_answer(struct osmocom_ms *ms)
}
alerting->ring = 0;
alerting->hold = 0;
+ alerting->connect = 1;
memset(&rsp, 0, sizeof(struct gsm_mncc));
rsp.callref = alerting->callref;
+ include_useruser(ms, &rsp);
return mncc_tx_to_cc(ms, MNCC_SETUP_RSP, &rsp);
}
@@ -772,6 +828,38 @@ int mncc_retrieve(struct osmocom_ms *ms, int number)
return mncc_tx_to_cc(ms, MNCC_RETRIEVE_REQ, &retr);
}
+int mncc_useruser(struct osmocom_ms *ms)
+{
+ struct gsm48_cclayer *cc = &ms->cclayer;
+ struct gsm_call *call, *found = NULL;
+ struct gsm_mncc user;
+
+ llist_for_each_entry(call, &call_list, entry) {
+ if (!call->hold && call->connect) {
+ found = call;
+ break;
+ }
+ }
+ if (!found) {
+ LOGP(DMNCC, LOGL_INFO, "No connected call to sent user-user "
+ "message\n");
+ vty_notify(ms, NULL);
+ vty_notify(ms, "No connected call\n");
+ return -EINVAL;
+ }
+
+ if (!cc->useruser[0]) {
+ LOGP(DMNCC, LOGL_INFO, "No user-user message set\n");
+ vty_notify(ms, NULL);
+ vty_notify(ms, "No user-user message set\n");
+ return -EINVAL;
+ }
+ memset(&user, 0, sizeof(struct gsm_mncc));
+ user.callref = call->callref;
+ include_useruser(ms, &user);
+ return mncc_tx_to_cc(ms, MNCC_USERINFO_REQ, &user);
+}
+
/*
* DTMF
*/
diff --git a/src/host/layer23/src/mobile/vty_interface.c b/src/host/layer23/src/mobile/vty_interface.c
index 4d7f6a27..b017ccbe 100644
--- a/src/host/layer23/src/mobile/vty_interface.c
+++ b/src/host/layer23/src/mobile/vty_interface.c
@@ -49,6 +49,7 @@ int mncc_answer(struct osmocom_ms *ms);
int mncc_hold(struct osmocom_ms *ms);
int mncc_retrieve(struct osmocom_ms *ms, int number);
int mncc_dtmf(struct osmocom_ms *ms, char *dtmf);
+int mncc_useruser(struct osmocom_ms *ms);
extern struct llist_head ms_list;
extern struct llist_head active_connections;
@@ -753,11 +754,12 @@ DEFUN(network_select, network_select_cmd,
return CMD_SUCCESS;
}
-DEFUN(call, call_cmd, "call MS_NAME (NUMBER|emergency|answer|hangup|hold)",
+DEFUN(call, call_cmd,
+ "call MS_NAME (NUMBER|emergency|answer|hangup|hold|useruser)",
"Make a call\nName of MS (see \"show ms\")\nPhone number to call "
"(Use digits '0123456789*#abc', and '+' to dial international)\n"
"Make an emergency call\nAnswer an incomming call\nHangup a call\n"
- "Hold current active call\n")
+ "Hold current active call\nSend user-user-message")
{
struct osmocom_ms *ms;
struct gsm_settings *set;
@@ -784,6 +786,8 @@ DEFUN(call, call_cmd, "call MS_NAME (NUMBER|emergency|answer|hangup|hold)",
mncc_hangup(ms);
else if (!strcmp(number, "hold"))
mncc_hold(ms);
+ else if (!strcmp(number, "useruser"))
+ mncc_useruser(ms);
else {
llist_for_each_entry(abbrev, &set->abbrev, list) {
if (!strcmp(number, abbrev->abbrev)) {
@@ -839,6 +843,49 @@ DEFUN(call_dtmf, call_dtmf_cmd, "call MS_NAME dtmf DIGITS",
return CMD_SUCCESS;
}
+DEFUN(call_set_user, call_set_user_cmd, "call MS_NAME set-useruser .LINE",
+ "Make a call\nName of MS (see \"show ms\")\n"
+ "Set next user-user message\nUser-user message")
+{
+ struct osmocom_ms *ms;
+ struct gsm48_cclayer *cc;
+
+ ms = get_ms(argv[0], vty);
+ if (!ms)
+ return CMD_WARNING;
+ cc = &ms->cclayer;
+
+ strncpy(cc->useruser, argv_concat(argv, argc, 1),
+ sizeof(cc->useruser) - 1);
+ vty_out(vty, "Message will be sent with next "
+ "setup/ringing/answer/hangup/useruser command%s", VTY_NEWLINE);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(call_unset_user, call_unset_user_cmd,
+ "call MS_NAME unset-useruser",
+ "Make a call\nName of MS (see \"show ms\")\n"
+ "Remove current user-user message")
+{
+ struct osmocom_ms *ms;
+ struct gsm48_cclayer *cc;
+
+ ms = get_ms(argv[0], vty);
+ if (!ms)
+ return CMD_WARNING;
+ cc = &ms->cclayer;
+
+ if (cc->useruser[0]) {
+ cc->useruser[0] = '\0';
+ vty_out(vty, "User-user message deleted%s", VTY_NEWLINE);
+ } else {
+ vty_out(vty, "No message deleted%s", VTY_NEWLINE);
+ }
+
+ return CMD_SUCCESS;
+}
+
DEFUN(sms, sms_cmd, "sms MS_NAME NUMBER .LINE",
"Send an SMS\nName of MS (see \"show ms\")\nPhone number to send SMS "
"(Use digits '0123456789*#abc', and '+' to dial international)\n"
@@ -2765,6 +2812,8 @@ int ms_vty_init(void)
install_element(ENABLE_NODE, &network_select_cmd);
install_element(ENABLE_NODE, &call_cmd);
install_element(ENABLE_NODE, &call_retr_cmd);
+ install_element(ENABLE_NODE, &call_set_user_cmd);
+ install_element(ENABLE_NODE, &call_unset_user_cmd);
install_element(ENABLE_NODE, &call_dtmf_cmd);
install_element(ENABLE_NODE, &sms_cmd);
install_element(ENABLE_NODE, &service_cmd);