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:
parent
f0964c1d67
commit
47f05aefdf
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue