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.
This commit is contained in:
Andreas Eversberg 2013-01-06 11:59:14 +01:00
parent f0964c1d67
commit 47f05aefdf
4 changed files with 146 additions and 6 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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
*/

View File

@ -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);