2 * (C) 2010 by Andreas Eversberg <jolly@eversberg.eu>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
28 #include <osmocom/core/talloc.h>
30 #include <osmocom/bb/common/logging.h>
31 #include <osmocom/bb/common/osmocom_data.h>
32 #include <osmocom/bb/mobile/mncc.h>
33 #include <osmocom/bb/mobile/vty.h>
36 static uint32_t new_callref = 1;
37 static LLIST_HEAD(call_list);
39 void mncc_set_cause(struct gsm_mncc *data, int loc, int val);
40 static int dtmf_statemachine(struct gsm_call *call, struct gsm_mncc *mncc);
41 static void timeout_dtmf(void *arg);
42 int mncc_answer(struct osmocom_ms *ms);
49 static void start_dtmf_timer(struct gsm_call *call, uint16_t ms)
51 LOGP(DCC, LOGL_INFO, "starting DTMF timer %d ms\n", ms);
52 call->dtmf_timer.cb = timeout_dtmf;
53 call->dtmf_timer.data = call;
54 osmo_timer_schedule(&call->dtmf_timer, 0, ms * 1000);
57 static void stop_dtmf_timer(struct gsm_call *call)
59 if (osmo_timer_pending(&call->dtmf_timer)) {
60 LOGP(DCC, LOGL_INFO, "stopping pending DTMF timer\n");
61 osmo_timer_del(&call->dtmf_timer);
65 /* free call instance */
66 static void free_call(struct gsm_call *call)
68 stop_dtmf_timer(call);
70 llist_del(&call->entry);
71 DEBUGP(DMNCC, "(call %x) Call removed.\n", call->callref);
76 struct gsm_call *get_call_ref(uint32_t callref)
78 struct gsm_call *callt;
80 llist_for_each_entry(callt, &call_list, entry) {
81 if (callt->callref == callref)
87 static int8_t mncc_get_bearer(struct gsm_settings *set, uint8_t speech_ver)
92 LOGP(DMNCC, LOGL_INFO, " net suggests full rate v3\n");
94 LOGP(DMNCC, LOGL_INFO, " full rate v3 not supported\n");
100 LOGP(DMNCC, LOGL_INFO, " net suggests full rate v2\n");
102 LOGP(DMNCC, LOGL_INFO, " full rate v2 not supported\n");
106 case 0: /* mandatory */
108 LOGP(DMNCC, LOGL_INFO, " net suggests full rate v1\n");
110 LOGP(DMNCC, LOGL_INFO, " full rate v1 not supported\n");
116 LOGP(DMNCC, LOGL_INFO, " net suggests half rate v3\n");
118 LOGP(DMNCC, LOGL_INFO, " half rate v3 not supported\n");
124 LOGP(DMNCC, LOGL_INFO, " net suggests half rate v1\n");
126 LOGP(DMNCC, LOGL_INFO, " half rate v1 not supported\n");
131 LOGP(DMNCC, LOGL_INFO, " net suggests unknown speech version "
139 static void mncc_set_bearer(struct osmocom_ms *ms, int8_t speech_ver,
140 struct gsm_mncc *mncc)
142 struct gsm_settings *set = &ms->settings;
145 mncc->fields |= MNCC_F_BEARER_CAP;
146 mncc->bearer_cap.coding = 0;
147 if (set->ch_cap == GSM_CAP_SDCCH_TCHF_TCHH
148 && (set->half_v1 || set->half_v3)) {
149 mncc->bearer_cap.radio = 3;
150 LOGP(DMNCC, LOGL_INFO, " support TCH/H also\n");
152 mncc->bearer_cap.radio = 1;
153 LOGP(DMNCC, LOGL_INFO, " support TCH/F only\n");
155 mncc->bearer_cap.speech_ctm = 0;
156 /* if no specific speech_ver is given */
157 if (speech_ver < 0) {
158 /* if half rate is supported and prefered */
159 if (set->half_v3 && set->half && set->half_prefer) {
160 mncc->bearer_cap.speech_ver[i++] = 5;
161 LOGP(DMNCC, LOGL_INFO, " support half rate v3\n");
163 if (set->half_v1 && set->half && set->half_prefer) {
164 mncc->bearer_cap.speech_ver[i++] = 1;
165 LOGP(DMNCC, LOGL_INFO, " support half rate v1\n");
167 /* if full rate is supported */
169 mncc->bearer_cap.speech_ver[i++] = 4;
170 LOGP(DMNCC, LOGL_INFO, " support full rate v3\n");
173 mncc->bearer_cap.speech_ver[i++] = 2;
174 LOGP(DMNCC, LOGL_INFO, " support full rate v2\n");
176 if (set->full_v1) { /* mandatory, so it's always true */
177 mncc->bearer_cap.speech_ver[i++] = 0;
178 LOGP(DMNCC, LOGL_INFO, " support full rate v1\n");
180 /* if half rate is supported and not prefered */
181 if (set->half_v3 && set->half && !set->half_prefer) {
182 mncc->bearer_cap.speech_ver[i++] = 5;
183 LOGP(DMNCC, LOGL_INFO, " support half rate v3\n");
185 if (set->half_v1 && set->half && !set->half_prefer) {
186 mncc->bearer_cap.speech_ver[i++] = 1;
187 LOGP(DMNCC, LOGL_INFO, " support half rate v1\n");
189 /* if specific speech_ver is given (it must be supported) */
191 mncc->bearer_cap.speech_ver[i++] = speech_ver;
192 mncc->bearer_cap.speech_ver[i] = -1; /* end of list */
193 mncc->bearer_cap.transfer = 0;
194 mncc->bearer_cap.mode = 0;
198 * MNCCms dummy application
201 /* this is a minimal implementation as required by GSM 04.08 */
202 int mncc_recv_dummy(struct osmocom_ms *ms, int msg_type, void *arg)
204 struct gsm_mncc *data = arg;
205 uint32_t callref = data->callref;
208 if (msg_type == MNCC_REL_IND || msg_type == MNCC_REL_CNF)
211 LOGP(DMNCC, LOGL_INFO, "Rejecting incoming call\n");
213 /* reject, as we don't support Calls */
214 memset(&rel, 0, sizeof(struct gsm_mncc));
215 rel.callref = callref;
216 mncc_set_cause(&rel, GSM48_CAUSE_LOC_USER,
217 GSM48_CC_CAUSE_INCOMPAT_DEST);
219 return mncc_send(ms, MNCC_REL_REQ, &rel);
223 * MNCCms basic call application
226 int mncc_recv_mobile(struct osmocom_ms *ms, int msg_type, void *arg)
228 struct gsm_settings *set = &ms->settings;
229 struct gsm_mncc *data = arg;
230 struct gsm_call *call = get_call_ref(data->callref);
231 struct gsm_mncc mncc;
233 int8_t speech_ver = -1, speech_ver_half = -1, temp;
236 /* call does not exist */
237 if (!call && msg_type != MNCC_SETUP_IND) {
238 LOGP(DMNCC, LOGL_INFO, "Rejecting incoming call "
239 "(callref %x)\n", data->callref);
240 if (msg_type == MNCC_REL_IND || msg_type == MNCC_REL_CNF)
242 cause = GSM48_CC_CAUSE_INCOMPAT_DEST;
244 memset(&mncc, 0, sizeof(struct gsm_mncc));
245 mncc.callref = data->callref;
246 mncc_set_cause(&mncc, GSM48_CAUSE_LOC_USER, cause);
247 return mncc_send(ms, MNCC_REL_REQ, &mncc);
250 /* setup without call */
252 if (llist_empty(&call_list))
254 call = talloc_zero(l23_ctx, struct gsm_call);
258 call->callref = data->callref;
259 llist_add_tail(&call->entry, &call_list);
262 /* not in initiated state anymore */
267 vty_notify(ms, NULL);
268 switch (data->cause.value) {
269 case GSM48_CC_CAUSE_UNASSIGNED_NR:
270 vty_notify(ms, "Call: Number not assigned\n");
272 case GSM48_CC_CAUSE_NO_ROUTE:
273 vty_notify(ms, "Call: Destination unreachable\n");
275 case GSM48_CC_CAUSE_NORM_CALL_CLEAR:
276 vty_notify(ms, "Call: Remote hangs up\n");
278 case GSM48_CC_CAUSE_USER_BUSY:
279 vty_notify(ms, "Call: Remote busy\n");
281 case GSM48_CC_CAUSE_USER_NOTRESPOND:
282 vty_notify(ms, "Call: Remote not responding\n");
284 case GSM48_CC_CAUSE_USER_ALERTING_NA:
285 vty_notify(ms, "Call: Remote not answering\n");
287 case GSM48_CC_CAUSE_CALL_REJECTED:
288 vty_notify(ms, "Call has been rejected\n");
290 case GSM48_CC_CAUSE_NUMBER_CHANGED:
291 vty_notify(ms, "Call: Number changed\n");
293 case GSM48_CC_CAUSE_PRE_EMPTION:
294 vty_notify(ms, "Call: Cleared due to pre-emption\n");
296 case GSM48_CC_CAUSE_DEST_OOO:
297 vty_notify(ms, "Call: Remote out of order\n");
299 case GSM48_CC_CAUSE_INV_NR_FORMAT:
300 vty_notify(ms, "Call: Number invalid or imcomplete\n");
302 case GSM48_CC_CAUSE_NO_CIRCUIT_CHAN:
303 vty_notify(ms, "Call: No channel available\n");
305 case GSM48_CC_CAUSE_NETWORK_OOO:
306 vty_notify(ms, "Call: Network out of order\n");
308 case GSM48_CC_CAUSE_TEMP_FAILURE:
309 vty_notify(ms, "Call: Temporary failure\n");
311 case GSM48_CC_CAUSE_SWITCH_CONG:
312 vty_notify(ms, "Congestion\n");
315 vty_notify(ms, "Call has been disconnected "
316 "(clear cause %d)\n", data->cause.value);
318 LOGP(DMNCC, LOGL_INFO, "Call has been disconnected "
319 "(cause %d)\n", data->cause.value);
320 if ((data->fields & MNCC_F_PROGRESS)
321 && data->progress.descr == 8) {
322 vty_notify(ms, "Please hang up!\n");
326 cause = GSM48_CC_CAUSE_NORM_CALL_CLEAR;
330 vty_notify(ms, NULL);
331 if (data->cause.value == GSM48_CC_CAUSE_CALL_REJECTED)
332 vty_notify(ms, "Call has been rejected\n");
334 vty_notify(ms, "Call has been released\n");
335 LOGP(DMNCC, LOGL_INFO, "Call has been released (cause %d)\n",
339 case MNCC_CALL_PROC_IND:
340 vty_notify(ms, NULL);
341 vty_notify(ms, "Call is proceeding\n");
342 LOGP(DMNCC, LOGL_INFO, "Call is proceeding\n");
343 if ((data->fields & MNCC_F_BEARER_CAP)
344 && data->bearer_cap.speech_ver[0] >= 0) {
345 mncc_get_bearer(set, data->bearer_cap.speech_ver[0]);
349 vty_notify(ms, NULL);
350 vty_notify(ms, "Call is alerting\n");
351 LOGP(DMNCC, LOGL_INFO, "Call is alerting\n");
354 vty_notify(ms, NULL);
355 vty_notify(ms, "Call is answered\n");
356 LOGP(DMNCC, LOGL_INFO, "Call is answered\n");
359 vty_notify(ms, NULL);
360 if (!first_call && !ms->settings.cw) {
361 vty_notify(ms, "Incoming call rejected while busy\n");
362 LOGP(DMNCC, LOGL_INFO, "Incoming call but busy\n");
363 cause = GSM48_CC_CAUSE_USER_BUSY;
366 /* select first supported speech_ver */
367 if ((data->fields & MNCC_F_BEARER_CAP)) {
370 for (i = 0; data->bearer_cap.speech_ver[i] >= 0; i++) {
372 temp = mncc_get_bearer(set,
373 data->bearer_cap.speech_ver[i]);
376 if (temp == 5 || temp == 1) { /* half */
377 /* only the first half rate */
378 if (speech_ver_half < 0)
379 speech_ver_half = temp;
381 /* only the first full rate */
386 /* half and full given */
387 if (speech_ver_half >= 0 && speech_ver >= 0) {
388 if (set->half_prefer) {
389 LOGP(DMNCC, LOGL_INFO, " both supported"
390 " codec rates are given, using "
391 "preferred half rate\n");
392 speech_ver = speech_ver_half;
394 LOGP(DMNCC, LOGL_INFO, " both supported"
395 " codec rates are given, using "
396 "preferred full rate\n");
397 } else if (speech_ver_half < 0 && speech_ver < 0) {
398 LOGP(DMNCC, LOGL_INFO, " no supported codec "
400 /* only half rate is given, use it */
401 } else if (speech_ver_half >= 0) {
402 LOGP(DMNCC, LOGL_INFO, " only supported half "
403 "rate codec is given, using it\n");
404 speech_ver = speech_ver_half;
405 /* only full rate is given, use it */
407 LOGP(DMNCC, LOGL_INFO, " only supported full "
408 "rate codec is given, using it\n");
411 /* presentation allowed if present == 0 */
412 if (data->calling.present || !data->calling.number[0])
413 vty_notify(ms, "Incoming call (anonymous)\n");
414 else if (data->calling.type == 1)
415 vty_notify(ms, "Incoming call (from +%s)\n",
416 data->calling.number);
417 else if (data->calling.type == 2)
418 vty_notify(ms, "Incoming call (from 0-%s)\n",
419 data->calling.number);
421 vty_notify(ms, "Incoming call (from %s)\n",
422 data->calling.number);
423 LOGP(DMNCC, LOGL_INFO, "Incoming call (from %s callref %x)\n",
424 data->calling.number, call->callref);
425 memset(&mncc, 0, sizeof(struct gsm_mncc));
426 mncc.callref = call->callref;
427 /* only include bearer cap, if not given in setup
428 * or if multiple codecs are given
429 * or if not only full rate
430 * or if given codec is unimplemented
432 if (!(data->fields & MNCC_F_BEARER_CAP) || speech_ver < 0)
433 mncc_set_bearer(ms, -1, &mncc);
434 else if (data->bearer_cap.speech_ver[1] >= 0
436 mncc_set_bearer(ms, speech_ver, &mncc);
437 /* CC capabilities (optional) */
438 if (ms->settings.cc_dtmf) {
439 mncc.fields |= MNCC_F_CCCAP;
442 mncc_send(ms, MNCC_CALL_CONF_REQ, &mncc);
444 LOGP(DMNCC, LOGL_INFO, "Ring!\n");
446 LOGP(DMNCC, LOGL_INFO, "Knock!\n");
450 memset(&mncc, 0, sizeof(struct gsm_mncc));
451 mncc.callref = call->callref;
452 mncc_send(ms, MNCC_ALERT_REQ, &mncc);
453 if (ms->settings.auto_answer) {
454 LOGP(DMNCC, LOGL_INFO, "Auto-answering call\n");
458 case MNCC_SETUP_COMPL_IND:
459 vty_notify(ms, NULL);
460 vty_notify(ms, "Call is connected\n");
461 LOGP(DMNCC, LOGL_INFO, "Call is connected\n");
464 vty_notify(ms, NULL);
465 vty_notify(ms, "Call is on hold\n");
466 LOGP(DMNCC, LOGL_INFO, "Call is on hold\n");
470 vty_notify(ms, NULL);
471 vty_notify(ms, "Call hold was rejected\n");
472 LOGP(DMNCC, LOGL_INFO, "Call hold was rejected\n");
474 case MNCC_RETRIEVE_CNF:
475 vty_notify(ms, NULL);
476 vty_notify(ms, "Call is retrieved\n");
477 LOGP(DMNCC, LOGL_INFO, "Call is retrieved\n");
480 case MNCC_RETRIEVE_REJ:
481 vty_notify(ms, NULL);
482 vty_notify(ms, "Call retrieve was rejected\n");
483 LOGP(DMNCC, LOGL_INFO, "Call retrieve was rejected\n");
485 case MNCC_FACILITY_IND:
486 LOGP(DMNCC, LOGL_INFO, "Facility info not displayed, "
489 case MNCC_START_DTMF_RSP:
490 case MNCC_START_DTMF_REJ:
491 case MNCC_STOP_DTMF_RSP:
492 dtmf_statemachine(call, data);
495 LOGP(DMNCC, LOGL_INFO, "Message 0x%02x unsupported\n",
503 int mncc_call(struct osmocom_ms *ms, char *number)
505 struct gsm_call *call;
506 struct gsm_mncc setup;
508 llist_for_each_entry(call, &call_list, entry) {
510 vty_notify(ms, NULL);
511 vty_notify(ms, "Please put active call on hold "
513 LOGP(DMNCC, LOGL_INFO, "Cannot make a call, busy!\n");
518 call = talloc_zero(l23_ctx, struct gsm_call);
522 call->callref = new_callref++;
524 llist_add_tail(&call->entry, &call_list);
526 memset(&setup, 0, sizeof(struct gsm_mncc));
527 setup.callref = call->callref;
529 if (!strncasecmp(number, "emerg", 5)) {
530 LOGP(DMNCC, LOGL_INFO, "Make emergency call\n");
534 LOGP(DMNCC, LOGL_INFO, "Make call to %s\n", number);
536 setup.fields |= MNCC_F_CALLED;
537 if (number[0] == '+') {
539 setup.called.type = 1; /* international */
541 setup.called.type = 0; /* auto/unknown - prefix must be
543 setup.called.plan = 1; /* ISDN */
544 strncpy(setup.called.number, number,
545 sizeof(setup.called.number) - 1);
547 /* bearer capability (mandatory) */
548 mncc_set_bearer(ms, -1, &setup);
549 if (ms->settings.clir)
551 else if (ms->settings.clip)
554 /* CC capabilities (optional) */
555 if (ms->settings.cc_dtmf) {
556 setup.fields |= MNCC_F_CCCAP;
557 setup.cccap.dtmf = 1;
561 return mncc_send(ms, MNCC_SETUP_REQ, &setup);
564 int mncc_hangup(struct osmocom_ms *ms)
566 struct gsm_call *call, *found = NULL;
567 struct gsm_mncc disc;
569 llist_for_each_entry(call, &call_list, entry) {
576 LOGP(DMNCC, LOGL_INFO, "No active call to hangup\n");
577 vty_notify(ms, NULL);
578 vty_notify(ms, "No active call\n");
582 memset(&disc, 0, sizeof(struct gsm_mncc));
583 disc.callref = found->callref;
584 mncc_set_cause(&disc, GSM48_CAUSE_LOC_USER,
585 GSM48_CC_CAUSE_NORM_CALL_CLEAR);
586 return mncc_send(ms, (call->init) ? MNCC_REL_REQ : MNCC_DISC_REQ,
590 int mncc_answer(struct osmocom_ms *ms)
592 struct gsm_call *call, *alerting = NULL;
596 llist_for_each_entry(call, &call_list, entry) {
599 else if (!call->hold)
603 LOGP(DMNCC, LOGL_INFO, "No call alerting\n");
604 vty_notify(ms, NULL);
605 vty_notify(ms, "No alerting call\n");
609 LOGP(DMNCC, LOGL_INFO, "Answer but we have an active call\n");
610 vty_notify(ms, NULL);
611 vty_notify(ms, "Please put active call on hold first!\n");
617 memset(&rsp, 0, sizeof(struct gsm_mncc));
618 rsp.callref = alerting->callref;
619 return mncc_send(ms, MNCC_SETUP_RSP, &rsp);
622 int mncc_hold(struct osmocom_ms *ms)
624 struct gsm_call *call, *found = NULL;
625 struct gsm_mncc hold;
627 llist_for_each_entry(call, &call_list, entry) {
634 LOGP(DMNCC, LOGL_INFO, "No active call to hold\n");
635 vty_notify(ms, NULL);
636 vty_notify(ms, "No active call\n");
640 memset(&hold, 0, sizeof(struct gsm_mncc));
641 hold.callref = found->callref;
642 return mncc_send(ms, MNCC_HOLD_REQ, &hold);
645 int mncc_retrieve(struct osmocom_ms *ms, int number)
647 struct gsm_call *call;
648 struct gsm_mncc retr;
649 int holdnum = 0, active = 0, i = 0;
651 llist_for_each_entry(call, &call_list, entry) {
658 LOGP(DMNCC, LOGL_INFO, "Cannot retrieve during active call\n");
659 vty_notify(ms, NULL);
660 vty_notify(ms, "Hold active call first!\n");
664 vty_notify(ms, NULL);
665 vty_notify(ms, "No call on hold!\n");
668 if (holdnum > 1 && number <= 0) {
669 vty_notify(ms, NULL);
670 vty_notify(ms, "Select call 1..%d\n", holdnum);
673 if (holdnum == 1 && number <= 0)
675 if (number > holdnum) {
676 vty_notify(ms, NULL);
677 vty_notify(ms, "Given number %d out of range!\n", number);
678 vty_notify(ms, "Select call 1..%d\n", holdnum);
682 llist_for_each_entry(call, &call_list, entry) {
688 memset(&retr, 0, sizeof(struct gsm_mncc));
689 retr.callref = call->callref;
690 return mncc_send(ms, MNCC_RETRIEVE_REQ, &retr);
697 static int dtmf_statemachine(struct gsm_call *call, struct gsm_mncc *mncc)
699 struct osmocom_ms *ms = call->ms;
700 struct gsm_mncc dtmf;
702 switch (call->dtmf_state) {
706 if (!call->dtmf[call->dtmf_index]) {
707 LOGP(DMNCC, LOGL_INFO, "done with DTMF\n");
708 call->dtmf_state = DTMF_ST_IDLE;
711 memset(&dtmf, 0, sizeof(struct gsm_mncc));
712 dtmf.callref = call->callref;
713 dtmf.keypad = call->dtmf[call->dtmf_index++];
714 call->dtmf_state = DTMF_ST_START;
715 LOGP(DMNCC, LOGL_INFO, "start DTMF (keypad %c)\n",
717 return mncc_send(ms, MNCC_START_DTMF_REQ, &dtmf);
719 if (mncc->msg_type != MNCC_START_DTMF_RSP) {
720 LOGP(DMNCC, LOGL_INFO, "DTMF was rejected\n");
723 start_dtmf_timer(call, 70);
724 call->dtmf_state = DTMF_ST_MARK;
725 LOGP(DMNCC, LOGL_INFO, "DTMF is on\n");
728 memset(&dtmf, 0, sizeof(struct gsm_mncc));
729 dtmf.callref = call->callref;
730 call->dtmf_state = DTMF_ST_STOP;
731 LOGP(DMNCC, LOGL_INFO, "stop DTMF\n");
732 return mncc_send(ms, MNCC_STOP_DTMF_REQ, &dtmf);
734 start_dtmf_timer(call, 120);
735 call->dtmf_state = DTMF_ST_SPACE;
736 LOGP(DMNCC, LOGL_INFO, "DTMF is off\n");
743 static void timeout_dtmf(void *arg)
745 struct gsm_call *call = arg;
747 LOGP(DCC, LOGL_INFO, "DTMF timer has fired\n");
748 dtmf_statemachine(call, NULL);
751 int mncc_dtmf(struct osmocom_ms *ms, char *dtmf)
753 struct gsm_call *call, *found = NULL;
755 llist_for_each_entry(call, &call_list, entry) {
762 LOGP(DMNCC, LOGL_INFO, "No active call to send DTMF\n");
763 vty_notify(ms, NULL);
764 vty_notify(ms, "No active call\n");
768 if (call->dtmf_state != DTMF_ST_IDLE) {
769 LOGP(DMNCC, LOGL_INFO, "sending DTMF already\n");
773 call->dtmf_index = 0;
774 strncpy(call->dtmf, dtmf, sizeof(call->dtmf) - 1);
775 return dtmf_statemachine(call, NULL);