summaryrefslogtreecommitdiffstats
path: root/src/host/layer23/src/mobile/mnccms.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/host/layer23/src/mobile/mnccms.c')
-rw-r--r--src/host/layer23/src/mobile/mnccms.c96
1 files changed, 92 insertions, 4 deletions
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
*/