From 47f05aefdf4eac7332aa4aa32238225e1c98aedb Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sun, 6 Jan 2013 11:59:14 +0100 Subject: 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 set-useruser ", it will can be transmitted with "call 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. --- .../layer23/include/osmocom/bb/mobile/gsm48_cc.h | 2 + src/host/layer23/include/osmocom/bb/mobile/mncc.h | 1 + src/host/layer23/src/mobile/mnccms.c | 96 +++++++++++++++++++++- 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); -- cgit v1.2.3