diff options
author | Andreas Eversberg <jolly@eversberg.eu> | 2013-01-06 11:59:14 +0100 |
---|---|---|
committer | Andreas Eversberg <jolly@eversberg.eu> | 2013-01-06 11:59:14 +0100 |
commit | 47f05aefdf4eac7332aa4aa32238225e1c98aedb (patch) | |
tree | 544bb405acc1397038d86d4d26ce3b159ff4b6db | |
parent | f0964c1d6752284f2fb7013f276a31f6aa08f9a2 (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.h | 2 | ||||
-rw-r--r-- | src/host/layer23/include/osmocom/bb/mobile/mncc.h | 1 | ||||
-rw-r--r-- | src/host/layer23/src/mobile/mnccms.c | 96 | ||||
-rw-r--r-- | src/host/layer23/src/mobile/vty_interface.c | 53 |
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); |