aboutsummaryrefslogtreecommitdiffstats
path: root/src/common/call.c
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2017-11-18 08:33:07 +0100
committerAndreas Eversberg <jolly@eversberg.eu>2017-12-03 08:45:54 +0100
commitab59a26a519d4bfb88f9ca6f882da8baab90a95a (patch)
tree1c49655c2344a3bd5edc4e76948eaa33d7754e1c /src/common/call.c
parented31a26ebabcd28678aff679093b6e6fba55b67f (diff)
Restructure: Move mobile from common code to 'libmobile'
Diffstat (limited to 'src/common/call.c')
-rw-r--r--src/common/call.c790
1 files changed, 0 insertions, 790 deletions
diff --git a/src/common/call.c b/src/common/call.c
deleted file mode 100644
index 85c0e9f..0000000
--- a/src/common/call.c
+++ /dev/null
@@ -1,790 +0,0 @@
-/* interface between mobile network/phone implementation and MNCC
- *
- * (C) 2016 by Andreas Eversberg <jolly@eversberg.eu>
- * All Rights Reserved
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/time.h>
-#include "../libsample/sample.h"
-#include "debug.h"
-#include "sender.h"
-#include "call.h"
-#include "../libtimer/timer.h"
-#include "../libmncc/mncc.h"
-#include "../libmncc/cause.h"
-
-#define DISC_TIMEOUT 30
-
-//#define DEBUG_LEVEL
-
-#ifdef DEBUG_LEVEL
-static double level_of(double *samples, int count)
-{
- double level = 0;
- int i;
-
- for (i = 0; i < count; i++) {
- if (samples[i] > level)
- level = samples[i];
- }
-
- return level;
-}
-#endif
-
-static int send_patterns; /* send patterns towards fixed network */
-static int release_on_disconnect; /* release towards mobile phone, if MNCC call disconnects, don't send disconnect tone */
-
-/* stream patterns/announcements */
-int16_t *ringback_spl = NULL;
-int ringback_size = 0;
-int ringback_max = 0;
-int16_t *hangup_spl = NULL;
-int hangup_size = 0;
-int hangup_max = 0;
-int16_t *busy_spl = NULL;
-int busy_size = 0;
-int busy_max = 0;
-int16_t *noanswer_spl = NULL;
-int noanswer_size = 0;
-int noanswer_max = 0;
-int16_t *outoforder_spl = NULL;
-int outoforder_size = 0;
-int outoforder_max = 0;
-int16_t *invalidnumber_spl = NULL;
-int invalidnumber_size = 0;
-int invalidnumber_max = 0;
-int16_t *congestion_spl = NULL;
-int congestion_size = 0;
-int congestion_max = 0;
-int16_t *recall_spl = NULL;
-int recall_size = 0;
-int recall_max = 0;
-
-enum audio_pattern {
- PATTERN_NONE = 0,
- PATTERN_TEST,
- PATTERN_RINGBACK,
- PATTERN_HANGUP,
- PATTERN_BUSY,
- PATTERN_NOANSWER,
- PATTERN_OUTOFORDER,
- PATTERN_INVALIDNUMBER,
- PATTERN_CONGESTION,
- PATTERN_RECALL,
-};
-
-static void get_pattern(const int16_t **spl, int *size, int *max, enum audio_pattern pattern)
-{
- *spl = NULL;
- *size = 0;
- *max = 0;
-
- switch (pattern) {
- case PATTERN_RINGBACK:
-no_recall:
- *spl = ringback_spl;
- *size = ringback_size;
- *max = ringback_max;
- break;
- case PATTERN_HANGUP:
- if (!hangup_spl)
- goto no_hangup;
- *spl = hangup_spl;
- *size = hangup_size;
- *max = hangup_max;
- break;
- case PATTERN_BUSY:
-no_hangup:
-no_noanswer:
- *spl = busy_spl;
- *size = busy_size;
- *max = busy_max;
- break;
- case PATTERN_NOANSWER:
- if (!noanswer_spl)
- goto no_noanswer;
- *spl = noanswer_spl;
- *size = noanswer_size;
- *max = noanswer_max;
- break;
- case PATTERN_OUTOFORDER:
- if (!outoforder_spl)
- goto no_outoforder;
- *spl = outoforder_spl;
- *size = outoforder_size;
- *max = outoforder_max;
- break;
- case PATTERN_INVALIDNUMBER:
- if (!invalidnumber_spl)
- goto no_invalidnumber;
- *spl = invalidnumber_spl;
- *size = invalidnumber_size;
- *max = invalidnumber_max;
- break;
- case PATTERN_CONGESTION:
-no_outoforder:
-no_invalidnumber:
- *spl = congestion_spl;
- *size = congestion_size;
- *max = congestion_max;
- break;
- case PATTERN_RECALL:
- if (!recall_spl)
- goto no_recall;
- *spl = recall_spl;
- *size = recall_size;
- *max = recall_max;
- break;
- default:
- ;
- }
-}
-
-static enum audio_pattern cause2pattern(int cause)
-{
- int pattern;
-
- switch (cause) {
- case CAUSE_NORMAL:
- pattern = PATTERN_HANGUP;
- break;
- case CAUSE_BUSY:
- pattern = PATTERN_BUSY;
- break;
- case CAUSE_NOANSWER:
- pattern = PATTERN_NOANSWER;
- break;
- case CAUSE_OUTOFORDER:
- pattern = PATTERN_OUTOFORDER;
- break;
- case CAUSE_INVALNUMBER:
- pattern = PATTERN_INVALIDNUMBER;
- break;
- case CAUSE_NOCHANNEL:
- pattern = PATTERN_CONGESTION;
- break;
- default:
- pattern = PATTERN_HANGUP;
- }
-
- return pattern;
-}
-
-enum process_state {
- PROCESS_IDLE = 0, /* IDLE */
- PROCESS_SETUP_RO, /* call from radio to MNCC */
- PROCESS_SETUP_RT, /* call from MNCC to radio */
- PROCESS_ALERTING_RO, /* call from radio to MNCC */
- PROCESS_ALERTING_RT, /* call from MNCC to radio */
- PROCESS_CONNECT,
- PROCESS_DISCONNECT,
-};
-
-/* MNCC call instance */
-typedef struct process {
- struct process *next;
- int callref;
- enum process_state state;
- int audio_disconnected; /* if not associated with transceiver anymore */
- enum audio_pattern pattern;
- int audio_pos;
- uint8_t cause;
- struct timer timer;
-} process_t;
-
-static process_t *process_head = NULL;
-
-static void process_timeout(struct timer *timer);
-
-static process_t *create_process(int callref, enum process_state state)
-{
- process_t *process;
-
- process = calloc(sizeof(*process), 1);
- if (!process) {
- PDEBUG(DCALL, DEBUG_ERROR, "No memory!\n");
- abort();
- }
- timer_init(&process->timer, process_timeout, process);
- process->next = process_head;
- process_head = process;
-
- process->callref = callref;
- process->state = state;
-
- return process;
-}
-
-static void destroy_process(int callref)
-{
- process_t *process = process_head;
- process_t **process_p = &process_head;
-
- while (process) {
- if (process->callref == callref) {
- *process_p = process->next;
- timer_exit(&process->timer);
- free(process);
- return;
- }
- process_p = &process->next;
- process = process->next;
- }
- PDEBUG(DCALL, DEBUG_ERROR, "Process with callref 0x%x not found!\n", callref);
-}
-
-static process_t *get_process(int callref)
-{
- process_t *process = process_head;
-
- while (process) {
- if (process->callref == callref)
- return process;
- process = process->next;
- }
- return NULL;
-}
-
-static void new_state_process(int callref, enum process_state state)
-{
- process_t *process = get_process(callref);
-
- if (!process) {
- PDEBUG(DCALL, DEBUG_ERROR, "Process with callref 0x%x not found!\n", callref);
- return;
- }
- process->state = state;
-}
-
-static void set_pattern_process(int callref, enum audio_pattern pattern)
-{
- process_t *process = get_process(callref);
-
- if (!process) {
- PDEBUG(DCALL, DEBUG_ERROR, "Process with callref 0x%x not found!\n", callref);
- return;
- }
- process->pattern = pattern;
- process->audio_pos = 0;
-}
-
-/* disconnect audio, now send audio directly from pattern/announcement, not from transceiver */
-static void disconnect_process(int callref, int cause)
-{
- process_t *process = get_process(callref);
-
- if (!process) {
- PDEBUG(DCALL, DEBUG_ERROR, "Process with callref 0x%x not found!\n", callref);
- return;
- }
- process->pattern = cause2pattern(cause);
- process->audio_disconnected = 1;
- process->audio_pos = 0;
- process->cause = cause;
- timer_start(&process->timer, DISC_TIMEOUT);
-}
-
-static void get_process_patterns(process_t *process, int16_t *samples, int length)
-{
- const int16_t *spl;
- int size, max, pos;
-
- get_pattern(&spl, &size, &max, process->pattern);
-
- /* stream sample */
- pos = process->audio_pos;
- while(length--) {
- if (pos >= size)
- *samples++ = 0;
- else
- *samples++ = spl[pos] >> 1;
- if (++pos == max)
- pos = 0;
- }
- process->audio_pos = pos;
-}
-
-static void process_timeout(struct timer *timer)
-{
- process_t *process = (process_t *)timer->priv;
-
- {
- /* announcement timeout */
- uint8_t buf[sizeof(struct gsm_mncc)];
- struct gsm_mncc *mncc = (struct gsm_mncc *)buf;
-
- memset(buf, 0, sizeof(buf));
- mncc->msg_type = MNCC_REL_IND;
- mncc->callref = process->callref;
- mncc->fields |= MNCC_F_CAUSE;
- mncc->cause.location = LOCATION_PRIVATE_LOCAL;
- mncc->cause.value = process->cause;
-
- destroy_process(process->callref);
- PDEBUG(DCALL, DEBUG_INFO, "Releasing MNCC call towards fixed network (after timeout)\n");
- mncc_up(buf, sizeof(struct gsm_mncc));
- }
-}
-
-int call_init(int _send_patterns, int _release_on_disconnect)
-{
- send_patterns = _send_patterns;
- release_on_disconnect = _release_on_disconnect;
-
- return 0;
-}
-
-/* Setup is received from transceiver. */
-static int _indicate_setup(int callref, const char *callerid, const char *dialing)
-{
- uint8_t buf[sizeof(struct gsm_mncc)];
- struct gsm_mncc *mncc = (struct gsm_mncc *)buf;
- int rc;
-
- memset(buf, 0, sizeof(buf));
- mncc->msg_type = MNCC_SETUP_IND;
- mncc->callref = callref;
- mncc->fields |= MNCC_F_CALLING;
- if (callerid) {
- strncpy(mncc->calling.number, callerid, sizeof(mncc->calling.number) - 1);
- mncc->calling.type = 4; /* caller ID is of type 'subscriber' */
- } // otherwise unknown and no number
- mncc->fields |= MNCC_F_CALLED;
- strncpy(mncc->called.number, dialing, sizeof(mncc->called.number) - 1);
- mncc->called.type = 0; /* dialing is of type 'unknown' */
- mncc->lchan_type = GSM_LCHAN_TCH_F;
- mncc->fields |= MNCC_F_BEARER_CAP;
- mncc->bearer_cap.speech_ver[0] = BCAP_ANALOG_8000HZ;
- mncc->bearer_cap.speech_ver[1] = -1;
-
- PDEBUG(DCALL, DEBUG_INFO, "Indicate MNCC setup towards fixed network\n");
- rc = mncc_up(buf, sizeof(struct gsm_mncc));
- if (rc < 0)
- destroy_process(callref);
- return rc;
-}
-int call_up_setup(int callref, const char *callerid, const char *dialing)
-{
- int rc;
-
- if (!callref) {
- PDEBUG(DCALL, DEBUG_DEBUG, "Ignoring setup, because callref not set. (not for us)\n");
- return -CAUSE_INVALCALLREF;
- }
-
- if (callref < 0x4000000) {
- PDEBUG(DCALL, DEBUG_ERROR, "Invalid callref from mobile station, please fix!\n");
- abort();
- }
-
- PDEBUG(DCALL, DEBUG_INFO, "Incoming call from '%s' to '%s'\n", callerid ? : "unknown", dialing);
- if (!strcmp(dialing, "010"))
- PDEBUG(DCALL, DEBUG_INFO, " -> Call to Operator '%s'\n", dialing);
-
-
- create_process(callref, PROCESS_SETUP_RO);
-
- rc = _indicate_setup(callref, callerid, dialing);
-
- return rc;
-}
-
-/* Transceiver indicates alerting. */
-static void _indicate_alerting(int callref)
-{
- uint8_t buf[sizeof(struct gsm_mncc)];
- struct gsm_mncc *mncc = (struct gsm_mncc *)buf;
- int rc;
-
- memset(buf, 0, sizeof(buf));
- mncc->msg_type = MNCC_ALERT_IND;
- mncc->callref = callref;
-
- PDEBUG(DCALL, DEBUG_INFO, "Indicate MNCC alerting towards fixed network\n");
- rc = mncc_up(buf, sizeof(struct gsm_mncc));
- if (rc < 0)
- destroy_process(callref);
-}
-void call_up_alerting(int callref)
-{
- if (!callref) {
- PDEBUG(DCALL, DEBUG_DEBUG, "Ignoring alerting, because callref not set. (not for us)\n");
- return;
- }
-
- PDEBUG(DCALL, DEBUG_INFO, "Call is alerting\n");
-
- if (!send_patterns)
- _indicate_alerting(callref);
- set_pattern_process(callref, PATTERN_RINGBACK);
- new_state_process(callref, PROCESS_ALERTING_RT);
-}
-
-/* Transceiver indicates answer. */
-static void _indicate_answer(int callref, const char *connect_id)
-{
- uint8_t buf[sizeof(struct gsm_mncc)];
- struct gsm_mncc *mncc = (struct gsm_mncc *)buf;
- int rc;
-
- memset(buf, 0, sizeof(buf));
- mncc->msg_type = MNCC_SETUP_CNF;
- mncc->callref = callref;
- mncc->fields |= MNCC_F_CONNECTED;
- /* copy connected number as subscriber number */
- strncpy(mncc->connected.number, connect_id, sizeof(mncc->connected.number));
- mncc->connected.type = 4;
- mncc->connected.plan = 1;
- mncc->connected.present = 0;
- mncc->connected.screen = 3;
-
- PDEBUG(DCALL, DEBUG_INFO, "Indicate MNCC answer towards fixed network\n");
- rc = mncc_up(buf, sizeof(struct gsm_mncc));
- if (rc < 0)
- destroy_process(callref);
-}
-void call_up_answer(int callref, const char *connect_id)
-{
- if (!callref) {
- PDEBUG(DCALL, DEBUG_DEBUG, "Ignoring answer, because callref not set. (not for us)\n");
- return;
- }
-
- PDEBUG(DCALL, DEBUG_INFO, "Call has been answered by '%s'\n", connect_id);
-
- if (!send_patterns)
- _indicate_answer(callref, connect_id);
- set_pattern_process(callref, PATTERN_NONE);
- new_state_process(callref, PROCESS_CONNECT);
-}
-
-/* Transceiver indicates release. */
-static void _indicate_disconnect_release(int callref, int cause, int disc)
-{
- uint8_t buf[sizeof(struct gsm_mncc)];
- struct gsm_mncc *mncc = (struct gsm_mncc *)buf;
- int rc;
-
- memset(buf, 0, sizeof(buf));
- mncc->msg_type = (disc) ? MNCC_DISC_IND : MNCC_REL_IND;
- mncc->callref = callref;
- mncc->fields |= MNCC_F_CAUSE;
- mncc->cause.location = LOCATION_PRIVATE_LOCAL;
- mncc->cause.value = cause;
-
- PDEBUG(DCALL, DEBUG_INFO, "Indicate MNCC %s towards fixed network\n", (disc) ? "disconnect" : "release");
- rc = mncc_up(buf, sizeof(struct gsm_mncc));
- if (rc < 0)
- destroy_process(callref);
-}
-void call_up_release(int callref, int cause)
-{
- process_t *process;
-
- if (!callref) {
- PDEBUG(DCALL, DEBUG_DEBUG, "Ignoring release, because callref not set. (not for us)\n");
- return;
- }
-
- PDEBUG(DCALL, DEBUG_INFO, "Call has been released with cause=%d\n", cause);
-
- process = get_process(callref);
- if (process) {
- /* just keep MNCC connection if tones shall be sent.
- * no tones while setting up / alerting the call. */
- if (send_patterns
- && process->state != PROCESS_SETUP_RO
- && process->state != PROCESS_ALERTING_RO)
- disconnect_process(callref, cause);
- else
- /* if no tones shall be sent, release on disconnect
- * or RO setup states */
- if (process->state == PROCESS_DISCONNECT
- || process->state == PROCESS_SETUP_RO
- || process->state == PROCESS_ALERTING_RO) {
- destroy_process(callref);
- _indicate_disconnect_release(callref, cause, 0);
- /* if no tones shall be sent, disconnect on all other states */
- } else {
- disconnect_process(callref, cause);
- _indicate_disconnect_release(callref, cause, 1);
- }
- } else {
- /* we don't know about the process, just send release to upper layer anyway */
- _indicate_disconnect_release(callref, cause, 0);
- }
-}
-
-/* turn recall tone on or off */
-void call_tone_recall(int callref, int on)
-{
- set_pattern_process(callref, (on) ? PATTERN_RECALL : PATTERN_NONE);
-}
-
-/* forward audio to MNCC or call instance */
-void call_up_audio(int callref, sample_t *samples, int count)
-{
- if (count != 160) {
- fprintf(stderr, "Samples must be 160, please fix!\n");
- abort();
- }
- /* is MNCC us used, forward audio */
- uint8_t buf[sizeof(struct gsm_data_frame) + 160 * sizeof(int16_t)];
- struct gsm_data_frame *data = (struct gsm_data_frame *)buf;
- process_t *process;
-
- if (!callref)
- return;
-
- /* if we are disconnected, ignore audio */
- process = get_process(callref);
- if (!process || process->pattern != PATTERN_NONE)
- return;
-
- /* forward audio */
- data->msg_type = ANALOG_8000HZ;
- data->callref = callref;
-#ifdef DEBUG_LEVEL
- double lev = level_of(samples, count);
- printf(" mobil-level: %s%.4f\n", debug_db(lev), (20 * log10(lev)));
-#endif
- samples_to_int16((int16_t *)data->data, samples, count);
-
- mncc_up(buf, sizeof(buf));
- /* don't destroy process here in case of an error */
-}
-
-/* clock that is used to transmit patterns */
-void call_clock(void)
-{
- process_t *process = process_head;
- uint8_t buf[sizeof(struct gsm_data_frame) + 160 * sizeof(int16_t)];
- struct gsm_data_frame *data = (struct gsm_data_frame *)buf;
-
- while(process) {
- if (process->pattern != PATTERN_NONE) {
- data->msg_type = ANALOG_8000HZ;
- data->callref = process->callref;
- /* try to get patterns, else copy the samples we got */
- get_process_patterns(process, (int16_t *)data->data, 160);
-#ifdef DEBUG_LEVEL
- sample_t samples[160];
- int16_to_samples(samples, (int16_t *)data->data, 160);
- double lev = level_of(samples, 160);
- printf(" mobil-level: %s%.4f\n", debug_db(lev), (20 * log10(lev)));
- samples_to_int16((int16_t *)data->data, samples, 160);
-#endif
- mncc_up(buf, sizeof(buf));
- /* don't destroy process here in case of an error */
- }
- process = process->next;
- }
-}
-
-/* mncc messages received from fixed network */
-void mncc_down(uint8_t *buf, int length)
-{
- struct gsm_mncc *mncc = (struct gsm_mncc *)buf;
- char number[sizeof(mncc->called.number)];
- char caller_id[sizeof(mncc->calling.number)];
- enum number_type caller_type;
- int callref;
- int rc;
- process_t *process;
-
- callref = mncc->callref;
- process = get_process(callref);
- if (!process) {
- if (mncc->msg_type == MNCC_SETUP_REQ)
- process = create_process(callref, PROCESS_SETUP_RT);
- else {
- if (mncc->msg_type != MNCC_REL_REQ)
- PDEBUG(DCALL, DEBUG_ERROR, "No process!\n");
- return;
- }
- }
-
- if (mncc->msg_type == ANALOG_8000HZ) {
- struct gsm_data_frame *data = (struct gsm_data_frame *)buf;
- sample_t samples[160];
-
- /* if we are disconnected, ignore audio */
- if (process->pattern != PATTERN_NONE)
- return;
- int16_to_samples(samples, (int16_t *)data->data, 160);
-#ifdef DEBUG_LEVEL
- double lev = level_of(samples, 160);
- printf("festnetz-level: %s %.4f\n", debug_db(lev), (20 * log10(lev)));
-#endif
- call_down_audio(callref, samples, 160);
- return;
- }
-
- if (process->audio_disconnected) {
- switch(mncc->msg_type) {
- case MNCC_DISC_REQ:
- PDEBUG(DCALL, DEBUG_INFO, "Received MNCC disconnect from fixed network with cause %d\n", mncc->cause.value);
-
- PDEBUG(DCALL, DEBUG_INFO, "Call disconnected, releasing!\n");
-
- destroy_process(callref);
-
- PDEBUG(DCALL, DEBUG_INFO, "Indicate MNCC release towards fixed network\n");
- mncc->msg_type = MNCC_REL_IND;
- rc = mncc_up(buf, sizeof(struct gsm_mncc));
- if (rc < 0)
- destroy_process(callref);
- break;
- case MNCC_REL_REQ:
- PDEBUG(DCALL, DEBUG_INFO, "Received MNCC release from fixed network with cause %d\n", mncc->cause.value);
-
- PDEBUG(DCALL, DEBUG_INFO, "Call released\n");
-
- destroy_process(callref);
- break;
- }
- return;
- }
-
- switch(mncc->msg_type) {
- case MNCC_SETUP_REQ:
- strcpy(number, mncc->called.number);
-
- /* caller ID conversion */
- strcpy(caller_id, mncc->calling.number);
- switch(mncc->calling.type) {
- case 1:
- caller_type = TYPE_INTERNATIONAL;
- break;
- case 2:
- caller_type = TYPE_NATIONAL;
- break;
- case 4:
- caller_type = TYPE_SUBSCRIBER;
- break;
- default: /* or 0 */
- caller_type = TYPE_UNKNOWN;
- break;
- }
- if (!caller_id[0])
- caller_type = TYPE_NOTAVAIL;
- if (mncc->calling.present == 1)
- caller_type = TYPE_ANONYMOUS;
-
- PDEBUG(DCALL, DEBUG_INFO, "Received MNCC call from fixed network '%s' to mobile '%s'\n", caller_id, number);
-
- if (mncc->callref >= 0x4000000) {
- fprintf(stderr, "Invalid callref from fixed network, please fix!\n");
- abort();
- }
-
- PDEBUG(DCALL, DEBUG_INFO, "Indicate MNCC call confirm towards fixed network\n");
- memset(buf, 0, length);
- mncc->msg_type = MNCC_CALL_CONF_IND;
- mncc->callref = callref;
- mncc->lchan_type = GSM_LCHAN_TCH_F;
- mncc->fields |= MNCC_F_BEARER_CAP;
- mncc->bearer_cap.speech_ver[0] = BCAP_ANALOG_8000HZ;
- mncc->bearer_cap.speech_ver[1] = -1;
-
- mncc_up(buf, sizeof(struct gsm_mncc));
-
- PDEBUG(DCALL, DEBUG_INFO, "Outgoing call from '%s' to '%s'\n", caller_id, number);
-
- rc = call_down_setup(callref, caller_id, caller_type, number);
- if (rc < 0) {
- PDEBUG(DCALL, DEBUG_NOTICE, "Call rejected, cause %d\n", -rc);
- if (send_patterns) {
- PDEBUG(DCALL, DEBUG_DEBUG, "Early connecting after setup\n");
- _indicate_answer(callref, number);
- } else {
- PDEBUG(DCALL, DEBUG_INFO, "Disconnecting MNCC call towards fixed network (cause=%d)\n", -rc);
- _indicate_disconnect_release(callref, -rc, 1);
- }
- disconnect_process(callref, -rc);
- break;
- }
-
- if (send_patterns) {
- PDEBUG(DCALL, DEBUG_DEBUG, "Early connecting after setup\n");
- _indicate_answer(callref, number);
- break;
- }
- break;
- case MNCC_ALERT_REQ:
- PDEBUG(DCALL, DEBUG_INFO, "Received MNCC alerting from fixed network\n");
- new_state_process(callref, PROCESS_ALERTING_RO);
- break;
- case MNCC_SETUP_RSP:
- PDEBUG(DCALL, DEBUG_INFO, "Received MNCC answer from fixed network\n");
- new_state_process(callref, PROCESS_CONNECT);
- PDEBUG(DCALL, DEBUG_INFO, "Call answered\n");
- call_down_answer(callref);
- PDEBUG(DCALL, DEBUG_INFO, "Indicate MNCC setup complete towards fixed network\n");
- memset(buf, 0, length);
- mncc->msg_type = MNCC_SETUP_COMPL_IND;
- mncc->callref = callref;
- rc = mncc_up(buf, sizeof(struct gsm_mncc));
- if (rc < 0)
- destroy_process(callref);
- break;
- case MNCC_DISC_REQ:
- PDEBUG(DCALL, DEBUG_INFO, "Received MNCC disconnect from fixed network with cause %d\n", mncc->cause.value);
-
- process = get_process(callref);
- if (process && process->state == PROCESS_CONNECT && release_on_disconnect) {
- PDEBUG(DCALL, DEBUG_INFO, "Releasing, because we don't send disconnect tones to mobile phone\n");
-
- PDEBUG(DCALL, DEBUG_INFO, "Indicate MNCC release towards fixed network\n");
- mncc->msg_type = MNCC_REL_IND;
- mncc_up(buf, sizeof(struct gsm_mncc));
- goto release;
- }
- new_state_process(callref, PROCESS_DISCONNECT);
- PDEBUG(DCALL, DEBUG_INFO, "Call disconnected\n");
- call_down_disconnect(callref, mncc->cause.value);
- break;
- case MNCC_REL_REQ:
- PDEBUG(DCALL, DEBUG_INFO, "Received MNCC release from fixed network with cause %d\n", mncc->cause.value);
-
-release:
- destroy_process(callref);
- PDEBUG(DCALL, DEBUG_INFO, "Call released\n");
- call_down_release(callref, mncc->cause.value);
- break;
- }
-}
-
-int (*mncc_up)(uint8_t *buf, int length) = NULL;
-
-/* break down of MNCC socket */
-void mncc_flush(void)
-{
- while(process_head) {
- PDEBUG(DCALL, DEBUG_NOTICE, "MNCC socket closed, releasing call\n");
- call_down_release(process_head->callref, CAUSE_TEMPFAIL);
- destroy_process(process_head->callref);
- /* note: callref is released by sender's instance */
- }
-}
-