Replaced MNCC by OSMO-CC
This commit is contained in:
parent
d0d14e2acf
commit
2cb2d5f3ac
|
@ -41,7 +41,6 @@ src/libfm/libfm.a
|
|||
src/libfilter/libfilter.a
|
||||
src/libwave/libwave.a
|
||||
src/libfft/libfft.a
|
||||
src/libmncc/libmncc.a
|
||||
src/libsound/libsound.a
|
||||
src/libsdr/libsdr.a
|
||||
src/libsample/libsample.a
|
||||
|
|
|
@ -79,7 +79,6 @@ AC_OUTPUT(
|
|||
src/libfilter/Makefile
|
||||
src/libwave/Makefile
|
||||
src/libfft/Makefile
|
||||
src/libmncc/Makefile
|
||||
src/libsound/Makefile
|
||||
src/libsdr/Makefile
|
||||
src/libsample/Makefile
|
||||
|
|
|
@ -24,7 +24,6 @@ SUBDIRS = \
|
|||
libfilter \
|
||||
libwave \
|
||||
libfft \
|
||||
libmncc \
|
||||
libclipper \
|
||||
libserial \
|
||||
libv27 \
|
||||
|
|
|
@ -32,6 +32,7 @@ amps_LDADD = \
|
|||
$(top_builddir)/src/liboptions/liboptions.a \
|
||||
$(top_builddir)/src/libdebug/libdebug.a \
|
||||
$(top_builddir)/src/libmobile/libmobile.a \
|
||||
$(top_builddir)/src/libosmocc/libosmocc.a \
|
||||
$(top_builddir)/src/libdisplay/libdisplay.a \
|
||||
$(top_builddir)/src/libcompandor/libcompandor.a \
|
||||
$(top_builddir)/src/libgoertzel/libgoertzel.a \
|
||||
|
@ -42,7 +43,6 @@ amps_LDADD = \
|
|||
$(top_builddir)/src/libfm/libfm.a \
|
||||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libwave/libwave.a \
|
||||
$(top_builddir)/src/libmncc/libmncc.a \
|
||||
$(top_builddir)/src/libsample/libsample.a \
|
||||
$(top_builddir)/src/libg711/libg711.a \
|
||||
-lm
|
||||
|
|
|
@ -45,7 +45,8 @@
|
|||
#include "../libsample/sample.h"
|
||||
#include "../libdebug/debug.h"
|
||||
#include "../libmobile/call.h"
|
||||
#include "../libmncc/cause.h"
|
||||
#include "../libmobile/cause.h"
|
||||
#include "../libosmocc/message.h"
|
||||
#include "amps.h"
|
||||
#include "dsp.h"
|
||||
#include "frame.h"
|
||||
|
@ -63,10 +64,6 @@
|
|||
#define ALERT_TO 60.0 /* max time to wait for answer */
|
||||
#define RELEASE_TIMER 5.0 /* max time to send release messages */
|
||||
|
||||
/* Call reference for calls from mobile station to network
|
||||
This offset of 0x400000000 is required for MNCC interface. */
|
||||
static int new_callref = 0x40000000;
|
||||
|
||||
/* Convert channel number to frequency number of base station.
|
||||
Set 'uplink' to 1 to get frequency of mobile station. */
|
||||
double amps_channel2freq(int channel, int uplink)
|
||||
|
@ -599,7 +596,7 @@ int amps_create(const char *kanal, enum amps_chan_type chan_type, const char *au
|
|||
uint32_t min1;
|
||||
uint16_t min2;
|
||||
amps_number2min("1234567890", &min1, &min2);
|
||||
transaction_t __attribute__((__unused__)) *trans = create_transaction(amps, TRANS_CALL_MO_ASSIGN, min1, min2, 0, 0, 0, amps->sender.kanal);
|
||||
transaction_t __attribute__((__unused__)) *trans = create_transaction(amps, TRANS_CALL_MO_ASSIGN, min1, min2, 0, 0, 0, 0, amps->sender.kanal);
|
||||
// amps_new_state(amps, STATE_BUSY);
|
||||
#endif
|
||||
|
||||
|
@ -820,7 +817,7 @@ _register:
|
|||
PDEBUG_CHAN(DAMPS, DEBUG_INFO, " -> Home country: %s\n", country);
|
||||
if (national_number)
|
||||
PDEBUG_CHAN(DAMPS, DEBUG_INFO, " -> Home number: %s\n", national_number);
|
||||
trans = create_transaction(amps, TRANS_REGISTER_ACK, min1, min2, msg_type, ordq, order, 0);
|
||||
trans = create_transaction(amps, TRANS_REGISTER_ACK, min1, min2, esn, msg_type, ordq, order, 0);
|
||||
if (!trans) {
|
||||
PDEBUG(DAMPS, DEBUG_ERROR, "Failed to create transaction\n");
|
||||
return;
|
||||
|
@ -847,7 +844,7 @@ _register:
|
|||
PDEBUG(DAMPS, DEBUG_NOTICE, "No free channel, rejecting call\n");
|
||||
reject:
|
||||
if (!trans) {
|
||||
trans = create_transaction(amps, TRANS_CALL_REJECT, min1, min2, 0, 0, 3, 0);
|
||||
trans = create_transaction(amps, TRANS_CALL_REJECT, min1, min2, esn, 0, 0, 3, 0);
|
||||
if (!trans) {
|
||||
PDEBUG(DAMPS, DEBUG_ERROR, "Failed to create transaction\n");
|
||||
return;
|
||||
|
@ -862,7 +859,7 @@ reject:
|
|||
return;
|
||||
}
|
||||
if (!trans) {
|
||||
trans = create_transaction(amps, TRANS_CALL_MO_ASSIGN, min1, min2, 0, 0, 0, atoi(vc->sender.kanal));
|
||||
trans = create_transaction(amps, TRANS_CALL_MO_ASSIGN, min1, min2, esn, 0, 0, 0, atoi(vc->sender.kanal));
|
||||
strncpy(trans->dialing, dialing, sizeof(trans->dialing) - 1);
|
||||
if (!trans) {
|
||||
PDEBUG(DAMPS, DEBUG_ERROR, "Failed to create transaction\n");
|
||||
|
@ -957,7 +954,7 @@ inval:
|
|||
PDEBUG_CHAN(DAMPS, DEBUG_INFO, "Call to mobile station, paging station id '%s'\n", dialing);
|
||||
|
||||
/* 6. trying to page mobile station */
|
||||
trans = create_transaction(amps, TRANS_PAGE, min1, min2, 0, 0, 0, 0);
|
||||
trans = create_transaction(amps, TRANS_PAGE, min1, min2, 0, 0, 0, 0, 0);
|
||||
if (!trans) {
|
||||
PDEBUG(DAMPS, DEBUG_ERROR, "Failed to create transaction\n");
|
||||
return -CAUSE_TEMPFAIL;
|
||||
|
@ -1120,8 +1117,6 @@ static amps_t *assign_voice_channel(transaction_t *trans)
|
|||
{
|
||||
amps_t *amps = trans->amps, *vc;
|
||||
const char *callerid = amps_min2number(trans->min1, trans->min2);
|
||||
int callref = ++new_callref;
|
||||
int rc;
|
||||
|
||||
vc = search_channel(trans->chan);
|
||||
if (!vc) {
|
||||
|
@ -1146,15 +1141,11 @@ static amps_t *assign_voice_channel(transaction_t *trans)
|
|||
amps_flush_other_transactions(vc, trans);
|
||||
|
||||
if (!trans->callref) {
|
||||
char esn_text[16];
|
||||
sprintf(esn_text, "%u", trans->esn);
|
||||
/* setup call */
|
||||
PDEBUG(DAMPS, DEBUG_INFO, "Setup call to network.\n");
|
||||
rc = call_up_setup(callref, callerid, trans->dialing);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DAMPS, DEBUG_NOTICE, "Call rejected (cause %d), releasing.\n", rc);
|
||||
amps_release(trans, 0);
|
||||
return NULL;
|
||||
}
|
||||
trans->callref = callref;
|
||||
trans->callref = call_up_setup(callerid, trans->dialing, OSMO_CC_NETWORK_AMPS_ESN, esn_text);
|
||||
}
|
||||
|
||||
return vc;
|
||||
|
|
|
@ -227,7 +227,7 @@ static int handle_options(int short_option, int argi, char **argv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int main_amps_tacs(int argc, char *argv[])
|
||||
int main_amps_tacs(const char *name, int argc, char *argv[])
|
||||
{
|
||||
int rc, argi;
|
||||
const char *station_id = "";
|
||||
|
@ -392,7 +392,7 @@ int main_amps_tacs(int argc, char *argv[])
|
|||
printf("Base station on channel %s ready (%s), please tune transmitter to %.4f MHz and receiver to %.4f MHz. (%.3f MHz offset)\n", kanal[i], chan_type_long_name(chan_type[i]), amps_channel2freq(atoi(kanal[i]), 0) / 1e6, amps_channel2freq(atoi(kanal[i]), 1) / 1e6, amps_channel2freq(atoi(kanal[i]), 2) / 1e6);
|
||||
}
|
||||
|
||||
main_mobile(&quit, latency, interval, NULL, station_id, 10);
|
||||
main_mobile(name, &quit, latency, interval, NULL, station_id, 10);
|
||||
|
||||
fail:
|
||||
/* destroy transceiver instance */
|
||||
|
|
|
@ -17,5 +17,5 @@ int main(int argc, char *argv[])
|
|||
init_invalidnumber();
|
||||
init_congestion();
|
||||
|
||||
return main_amps_tacs(argc, argv);
|
||||
return main_amps_tacs("amps", argc, argv);
|
||||
}
|
||||
|
|
|
@ -2,5 +2,5 @@
|
|||
extern const int tacs;
|
||||
extern const int jtacs;
|
||||
|
||||
int main_amps_tacs(int argc, char *argv[]);
|
||||
int main_amps_tacs(const char *name, int argc, char *argv[]);
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "../libsample/sample.h"
|
||||
#include "../libdebug/debug.h"
|
||||
#include "../libmobile/call.h"
|
||||
#include "../libmncc/cause.h"
|
||||
#include "../libmobile/cause.h"
|
||||
#include "amps.h"
|
||||
//#include "database.h"
|
||||
|
||||
|
@ -103,7 +103,7 @@ const char *trans_short_state_name(int state)
|
|||
}
|
||||
|
||||
/* create transaction */
|
||||
transaction_t *create_transaction(amps_t *amps, enum amps_trans_state state, uint32_t min1, uint16_t min2, uint8_t msg_type, uint8_t ordq, uint8_t order, uint16_t chan)
|
||||
transaction_t *create_transaction(amps_t *amps, enum amps_trans_state state, uint32_t min1, uint16_t min2, uint32_t esn, uint8_t msg_type, uint8_t ordq, uint8_t order, uint16_t chan)
|
||||
{
|
||||
sender_t *sender;
|
||||
transaction_t *trans = NULL;
|
||||
|
@ -140,6 +140,7 @@ transaction_t *create_transaction(amps_t *amps, enum amps_trans_state state, uin
|
|||
trans_new_state(trans, state);
|
||||
trans->min1 = min1;
|
||||
trans->min2 = min2;
|
||||
trans->esn = esn;
|
||||
trans->msg_type = msg_type;
|
||||
trans->ordq = ordq;
|
||||
trans->order = order;
|
||||
|
|
|
@ -26,6 +26,7 @@ typedef struct transaction {
|
|||
int page_retry; /* current number of paging (re)try */
|
||||
uint32_t min1; /* current station ID (2 values) */
|
||||
uint16_t min2;
|
||||
uint32_t esn; /* ESN */
|
||||
uint8_t msg_type; /* message type (3 values) */
|
||||
uint8_t ordq;
|
||||
uint8_t order;
|
||||
|
@ -37,7 +38,7 @@ typedef struct transaction {
|
|||
int dtx; /* if set, DTX is used with this call */
|
||||
} transaction_t;
|
||||
|
||||
transaction_t *create_transaction(amps_t *amps, enum amps_trans_state trans_state, uint32_t min1, uint16_t min2, uint8_t msg_type, uint8_t ordq, uint8_t order, uint16_t chan);
|
||||
transaction_t *create_transaction(amps_t *amps, enum amps_trans_state trans_state, uint32_t min1, uint16_t min2, uint32_t esn, uint8_t msg_type, uint8_t ordq, uint8_t order, uint16_t chan);
|
||||
void destroy_transaction(transaction_t *trans);
|
||||
void link_transaction(transaction_t *trans, amps_t *amps);
|
||||
void unlink_transaction(transaction_t *trans);
|
||||
|
|
|
@ -21,6 +21,7 @@ anetz_LDADD = \
|
|||
$(top_builddir)/src/liboptions/liboptions.a \
|
||||
$(top_builddir)/src/libdebug/libdebug.a \
|
||||
$(top_builddir)/src/libmobile/libmobile.a \
|
||||
$(top_builddir)/src/libosmocc/libosmocc.a \
|
||||
$(top_builddir)/src/libdisplay/libdisplay.a \
|
||||
$(top_builddir)/src/libgoertzel/libgoertzel.a \
|
||||
$(top_builddir)/src/libjitter/libjitter.a \
|
||||
|
@ -31,7 +32,6 @@ anetz_LDADD = \
|
|||
$(top_builddir)/src/libfm/libfm.a \
|
||||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libwave/libwave.a \
|
||||
$(top_builddir)/src/libmncc/libmncc.a \
|
||||
$(top_builddir)/src/libsample/libsample.a \
|
||||
$(top_builddir)/src/libg711/libg711.a \
|
||||
-lm
|
||||
|
|
|
@ -28,14 +28,11 @@
|
|||
#include "../libdebug/debug.h"
|
||||
#include "../libtimer/timer.h"
|
||||
#include "../libmobile/call.h"
|
||||
#include "../libmncc/cause.h"
|
||||
#include "../libmobile/cause.h"
|
||||
#include "../libosmocc/message.h"
|
||||
#include "anetz.h"
|
||||
#include "dsp.h"
|
||||
|
||||
/* Call reference for calls from mobile station to network
|
||||
This offset of 0x400000000 is required for MNCC interface. */
|
||||
static int new_callref = 0x40000000;
|
||||
|
||||
/* Timers */
|
||||
#define PAGING_TO 30 /* Nach dieser Zeit ist der Operator genervt... */
|
||||
#define RELEASE_TO 3 /* Release time, so station keeps blocked for a while */
|
||||
|
@ -326,17 +323,8 @@ void anetz_receive_tone(anetz_t *anetz, int tone)
|
|||
/* throughconnect speech when calling/answer tone is gone */
|
||||
if (tone != 1) {
|
||||
if (!anetz->callref) {
|
||||
int callref = ++new_callref;
|
||||
int rc;
|
||||
|
||||
PDEBUG_CHAN(DANETZ, DEBUG_INFO, "1750 Hz signal from mobile station is gone, setup call.\n");
|
||||
rc = call_up_setup(callref, NULL, anetz->operator);
|
||||
if (rc < 0) {
|
||||
PDEBUG_CHAN(DANETZ, DEBUG_NOTICE, "Call rejected (cause %d), sending release tone.\n", -rc);
|
||||
anetz_release(anetz);
|
||||
break;
|
||||
}
|
||||
anetz->callref = callref;
|
||||
anetz->callref = call_up_setup(NULL, anetz->operator, OSMO_CC_NETWORK_ANETZ_NONE, "");
|
||||
} else {
|
||||
PDEBUG_CHAN(DANETZ, DEBUG_INFO, "1750 Hz signal from mobile station is gone, answer call.\n");
|
||||
call_up_answer(anetz->callref, anetz->station_id);
|
||||
|
|
|
@ -188,7 +188,7 @@ int main(int argc, char *argv[])
|
|||
printf("Base station on channel %s ready, please tune transmitter to %.3f MHz and receiver to %.3f MHz. (%.3f MHz offset)\n", kanal[i], anetz_kanal2freq(atoi(kanal[i]), 0) / 1e6, anetz_kanal2freq(atoi(kanal[i]), 1) / 1e6, anetz_kanal2freq(atoi(kanal[i]), 2) / 1e6);
|
||||
}
|
||||
|
||||
main_mobile(&quit, latency, interval, NULL, station_id, 5);
|
||||
main_mobile("anetz", &quit, latency, interval, NULL, station_id, 5);
|
||||
|
||||
fail:
|
||||
/* destroy transceiver instance */
|
||||
|
|
|
@ -18,6 +18,7 @@ bnetz_LDADD = \
|
|||
$(top_builddir)/src/liboptions/liboptions.a \
|
||||
$(top_builddir)/src/libdebug/libdebug.a \
|
||||
$(top_builddir)/src/libmobile/libmobile.a \
|
||||
$(top_builddir)/src/libosmocc/libosmocc.a \
|
||||
$(top_builddir)/src/libdisplay/libdisplay.a \
|
||||
$(top_builddir)/src/libjitter/libjitter.a \
|
||||
$(top_builddir)/src/libsquelch/libsquelch.a \
|
||||
|
@ -28,7 +29,6 @@ bnetz_LDADD = \
|
|||
$(top_builddir)/src/libfm/libfm.a \
|
||||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libwave/libwave.a \
|
||||
$(top_builddir)/src/libmncc/libmncc.a \
|
||||
$(top_builddir)/src/libsample/libsample.a \
|
||||
$(top_builddir)/src/libg711/libg711.a \
|
||||
-lm
|
||||
|
@ -44,7 +44,6 @@ bnetz_dialer_LDADD = \
|
|||
$(top_builddir)/src/libfm/libfm.a \
|
||||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libwave/libwave.a \
|
||||
$(top_builddir)/src/libmncc/libmncc.a \
|
||||
$(top_builddir)/src/libsample/libsample.a \
|
||||
$(ALSA_LIBS)
|
||||
-lm
|
||||
|
|
|
@ -27,15 +27,12 @@
|
|||
#include "../libsample/sample.h"
|
||||
#include "../libdebug/debug.h"
|
||||
#include "../libmobile/call.h"
|
||||
#include "../libmncc/cause.h"
|
||||
#include "../libmobile/cause.h"
|
||||
#include "../libosmocc/message.h"
|
||||
#include "bnetz.h"
|
||||
#include "telegramm.h"
|
||||
#include "dsp.h"
|
||||
|
||||
/* Call reference for calls from mobile station to network
|
||||
This offset of 0x400000000 is required for MNCC interface. */
|
||||
static int new_callref = 0x40000000;
|
||||
|
||||
/* mobile originating call */
|
||||
#define CARRIER_TO 0.08 /* 80 ms search for carrier */
|
||||
#define DIALING_TO 3.8 /* timeout after channel allocation "Kanalbelegung" (according to FTZ 1727 Pfl 32 Clause 3.2.2.2.8) */
|
||||
|
@ -565,8 +562,6 @@ void bnetz_receive_telegramm(bnetz_t *bnetz, uint16_t telegramm)
|
|||
break;
|
||||
case DIAL_MODE_NUMBER2:
|
||||
if (digit == 'e') {
|
||||
int callref = ++new_callref;
|
||||
int rc;
|
||||
/* add 0 in front of number */
|
||||
char dialing[sizeof(bnetz->dial_number) + 1] = "0";
|
||||
strcpy(dialing + 1, bnetz->dial_number);
|
||||
|
@ -594,13 +589,7 @@ void bnetz_receive_telegramm(bnetz_t *bnetz, uint16_t telegramm)
|
|||
|
||||
/* setup call */
|
||||
PDEBUG(DBNETZ, DEBUG_INFO, "Setup call to network.\n");
|
||||
rc = call_up_setup(callref, bnetz->station_id, dialing);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DBNETZ, DEBUG_NOTICE, "Call rejected (cause %d), releasing.\n", -rc);
|
||||
bnetz_release(bnetz, TRENN_COUNT);
|
||||
return;
|
||||
}
|
||||
bnetz->callref = callref;
|
||||
bnetz->callref = call_up_setup(bnetz->station_id, dialing, OSMO_CC_NETWORK_BNETZ_MUENZ, (bnetz->dial_type == DIAL_TYPE_METER_MUENZ) ? "MUENZ" : "");
|
||||
break;
|
||||
}
|
||||
if (digit < '0' || digit > '9') {
|
||||
|
|
|
@ -194,7 +194,7 @@ int main(int argc, char *argv[])
|
|||
printf("To call phone, switch transmitter (using paging signal) to %.3f MHz.\n", bnetz_kanal2freq(19, 0) / 1e6);
|
||||
}
|
||||
|
||||
main_mobile(&quit, latency, interval, NULL, station_id, 5);
|
||||
main_mobile("bnetz", &quit, latency, interval, NULL, station_id, 5);
|
||||
|
||||
fail:
|
||||
/* destroy transceiver instance */
|
||||
|
|
|
@ -26,6 +26,7 @@ cnetz_LDADD = \
|
|||
$(top_builddir)/src/liboptions/liboptions.a \
|
||||
$(top_builddir)/src/libdebug/libdebug.a \
|
||||
$(top_builddir)/src/libmobile/libmobile.a \
|
||||
$(top_builddir)/src/libosmocc/libosmocc.a \
|
||||
$(top_builddir)/src/libdisplay/libdisplay.a \
|
||||
$(top_builddir)/src/libcompandor/libcompandor.a \
|
||||
$(top_builddir)/src/libjitter/libjitter.a \
|
||||
|
@ -36,7 +37,6 @@ cnetz_LDADD = \
|
|||
$(top_builddir)/src/libfm/libfm.a \
|
||||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libwave/libwave.a \
|
||||
$(top_builddir)/src/libmncc/libmncc.a \
|
||||
$(top_builddir)/src/libsample/libsample.a \
|
||||
$(top_builddir)/src/libg711/libg711.a \
|
||||
-lm
|
||||
|
|
|
@ -145,7 +145,8 @@
|
|||
#include "../libsample/sample.h"
|
||||
#include "../libdebug/debug.h"
|
||||
#include "../libmobile/call.h"
|
||||
#include "../libmncc/cause.h"
|
||||
#include "../libmobile/cause.h"
|
||||
#include "../libosmocc/message.h"
|
||||
#include "cnetz.h"
|
||||
#include "database.h"
|
||||
#include "sysinfo.h"
|
||||
|
@ -158,10 +159,6 @@
|
|||
|
||||
#define CUT_OFF_EMPHASIS_CNETZ 796.0 /* 200 uS time constant */
|
||||
|
||||
/* Call reference for calls from mobile station to network
|
||||
This offset of 0x400000000 is required for MNCC interface. */
|
||||
static int new_callref = 0x40000000;
|
||||
|
||||
/* Convert channel number to frequency number of base station.
|
||||
Set 'unterband' to 1 to get frequency of mobile station. */
|
||||
double cnetz_kanal2freq(int kanal, int unterband)
|
||||
|
@ -1359,15 +1356,7 @@ no_auth:
|
|||
if (!cnetz->sender.loopback && (cnetz->sched_ts & 7) == 7 && cnetz->sched_r_m && !timer_running(&trans->timer)) {
|
||||
/* next sub frame */
|
||||
if (trans->mo_call) {
|
||||
int rc;
|
||||
trans->callref = ++new_callref;
|
||||
rc = call_up_setup(trans->callref, transaction2rufnummer(trans), trans->dialing);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Call rejected (cause %d), releasing.\n", -rc);
|
||||
trans->callref = 0;
|
||||
cnetz_release(trans, cnetz_cause_isdn2cnetz(-rc));
|
||||
goto call_failed;
|
||||
}
|
||||
trans->callref = call_up_setup(transaction2rufnummer(trans), trans->dialing, OSMO_CC_NETWORK_CNETZ_NONE, "");
|
||||
trans_new_state(trans, TRANS_DS);
|
||||
trans->repeat = 0;
|
||||
timer_start(&trans->timer, 0.0375 * F_DS); /* F_DS frames */
|
||||
|
@ -1410,7 +1399,6 @@ no_auth:
|
|||
}
|
||||
break;
|
||||
case TRANS_AF:
|
||||
call_failed:
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Ausloesen durch FuFSt' on traffic channel\n");
|
||||
telegramm.opcode = OPCODE_AF_K;
|
||||
if (++trans->repeat < N_AFKT)
|
||||
|
|
|
@ -647,7 +647,7 @@ int main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
main_mobile(&quit, latency, interval, NULL, station_id, 7);
|
||||
main_mobile("cnetz", &quit, latency, interval, NULL, station_id, 7);
|
||||
|
||||
fail:
|
||||
flush_db();
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include "../libsample/sample.h"
|
||||
#include "../libdebug/debug.h"
|
||||
#include "../libmobile/call.h"
|
||||
#include "../libmncc/cause.h"
|
||||
#include "../libmobile/cause.h"
|
||||
#include "cnetz.h"
|
||||
#include "telegramm.h"
|
||||
#include "database.h"
|
||||
|
|
|
@ -18,6 +18,7 @@ eurosignal_LDADD = \
|
|||
$(top_builddir)/src/liboptions/liboptions.a \
|
||||
$(top_builddir)/src/libdebug/libdebug.a \
|
||||
$(top_builddir)/src/libmobile/libmobile.a \
|
||||
$(top_builddir)/src/libosmocc/libosmocc.a \
|
||||
$(top_builddir)/src/libdisplay/libdisplay.a \
|
||||
$(top_builddir)/src/libjitter/libjitter.a \
|
||||
$(top_builddir)/src/libtimer/libtimer.a \
|
||||
|
@ -27,7 +28,6 @@ eurosignal_LDADD = \
|
|||
$(top_builddir)/src/libfm/libfm.a \
|
||||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libwave/libwave.a \
|
||||
$(top_builddir)/src/libmncc/libmncc.a \
|
||||
$(top_builddir)/src/libsample/libsample.a \
|
||||
$(top_builddir)/src/libg711/libg711.a \
|
||||
-lm
|
||||
|
|
|
@ -28,7 +28,8 @@
|
|||
#include "../libsample/sample.h"
|
||||
#include "../libdebug/debug.h"
|
||||
#include "../libmobile/call.h"
|
||||
#include "../libmncc/cause.h"
|
||||
#include "../libmobile/cause.h"
|
||||
#include "../libosmocc/message.h"
|
||||
#include "eurosignal.h"
|
||||
#include "dsp.h"
|
||||
|
||||
|
@ -42,10 +43,6 @@
|
|||
#define ACKNOWLEDGE_TIME2 4.6 /* announcement 1.7 s, pause 2.9 s */
|
||||
#define BEEP_TIME 4.0 /* beep after answer */
|
||||
|
||||
/* Call reference for calls from mobile station to network
|
||||
This offset of 0x400000000 is required for MNCC interface. */
|
||||
static int new_callref = 0x40000000;
|
||||
|
||||
/* these calls are not associated with a transmitter */
|
||||
euro_call_t *ooo_call_list = NULL;
|
||||
|
||||
|
@ -469,10 +466,9 @@ void euro_receive_id(euro_t *euro, char *id)
|
|||
|
||||
/* we want to send beep via MNCC */
|
||||
if (id_list) {
|
||||
uint32_t callref;
|
||||
euro_call_t *call;
|
||||
char dialing[32];
|
||||
int callref;
|
||||
int rc;
|
||||
|
||||
/* check if we already have a call that beeps */
|
||||
for (call = ooo_call_list; call; call = call->next) {
|
||||
|
@ -485,13 +481,10 @@ void euro_receive_id(euro_t *euro, char *id)
|
|||
|
||||
/* create call and send setup */
|
||||
PDEBUG_CHAN(DEURO, DEBUG_INFO, "Sending setup towards network.'\n");
|
||||
callref = ++new_callref;
|
||||
sprintf(dialing, "%d", count);
|
||||
callref = call_up_setup(call->station_id, dialing, OSMO_CC_NETWORK_EUROSIGNAL_NONE, "");
|
||||
call = euro_call_create(NULL, callref, id);
|
||||
call_new_state(call, EURO_CALL_BEEPING);
|
||||
sprintf(dialing, "%d", count);
|
||||
rc = call_up_setup(callref, call->station_id, dialing);
|
||||
if (rc < 0)
|
||||
euro_call_destroy(call);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -239,7 +239,7 @@ int main(int argc, char *argv[])
|
|||
printf("Base station for channel %s ready, please tune transmitter and/or receiver to %.4f MHz\n", kanal[i], euro_kanal2freq(kanal[i], fm) / 1e6);
|
||||
}
|
||||
|
||||
main_mobile(&quit, latency, interval, NULL, station_id, 6);
|
||||
main_mobile("eurosignal", &quit, latency, interval, NULL, station_id, 6);
|
||||
|
||||
fail:
|
||||
/* destroy transceiver instance */
|
||||
|
|
|
@ -17,6 +17,7 @@ fuvst_LDADD = \
|
|||
$(top_builddir)/src/liboptions/liboptions.a \
|
||||
$(top_builddir)/src/libdebug/libdebug.a \
|
||||
$(top_builddir)/src/libmobile/libmobile.a \
|
||||
$(top_builddir)/src/libosmocc/libosmocc.a \
|
||||
$(top_builddir)/src/libdisplay/libdisplay.a \
|
||||
$(top_builddir)/src/libcompandor/libcompandor.a \
|
||||
$(top_builddir)/src/libjitter/libjitter.a \
|
||||
|
@ -29,7 +30,6 @@ fuvst_LDADD = \
|
|||
$(top_builddir)/src/libmtp/libmtp.a \
|
||||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libwave/libwave.a \
|
||||
$(top_builddir)/src/libmncc/libmncc.a \
|
||||
$(top_builddir)/src/libsample/libsample.a \
|
||||
$(top_builddir)/src/libsound/libsound.a \
|
||||
$(top_builddir)/src/libg711/libg711.a \
|
||||
|
@ -43,6 +43,7 @@ fuvst_sniffer_LDADD = \
|
|||
$(top_builddir)/src/liboptions/liboptions.a \
|
||||
$(top_builddir)/src/libdebug/libdebug.a \
|
||||
$(top_builddir)/src/libmobile/libmobile.a \
|
||||
$(top_builddir)/src/libosmocc/libosmocc.a \
|
||||
$(top_builddir)/src/libdisplay/libdisplay.a \
|
||||
$(top_builddir)/src/libcompandor/libcompandor.a \
|
||||
$(top_builddir)/src/libjitter/libjitter.a \
|
||||
|
@ -55,7 +56,6 @@ fuvst_sniffer_LDADD = \
|
|||
$(top_builddir)/src/libmtp/libmtp.a \
|
||||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libwave/libwave.a \
|
||||
$(top_builddir)/src/libmncc/libmncc.a \
|
||||
$(top_builddir)/src/libsample/libsample.a \
|
||||
$(top_builddir)/src/libsound/libsound.a \
|
||||
$(top_builddir)/src/libg711/libg711.a \
|
||||
|
|
|
@ -37,8 +37,9 @@
|
|||
#include "../libsample/sample.h"
|
||||
#include "../libdebug/debug.h"
|
||||
#include "../libmobile/call.h"
|
||||
#include "../libmncc/cause.h"
|
||||
#include "../libmobile/cause.h"
|
||||
#include "../libtimer/timer.h"
|
||||
#include "../libosmocc/message.h"
|
||||
#include "fuvst.h"
|
||||
|
||||
/* digital loopback test */
|
||||
|
@ -367,10 +368,6 @@ static void add_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest,
|
|||
* transactions
|
||||
*/
|
||||
|
||||
/* Call reference for calls from mobile station to network
|
||||
This offset of 0x400000000 is required for MNCC interface. */
|
||||
static int new_callref = 0x40000000;
|
||||
|
||||
/* Release timeout */
|
||||
#define RELEASE_TO 3.0
|
||||
|
||||
|
@ -982,19 +979,8 @@ outgoing:
|
|||
message_send(ident, opcode, data, len);
|
||||
/* no callref == outgoing call */
|
||||
if (!trans->callref) {
|
||||
int rc;
|
||||
PDEBUG(DCNETZ, DEBUG_INFO, "Setup call to network. (Ident = %d, FuTln=%s, number=%s)\n", ident, transaction2rufnummer(trans), trans->number);
|
||||
trans->callref = trans->old_callref = ++new_callref;
|
||||
rc = call_up_setup(trans->callref, transaction2rufnummer(trans), trans->number);
|
||||
/* rejected by network, release towards BS */
|
||||
if (rc < 0) {
|
||||
len = encode_aau(&opcode, &data, Q, 0, cnetz_cause2futln(-rc));
|
||||
message_send(ident, opcode, data, len);
|
||||
trans->callref = 0;
|
||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Call rejected (cause %d), releasing.\n", -rc);
|
||||
destroy_transaction(trans);
|
||||
break;
|
||||
}
|
||||
trans->callref = trans->old_callref = call_up_setup(transaction2rufnummer(trans), trans->number, OSMO_CC_NETWORK_CNETZ_NONE, "");
|
||||
} else {
|
||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Call to mobile is alerting.\n");
|
||||
new_call_state(trans, STATE_MT_ALERTING);
|
||||
|
|
|
@ -265,7 +265,7 @@ int main(int argc, char *argv[])
|
|||
printf("Using Speech Channel: SPK-%s\n", kanal[i]);
|
||||
}
|
||||
|
||||
main_mobile(&quit, latency, interval, NULL, station_id, 7);
|
||||
main_mobile("fuvst", &quit, latency, interval, NULL, station_id, 7);
|
||||
fail:
|
||||
|
||||
/* destroy transceiver instance */
|
||||
|
|
|
@ -225,7 +225,7 @@ int main(int argc, char *argv[])
|
|||
goto fail;
|
||||
}
|
||||
|
||||
main_mobile(&quit, latency, interval, NULL, NULL, 0);
|
||||
main_mobile(NULL, &quit, latency, interval, NULL, NULL, 0);
|
||||
|
||||
fail:
|
||||
/* destroy transceiver instance */
|
||||
|
|
|
@ -15,6 +15,7 @@ imts_LDADD = \
|
|||
$(top_builddir)/src/liboptions/liboptions.a \
|
||||
$(top_builddir)/src/libdebug/libdebug.a \
|
||||
$(top_builddir)/src/libmobile/libmobile.a \
|
||||
$(top_builddir)/src/libosmocc/libosmocc.a \
|
||||
$(top_builddir)/src/libdisplay/libdisplay.a \
|
||||
$(top_builddir)/src/libjitter/libjitter.a \
|
||||
$(top_builddir)/src/libsquelch/libsquelch.a \
|
||||
|
@ -24,7 +25,6 @@ imts_LDADD = \
|
|||
$(top_builddir)/src/libfm/libfm.a \
|
||||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libwave/libwave.a \
|
||||
$(top_builddir)/src/libmncc/libmncc.a \
|
||||
$(top_builddir)/src/libsample/libsample.a \
|
||||
$(top_builddir)/src/libg711/libg711.a \
|
||||
-lm
|
||||
|
|
|
@ -42,16 +42,13 @@
|
|||
#include "../libdebug/debug.h"
|
||||
#include "../libtimer/timer.h"
|
||||
#include "../libmobile/call.h"
|
||||
#include "../libmncc/cause.h"
|
||||
#include "../libmobile/cause.h"
|
||||
#include "../libosmocc/message.h"
|
||||
#include "imts.h"
|
||||
#include "dsp.h"
|
||||
|
||||
#define CUT_OFF_EMPHASIS_IMTS 796.0 /* FIXME: really 200 uS time constant? */
|
||||
|
||||
/* Call reference for calls from mobile station to network
|
||||
This offset of 0x400000000 is required for MNCC interface. */
|
||||
static int new_callref = 0x40000000;
|
||||
|
||||
/* band info */
|
||||
#define VHF_LOW 0
|
||||
#define VHF_HIGH 1
|
||||
|
@ -535,17 +532,8 @@ void imts_signal_indication(imts_t *imts)
|
|||
{
|
||||
/* setup a call from mobile to base station */
|
||||
if (imts->mode == MODE_MTS && imts->state == IMTS_IDLE) {
|
||||
int callref = ++new_callref;
|
||||
int rc;
|
||||
|
||||
PDEBUG_CHAN(DIMTS, DEBUG_INFO, "Detectes RF signal in IDLE mode, calling the opterator at '%s'.\n", imts->operator);
|
||||
rc = call_up_setup(callref, NULL, imts->operator);
|
||||
if (rc < 0) {
|
||||
PDEBUG_CHAN(DANETZ, DEBUG_NOTICE, "Call rejected (cause %d), releasing!\n", -rc);
|
||||
imts_release(imts);
|
||||
return;
|
||||
}
|
||||
imts->callref = callref;
|
||||
imts->callref = call_up_setup(NULL, imts->operator, OSMO_CC_NETWORK_MTS_NONE, "");
|
||||
imts_new_state(imts, IMTS_CONVERSATION);
|
||||
imts_set_dsp_mode(imts, DSP_MODE_AUDIO, 0, 0.0, 0);
|
||||
}
|
||||
|
@ -864,17 +852,8 @@ static void dial_after_digit(imts_t *imts)
|
|||
imts->dial_number[++imts->rx_dial_index] = '\0';
|
||||
timer_start(&imts->timer, DIALING_TO);
|
||||
} else {
|
||||
int callref = ++new_callref;
|
||||
int rc;
|
||||
|
||||
PDEBUG_CHAN(DIMTS, DEBUG_INFO, "Timeout receiving dialing from mobile phone, number complete.\n");
|
||||
rc = call_up_setup(callref, imts->station_id, imts->dial_number);
|
||||
if (rc < 0) {
|
||||
PDEBUG_CHAN(DANETZ, DEBUG_NOTICE, "Call rejected (cause %d), releasing!\n", -rc);
|
||||
imts_release(imts);
|
||||
return;
|
||||
}
|
||||
imts->callref = callref;
|
||||
imts->callref = call_up_setup(imts->station_id, imts->dial_number, OSMO_CC_NETWORK_IMTS_NONE, "");
|
||||
imts_new_state(imts, IMTS_CONVERSATION);
|
||||
imts_set_dsp_mode(imts, DSP_MODE_AUDIO, 0, 0.0, 0);
|
||||
imts->rx_disc_pulse = 0;
|
||||
|
|
|
@ -274,7 +274,7 @@ int main(int argc, char *argv[])
|
|||
printf("Base station on channel %s ready, please tune transmitter to %.3f MHz and receiver to %.3f MHz. (%.3f MHz offset)\n", kanal[i], imts_channel2freq(kanal[i], 0) / 1e6, imts_channel2freq(kanal[i], 1) / 1e6, imts_channel2freq(kanal[i], 2) / 1e6);
|
||||
}
|
||||
|
||||
main_mobile(&quit, latency, interval, NULL, station_id, station_length);
|
||||
main_mobile((mode == MODE_IMTS) ? "imts" : "mts", &quit, latency, interval, NULL, station_id, station_length);
|
||||
|
||||
fail:
|
||||
/* destroy transceiver instance */
|
||||
|
|
|
@ -14,6 +14,7 @@ jollycom_LDADD = \
|
|||
$(top_builddir)/src/liboptions/liboptions.a \
|
||||
$(top_builddir)/src/libdebug/libdebug.a \
|
||||
$(top_builddir)/src/libmobile/libmobile.a \
|
||||
$(top_builddir)/src/libosmocc/libosmocc.a \
|
||||
$(top_builddir)/src/libdisplay/libdisplay.a \
|
||||
$(top_builddir)/src/libgoertzel/libgoertzel.a \
|
||||
$(top_builddir)/src/libjitter/libjitter.a \
|
||||
|
@ -24,7 +25,6 @@ jollycom_LDADD = \
|
|||
$(top_builddir)/src/libemphasis/libemphasis.a \
|
||||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libwave/libwave.a \
|
||||
$(top_builddir)/src/libmncc/libmncc.a \
|
||||
$(top_builddir)/src/libsample/libsample.a \
|
||||
$(top_builddir)/src/libfm/libfm.a \
|
||||
$(top_builddir)/src/libg711/libg711.a \
|
||||
|
|
|
@ -137,15 +137,12 @@
|
|||
#include "../libdebug/debug.h"
|
||||
#include "../libtimer/timer.h"
|
||||
#include "../libmobile/call.h"
|
||||
#include "../libmncc/cause.h"
|
||||
#include "../libmobile/cause.h"
|
||||
#include "../libosmocc/message.h"
|
||||
#include "jolly.h"
|
||||
#include "dsp.h"
|
||||
#include "voice.h"
|
||||
|
||||
/* Call reference for calls from mobile station to network
|
||||
This offset of 0x400000000 is required for MNCC interface. */
|
||||
static int new_callref = 0x40000000;
|
||||
|
||||
#define db2level(db) pow(10, (double)db / 20.0)
|
||||
|
||||
/* Timers */
|
||||
|
@ -390,18 +387,9 @@ void jolly_receive_dtmf(void *priv, char digit, dtmf_meas_t *meas)
|
|||
break;
|
||||
}
|
||||
if (digit == '#') {
|
||||
int callref = ++new_callref;
|
||||
int rc;
|
||||
|
||||
PDEBUG_CHAN(DJOLLY, DEBUG_INFO, "Received ack digit, entering call state.\n");
|
||||
timer_stop(&jolly->timer);
|
||||
rc = call_up_setup(callref, NULL, jolly->dialing);
|
||||
if (rc < 0) {
|
||||
PDEBUG_CHAN(DJOLLY, DEBUG_NOTICE, "Call rejected (cause %d), going idle.\n", -rc);
|
||||
jolly_release(jolly);
|
||||
break;
|
||||
}
|
||||
jolly->callref = callref;
|
||||
jolly->callref = call_up_setup(NULL, jolly->dialing, OSMO_CC_NETWORK_JOLLYCOM_NONE, "");
|
||||
jolly_new_state(jolly, STATE_CALL);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include "../libmobile/main_mobile.h"
|
||||
#include "../libdebug/debug.h"
|
||||
#include "../libtimer/timer.h"
|
||||
#include "../libmncc/mncc_sock.h"
|
||||
#include "../anetz/freiton.h"
|
||||
#include "../anetz/besetztton.h"
|
||||
#include "../liboptions/options.h"
|
||||
|
@ -199,7 +198,7 @@ int main(int argc, char *argv[])
|
|||
printf("base station on channel %s ready, please tune transmitter to %.4f MHz and receiver to %.4f MHz. (%.4f MHz offset)\n", kanal[i], dl_freq + step / 1e3 * (double)atoi(kanal[i]), ul_freq + step / 1e3 * (double)atoi(kanal[i]), ul_freq - dl_freq);
|
||||
}
|
||||
|
||||
main_mobile(&quit, latency, interval, NULL, station_id, 4);
|
||||
main_mobile("jollycom", &quit, latency, interval, NULL, station_id, 4);
|
||||
|
||||
fail:
|
||||
/* destroy transceiver instance */
|
||||
|
|
|
@ -15,6 +15,7 @@ jtacs_LDADD = \
|
|||
$(top_builddir)/src/liboptions/liboptions.a \
|
||||
$(top_builddir)/src/libdebug/libdebug.a \
|
||||
$(top_builddir)/src/libmobile/libmobile.a \
|
||||
$(top_builddir)/src/libosmocc/libosmocc.a \
|
||||
$(top_builddir)/src/libdisplay/libdisplay.a \
|
||||
$(top_builddir)/src/libcompandor/libcompandor.a \
|
||||
$(top_builddir)/src/libgoertzel/libgoertzel.a \
|
||||
|
@ -25,7 +26,6 @@ jtacs_LDADD = \
|
|||
$(top_builddir)/src/libfm/libfm.a \
|
||||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libwave/libwave.a \
|
||||
$(top_builddir)/src/libmncc/libmncc.a \
|
||||
$(top_builddir)/src/libsample/libsample.a \
|
||||
$(top_builddir)/src/libg711/libg711.a \
|
||||
-lm
|
||||
|
|
|
@ -10,5 +10,5 @@ int main(int argc, char *argv[])
|
|||
/* init common tones */
|
||||
init_tones();
|
||||
|
||||
return main_amps_tacs(argc, argv);
|
||||
return main_amps_tacs("jtacs", argc, argv);
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@
|
|||
#define DEURO 12
|
||||
#define DFRAME 13
|
||||
#define DCALL 14
|
||||
#define DMNCC 15
|
||||
#define DCC 15
|
||||
#define DDB 16
|
||||
#define DTRANS 17
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
AM_CPPFLAGS = -Wall -Wextra -g $(all_includes)
|
||||
|
||||
noinst_LIBRARIES = libmncc.a
|
||||
|
||||
libmncc_a_SOURCES = \
|
||||
mncc_console.c \
|
||||
mncc_cross.c \
|
||||
mncc_sock.c \
|
||||
testton.c \
|
||||
cause.c
|
||||
|
||||
if HAVE_ALSA
|
||||
AM_CPPFLAGS += -DHAVE_ALSA
|
||||
endif
|
||||
|
|
@ -1,347 +0,0 @@
|
|||
|
||||
#define MNCC_SETUP_REQ 0x0101
|
||||
#define MNCC_SETUP_IND 0x0102
|
||||
#define MNCC_SETUP_RSP 0x0103
|
||||
#define MNCC_SETUP_CNF 0x0104
|
||||
#define MNCC_SETUP_COMPL_REQ 0x0105
|
||||
#define MNCC_SETUP_COMPL_IND 0x0106
|
||||
/* MNCC_REJ_* is perfomed via MNCC_REL_* */
|
||||
#define MNCC_CALL_CONF_IND 0x0107
|
||||
#define MNCC_CALL_PROC_REQ 0x0108
|
||||
#define MNCC_PROGRESS_REQ 0x0109
|
||||
#define MNCC_ALERT_REQ 0x010a
|
||||
#define MNCC_ALERT_IND 0x010b
|
||||
#define MNCC_NOTIFY_REQ 0x010c
|
||||
#define MNCC_NOTIFY_IND 0x010d
|
||||
#define MNCC_DISC_REQ 0x010e
|
||||
#define MNCC_DISC_IND 0x010f
|
||||
#define MNCC_REL_REQ 0x0110
|
||||
#define MNCC_REL_IND 0x0111
|
||||
#define MNCC_REL_CNF 0x0112
|
||||
#define MNCC_FACILITY_REQ 0x0113
|
||||
#define MNCC_FACILITY_IND 0x0114
|
||||
#define MNCC_START_DTMF_IND 0x0115
|
||||
#define MNCC_START_DTMF_RSP 0x0116
|
||||
#define MNCC_START_DTMF_REJ 0x0117
|
||||
#define MNCC_STOP_DTMF_IND 0x0118
|
||||
#define MNCC_STOP_DTMF_RSP 0x0119
|
||||
#define MNCC_MODIFY_REQ 0x011a
|
||||
#define MNCC_MODIFY_IND 0x011b
|
||||
#define MNCC_MODIFY_RSP 0x011c
|
||||
#define MNCC_MODIFY_CNF 0x011d
|
||||
#define MNCC_MODIFY_REJ 0x011e
|
||||
#define MNCC_HOLD_IND 0x011f
|
||||
#define MNCC_HOLD_CNF 0x0120
|
||||
#define MNCC_HOLD_REJ 0x0121
|
||||
#define MNCC_RETRIEVE_IND 0x0122
|
||||
#define MNCC_RETRIEVE_CNF 0x0123
|
||||
#define MNCC_RETRIEVE_REJ 0x0124
|
||||
#define MNCC_USERINFO_REQ 0x0125
|
||||
#define MNCC_USERINFO_IND 0x0126
|
||||
#define MNCC_REJ_REQ 0x0127
|
||||
#define MNCC_REJ_IND 0x0128
|
||||
#define MNCC_PROGRESS_IND 0x0129
|
||||
#define MNCC_CALL_PROC_IND 0x012a
|
||||
#define MNCC_CALL_CONF_REQ 0x012b
|
||||
#define MNCC_START_DTMF_REQ 0x012c
|
||||
#define MNCC_STOP_DTMF_REQ 0x012d
|
||||
#define MNCC_HOLD_REQ 0x012e
|
||||
#define MNCC_RETRIEVE_REQ 0x012f
|
||||
|
||||
#define MNCC_BRIDGE 0x0200
|
||||
#define MNCC_FRAME_RECV 0x0201
|
||||
#define MNCC_FRAME_DROP 0x0202
|
||||
#define MNCC_LCHAN_MODIFY 0x0203
|
||||
#define MNCC_RTP_CREATE 0x0204
|
||||
#define MNCC_RTP_CONNECT 0x0205
|
||||
#define MNCC_RTP_FREE 0x0206
|
||||
|
||||
#define GSM_TCHF_FRAME 0x0300
|
||||
#define GSM_TCHF_FRAME_EFR 0x0301
|
||||
#define GSM_TCHH_FRAME 0x0302
|
||||
#define GSM_TCH_FRAME_AMR 0x0303
|
||||
#define ANALOG_8000HZ 0x0380
|
||||
#define GSM_BAD_FRAME 0x03ff
|
||||
|
||||
#define MNCC_SOCKET_HELLO 0x0400
|
||||
|
||||
#define GSM_MAX_FACILITY 128
|
||||
#define GSM_MAX_SSVERSION 128
|
||||
#define GSM_MAX_USERUSER 128
|
||||
|
||||
#define MNCC_F_BEARER_CAP 0x0001
|
||||
#define MNCC_F_CALLED 0x0002
|
||||
#define MNCC_F_CALLING 0x0004
|
||||
#define MNCC_F_REDIRECTING 0x0008
|
||||
#define MNCC_F_CONNECTED 0x0010
|
||||
#define MNCC_F_CAUSE 0x0020
|
||||
#define MNCC_F_USERUSER 0x0040
|
||||
#define MNCC_F_PROGRESS 0x0080
|
||||
#define MNCC_F_EMERGENCY 0x0100
|
||||
#define MNCC_F_FACILITY 0x0200
|
||||
#define MNCC_F_SSVERSION 0x0400
|
||||
#define MNCC_F_CCCAP 0x0800
|
||||
#define MNCC_F_KEYPAD 0x1000
|
||||
#define MNCC_F_SIGNAL 0x2000
|
||||
|
||||
#define GSM_MAX_FACILITY 128
|
||||
#define GSM_MAX_SSVERSION 128
|
||||
#define GSM_MAX_USERUSER 128
|
||||
|
||||
/* GSM 04.08 Bearer Capability: Information Transfer Capability */
|
||||
enum gsm48_bcap_itcap {
|
||||
GSM48_BCAP_ITCAP_SPEECH = 0,
|
||||
GSM48_BCAP_ITCAP_UNR_DIG_INF = 1,
|
||||
GSM48_BCAP_ITCAP_3k1_AUDIO = 2,
|
||||
GSM48_BCAP_ITCAP_FAX_G3 = 3,
|
||||
GSM48_BCAP_ITCAP_OTHER = 5,
|
||||
GSM48_BCAP_ITCAP_RESERVED = 7,
|
||||
};
|
||||
|
||||
/* GSM 04.08 Bearer Capability: Transfer Mode */
|
||||
enum gsm48_bcap_tmod {
|
||||
GSM48_BCAP_TMOD_CIRCUIT = 0,
|
||||
GSM48_BCAP_TMOD_PACKET = 1,
|
||||
};
|
||||
|
||||
/* GSM 04.08 Bearer Capability: Coding Standard */
|
||||
enum gsm48_bcap_coding {
|
||||
GSM48_BCAP_CODING_GSM_STD = 0,
|
||||
};
|
||||
|
||||
/* GSM 04.08 Bearer Capability: Radio Channel Requirements */
|
||||
enum gsm48_bcap_rrq {
|
||||
GSM48_BCAP_RRQ_FR_ONLY = 1,
|
||||
GSM48_BCAP_RRQ_DUAL_HR = 2,
|
||||
GSM48_BCAP_RRQ_DUAL_FR = 3,
|
||||
};
|
||||
|
||||
/* GSM 04.08 Bearer Capability: Rate Adaption */
|
||||
enum gsm48_bcap_ra {
|
||||
GSM48_BCAP_RA_NONE = 0,
|
||||
GSM48_BCAP_RA_V110_X30 = 1,
|
||||
GSM48_BCAP_RA_X31 = 2,
|
||||
GSM48_BCAP_RA_OTHER = 3,
|
||||
};
|
||||
|
||||
/* GSM 04.08 Bearer Capability: Signaling access protocol */
|
||||
enum gsm48_bcap_sig_access {
|
||||
GSM48_BCAP_SA_I440_I450 = 1,
|
||||
GSM48_BCAP_SA_X21 = 2,
|
||||
GSM48_BCAP_SA_X28_DP_IN = 3,
|
||||
GSM48_BCAP_SA_X28_DP_UN = 4,
|
||||
GSM48_BCAP_SA_X28_NDP = 5,
|
||||
GSM48_BCAP_SA_X32 = 6,
|
||||
};
|
||||
|
||||
/* GSM 04.08 Bearer Capability: User Rate */
|
||||
enum gsm48_bcap_user_rate {
|
||||
GSM48_BCAP_UR_300 = 1,
|
||||
GSM48_BCAP_UR_1200 = 2,
|
||||
GSM48_BCAP_UR_2400 = 3,
|
||||
GSM48_BCAP_UR_4800 = 4,
|
||||
GSM48_BCAP_UR_9600 = 5,
|
||||
GSM48_BCAP_UR_12000 = 6,
|
||||
GSM48_BCAP_UR_1200_75 = 7,
|
||||
};
|
||||
|
||||
/* GSM 04.08 Bearer Capability: Parity */
|
||||
enum gsm48_bcap_parity {
|
||||
GSM48_BCAP_PAR_ODD = 0,
|
||||
GSM48_BCAP_PAR_EVEN = 2,
|
||||
GSM48_BCAP_PAR_NONE = 3,
|
||||
GSM48_BCAP_PAR_ZERO = 4,
|
||||
GSM48_BCAP_PAR_ONE = 5,
|
||||
};
|
||||
|
||||
/* GSM 04.08 Bearer Capability: Intermediate Rate */
|
||||
enum gsm48_bcap_interm_rate {
|
||||
GSM48_BCAP_IR_8k = 2,
|
||||
GSM48_BCAP_IR_16k = 3,
|
||||
};
|
||||
|
||||
/* GSM 04.08 Bearer Capability: Transparency */
|
||||
enum gsm48_bcap_transp {
|
||||
GSM48_BCAP_TR_TRANSP = 0,
|
||||
GSM48_BCAP_TR_RLP = 1,
|
||||
GSM48_BCAP_TR_TR_PREF = 2,
|
||||
GSM48_BCAP_TR_RLP_PREF = 3,
|
||||
};
|
||||
|
||||
/* GSM 04.08 Bearer Capability: Modem Type */
|
||||
enum gsm48_bcap_modem_type {
|
||||
GSM48_BCAP_MT_NONE = 0,
|
||||
GSM48_BCAP_MT_V21 = 1,
|
||||
GSM48_BCAP_MT_V22 = 2,
|
||||
GSM48_BCAP_MT_V22bis = 3,
|
||||
GSM48_BCAP_MT_V23 = 4,
|
||||
GSM48_BCAP_MT_V26ter = 5,
|
||||
GSM48_BCAP_MT_V32 = 6,
|
||||
GSM48_BCAP_MT_UNDEF = 7,
|
||||
GSM48_BCAP_MT_AUTO_1 = 8,
|
||||
};
|
||||
|
||||
/* GSM 04.08 Bearer Capability: Speech Version Indication */
|
||||
enum gsm48_bcap_speech_ver {
|
||||
GSM48_BCAP_SV_FR = 0,
|
||||
GSM48_BCAP_SV_HR = 1,
|
||||
GSM48_BCAP_SV_EFR = 2,
|
||||
GSM48_BCAP_SV_AMR_F = 4,
|
||||
GSM48_BCAP_SV_AMR_H = 5,
|
||||
BCAP_ANALOG_8000HZ = 0x80,
|
||||
};
|
||||
|
||||
/* Expanded fields from GSM TS 04.08, Table 10.5.102 */
|
||||
struct gsm_mncc_bearer_cap {
|
||||
int transfer; /* Information Transfer Capability */
|
||||
int mode; /* Transfer Mode */
|
||||
int coding; /* Coding Standard */
|
||||
int radio; /* Radio Channel Requirement */
|
||||
int speech_ctm; /* CTM text telephony indication */
|
||||
int speech_ver[8]; /* Speech version indication */
|
||||
struct {
|
||||
enum gsm48_bcap_ra rate_adaption;
|
||||
enum gsm48_bcap_sig_access sig_access;
|
||||
int async;
|
||||
int nr_stop_bits;
|
||||
int nr_data_bits;
|
||||
enum gsm48_bcap_user_rate user_rate;
|
||||
enum gsm48_bcap_parity parity;
|
||||
enum gsm48_bcap_interm_rate interm_rate;
|
||||
enum gsm48_bcap_transp transp;
|
||||
enum gsm48_bcap_modem_type modem_type;
|
||||
} data;
|
||||
};
|
||||
|
||||
struct gsm_mncc_number {
|
||||
int type;
|
||||
int plan;
|
||||
int present;
|
||||
int screen;
|
||||
char number[33];
|
||||
};
|
||||
|
||||
struct gsm_mncc_cause {
|
||||
int location;
|
||||
int coding;
|
||||
int rec;
|
||||
int rec_val;
|
||||
int value;
|
||||
int diag_len;
|
||||
char diag[32];
|
||||
};
|
||||
|
||||
struct gsm_mncc_useruser {
|
||||
int proto;
|
||||
char info[GSM_MAX_USERUSER + 1]; /* + termination char */
|
||||
};
|
||||
|
||||
struct gsm_mncc_progress {
|
||||
int coding;
|
||||
int location;
|
||||
int descr;
|
||||
};
|
||||
|
||||
struct gsm_mncc_facility {
|
||||
int len;
|
||||
char info[GSM_MAX_FACILITY];
|
||||
};
|
||||
|
||||
struct gsm_mncc_ssversion {
|
||||
int len;
|
||||
char info[GSM_MAX_SSVERSION];
|
||||
};
|
||||
|
||||
struct gsm_mncc_cccap {
|
||||
int dtmf;
|
||||
int pcp;
|
||||
};
|
||||
|
||||
enum {
|
||||
GSM_MNCC_BCAP_SPEECH = 0,
|
||||
GSM_MNCC_BCAP_UNR_DIG = 1,
|
||||
GSM_MNCC_BCAP_AUDIO = 2,
|
||||
GSM_MNCC_BCAP_FAX_G3 = 3,
|
||||
GSM_MNCC_BCAP_OTHER_ITC = 5,
|
||||
GSM_MNCC_BCAP_RESERVED = 7,
|
||||
};
|
||||
|
||||
enum {
|
||||
GSM_LCHAN_NONE,
|
||||
GSM_LCHAN_SDCCH,
|
||||
GSM_LCHAN_TCH_F,
|
||||
GSM_LCHAN_TCH_H,
|
||||
GSM_LCHAN_UNKNOWN,
|
||||
GSM_LCHAN_CCCH,
|
||||
GSM_LCHAN_PDTCH,
|
||||
_GSM_LCHAN_MAX
|
||||
};
|
||||
|
||||
struct gsm_mncc {
|
||||
/* context based information */
|
||||
uint32_t msg_type;
|
||||
uint32_t callref;
|
||||
|
||||
/* which fields are present */
|
||||
uint32_t fields;
|
||||
|
||||
/* data derived informations (MNCC_F_ based) */
|
||||
struct gsm_mncc_bearer_cap bearer_cap;
|
||||
struct gsm_mncc_number called;
|
||||
struct gsm_mncc_number calling;
|
||||
struct gsm_mncc_number redirecting;
|
||||
struct gsm_mncc_number connected;
|
||||
struct gsm_mncc_cause cause;
|
||||
struct gsm_mncc_progress progress;
|
||||
struct gsm_mncc_useruser useruser;
|
||||
struct gsm_mncc_facility facility;
|
||||
struct gsm_mncc_cccap cccap;
|
||||
struct gsm_mncc_ssversion ssversion;
|
||||
struct {
|
||||
int sup;
|
||||
int inv;
|
||||
} clir;
|
||||
int signal;
|
||||
|
||||
/* data derived information, not MNCC_F based */
|
||||
int keypad;
|
||||
int more;
|
||||
int notify; /* 0..127 */
|
||||
int emergency;
|
||||
char imsi[16];
|
||||
|
||||
unsigned char lchan_type;
|
||||
unsigned char lchan_mode;
|
||||
};
|
||||
|
||||
struct gsm_data_frame {
|
||||
uint32_t msg_type;
|
||||
uint32_t callref;
|
||||
unsigned char data[0];
|
||||
};
|
||||
|
||||
struct gsm_mncc_rtp {
|
||||
uint32_t msg_type;
|
||||
uint32_t callref;
|
||||
uint32_t ip;
|
||||
uint16_t port;
|
||||
uint32_t payload_type;
|
||||
uint32_t payload_msg_type;
|
||||
};
|
||||
|
||||
|
||||
#define MNCC_SOCK_VERSION 5
|
||||
struct gsm_mncc_hello {
|
||||
uint32_t msg_type;
|
||||
uint32_t version;
|
||||
|
||||
/* send the sizes of the structs */
|
||||
uint32_t mncc_size;
|
||||
uint32_t data_frame_size;
|
||||
|
||||
/* send some offsets */
|
||||
uint32_t called_offset;
|
||||
uint32_t signal_offset;
|
||||
uint32_t emergency_offset;
|
||||
uint32_t lchan_type_offset;
|
||||
};
|
|
@ -1,240 +0,0 @@
|
|||
/* Mobie Network Call Control (MNCC) cross connecting mobiles
|
||||
*
|
||||
* (C) 2017 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 <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "../libsample/sample.h"
|
||||
#include "../libdebug/debug.h"
|
||||
#include "../libmobile/call.h"
|
||||
#include "cause.h"
|
||||
#include "mncc.h"
|
||||
#include "mncc_cross.h"
|
||||
|
||||
int new_callref = 0; /* toward mobile */
|
||||
|
||||
typedef struct cross {
|
||||
struct cross *next;
|
||||
int callref1;
|
||||
int callref2;
|
||||
} cross_t;
|
||||
|
||||
static cross_t *cross_head = NULL;
|
||||
|
||||
static int create_cross(int callref)
|
||||
{
|
||||
cross_t *cross;
|
||||
|
||||
cross = calloc(1, sizeof(*cross));
|
||||
if (!cross) {
|
||||
PDEBUG(DMNCC, DEBUG_ERROR, "No memory!\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
cross->callref1 = callref;
|
||||
cross->callref2 = ++new_callref;
|
||||
|
||||
/* attach to list */
|
||||
cross->next = cross_head;
|
||||
cross_head = cross;
|
||||
|
||||
PDEBUG(DMNCC, DEBUG_INFO, "Cross connection created\n");
|
||||
|
||||
return cross->callref2;
|
||||
}
|
||||
|
||||
static void destroy_cross(cross_t *cross)
|
||||
{
|
||||
cross_t **crossp;
|
||||
|
||||
/* detach from list */
|
||||
crossp = &cross_head;
|
||||
while (*crossp && *crossp != cross)
|
||||
crossp = &((*crossp)->next);
|
||||
if (!(*crossp)) {
|
||||
PDEBUG(DMNCC, DEBUG_ERROR, "Transaction not in list, please fix!!\n");
|
||||
abort();
|
||||
}
|
||||
*crossp = cross->next;
|
||||
|
||||
free(cross);
|
||||
|
||||
PDEBUG(DMNCC, DEBUG_INFO, "Cross connection destroyed\n");
|
||||
}
|
||||
|
||||
typedef struct queue {
|
||||
struct queue *next;
|
||||
int length;
|
||||
uint8_t buf[0];
|
||||
} queue_t;
|
||||
|
||||
static queue_t *queue_head;
|
||||
|
||||
static void cross_mncc_up(uint8_t *buf, int length);
|
||||
|
||||
static int cross_mncc_up_queue(uint8_t *buf, int length)
|
||||
{
|
||||
struct gsm_mncc *mncc = (struct gsm_mncc *)buf;
|
||||
queue_t *queue, **queuep;
|
||||
|
||||
/* directly forward voice */
|
||||
if (mncc->msg_type == ANALOG_8000HZ) {
|
||||
cross_mncc_up(buf, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* queue all other messages */
|
||||
queue = calloc(1, sizeof(*queue) + length);
|
||||
if (!queue) {
|
||||
PDEBUG(DMNCC, DEBUG_ERROR, "No memory!\n");
|
||||
return -CAUSE_TEMPFAIL;
|
||||
}
|
||||
queue->length = length;
|
||||
memcpy(queue->buf, buf, length);
|
||||
|
||||
/* add tail */
|
||||
queuep = &queue_head;
|
||||
while (*queuep)
|
||||
queuep = &((*queuep)->next);
|
||||
*queuep = queue;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cross_mncc_up(uint8_t *buf, int length)
|
||||
{
|
||||
struct gsm_mncc *mncc = (struct gsm_mncc *)buf;
|
||||
cross_t *cross = NULL;
|
||||
int callref = mncc->callref, remote = 0;
|
||||
|
||||
/* find cross instance */
|
||||
for (cross = cross_head; cross; cross = cross->next) {
|
||||
if (cross->callref1 == callref) {
|
||||
remote = cross->callref2;
|
||||
break;
|
||||
}
|
||||
if (cross->callref2 == callref) {
|
||||
remote = cross->callref1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (mncc->msg_type == MNCC_REL_CNF) {
|
||||
if (cross)
|
||||
destroy_cross(cross);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!remote && mncc->msg_type != MNCC_SETUP_IND) {
|
||||
PDEBUG(DMNCC, DEBUG_ERROR, "invalid call ref.\n");
|
||||
/* send down reused MNCC */
|
||||
mncc->msg_type = MNCC_REL_REQ;
|
||||
mncc->fields |= MNCC_F_CAUSE;
|
||||
mncc->cause.location = LOCATION_USER;
|
||||
mncc->cause.value = CAUSE_INVALCALLREF;
|
||||
mncc_down(buf, length);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (mncc->msg_type) {
|
||||
case ANALOG_8000HZ:
|
||||
/* send down reused MNCC */
|
||||
mncc->callref = remote;
|
||||
mncc_down(buf, length);
|
||||
break;
|
||||
case MNCC_SETUP_IND:
|
||||
remote = create_cross(callref);
|
||||
/* send down reused MNCC */
|
||||
mncc->msg_type = MNCC_SETUP_REQ;
|
||||
mncc->callref = remote;
|
||||
mncc_down(buf, length);
|
||||
break;
|
||||
case MNCC_CALL_CONF_IND:
|
||||
/* send down reused MNCC */
|
||||
mncc->msg_type = MNCC_CALL_PROC_REQ;
|
||||
mncc->callref = remote;
|
||||
mncc_down(buf, length);
|
||||
break;
|
||||
case MNCC_ALERT_IND:
|
||||
/* send down reused MNCC */
|
||||
mncc->msg_type = MNCC_ALERT_REQ;
|
||||
mncc->callref = remote;
|
||||
mncc_down(buf, length);
|
||||
break;
|
||||
case MNCC_SETUP_CNF:
|
||||
/* send down reused MNCC */
|
||||
mncc->msg_type = MNCC_SETUP_RSP;
|
||||
mncc->callref = remote;
|
||||
mncc_down(buf, length);
|
||||
break;
|
||||
case MNCC_SETUP_COMPL_IND:
|
||||
/* send down reused MNCC */
|
||||
mncc->msg_type = MNCC_SETUP_COMPL_REQ;
|
||||
mncc->callref = remote;
|
||||
mncc_down(buf, length);
|
||||
break;
|
||||
case MNCC_DISC_IND:
|
||||
/* send down reused MNCC */
|
||||
mncc->msg_type = MNCC_DISC_REQ;
|
||||
mncc->callref = remote;
|
||||
mncc_down(buf, length);
|
||||
break;
|
||||
case MNCC_REL_IND:
|
||||
/* send down reused MNCC */
|
||||
mncc->msg_type = MNCC_REL_REQ;
|
||||
mncc->callref = remote;
|
||||
mncc_down(buf, length);
|
||||
destroy_cross(cross);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void mncc_cross_handle(void)
|
||||
{
|
||||
queue_t *queue;
|
||||
|
||||
while (queue_head) {
|
||||
/* remove from head */
|
||||
queue = queue_head;
|
||||
queue_head = queue->next;
|
||||
|
||||
cross_mncc_up(queue->buf, queue->length);
|
||||
free(queue);
|
||||
}
|
||||
}
|
||||
|
||||
int mncc_cross_init(void)
|
||||
{
|
||||
mncc_up = cross_mncc_up_queue;
|
||||
|
||||
PDEBUG(DMNCC, DEBUG_DEBUG, "MNCC crossconnect initialized, waiting for connection.\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mncc_cross_exit(void)
|
||||
{
|
||||
while (cross_head)
|
||||
destroy_cross(cross_head);
|
||||
|
||||
PDEBUG(DMNCC, DEBUG_DEBUG, "MNCC crossconnect removed.\n");
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
|
||||
void mncc_cross_handle(void);
|
||||
int mncc_cross_init(void);
|
||||
void mncc_cross_exit(void);
|
||||
|
|
@ -1,239 +0,0 @@
|
|||
/* Mobie Network Call Control (MNCC) socket handling
|
||||
*
|
||||
* (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 <stdint.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <stddef.h>
|
||||
#include <unistd.h>
|
||||
#include "../libsample/sample.h"
|
||||
#include "../libdebug/debug.h"
|
||||
#include "../libmobile/call.h"
|
||||
#include "cause.h"
|
||||
#include "mncc_sock.h"
|
||||
|
||||
static int listen_sock = -1;
|
||||
static int mncc_sock = -1;
|
||||
|
||||
/* write to mncc socket, return error or -EIO if no socket connection */
|
||||
static int mncc_write(uint8_t *buf, int length)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (mncc_sock <= 0) {
|
||||
PDEBUG(DMNCC, DEBUG_NOTICE, "We have no MNCC connection, rejecting.\n");
|
||||
return -CAUSE_TEMPFAIL;
|
||||
}
|
||||
rc = send(mncc_sock, buf, length, 0);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DMNCC, DEBUG_ERROR, "MNCC connection failed (errno = %d).\n", errno);
|
||||
mncc_sock_close();
|
||||
return -CAUSE_TEMPFAIL;
|
||||
}
|
||||
if (rc != length) {
|
||||
PDEBUG(DMNCC, DEBUG_NOTICE, "MNCC write failed.\n");
|
||||
mncc_sock_close();
|
||||
return -CAUSE_TEMPFAIL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* read from mncc socket */
|
||||
static int mncc_read(void)
|
||||
{
|
||||
uint8_t buf[sizeof(struct gsm_mncc)+1024];
|
||||
int rc;
|
||||
|
||||
memset(buf, 0, sizeof(buf));
|
||||
rc = recv(mncc_sock, buf, sizeof(buf), 0);
|
||||
if (rc == 0) {
|
||||
PDEBUG(DMNCC, DEBUG_NOTICE, "MNCC connection closed.\n");
|
||||
mncc_sock_close();
|
||||
return 0;
|
||||
}
|
||||
if (rc < 0) {
|
||||
if (errno == EWOULDBLOCK)
|
||||
return -errno;
|
||||
PDEBUG(DMNCC, DEBUG_ERROR, "MNCC connection failed (errno = %d).\n", errno);
|
||||
mncc_sock_close();
|
||||
return -errno;
|
||||
}
|
||||
|
||||
mncc_down(buf, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void mncc_hello(void)
|
||||
{
|
||||
struct gsm_mncc_hello hello;
|
||||
|
||||
memset(&hello, 0, sizeof(hello));
|
||||
hello.msg_type = MNCC_SOCKET_HELLO;
|
||||
hello.version = MNCC_SOCK_VERSION;
|
||||
hello.mncc_size = sizeof(struct gsm_mncc);
|
||||
hello.data_frame_size = sizeof(struct gsm_data_frame);
|
||||
hello.called_offset = offsetof(struct gsm_mncc, called);
|
||||
hello.signal_offset = offsetof(struct gsm_mncc, signal);
|
||||
hello.emergency_offset = offsetof(struct gsm_mncc, emergency);
|
||||
hello.lchan_type_offset = offsetof(struct gsm_mncc, lchan_type);
|
||||
|
||||
mncc_write((uint8_t *) &hello, sizeof(hello));
|
||||
}
|
||||
|
||||
|
||||
static int mncc_accept(void)
|
||||
{
|
||||
struct sockaddr_un __attribute__((__unused__)) un_addr;
|
||||
socklen_t __attribute__((__unused__)) len;
|
||||
int flags;
|
||||
int rc;
|
||||
|
||||
len = sizeof(un_addr);
|
||||
rc = accept(listen_sock, (struct sockaddr *) &un_addr, &len);
|
||||
if (rc < 0) {
|
||||
if (errno == EWOULDBLOCK)
|
||||
return 0;
|
||||
PDEBUG(DMNCC, DEBUG_ERROR, "Failed to accept incoming connection (errno=%d).\n", errno);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (mncc_sock > 0) {
|
||||
PDEBUG(DMNCC, DEBUG_NOTICE, "Rejecting multiple incoming connections.\n");
|
||||
close(rc);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
mncc_sock = rc;
|
||||
flags = fcntl(mncc_sock, F_GETFL, 0);
|
||||
rc = fcntl(mncc_sock, F_SETFL, flags | O_NONBLOCK);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DMNCC, DEBUG_ERROR, "Failed to set socket into non-blocking IO mode.\n");
|
||||
mncc_sock_close();
|
||||
return rc;
|
||||
}
|
||||
|
||||
PDEBUG(DMNCC, DEBUG_NOTICE, "MNCC socket connected.\n");
|
||||
|
||||
mncc_hello();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void mncc_sock_handle(void)
|
||||
{
|
||||
mncc_accept();
|
||||
|
||||
if (mncc_sock > 0) {
|
||||
while ((mncc_read()) > 0)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void mncc_sock_close(void)
|
||||
{
|
||||
if (mncc_sock > 0) {
|
||||
PDEBUG(DMNCC, DEBUG_NOTICE, "MNCC socket disconnected.\n");
|
||||
close(mncc_sock);
|
||||
mncc_sock = -1;
|
||||
/* clear all call instances */
|
||||
mncc_flush();
|
||||
}
|
||||
}
|
||||
|
||||
int mncc_sock_init(const char *sock_name)
|
||||
{
|
||||
struct sockaddr_un local;
|
||||
unsigned int namelen;
|
||||
int flags;
|
||||
int rc;
|
||||
|
||||
listen_sock = socket(PF_UNIX, SOCK_SEQPACKET, 0);
|
||||
if (listen_sock < 0) {
|
||||
PDEBUG(DMNCC, DEBUG_ERROR, "Failed to create socket.\n");
|
||||
return listen_sock;
|
||||
}
|
||||
|
||||
local.sun_family = AF_UNIX;
|
||||
strncpy(local.sun_path, sock_name, sizeof(local.sun_path));
|
||||
local.sun_path[sizeof(local.sun_path) - 1] = '\0';
|
||||
unlink(local.sun_path);
|
||||
|
||||
/* we use the same magic that X11 uses in Xtranssock.c for
|
||||
* calculating the proper length of the sockaddr */
|
||||
#if defined(BSD44SOCKETS) || defined(__UNIXWARE__)
|
||||
local.sun_len = strlen(local.sun_path);
|
||||
#endif
|
||||
#if defined(BSD44SOCKETS) || defined(SUN_LEN)
|
||||
namelen = SUN_LEN(&local);
|
||||
#else
|
||||
namelen = strlen(local.sun_path) +
|
||||
offsetof(struct sockaddr_un, sun_path);
|
||||
#endif
|
||||
|
||||
rc = bind(listen_sock, (struct sockaddr *) &local, namelen);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DMNCC, DEBUG_ERROR, "Failed to bind the unix domain "
|
||||
"socket. '%s'\n", local.sun_path);
|
||||
mncc_sock_exit();
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = listen(listen_sock, 0);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DMNCC, DEBUG_ERROR, "Failed to listen.\n");
|
||||
mncc_sock_exit();
|
||||
return rc;
|
||||
}
|
||||
|
||||
flags = fcntl(listen_sock, F_GETFL, 0);
|
||||
flags = 0;
|
||||
rc = fcntl(listen_sock, F_SETFL, flags | O_NONBLOCK);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DMNCC, DEBUG_ERROR, "Failed to set socket into non-blocking IO mode.\n");
|
||||
mncc_sock_exit();
|
||||
return rc;
|
||||
}
|
||||
|
||||
mncc_up = mncc_write;
|
||||
|
||||
PDEBUG(DMNCC, DEBUG_DEBUG, "MNCC socket at '%s' initialized, waiting for connection.\n", sock_name);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mncc_sock_exit(void)
|
||||
{
|
||||
mncc_sock_close();
|
||||
|
||||
if (listen_sock > 0) {
|
||||
close(listen_sock);
|
||||
listen_sock = -1;
|
||||
}
|
||||
|
||||
PDEBUG(DMNCC, DEBUG_DEBUG, "MNCC socket removed.\n");
|
||||
}
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
#include "mncc.h"
|
||||
|
||||
void mncc_sock_handle(void);
|
||||
void mncc_sock_close(void);
|
||||
int mncc_sock_init(const char *sock_name);
|
||||
void mncc_sock_exit(void);
|
||||
|
|
@ -5,6 +5,9 @@ noinst_LIBRARIES = libmobile.a
|
|||
libmobile_a_SOURCES = \
|
||||
sender.c \
|
||||
call.c \
|
||||
console.c \
|
||||
testton.c \
|
||||
cause.c \
|
||||
main_mobile.c
|
||||
|
||||
if HAVE_ALSA
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* interface between mobile network/phone implementation and MNCC
|
||||
/* interface between mobile network/phone implementation and OsmoCC
|
||||
*
|
||||
* (C) 2016 by Andreas Eversberg <jolly@eversberg.eu>
|
||||
* All Rights Reserved
|
||||
|
@ -24,13 +24,17 @@
|
|||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "../libsample/sample.h"
|
||||
#include "../libdebug/debug.h"
|
||||
#include "../libtimer/timer.h"
|
||||
#include "../libosmocc/endpoint.h"
|
||||
#include "../libosmocc/helper.h"
|
||||
#include "../libg711/g711.h"
|
||||
#include "cause.h"
|
||||
#include "sender.h"
|
||||
#include "call.h"
|
||||
#include "../libtimer/timer.h"
|
||||
#include "../libmncc/mncc.h"
|
||||
#include "../libmncc/cause.h"
|
||||
#include "console.h"
|
||||
|
||||
#define DISC_TIMEOUT 30
|
||||
|
||||
|
@ -52,7 +56,44 @@ static double level_of(double *samples, int count)
|
|||
#endif
|
||||
|
||||
static int connect_on_setup; /* send patterns towards fixed network */
|
||||
static int release_on_disconnect; /* release towards mobile phone, if MNCC call disconnects, don't send disconnect tone */
|
||||
static int release_on_disconnect; /* release towards mobile phone, if OSMO-CC call disconnects, don't send disconnect tone */
|
||||
|
||||
osmo_cc_endpoint_t endpoint, *ep;
|
||||
|
||||
void encode_l16(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len)
|
||||
{
|
||||
uint16_t *src = (uint16_t *)src_data, *dst;
|
||||
int len = src_len / 2, i;
|
||||
|
||||
dst = malloc(len * 2);
|
||||
if (!dst)
|
||||
return;
|
||||
for (i = 0; i < len; i++)
|
||||
dst[i] = htons(src[i]);
|
||||
*dst_data = (uint8_t *)dst;
|
||||
*dst_len = len * 2;
|
||||
}
|
||||
|
||||
void decode_l16(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len)
|
||||
{
|
||||
uint16_t *src = (uint16_t *)src_data, *dst;
|
||||
int len = src_len / 2, i;
|
||||
|
||||
dst = malloc(len * 2);
|
||||
if (!dst)
|
||||
return;
|
||||
for (i = 0; i < len; i++)
|
||||
dst[i] = ntohs(src[i]);
|
||||
*dst_data = (uint8_t *)dst;
|
||||
*dst_len = len * 2;
|
||||
}
|
||||
|
||||
static struct osmo_cc_helper_audio_codecs codecs[] = {
|
||||
{ "L16", 8000, 1, encode_l16, decode_l16 },
|
||||
{ "PCMA", 8000, 1, g711_encode_alaw, g711_decode_alaw },
|
||||
{ "PCMU", 8000, 1, g711_encode_ulaw, g711_decode_ulaw },
|
||||
{ NULL, 0, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
/* stream patterns/announcements */
|
||||
int16_t *ringback_spl = NULL;
|
||||
|
@ -192,15 +233,15 @@ static enum audio_pattern cause2pattern(int cause)
|
|||
|
||||
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_SETUP_RO, /* call from radio to OSMO-CC */
|
||||
PROCESS_SETUP_RT, /* call from OSMO-CC to radio */
|
||||
PROCESS_ALERTING_RO, /* call from radio to OSMO-CC */
|
||||
PROCESS_ALERTING_RT, /* call from OSMO-CC to radio */
|
||||
PROCESS_CONNECT,
|
||||
PROCESS_DISCONNECT,
|
||||
};
|
||||
|
||||
/* MNCC call instance */
|
||||
/* call process */
|
||||
typedef struct process {
|
||||
struct process *next;
|
||||
int callref;
|
||||
|
@ -210,11 +251,14 @@ typedef struct process {
|
|||
int audio_pos;
|
||||
uint8_t cause;
|
||||
struct timer timer;
|
||||
osmo_cc_session_t *session;
|
||||
osmo_cc_session_codec_t *codec; /* codec to send */
|
||||
} process_t;
|
||||
|
||||
static process_t *process_head = NULL;
|
||||
|
||||
static void process_timeout(struct timer *timer);
|
||||
static void indicate_disconnect_release(int callref, int cause, uint8_t msg_type);
|
||||
|
||||
static process_t *create_process(int callref, enum process_state state)
|
||||
{
|
||||
|
@ -244,13 +288,15 @@ static void destroy_process(int callref)
|
|||
if (process->callref == callref) {
|
||||
*process_p = process->next;
|
||||
timer_exit(&process->timer);
|
||||
if (process->session)
|
||||
osmo_cc_free_session(process->session);
|
||||
free(process);
|
||||
return;
|
||||
}
|
||||
process_p = &process->next;
|
||||
process = process->next;
|
||||
}
|
||||
PDEBUG(DCALL, DEBUG_ERROR, "Process with callref 0x%x not found!\n", callref);
|
||||
PDEBUG(DCALL, DEBUG_ERROR, "Process with callref %d not found!\n", callref);
|
||||
}
|
||||
|
||||
static process_t *get_process(int callref)
|
||||
|
@ -270,9 +316,10 @@ 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);
|
||||
PDEBUG(DCALL, DEBUG_ERROR, "Process with callref %d not found!\n", callref);
|
||||
return;
|
||||
}
|
||||
PDEBUG(DCALL, DEBUG_DEBUG, "Changing state for callref %d %d->%d\n", callref, process->state, state);
|
||||
process->state = state;
|
||||
}
|
||||
|
||||
|
@ -281,7 +328,7 @@ 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);
|
||||
PDEBUG(DCALL, DEBUG_ERROR, "Process with callref %d not found!\n", callref);
|
||||
return;
|
||||
}
|
||||
process->pattern = pattern;
|
||||
|
@ -294,7 +341,7 @@ 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);
|
||||
PDEBUG(DCALL, DEBUG_ERROR, "Process with callref %d not found!\n", callref);
|
||||
return;
|
||||
}
|
||||
process->pattern = cause2pattern(cause);
|
||||
|
@ -330,106 +377,140 @@ static void process_timeout(struct timer *timer)
|
|||
|
||||
{
|
||||
/* announcement timeout */
|
||||
uint8_t buf[sizeof(struct gsm_mncc)];
|
||||
struct gsm_mncc *mncc = (struct gsm_mncc *)buf;
|
||||
|
||||
if (process->state == PROCESS_DISCONNECT) {
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Call released toward mobile network (after timeout)\n");
|
||||
call_down_release(process->callref, process->cause);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
indicate_disconnect_release(process->callref, process->cause, OSMO_CC_MSG_REL_IND);
|
||||
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)
|
||||
void down_audio(struct osmo_cc_session_codec *codec, uint16_t __attribute__((unused)) sequence_number, uint32_t __attribute__((unused)) timestamp, uint8_t *data, int len)
|
||||
{
|
||||
connect_on_setup = _send_patterns;
|
||||
release_on_disconnect = _release_on_disconnect;
|
||||
process_t *process = codec->media->session->priv;
|
||||
sample_t samples[len / 2];
|
||||
|
||||
return 0;
|
||||
/* if we are disconnected, ignore audio */
|
||||
if (!process || process->pattern != PATTERN_NONE)
|
||||
return;
|
||||
int16_to_samples(samples, (int16_t *)data, len / 2);
|
||||
#ifdef DEBUG_LEVEL
|
||||
double lev = level_of(samples, len / 2);
|
||||
printf("festnetz-level: %s %.4f\n", debug_db(lev), (20 * log10(lev)));
|
||||
#endif
|
||||
call_down_audio(process->callref, samples, len / 2);
|
||||
}
|
||||
|
||||
static void indicate_setup(process_t *process, const char *callerid, const char *dialing, uint8_t network_type, const char *network_id)
|
||||
{
|
||||
osmo_cc_msg_t *msg;
|
||||
|
||||
msg = osmo_cc_new_msg(OSMO_CC_MSG_SETUP_IND);
|
||||
/* network type */
|
||||
if (network_type)
|
||||
osmo_cc_add_ie_calling_network(msg, network_type, network_id);
|
||||
/* calling number */
|
||||
if (callerid && callerid[0])
|
||||
osmo_cc_add_ie_calling(msg, OSMO_CC_TYPE_SUBSCRIBER, OSMO_CC_PLAN_TELEPHONY, OSMO_CC_PRESENT_ALLOWED, OSMO_CC_SCREEN_NETWORK, callerid);
|
||||
/* called number */
|
||||
if (dialing && dialing[0])
|
||||
osmo_cc_add_ie_called(msg, OSMO_CC_TYPE_UNKNOWN, OSMO_CC_PLAN_TELEPHONY, dialing);
|
||||
/* bearer capability */
|
||||
osmo_cc_add_ie_bearer(msg, OSMO_CC_CODING_ITU_T, OSMO_CC_CAPABILITY_AUDIO, OSMO_CC_MODE_CIRCUIT);
|
||||
/* sdp offer */
|
||||
process->session = osmo_cc_helper_audio_offer(process, codecs, down_audio, msg, 1);
|
||||
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Indicate OSMO-CC setup towards fixed network\n");
|
||||
osmo_cc_ll_msg(ep, process->callref, msg);
|
||||
}
|
||||
|
||||
static void indicate_proceeding(int callref, const char *sdp)
|
||||
{
|
||||
osmo_cc_msg_t *msg;
|
||||
|
||||
msg = osmo_cc_new_msg(OSMO_CC_MSG_PROC_IND);
|
||||
|
||||
/* sdp */
|
||||
osmo_cc_add_ie_sdp(msg, sdp);
|
||||
|
||||
/* progress information */
|
||||
osmo_cc_add_ie_progress(msg, OSMO_CC_CODING_ITU_T, OSMO_CC_LOCATION_BEYOND_INTERWORKING, OSMO_CC_PROGRESS_INBAND_INFO_AVAILABLE);
|
||||
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Indicate OSMO-CC call confirm towards fixed network\n");
|
||||
osmo_cc_ll_msg(ep, callref, msg);
|
||||
}
|
||||
|
||||
static void indicate_alerting(int callref)
|
||||
{
|
||||
osmo_cc_msg_t *msg;
|
||||
|
||||
msg = osmo_cc_new_msg(OSMO_CC_MSG_ALERT_IND);
|
||||
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Indicate OSMO-CC alerting towards fixed network\n");
|
||||
osmo_cc_ll_msg(ep, callref, msg);
|
||||
}
|
||||
|
||||
static void indicate_answer(int callref, const char *connectid)
|
||||
{
|
||||
osmo_cc_msg_t *msg;
|
||||
|
||||
msg = osmo_cc_new_msg(OSMO_CC_MSG_SETUP_CNF);
|
||||
/* calling number */
|
||||
if (connectid && connectid[0])
|
||||
osmo_cc_add_ie_calling(msg, OSMO_CC_TYPE_SUBSCRIBER, OSMO_CC_PLAN_TELEPHONY, OSMO_CC_PRESENT_ALLOWED, OSMO_CC_SCREEN_NETWORK, connectid);
|
||||
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Indicate OSMO-CC answer towards fixed network\n");
|
||||
osmo_cc_ll_msg(ep, callref, msg);
|
||||
}
|
||||
|
||||
static void indicate_answer_ack(int callref)
|
||||
{
|
||||
osmo_cc_msg_t *msg;
|
||||
|
||||
msg = osmo_cc_new_msg(OSMO_CC_MSG_SETUP_COMP_IND);
|
||||
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Indicate OSMO-CC setup complete towards fixed network\n");
|
||||
osmo_cc_ll_msg(ep, callref, msg);
|
||||
}
|
||||
|
||||
static void indicate_disconnect_release(int callref, int cause, uint8_t msg_type)
|
||||
{
|
||||
osmo_cc_msg_t *msg;
|
||||
|
||||
msg = osmo_cc_new_msg(msg_type);
|
||||
|
||||
/* cause */
|
||||
osmo_cc_add_ie_cause(msg, OSMO_CC_LOCATION_PRIV_SERV_LOC_USER, cause, 0, 0);
|
||||
|
||||
/* progress information */
|
||||
if (msg_type == OSMO_CC_MSG_DISC_IND)
|
||||
osmo_cc_add_ie_progress(msg, OSMO_CC_CODING_ITU_T, OSMO_CC_LOCATION_BEYOND_INTERWORKING, OSMO_CC_PROGRESS_INBAND_INFO_AVAILABLE);
|
||||
|
||||
PDEBUG(DCALL, DEBUG_INFO, "%s OSMO-CC %s towards fixed network\n", (msg_type == OSMO_CC_MSG_REL_CNF) ? "Confirm" : "Indicated", (msg_type == OSMO_CC_MSG_DISC_IND) ? "disconnect" : "release");
|
||||
osmo_cc_ll_msg(ep, callref, msg);
|
||||
}
|
||||
|
||||
/* Setup is received from transceiver. */
|
||||
static int _indicate_setup(int callref, const char *callerid, const char *dialing)
|
||||
int call_up_setup(const char *callerid, const char *dialing, uint8_t network, const char *network_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_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();
|
||||
}
|
||||
osmo_cc_call_t *call;
|
||||
process_t *process;
|
||||
|
||||
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);
|
||||
|
||||
call = osmo_cc_call_new(ep);
|
||||
|
||||
create_process(callref, PROCESS_SETUP_RO);
|
||||
process = create_process(call->callref, PROCESS_SETUP_RO);
|
||||
|
||||
rc = _indicate_setup(callref, callerid, dialing);
|
||||
indicate_setup(process, callerid, dialing, network, network_id);
|
||||
|
||||
return rc;
|
||||
return call->callref;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
|
@ -440,7 +521,7 @@ void call_up_alerting(int callref)
|
|||
PDEBUG(DCALL, DEBUG_INFO, "Call is alerting\n");
|
||||
|
||||
if (!connect_on_setup)
|
||||
_indicate_alerting(callref);
|
||||
indicate_alerting(callref);
|
||||
set_pattern_process(callref, PATTERN_RINGBACK);
|
||||
new_state_process(callref, PROCESS_ALERTING_RT);
|
||||
}
|
||||
|
@ -452,28 +533,6 @@ void call_up_early(int callref)
|
|||
}
|
||||
|
||||
/* 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) {
|
||||
|
@ -484,30 +543,12 @@ void call_up_answer(int callref, const char *connect_id)
|
|||
PDEBUG(DCALL, DEBUG_INFO, "Call has been answered by '%s'\n", connect_id);
|
||||
|
||||
if (!connect_on_setup)
|
||||
_indicate_answer(callref, connect_id);
|
||||
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;
|
||||
|
@ -521,7 +562,7 @@ void call_up_release(int callref, int cause)
|
|||
|
||||
process = get_process(callref);
|
||||
if (process) {
|
||||
/* just keep MNCC connection if tones shall be sent.
|
||||
/* just keep OSMO-CC connection if tones shall be sent.
|
||||
* no tones while setting up / alerting the call. */
|
||||
if (connect_on_setup
|
||||
&& process->state != PROCESS_SETUP_RO
|
||||
|
@ -534,15 +575,15 @@ void call_up_release(int callref, int cause)
|
|||
|| process->state == PROCESS_SETUP_RO
|
||||
|| process->state == PROCESS_ALERTING_RO) {
|
||||
destroy_process(callref);
|
||||
_indicate_disconnect_release(callref, cause, 0);
|
||||
indicate_disconnect_release(callref, cause, OSMO_CC_MSG_REL_IND);
|
||||
/* if no tones shall be sent, disconnect on all other states */
|
||||
} else {
|
||||
disconnect_process(callref, cause);
|
||||
_indicate_disconnect_release(callref, cause, 1);
|
||||
indicate_disconnect_release(callref, cause, OSMO_CC_MSG_DISC_IND);
|
||||
}
|
||||
} else {
|
||||
/* we don't know about the process, just send release to upper layer anyway */
|
||||
_indicate_disconnect_release(callref, cause, 0);
|
||||
indicate_disconnect_release(callref, cause, OSMO_CC_MSG_REL_IND);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -552,18 +593,16 @@ void call_tone_recall(int callref, int on)
|
|||
set_pattern_process(callref, (on) ? PATTERN_RECALL : PATTERN_NONE);
|
||||
}
|
||||
|
||||
/* forward audio to MNCC or call instance */
|
||||
/* forward audio to OSMO-CC or call instance */
|
||||
void call_up_audio(int callref, sample_t *samples, int count)
|
||||
{
|
||||
process_t *process;
|
||||
int16_t data[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;
|
||||
|
||||
|
@ -573,15 +612,12 @@ void call_up_audio(int callref, sample_t *samples, int count)
|
|||
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));
|
||||
samples_to_int16(data, samples, count);
|
||||
osmo_cc_rtp_send(process->codec, (uint8_t *)data, count * 2, 1, count);
|
||||
/* don't destroy process here in case of an error */
|
||||
}
|
||||
|
||||
|
@ -589,140 +625,115 @@ void call_up_audio(int callref, sample_t *samples, int count)
|
|||
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;
|
||||
|
||||
call_down_clock();
|
||||
|
||||
while(process) {
|
||||
if (process->pattern != PATTERN_NONE) {
|
||||
data->msg_type = ANALOG_8000HZ;
|
||||
data->callref = process->callref;
|
||||
int16_t data[160];
|
||||
/* try to get patterns, else copy the samples we got */
|
||||
get_process_patterns(process, (int16_t *)data->data, 160);
|
||||
get_process_patterns(process, 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);
|
||||
samples_to_int16(data, samples, 160);
|
||||
#endif
|
||||
mncc_up(buf, sizeof(buf));
|
||||
osmo_cc_rtp_send(process->codec, (uint8_t *)data, 160 * 2, 1, 160);
|
||||
/* 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)
|
||||
/* messages received from fixed network */
|
||||
void ll_msg_cb(osmo_cc_endpoint_t __attribute__((unused)) *ep, uint32_t callref, osmo_cc_msg_t *msg)
|
||||
{
|
||||
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;
|
||||
uint8_t coding, location, progress, isdn_cause, socket_cause;
|
||||
uint16_t sip_cause;
|
||||
uint8_t type, plan, present, screen, caller_type;
|
||||
char caller_id[33], number[33];
|
||||
int rc;
|
||||
|
||||
callref = mncc->callref;
|
||||
process = get_process(callref);
|
||||
if (!process) {
|
||||
if (mncc->msg_type == MNCC_SETUP_REQ)
|
||||
if (msg->type == OSMO_CC_MSG_SETUP_REQ)
|
||||
process = create_process(callref, PROCESS_SETUP_RT);
|
||||
else {
|
||||
/* release collisions and audio packet are not forbidden */
|
||||
if (mncc->msg_type != MNCC_REL_REQ && mncc->msg_type != ANALOG_8000HZ)
|
||||
/* release collisions is not forbidden */
|
||||
if (msg->type != OSMO_CC_MSG_REL_REQ)
|
||||
PDEBUG(DCALL, DEBUG_ERROR, "No process!\n");
|
||||
osmo_cc_free_msg(msg);
|
||||
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));
|
||||
switch(msg->type) {
|
||||
case OSMO_CC_MSG_DISC_REQ:
|
||||
rc = osmo_cc_get_ie_cause(msg, 0, &location, &isdn_cause, &sip_cause, &socket_cause);
|
||||
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");
|
||||
|
||||
isdn_cause = OSMO_CC_ISDN_CAUSE_NORM_CALL_CLEAR;
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Received OSMO-CC disconnect from fixed network with cause %d\n", isdn_cause);
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Call disconnected, releasing!\n");
|
||||
destroy_process(callref);
|
||||
indicate_disconnect_release(callref, isdn_cause, OSMO_CC_MSG_REL_IND);
|
||||
break;
|
||||
case OSMO_CC_MSG_REL_REQ:
|
||||
rc = osmo_cc_get_ie_cause(msg, 0, &location, &isdn_cause, &sip_cause, &socket_cause);
|
||||
if (rc < 0)
|
||||
isdn_cause = OSMO_CC_ISDN_CAUSE_NORM_CALL_CLEAR;
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Received OSMO-CC release from fixed network with cause %d\n", isdn_cause);
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Call released\n");
|
||||
destroy_process(callref);
|
||||
indicate_disconnect_release(callref, isdn_cause, OSMO_CC_MSG_REL_CNF);
|
||||
break;
|
||||
}
|
||||
osmo_cc_free_msg(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(mncc->msg_type) {
|
||||
case MNCC_SETUP_REQ:
|
||||
strcpy(number, mncc->called.number);
|
||||
switch(msg->type) {
|
||||
case OSMO_CC_MSG_SETUP_REQ:
|
||||
{
|
||||
const char *sdp;
|
||||
|
||||
/* 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;
|
||||
/* sdp accept */
|
||||
sdp = osmo_cc_helper_audio_accept(process, codecs, down_audio, msg, &process->session, &process->codec, 0);
|
||||
if (!sdp) {
|
||||
disconnect_process(callref, 47);
|
||||
break;
|
||||
}
|
||||
if (!caller_id[0])
|
||||
|
||||
/* caller id */
|
||||
rc = osmo_cc_get_ie_calling(msg, 0, &type, &plan, &present, &screen, caller_id, sizeof(caller_id));
|
||||
if (rc < 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();
|
||||
else {
|
||||
switch (type) {
|
||||
case OSMO_CC_TYPE_INTERNATIONAL:
|
||||
caller_type = TYPE_INTERNATIONAL;
|
||||
break;
|
||||
case OSMO_CC_TYPE_NATIONAL:
|
||||
caller_type = TYPE_NATIONAL;
|
||||
break;
|
||||
case OSMO_CC_TYPE_SUBSCRIBER:
|
||||
caller_type = TYPE_SUBSCRIBER;
|
||||
break;
|
||||
default:
|
||||
caller_type = TYPE_UNKNOWN;
|
||||
}
|
||||
if (present == OSMO_CC_PRESENT_RESTRICTED)
|
||||
caller_type = TYPE_ANONYMOUS;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
/* dialing */
|
||||
rc = osmo_cc_get_ie_called(msg, 0, &type, &plan, number, sizeof(number));
|
||||
if (rc < 0)
|
||||
number[0] = '\0';
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Received OSMO-CC call from fixed network '%s' to mobile '%s'\n", caller_id, number);
|
||||
indicate_proceeding(callref, sdp);
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Outgoing call from '%s' to '%s'\n", caller_id, number);
|
||||
|
||||
rc = call_down_setup(callref, caller_id, caller_type, number);
|
||||
|
@ -730,10 +741,10 @@ void mncc_down(uint8_t *buf, int length)
|
|||
PDEBUG(DCALL, DEBUG_NOTICE, "Call rejected, cause %d\n", -rc);
|
||||
if (connect_on_setup) {
|
||||
PDEBUG(DCALL, DEBUG_DEBUG, "Early connecting after setup\n");
|
||||
_indicate_answer(callref, number);
|
||||
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);
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Disconnecting OSMO-CC call towards fixed network (cause=%d)\n", -rc);
|
||||
indicate_disconnect_release(callref, -rc, OSMO_CC_MSG_DISC_IND);
|
||||
}
|
||||
disconnect_process(callref, -rc);
|
||||
break;
|
||||
|
@ -741,65 +752,138 @@ void mncc_down(uint8_t *buf, int length)
|
|||
|
||||
if (connect_on_setup) {
|
||||
PDEBUG(DCALL, DEBUG_DEBUG, "Early connecting after setup\n");
|
||||
_indicate_answer(callref, number);
|
||||
indicate_answer(callref, number);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MNCC_ALERT_REQ:
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Received MNCC alerting from fixed network\n");
|
||||
}
|
||||
case OSMO_CC_MSG_SETUP_ACK_REQ:
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Received OSMO-CC overlap from fixed network\n");
|
||||
rc = osmo_cc_helper_audio_negotiate(msg, &process->session, &process->codec);
|
||||
if (rc < 0) {
|
||||
nego_failed:
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Releasing, because codec negotiation failed.\n");
|
||||
destroy_process(callref);
|
||||
indicate_disconnect_release(callref, 47, OSMO_CC_MSG_REL_IND);
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Call released toward mobile network\n");
|
||||
call_down_release(callref, 47);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case OSMO_CC_MSG_PROC_REQ:
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Received OSMO-CC proceeding from fixed network\n");
|
||||
rc = osmo_cc_helper_audio_negotiate(msg, &process->session, &process->codec);
|
||||
if (rc < 0)
|
||||
goto nego_failed;
|
||||
break;
|
||||
case OSMO_CC_MSG_PROGRESS_REQ:
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Received OSMO-CC progress from fixed network\n");
|
||||
rc = osmo_cc_helper_audio_negotiate(msg, &process->session, &process->codec);
|
||||
if (rc < 0)
|
||||
goto nego_failed;
|
||||
break;
|
||||
case OSMO_CC_MSG_ALERT_REQ:
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Received OSMO-CC alerting from fixed network\n");
|
||||
rc = osmo_cc_helper_audio_negotiate(msg, &process->session, &process->codec);
|
||||
if (rc < 0)
|
||||
goto nego_failed;
|
||||
new_state_process(callref, PROCESS_ALERTING_RO);
|
||||
break;
|
||||
case MNCC_SETUP_RSP:
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Received MNCC answer from fixed network\n");
|
||||
case OSMO_CC_MSG_SETUP_RSP:
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Received OSMO-CC answer from fixed network\n");
|
||||
rc = osmo_cc_helper_audio_negotiate(msg, &process->session, &process->codec);
|
||||
if (rc < 0)
|
||||
goto nego_failed;
|
||||
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);
|
||||
indicate_answer_ack(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) {
|
||||
case OSMO_CC_MSG_DISC_REQ:
|
||||
rc = osmo_cc_helper_audio_negotiate(msg, &process->session, &process->codec);
|
||||
if (rc < 0)
|
||||
goto nego_failed;
|
||||
rc = osmo_cc_get_ie_cause(msg, 0, &location, &isdn_cause, &sip_cause, &socket_cause);
|
||||
if (rc < 0)
|
||||
isdn_cause = OSMO_CC_ISDN_CAUSE_NORM_CALL_CLEAR;
|
||||
rc = osmo_cc_get_ie_progress(msg, 0, &coding, &location, &progress);
|
||||
if (rc < 0)
|
||||
progress = 0;
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Received OSMO-CC disconnect from fixed network with cause %d\n", isdn_cause);
|
||||
if (release_on_disconnect || (progress != 1 && progress != 8)) {
|
||||
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;
|
||||
destroy_process(callref);
|
||||
indicate_disconnect_release(callref, isdn_cause, OSMO_CC_MSG_REL_IND);
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Call released toward mobile network\n");
|
||||
call_down_release(callref, isdn_cause);
|
||||
break;
|
||||
}
|
||||
new_state_process(callref, PROCESS_DISCONNECT);
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Call disconnected\n");
|
||||
call_down_disconnect(callref, mncc->cause.value);
|
||||
timer_start(&process->timer, DISC_TIMEOUT);
|
||||
call_down_disconnect(callref, isdn_cause);
|
||||
/* we might get released during disconnect handling!!! */
|
||||
process = get_process(callref);
|
||||
if (process && process->state == PROCESS_DISCONNECT)
|
||||
timer_start(&process->timer, DISC_TIMEOUT);
|
||||
break;
|
||||
case MNCC_REL_REQ:
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Received MNCC release from fixed network with cause %d\n", mncc->cause.value);
|
||||
|
||||
release:
|
||||
case OSMO_CC_MSG_REJ_REQ:
|
||||
case OSMO_CC_MSG_REL_REQ:
|
||||
rc = osmo_cc_get_ie_cause(msg, 0, &location, &isdn_cause, &sip_cause, &socket_cause);
|
||||
if (rc < 0)
|
||||
isdn_cause = OSMO_CC_ISDN_CAUSE_NORM_CALL_CLEAR;
|
||||
destroy_process(callref);
|
||||
if (msg->type == OSMO_CC_MSG_REL_REQ) {
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Received OSMO-CC release from fixed network with cause %d\n", isdn_cause);
|
||||
indicate_disconnect_release(callref, isdn_cause, OSMO_CC_MSG_REL_CNF);
|
||||
} else
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Received OSMO-CC reject from fixed network with cause %d\n", isdn_cause);
|
||||
PDEBUG(DCALL, DEBUG_INFO, "Call released toward mobile network\n");
|
||||
call_down_release(callref, mncc->cause.value);
|
||||
call_down_release(callref, isdn_cause);
|
||||
break;
|
||||
}
|
||||
osmo_cc_free_msg(msg);
|
||||
}
|
||||
|
||||
int (*mncc_up)(uint8_t *buf, int length) = NULL;
|
||||
|
||||
/* break down of MNCC socket */
|
||||
void mncc_flush(void)
|
||||
int call_init(const char *name, int _send_patterns, int _release_on_disconnect, int use_socket, int argc, const char *argv[])
|
||||
{
|
||||
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 */
|
||||
int rc;
|
||||
|
||||
connect_on_setup = _send_patterns;
|
||||
release_on_disconnect = _release_on_disconnect;
|
||||
|
||||
g711_init();
|
||||
|
||||
ep = &endpoint;
|
||||
rc = osmo_cc_new(ep, OSMO_CC_VERSION, name, OSMO_CC_LOCATION_PRIV_SERV_LOC_USER, ll_msg_cb, (use_socket) ? NULL : console_msg, NULL, argc, argv);
|
||||
if (rc > 0)
|
||||
return -EINVAL;
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void call_exit(void)
|
||||
{
|
||||
if (ep) {
|
||||
osmo_cc_delete(ep);
|
||||
ep = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int call_handle(void)
|
||||
{
|
||||
return osmo_cc_handle();
|
||||
}
|
||||
|
||||
void call_media_handle(void)
|
||||
{
|
||||
process_t *process = process_head;
|
||||
|
||||
while(process) {
|
||||
if (process->session)
|
||||
osmo_cc_session_handle(process->session);
|
||||
process = process->next;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,10 @@ enum number_type {
|
|||
TYPE_INTERNATIONAL,
|
||||
};
|
||||
|
||||
int call_init(int _send_patterns, int _release_on_disconnect);
|
||||
int call_init(const char *name, int _send_patterns, int _release_on_disconnect, int use_socket, int argc, const char *argv[]);
|
||||
void call_exit(void);
|
||||
int call_handle(void);
|
||||
void call_media_handle(void);
|
||||
|
||||
/* function pointer to delive MNCC messages to upper layer */
|
||||
extern int (*mncc_up)(uint8_t *buf, int length);
|
||||
|
@ -19,7 +22,7 @@ void mncc_down(uint8_t *buf, int length);
|
|||
void mncc_flush(void);
|
||||
|
||||
/* received messages */
|
||||
int call_up_setup(int callref, const char *callerid, const char *dialing);
|
||||
int call_up_setup(const char *callerid, const char *dialing, uint8_t network, const char *network_id);
|
||||
void call_up_alerting(int callref);
|
||||
void call_up_early(int callref);
|
||||
void call_up_answer(int callref, const char *connect_id);
|
||||
|
|
|
@ -39,6 +39,8 @@ const char *cause_name(int cause)
|
|||
return "no-channel";
|
||||
case CAUSE_TEMPFAIL:
|
||||
return "link-failure";
|
||||
case CAUSE_RESOURCE_UNAVAIL:
|
||||
return "resource-unavail";
|
||||
case CAUSE_INVALCALLREF:
|
||||
return "invalid-callref";
|
||||
default:
|
|
@ -5,6 +5,7 @@
|
|||
#define CAUSE_INVALNUMBER 28
|
||||
#define CAUSE_NOCHANNEL 34
|
||||
#define CAUSE_TEMPFAIL 41
|
||||
#define CAUSE_RESOURCE_UNAVAIL 47
|
||||
#define CAUSE_INVALCALLREF 81
|
||||
|
||||
#define LOCATION_USER 0
|
|
@ -28,17 +28,17 @@
|
|||
#include "../libsamplerate/samplerate.h"
|
||||
#include "../libjitter/jitter.h"
|
||||
#include "../libdebug/debug.h"
|
||||
#include "../libtimer/timer.h"
|
||||
#include "../libosmocc/endpoint.h"
|
||||
#include "../libosmocc/helper.h"
|
||||
#include "testton.h"
|
||||
#include "mncc.h"
|
||||
#include "mncc_console.h"
|
||||
#include "console.h"
|
||||
#include "cause.h"
|
||||
#include "../libmobile/call.h"
|
||||
#ifdef HAVE_ALSA
|
||||
#include "../libsound/sound.h"
|
||||
#endif
|
||||
|
||||
static int new_callref = 0; /* toward mobile */
|
||||
|
||||
enum console_state {
|
||||
CONSOLE_IDLE = 0, /* IDLE */
|
||||
CONSOLE_SETUP_RO, /* call from radio to console */
|
||||
|
@ -46,7 +46,7 @@ enum console_state {
|
|||
CONSOLE_ALERTING_RO, /* call from radio to console */
|
||||
CONSOLE_ALERTING_RT, /* call from console to radio */
|
||||
CONSOLE_CONNECT,
|
||||
CONSOLE_DISCONNECT,
|
||||
CONSOLE_DISCONNECT_RO,
|
||||
};
|
||||
|
||||
static const char *console_state_name[] = {
|
||||
|
@ -56,11 +56,13 @@ static const char *console_state_name[] = {
|
|||
"ALERTING_RO",
|
||||
"ALERTING_RT",
|
||||
"CONNECT",
|
||||
"DISCONNECT",
|
||||
"DISCONNECT_RO",
|
||||
};
|
||||
|
||||
/* console call instance */
|
||||
typedef struct console {
|
||||
osmo_cc_session_t *session;
|
||||
osmo_cc_session_codec_t *codec;
|
||||
uint32_t callref;
|
||||
enum console_state state;
|
||||
int disc_cause; /* cause that has been sent by transceiver instance for release */
|
||||
|
@ -83,6 +85,16 @@ typedef struct console {
|
|||
|
||||
static console_t console;
|
||||
|
||||
extern osmo_cc_endpoint_t *ep;
|
||||
|
||||
void encode_l16(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len);
|
||||
void decode_l16(uint8_t *src_data, int src_len, uint8_t **dst_data, int *dst_len);
|
||||
|
||||
static struct osmo_cc_helper_audio_codecs codecs[] = {
|
||||
{ "L16", 8000, 1, encode_l16, decode_l16 },
|
||||
{ NULL, 0, 0, NULL, NULL},
|
||||
};
|
||||
|
||||
/* stream test music */
|
||||
int16_t *test_spl = NULL;
|
||||
int test_size = 0;
|
||||
|
@ -112,118 +124,214 @@ static void get_test_patterns(int16_t *samples, int length)
|
|||
|
||||
static void console_new_state(enum console_state state)
|
||||
{
|
||||
PDEBUG(DMNCC, DEBUG_DEBUG, "Call state '%s' -> '%s'\n", console_state_name[console.state], console_state_name[state]);
|
||||
PDEBUG(DCC, DEBUG_DEBUG, "Call state '%s' -> '%s'\n", console_state_name[console.state], console_state_name[state]);
|
||||
console.state = state;
|
||||
console.test_audio_pos = 0;
|
||||
}
|
||||
|
||||
static int console_mncc_up(uint8_t *buf, int length)
|
||||
static void free_console(void)
|
||||
{
|
||||
struct gsm_mncc *mncc = (struct gsm_mncc *)buf;
|
||||
if (console.session) {
|
||||
osmo_cc_free_session(console.session);
|
||||
console.session = NULL;
|
||||
}
|
||||
console.codec = NULL;
|
||||
console.callref = 0;
|
||||
}
|
||||
|
||||
if (mncc->msg_type == ANALOG_8000HZ) {
|
||||
struct gsm_data_frame *data = (struct gsm_data_frame *)buf;
|
||||
int count = 160;
|
||||
sample_t samples[count];
|
||||
void up_audio(struct osmo_cc_session_codec *codec, uint16_t __attribute__((unused)) sequence_number, uint32_t __attribute__((unused)) timestamp, uint8_t *data, int len)
|
||||
{
|
||||
int count = len / 2;
|
||||
sample_t samples[count];
|
||||
|
||||
/* save audio from transceiver to jitter buffer */
|
||||
if (console.sound) {
|
||||
sample_t up[(int)((double)count * console.srstate.factor + 0.5) + 10];
|
||||
int16_to_samples(samples, (int16_t *)data->data, count);
|
||||
count = samplerate_upsample(&console.srstate, samples, count, up);
|
||||
jitter_save(&console.dejitter, up, count);
|
||||
return 0;
|
||||
}
|
||||
/* if echo test is used, send echo back to mobile */
|
||||
if (console.echo_test) {
|
||||
/* send down reused MNCC */
|
||||
mncc_down(buf, length);
|
||||
return 0;
|
||||
}
|
||||
/* if no sound is used, send test tone to mobile */
|
||||
if (console.state == CONSOLE_CONNECT) {
|
||||
/* send down reused MNCC */
|
||||
get_test_patterns((int16_t *)data->data, count);
|
||||
mncc_down(buf, length);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
/* save audio from transceiver to jitter buffer */
|
||||
if (console.sound) {
|
||||
sample_t up[(int)((double)count * console.srstate.factor + 0.5) + 10];
|
||||
int16_to_samples(samples, (int16_t *)data, count);
|
||||
count = samplerate_upsample(&console.srstate, samples, count, up);
|
||||
jitter_save(&console.dejitter, up, count);
|
||||
return;
|
||||
}
|
||||
/* if echo test is used, send echo back to mobile */
|
||||
if (console.echo_test) {
|
||||
osmo_cc_rtp_send(codec, (uint8_t *)data, count * 2, 1, count);
|
||||
return;
|
||||
}
|
||||
/* if no sound is used, send test tone to mobile */
|
||||
if (console.state == CONSOLE_CONNECT) {
|
||||
get_test_patterns((int16_t *)data, count);
|
||||
osmo_cc_rtp_send(codec, (uint8_t *)data, count * 2, 1, count);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void request_setup(int callref, const char *dialing)
|
||||
{
|
||||
osmo_cc_msg_t *msg;
|
||||
|
||||
msg = osmo_cc_new_msg(OSMO_CC_MSG_SETUP_REQ);
|
||||
/* called number */
|
||||
if (dialing)
|
||||
osmo_cc_add_ie_called(msg, OSMO_CC_TYPE_UNKNOWN, OSMO_CC_PLAN_TELEPHONY, dialing);
|
||||
/* bearer capability */
|
||||
osmo_cc_add_ie_bearer(msg, OSMO_CC_CODING_ITU_T, OSMO_CC_CAPABILITY_AUDIO, OSMO_CC_MODE_CIRCUIT);
|
||||
/* sdp offer */
|
||||
console.session = osmo_cc_helper_audio_offer(NULL, codecs, up_audio, msg, 1);
|
||||
|
||||
osmo_cc_ul_msg(ep, callref, msg);
|
||||
}
|
||||
|
||||
static void request_answer(int callref, const char *connectid, const char *sdp)
|
||||
{
|
||||
osmo_cc_msg_t *msg;
|
||||
|
||||
msg = osmo_cc_new_msg(OSMO_CC_MSG_SETUP_RSP);
|
||||
/* calling number */
|
||||
if (connectid)
|
||||
osmo_cc_add_ie_calling(msg, OSMO_CC_TYPE_SUBSCRIBER, OSMO_CC_PLAN_TELEPHONY, OSMO_CC_PRESENT_ALLOWED, OSMO_CC_SCREEN_NETWORK, connectid);
|
||||
/* SDP */
|
||||
if (sdp)
|
||||
osmo_cc_add_ie_sdp(msg, sdp);
|
||||
|
||||
osmo_cc_ul_msg(ep, callref, msg);
|
||||
}
|
||||
|
||||
static void request_answer_ack(int callref)
|
||||
{
|
||||
osmo_cc_msg_t *msg;
|
||||
|
||||
msg = osmo_cc_new_msg(OSMO_CC_MSG_SETUP_COMP_REQ);
|
||||
|
||||
osmo_cc_ul_msg(ep, callref, msg);
|
||||
}
|
||||
|
||||
static void request_disconnect_release_reject(int callref, int cause, uint8_t msg_type)
|
||||
{
|
||||
osmo_cc_msg_t *msg;
|
||||
|
||||
msg = osmo_cc_new_msg(msg_type);
|
||||
osmo_cc_add_ie_cause(msg, OSMO_CC_LOCATION_USER, cause, 0, 0);
|
||||
|
||||
osmo_cc_ul_msg(ep, callref, msg);
|
||||
}
|
||||
|
||||
void console_msg(osmo_cc_call_t *call, osmo_cc_msg_t *msg)
|
||||
{
|
||||
uint8_t location, isdn_cause, socket_cause;
|
||||
uint16_t sip_cause;
|
||||
uint8_t type, plan, present, screen;
|
||||
uint8_t progress, coding;
|
||||
char caller_id[33], number[33];
|
||||
const char *sdp;
|
||||
int rc;
|
||||
|
||||
if (msg->type != OSMO_CC_MSG_SETUP_IND && console.callref != call->callref) {
|
||||
PDEBUG(DCC, DEBUG_ERROR, "invalid call ref %u (msg=0x%02x).\n", call->callref, msg->type);
|
||||
request_disconnect_release_reject(call->callref, CAUSE_INVALCALLREF, OSMO_CC_MSG_REL_REQ);
|
||||
osmo_cc_free_msg(msg);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mncc->msg_type != MNCC_SETUP_IND && console.callref != mncc->callref) {
|
||||
PDEBUG(DMNCC, DEBUG_ERROR, "invalid call ref.\n");
|
||||
/* send down reused MNCC */
|
||||
mncc->msg_type = MNCC_REL_REQ;
|
||||
mncc->fields |= MNCC_F_CAUSE;
|
||||
mncc->cause.location = LOCATION_USER;
|
||||
mncc->cause.value = CAUSE_INVALCALLREF;
|
||||
mncc_down(buf, length);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch(mncc->msg_type) {
|
||||
case MNCC_SETUP_IND:
|
||||
PDEBUG(DMNCC, DEBUG_INFO, "Incoming call from '%s'\n", mncc->calling.number);
|
||||
switch(msg->type) {
|
||||
case OSMO_CC_MSG_SETUP_IND:
|
||||
{
|
||||
/* caller id */
|
||||
rc = osmo_cc_get_ie_calling(msg, 0, &type, &plan, &present, &screen, caller_id, sizeof(caller_id));
|
||||
if (rc < 0)
|
||||
caller_id[0] = '\0';
|
||||
/* dialing */
|
||||
rc = osmo_cc_get_ie_called(msg, 0, &type, &plan, number, sizeof(number));
|
||||
if (rc < 0)
|
||||
number[0] = '\0';
|
||||
PDEBUG(DCC, DEBUG_INFO, "Incoming call from '%s'\n", caller_id);
|
||||
/* setup is also allowed on disconnected call */
|
||||
if (console.state == CONSOLE_DISCONNECT) {
|
||||
PDEBUG(DMNCC, DEBUG_INFO, "Releasing pending disconnected call\n");
|
||||
if (console.state == CONSOLE_DISCONNECT_RO) {
|
||||
PDEBUG(DCC, DEBUG_INFO, "Releasing pending disconnected call\n");
|
||||
if (console.callref) {
|
||||
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_REQ;
|
||||
mncc->callref = console.callref;
|
||||
mncc->fields |= MNCC_F_CAUSE;
|
||||
mncc->cause.location = LOCATION_USER;
|
||||
mncc->cause.value = CAUSE_NORMAL;
|
||||
mncc_down(buf, sizeof(struct gsm_mncc));
|
||||
console.callref = 0;
|
||||
request_disconnect_release_reject(console.callref, CAUSE_NORMAL, OSMO_CC_MSG_REL_REQ);
|
||||
free_console();
|
||||
}
|
||||
console_new_state(CONSOLE_IDLE);
|
||||
}
|
||||
if (console.state != CONSOLE_IDLE) {
|
||||
PDEBUG(DMNCC, DEBUG_NOTICE, "We are busy, rejecting.\n");
|
||||
return -CAUSE_BUSY;
|
||||
PDEBUG(DCC, DEBUG_NOTICE, "We are busy, rejecting.\n");
|
||||
request_disconnect_release_reject(console.callref, CAUSE_NORMAL, OSMO_CC_MSG_REJ_REQ);
|
||||
osmo_cc_free_msg(msg);
|
||||
return;
|
||||
}
|
||||
console.callref = mncc->callref;
|
||||
if (mncc->calling.number[0]) {
|
||||
strncpy(console.station_id, mncc->calling.number, console.num_digits);
|
||||
console.callref = call->callref;
|
||||
/* sdp accept */
|
||||
sdp = osmo_cc_helper_audio_accept(NULL, codecs, up_audio, msg, &console.session, &console.codec, 0);
|
||||
if (!sdp) {
|
||||
PDEBUG(DCC, DEBUG_NOTICE, "Cannot accept codec, rejecting.\n");
|
||||
request_disconnect_release_reject(console.callref, CAUSE_RESOURCE_UNAVAIL, OSMO_CC_MSG_REJ_REQ);
|
||||
osmo_cc_free_msg(msg);
|
||||
return;
|
||||
}
|
||||
if (caller_id[0]) {
|
||||
strncpy(console.station_id, caller_id, console.num_digits);
|
||||
console.station_id[console.num_digits] = '\0';
|
||||
}
|
||||
strncpy(console.dialing, mncc->called.number, sizeof(console.dialing) - 1);
|
||||
strncpy(console.dialing, number, sizeof(console.dialing) - 1);
|
||||
console.dialing[sizeof(console.dialing) - 1] = '\0';
|
||||
console_new_state(CONSOLE_CONNECT);
|
||||
PDEBUG(DMNCC, DEBUG_INFO, "Call automatically answered\n");
|
||||
/* send down reused MNCC */
|
||||
mncc->msg_type = MNCC_SETUP_RSP;
|
||||
mncc_down(buf, length);
|
||||
PDEBUG(DCC, DEBUG_INFO, "Call automatically answered\n");
|
||||
request_answer(console.callref, number, sdp);
|
||||
break;
|
||||
case MNCC_ALERT_IND:
|
||||
PDEBUG(DMNCC, DEBUG_INFO, "Call alerting\n");
|
||||
}
|
||||
case OSMO_CC_MSG_SETUP_ACK_IND:
|
||||
case OSMO_CC_MSG_PROC_IND:
|
||||
osmo_cc_helper_audio_negotiate(msg, &console.session, &console.codec);
|
||||
break;
|
||||
case OSMO_CC_MSG_ALERT_IND:
|
||||
PDEBUG(DCC, DEBUG_INFO, "Call alerting\n");
|
||||
osmo_cc_helper_audio_negotiate(msg, &console.session, &console.codec);
|
||||
console_new_state(CONSOLE_ALERTING_RT);
|
||||
break;
|
||||
case MNCC_SETUP_CNF:
|
||||
PDEBUG(DMNCC, DEBUG_INFO, "Call connected to '%s'\n", mncc->connected.number);
|
||||
case OSMO_CC_MSG_SETUP_CNF:
|
||||
{
|
||||
/* connected id */
|
||||
rc = osmo_cc_get_ie_calling(msg, 0, &type, &plan, &present, &screen, caller_id, sizeof(caller_id));
|
||||
if (rc < 0)
|
||||
caller_id[0] = '\0';
|
||||
PDEBUG(DCC, DEBUG_INFO, "Call connected to '%s'\n", caller_id);
|
||||
osmo_cc_helper_audio_negotiate(msg, &console.session, &console.codec);
|
||||
console_new_state(CONSOLE_CONNECT);
|
||||
strncpy(console.station_id, mncc->connected.number, console.num_digits);
|
||||
strncpy(console.station_id, caller_id, console.num_digits);
|
||||
console.station_id[console.num_digits] = '\0';
|
||||
/* send down reused MNCC */
|
||||
mncc->msg_type = MNCC_SETUP_COMPL_REQ;
|
||||
mncc_down(buf, length);
|
||||
request_answer_ack(console.callref);
|
||||
break;
|
||||
case MNCC_DISC_IND:
|
||||
PDEBUG(DMNCC, DEBUG_INFO, "Call disconnected (%s)\n", cause_name(mncc->cause.value));
|
||||
console_new_state(CONSOLE_DISCONNECT);
|
||||
console.disc_cause = mncc->cause.value;
|
||||
}
|
||||
case OSMO_CC_MSG_SETUP_COMP_IND:
|
||||
break;
|
||||
case MNCC_REL_IND:
|
||||
PDEBUG(DMNCC, DEBUG_INFO, "Call released (%s)\n", cause_name(mncc->cause.value));
|
||||
case OSMO_CC_MSG_DISC_IND:
|
||||
rc = osmo_cc_get_ie_cause(msg, 0, &location, &isdn_cause, &sip_cause, &socket_cause);
|
||||
if (rc < 0)
|
||||
isdn_cause = OSMO_CC_ISDN_CAUSE_NORM_CALL_CLEAR;
|
||||
rc = osmo_cc_get_ie_progress(msg, 0, &coding, &location, &progress);
|
||||
osmo_cc_helper_audio_negotiate(msg, &console.session, &console.codec);
|
||||
if (rc >= 0 && (progress == 1 || progress == 8)) {
|
||||
PDEBUG(DCC, DEBUG_INFO, "Call disconnected with audio (%s)\n", cause_name(isdn_cause));
|
||||
console_new_state(CONSOLE_DISCONNECT_RO);
|
||||
console.disc_cause = isdn_cause;
|
||||
} else {
|
||||
PDEBUG(DCC, DEBUG_INFO, "Call disconnected without audio (%s)\n", cause_name(isdn_cause));
|
||||
request_disconnect_release_reject(console.callref, isdn_cause, OSMO_CC_MSG_REL_REQ);
|
||||
console_new_state(CONSOLE_IDLE);
|
||||
free_console();
|
||||
}
|
||||
break;
|
||||
case OSMO_CC_MSG_REL_IND:
|
||||
case OSMO_CC_MSG_REJ_IND:
|
||||
rc = osmo_cc_get_ie_cause(msg, 0, &location, &isdn_cause, &sip_cause, &socket_cause);
|
||||
if (rc < 0)
|
||||
isdn_cause = OSMO_CC_ISDN_CAUSE_NORM_CALL_CLEAR;
|
||||
PDEBUG(DCC, DEBUG_INFO, "Call released (%s)\n", cause_name(isdn_cause));
|
||||
console_new_state(CONSOLE_IDLE);
|
||||
console.callref = 0;
|
||||
free_console();
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
osmo_cc_free_msg(msg);
|
||||
}
|
||||
|
||||
static char console_text[256];
|
||||
|
@ -270,8 +378,6 @@ int console_init(const char *station_id, const char *audiodev, int samplerate, i
|
|||
console.echo_test = echo_test;
|
||||
console.digits = digits;
|
||||
|
||||
mncc_up = console_mncc_up;
|
||||
|
||||
if (!audiodev[0])
|
||||
return 0;
|
||||
|
||||
|
@ -331,16 +437,23 @@ void console_cleanup(void)
|
|||
{
|
||||
#ifdef HAVE_ALSA
|
||||
/* close sound devoice */
|
||||
if (console.sound)
|
||||
if (console.sound) {
|
||||
sound_close(console.sound);
|
||||
console.sound = NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
jitter_destroy(&console.dejitter);
|
||||
|
||||
if (console.session) {
|
||||
osmo_cc_free_session(console.session);
|
||||
console.session = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void process_ui(int c)
|
||||
{
|
||||
char text[256];
|
||||
char text[256] = "";
|
||||
int len;
|
||||
int i;
|
||||
|
||||
|
@ -359,25 +472,11 @@ static void process_ui(int c)
|
|||
console.station_id[strlen(console.station_id) - 1] = '\0';
|
||||
dial_after_hangup:
|
||||
if (c == 'd' && (int)strlen(console.station_id) == console.num_digits) {
|
||||
int callref = ++new_callref;
|
||||
uint8_t buf[sizeof(struct gsm_mncc)];
|
||||
struct gsm_mncc *mncc = (struct gsm_mncc *)buf;
|
||||
|
||||
PDEBUG(DMNCC, DEBUG_INFO, "Outgoing call to '%s'\n", console.station_id);
|
||||
PDEBUG(DCC, DEBUG_INFO, "Outgoing call to '%s'\n", console.station_id);
|
||||
console.dialing[0] = '\0';
|
||||
console_new_state(CONSOLE_SETUP_RT);
|
||||
console.callref = callref;
|
||||
memset(buf, 0, sizeof(buf));
|
||||
mncc->msg_type = MNCC_SETUP_REQ;
|
||||
mncc->callref = callref;
|
||||
mncc->fields |= MNCC_F_CALLED;
|
||||
strncpy(mncc->called.number, console.station_id, 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;
|
||||
mncc_down(buf, sizeof(struct gsm_mncc));
|
||||
console.callref = osmo_cc_new_callref();
|
||||
request_setup(console.callref, console.station_id);
|
||||
}
|
||||
}
|
||||
if (console.num_digits != (int)strlen(console.station_id))
|
||||
|
@ -390,24 +489,18 @@ dial_after_hangup:
|
|||
case CONSOLE_ALERTING_RO:
|
||||
case CONSOLE_ALERTING_RT:
|
||||
case CONSOLE_CONNECT:
|
||||
case CONSOLE_DISCONNECT:
|
||||
case CONSOLE_DISCONNECT_RO:
|
||||
if (c > 0) {
|
||||
if (c == 'h' || (c == 'd' && console.state == CONSOLE_DISCONNECT)) {
|
||||
PDEBUG(DMNCC, DEBUG_INFO, "Call hangup\n");
|
||||
console_new_state(CONSOLE_IDLE);
|
||||
if (c == 'h' || (c == 'd' && console.state == CONSOLE_DISCONNECT_RO)) {
|
||||
PDEBUG(DCC, DEBUG_INFO, "Call hangup\n");
|
||||
if (console.callref) {
|
||||
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_REQ;
|
||||
mncc->callref = console.callref;
|
||||
mncc->fields |= MNCC_F_CAUSE;
|
||||
mncc->cause.location = LOCATION_USER;
|
||||
mncc->cause.value = CAUSE_NORMAL;
|
||||
mncc_down(buf, sizeof(struct gsm_mncc));
|
||||
console.callref = 0;
|
||||
if (console.state == CONSOLE_SETUP_RO)
|
||||
request_disconnect_release_reject(console.callref, CAUSE_NORMAL, OSMO_CC_MSG_REJ_REQ);
|
||||
else
|
||||
request_disconnect_release_reject(console.callref, CAUSE_NORMAL, OSMO_CC_MSG_REL_REQ);
|
||||
free_console();
|
||||
}
|
||||
console_new_state(CONSOLE_IDLE);
|
||||
if (c == 'd')
|
||||
goto dial_after_hangup;
|
||||
}
|
||||
|
@ -422,7 +515,7 @@ dial_after_hangup:
|
|||
else
|
||||
sprintf(text, "call active: %s (press h=hangup)\r", console.station_id);
|
||||
}
|
||||
if (console.state == CONSOLE_DISCONNECT)
|
||||
if (console.state == CONSOLE_DISCONNECT_RO)
|
||||
sprintf(text, "call disconnected: %s (press h=hangup d=redial)\r", cause_name(console.disc_cause));
|
||||
break;
|
||||
}
|
||||
|
@ -446,6 +539,9 @@ void process_console(int c)
|
|||
if (!console.loopback && console.num_digits)
|
||||
process_ui(c);
|
||||
|
||||
if (console.session)
|
||||
osmo_cc_session_handle(console.session);
|
||||
|
||||
if (!console.sound)
|
||||
return;
|
||||
|
||||
|
@ -496,14 +592,10 @@ void process_console(int c)
|
|||
if (++console.tx_buffer_pos == 160) {
|
||||
console.tx_buffer_pos = 0;
|
||||
/* only if we have a call */
|
||||
if (console.callref) {
|
||||
uint8_t buf[sizeof(struct gsm_data_frame) + 160 * sizeof(int16_t)];
|
||||
struct gsm_data_frame *data = (struct gsm_data_frame *)buf;
|
||||
|
||||
data->msg_type = ANALOG_8000HZ;
|
||||
data->callref = console.callref;
|
||||
samples_to_int16((int16_t *)data->data, console.tx_buffer, 160);
|
||||
mncc_down(buf, sizeof(struct gsm_mncc));
|
||||
if (console.callref && console.codec) {
|
||||
int16_t data[160];
|
||||
samples_to_int16(data, console.tx_buffer, 160);
|
||||
osmo_cc_rtp_send(console.codec, (uint8_t *)data, 160 * 2, 1, 160);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
void console_msg(osmo_cc_call_t *call, osmo_cc_msg_t *msg);
|
||||
int console_init(const char *station_id, const char *audiodev, int samplerate, int latency, int dial_digits, int loopback, int echo_test, const char *digits);
|
||||
void console_cleanup(void);
|
||||
int console_open_audio(int latspl);
|
|
@ -33,9 +33,8 @@
|
|||
#include "sender.h"
|
||||
#include "../libtimer/timer.h"
|
||||
#include "call.h"
|
||||
#include "../libmncc/mncc_console.h"
|
||||
#include "../libmncc/mncc_sock.h"
|
||||
#include "../libmncc/mncc_cross.h"
|
||||
#include "../libosmocc/endpoint.h"
|
||||
#include "console.h"
|
||||
#ifdef HAVE_SDR
|
||||
#include "../libsdr/sdr.h"
|
||||
#include "../libsdr/sdr_config.h"
|
||||
|
@ -66,9 +65,11 @@ int do_de_emphasis = 0;
|
|||
double rx_gain = 1.0;
|
||||
double tx_gain = 1.0;
|
||||
static int echo_test = 0;
|
||||
static int use_mncc_sock = 0;
|
||||
static int use_mncc_cross = 0;
|
||||
const char *mncc_name = "";
|
||||
static int use_osmocc_cross = 0;
|
||||
static int use_osmocc_sock = 0;
|
||||
#define MAX_CC_ARGS 1024
|
||||
static int cc_argc = 0;
|
||||
static const char *cc_argv[MAX_CC_ARGS];
|
||||
int send_patterns = 1;
|
||||
static int release_on_disconnect = 1;
|
||||
int loopback = 0;
|
||||
|
@ -82,6 +83,8 @@ const char *console_digits = "0123456789";
|
|||
|
||||
void main_mobile_init(void)
|
||||
{
|
||||
cc_argv[cc_argc++] = strdup("remote auto");
|
||||
|
||||
got_init = 1;
|
||||
#ifdef HAVE_SDR
|
||||
sdr_config_init(DEFAULT_LO_OFFSET);
|
||||
|
@ -135,15 +138,14 @@ void main_mobile_print_help(const char *arg0, const char *ext_usage)
|
|||
printf(" Sound card and device number for headset (default = '%s')\n", call_audiodev);
|
||||
printf(" --call-samplerate <rate>\n");
|
||||
printf(" Sample rate of sound device for headset (default = '%d')\n", call_samplerate);
|
||||
printf(" -x --mncc-cross\n");
|
||||
printf(" -x --osmocc-cross\n");
|
||||
printf(" Enable built-in call forwarding between mobiles. Be sure to have\n");
|
||||
printf(" at least one control channel and two voice channels. Alternatively\n");
|
||||
printf(" use one combined control+voice channel and one voice channels.\n");
|
||||
printf(" -m --mncc-sock\n");
|
||||
printf(" Disable built-in call contol and offer socket (to LCR)\n");
|
||||
printf(" --mncc-name <name>\n");
|
||||
printf(" '/tmp/bsc_mncc' is used by default, give name to change socket to\n");
|
||||
printf(" '/tmp/bsc_mncc_<name>'. (Useful to run multiple networks.)\n");
|
||||
printf(" -o --osmocc-sock\n");
|
||||
printf(" Disable built-in call contol and offer socket\n");
|
||||
printf(" --cc \"<osmo-cc arg>\" [--cc ...]\n");
|
||||
printf(" Pass arguments to Osmo-CC endpoint. Use '-cc help' for description.\n");
|
||||
printf(" -t --tones 0 | 1\n");
|
||||
printf(" Connect call on setup/release to provide classic tones towards fixed\n");
|
||||
printf(" network (default = '%d')\n", send_patterns);
|
||||
|
@ -191,12 +193,12 @@ void main_mobile_print_hotkeys(void)
|
|||
#define OPT_CHANNEL 1000
|
||||
#define OPT_RX_GAIN 1001
|
||||
#define OPT_TX_GAIN 1002
|
||||
#define OPT_WRITE_RX_WAVE 1003
|
||||
#define OPT_WRITE_TX_WAVE 1004
|
||||
#define OPT_READ_RX_WAVE 1005
|
||||
#define OPT_READ_TX_WAVE 1006
|
||||
#define OPT_CALL_SAMPLERATE 1007
|
||||
#define OPT_MNCC_NAME 1008
|
||||
#define OPT_OSMO_CC 1003
|
||||
#define OPT_WRITE_RX_WAVE 1004
|
||||
#define OPT_WRITE_TX_WAVE 1005
|
||||
#define OPT_READ_RX_WAVE 1006
|
||||
#define OPT_READ_TX_WAVE 1007
|
||||
#define OPT_CALL_SAMPLERATE 1008
|
||||
#define OPT_FAST_MATH 1009
|
||||
#define OPT_LIMESDR 1100
|
||||
#define OPT_LIMESDR_MINI 1101
|
||||
|
@ -204,7 +206,7 @@ void main_mobile_print_hotkeys(void)
|
|||
void main_mobile_add_options(void)
|
||||
{
|
||||
option_add('h', "help", 0);
|
||||
option_add('v', "debug", 1);
|
||||
option_add('v', "verbose", 1);
|
||||
option_add('k', "kanal", 1);
|
||||
option_add(OPT_CHANNEL, "channel", 1);
|
||||
option_add('a', "audio-device", 1);
|
||||
|
@ -216,9 +218,9 @@ void main_mobile_add_options(void)
|
|||
option_add(OPT_RX_GAIN, "rx-gain", 1);
|
||||
option_add(OPT_TX_GAIN, "tx-gain", 1);
|
||||
option_add('e', "echo-test", 0);
|
||||
option_add('x', "mncc-cross", 0);
|
||||
option_add('m', "mncc-sock", 0);
|
||||
option_add(OPT_MNCC_NAME, "mncc-name", 1);
|
||||
option_add('x', "osmocc-cross", 0);
|
||||
option_add('o', "osmocc-sock", 0);
|
||||
option_add(OPT_OSMO_CC, "cc", 1);
|
||||
option_add('c', "call-device", 1);
|
||||
option_add(OPT_CALL_SAMPLERATE, "call-samplerate", 1);
|
||||
option_add('t', "tones", 1);
|
||||
|
@ -303,13 +305,21 @@ int main_mobile_handle_options(int short_option, int argi, char **argv)
|
|||
echo_test = 1;
|
||||
break;
|
||||
case 'x':
|
||||
use_mncc_cross = 1;
|
||||
use_osmocc_cross = 1;
|
||||
break;
|
||||
case 'm':
|
||||
use_mncc_sock = 1;
|
||||
case 'o':
|
||||
use_osmocc_sock = 1;
|
||||
break;
|
||||
case OPT_MNCC_NAME:
|
||||
mncc_name = strdup(argv[argi]);
|
||||
case OPT_OSMO_CC:
|
||||
if (!strcasecmp(argv[argi], "help")) {
|
||||
osmo_cc_help();
|
||||
return 0;
|
||||
}
|
||||
if (cc_argc == MAX_CC_ARGS) {
|
||||
fprintf(stderr, "Too many osmo-cc args!\n");
|
||||
break;
|
||||
}
|
||||
cc_argv[cc_argc++] = strdup(argv[argi]);
|
||||
break;
|
||||
case 'c':
|
||||
call_audiodev = strdup(argv[argi]);
|
||||
|
@ -420,7 +430,7 @@ static int get_char()
|
|||
}
|
||||
|
||||
/* Loop through all transceiver instances of one network. */
|
||||
void main_mobile(int *quit, int latency, int interval, void (*myhandler)(void), const char *station_id, int station_id_digits)
|
||||
void main_mobile(const char *name, int *quit, int latency, int interval, void (*myhandler)(void), const char *station_id, int station_id_digits)
|
||||
{
|
||||
int latspl;
|
||||
sender_t *sender;
|
||||
|
@ -437,61 +447,42 @@ void main_mobile(int *quit, int latency, int interval, void (*myhandler)(void),
|
|||
/* latency of send buffer in samples */
|
||||
latspl = samplerate * latency / 1000;
|
||||
|
||||
/* check MNCC support */
|
||||
if (use_mncc_cross && num_kanal == 1) {
|
||||
/* check OSMO-CC support */
|
||||
if (use_osmocc_cross && num_kanal == 1) {
|
||||
fprintf(stderr, "You selected built-in call forwarding, but only channel is used. Does this makes sense?\n");
|
||||
return;
|
||||
}
|
||||
if (use_mncc_sock && use_mncc_cross) {
|
||||
fprintf(stderr, "You selected MNCC socket interface and built-in call forwarding, but only one can be selected.\n");
|
||||
if (use_osmocc_sock && use_osmocc_cross) {
|
||||
fprintf(stderr, "You selected OSMO-CC socket interface and built-in call forwarding, but only one can be selected.\n");
|
||||
return;
|
||||
}
|
||||
if (echo_test && call_audiodev[0]) {
|
||||
fprintf(stderr, "You selected call device (headset) and echo test, but only one can be selected.\n");
|
||||
return;
|
||||
}
|
||||
if (use_mncc_sock && call_audiodev[0]) {
|
||||
fprintf(stderr, "You selected MNCC socket interface, but it cannot be used with call device (headset).\n");
|
||||
if (use_osmocc_sock && call_audiodev[0]) {
|
||||
fprintf(stderr, "You selected OSMO-CC socket interface, but it cannot be used with call device (headset).\n");
|
||||
return;
|
||||
}
|
||||
if (use_mncc_cross && call_audiodev[0]) {
|
||||
if (use_osmocc_cross && call_audiodev[0]) {
|
||||
fprintf(stderr, "You selected built-in call forwarding, but it cannot be used with call device (headset).\n");
|
||||
return;
|
||||
}
|
||||
if (use_mncc_sock && echo_test) {
|
||||
fprintf(stderr, "You selected MNCC socket interface, but it cannot be used with echo test.\n");
|
||||
if (use_osmocc_sock && echo_test) {
|
||||
fprintf(stderr, "You selected OSMO-CC socket interface, but it cannot be used with echo test.\n");
|
||||
return;
|
||||
}
|
||||
if (use_mncc_cross && echo_test) {
|
||||
if (use_osmocc_cross && echo_test) {
|
||||
fprintf(stderr, "You selected built-in call forwarding, but it cannot be used with echo test.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* init mncc */
|
||||
if (use_mncc_sock) {
|
||||
char mncc_sock_name[64];
|
||||
if (mncc_name[0]) {
|
||||
snprintf(mncc_sock_name, sizeof(mncc_sock_name), "/tmp/bsc_mncc_%s", mncc_name);
|
||||
mncc_sock_name[sizeof(mncc_sock_name) - 1] = '\0';
|
||||
} else
|
||||
strcpy(mncc_sock_name, "/tmp/bsc_mncc");
|
||||
rc = mncc_sock_init(mncc_sock_name);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to setup MNCC socket. Quitting!\n");
|
||||
return;
|
||||
}
|
||||
} else if (use_mncc_cross) {
|
||||
rc = mncc_cross_init();
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to setup MNCC crossing process. Quitting!\n");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
/* init OSMO-CC */
|
||||
if (!use_osmocc_sock)
|
||||
console_init(station_id, call_audiodev, call_samplerate, latency, station_id_digits, loopback, echo_test, console_digits);
|
||||
}
|
||||
|
||||
/* init call control instance */
|
||||
rc = call_init((use_mncc_sock) ? send_patterns : 0, release_on_disconnect);
|
||||
rc = call_init(name, (use_osmocc_sock) ? send_patterns : 0, release_on_disconnect, use_osmocc_sock, cc_argc, cc_argv);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to create call control instance. Quitting!\n");
|
||||
return;
|
||||
|
@ -558,7 +549,7 @@ void main_mobile(int *quit, int latency, int interval, void (*myhandler)(void),
|
|||
/* process timers */
|
||||
process_timer();
|
||||
|
||||
/* process audio for mncc call instances */
|
||||
/* process audio for call instances */
|
||||
now = get_time();
|
||||
if (now - last_time_call >= 0.1)
|
||||
last_time_call = now;
|
||||
|
@ -638,11 +629,9 @@ next_char:
|
|||
}
|
||||
|
||||
/* process call control */
|
||||
if (use_mncc_sock)
|
||||
mncc_sock_handle();
|
||||
else if (use_mncc_cross)
|
||||
mncc_cross_handle();
|
||||
else
|
||||
call_media_handle();
|
||||
while (call_handle());
|
||||
if (!use_osmocc_sock)
|
||||
process_console(c);
|
||||
|
||||
if (myhandler)
|
||||
|
@ -683,16 +672,11 @@ next_char:
|
|||
sched_setscheduler(0, SCHED_OTHER, &schedp);
|
||||
}
|
||||
|
||||
/* cleanup call control */
|
||||
if (!use_mncc_sock && !use_mncc_cross)
|
||||
//* cleanup call control */
|
||||
call_exit();
|
||||
|
||||
/* cleanup console */
|
||||
if (!use_osmocc_sock)
|
||||
console_cleanup();
|
||||
|
||||
/* close mncc socket */
|
||||
if (use_mncc_sock)
|
||||
mncc_sock_exit();
|
||||
|
||||
/* close mncc forwarding */
|
||||
if (use_mncc_cross)
|
||||
mncc_cross_exit();
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ int main_mobile_handle_options(int short_option, int argi, char **argv);
|
|||
extern int quit;
|
||||
void sighandler(int sigset);
|
||||
|
||||
void main_mobile(int *quit, int latency, int interval, void (*myhandler)(void), const char *station_id, int station_id_digits);
|
||||
void main_mobile(const char *name, int *quit, int latency, int interval, void (*myhandler)(void), const char *station_id, int station_id_digits);
|
||||
|
||||
void dump_info(void);
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ nmt_LDADD = \
|
|||
$(top_builddir)/src/liboptions/liboptions.a \
|
||||
$(top_builddir)/src/libdebug/libdebug.a \
|
||||
$(top_builddir)/src/libmobile/libmobile.a \
|
||||
$(top_builddir)/src/libosmocc/libosmocc.a \
|
||||
$(top_builddir)/src/libdisplay/libdisplay.a \
|
||||
$(top_builddir)/src/libcompandor/libcompandor.a \
|
||||
$(top_builddir)/src/libgoertzel/libgoertzel.a \
|
||||
|
@ -38,7 +39,6 @@ nmt_LDADD = \
|
|||
$(top_builddir)/src/libfm/libfm.a \
|
||||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libwave/libwave.a \
|
||||
$(top_builddir)/src/libmncc/libmncc.a \
|
||||
$(top_builddir)/src/libsample/libsample.a \
|
||||
$(top_builddir)/src/libg711/libg711.a \
|
||||
-lm
|
||||
|
|
|
@ -407,7 +407,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
nmt_check_channels(nmt_system);
|
||||
|
||||
main_mobile(&quit, latency, interval, myhandler, station_id, 7);
|
||||
main_mobile("nmt", &quit, latency, interval, myhandler, station_id, 7);
|
||||
|
||||
fail:
|
||||
/* fifo */
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
#include <time.h>
|
||||
#include "../libsample/sample.h"
|
||||
#include "../libdebug/debug.h"
|
||||
#include "../libmncc/cause.h"
|
||||
#include "../libmobile/cause.h"
|
||||
#include "../libosmocc/message.h"
|
||||
#include "nmt.h"
|
||||
#include "transaction.h"
|
||||
#include "dsp.h"
|
||||
|
@ -49,10 +50,6 @@
|
|||
|
||||
static int sms_ref = 0;
|
||||
|
||||
/* Call reference for calls from mobile station to network
|
||||
This offset of 0x400000000 is required for MNCC interface. */
|
||||
static int new_callref = 0x40000000;
|
||||
|
||||
/* Timers */
|
||||
#define PAGING_TO 1.0 /* wait for paging response: fictive value */
|
||||
#define RELEASE_TO 2.0 /* how long do we wait for release guard of the phone */
|
||||
|
@ -915,16 +912,8 @@ static void rx_mo_dialing(nmt_t *nmt, frame_t *frame)
|
|||
PDEBUG(DNMT, DEBUG_INFO, "Setup call to SMSC.\n");
|
||||
trans->dms_call = 1;
|
||||
} else {
|
||||
int callref = ++new_callref;
|
||||
int rc;
|
||||
PDEBUG(DNMT, DEBUG_INFO, "Setup call to network.\n");
|
||||
rc = call_up_setup(callref, &trans->subscriber.country, nmt->dialing);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DNMT, DEBUG_NOTICE, "Call rejected (cause %d), releasing.\n", rc);
|
||||
nmt_release(nmt);
|
||||
return;
|
||||
}
|
||||
trans->callref = callref;
|
||||
trans->callref = call_up_setup(&trans->subscriber.country, nmt->dialing, OSMO_CC_NETWORK_NMT_NONE, "");
|
||||
}
|
||||
timer_stop(&nmt->timer);
|
||||
nmt_new_state(nmt, STATE_MO_COMPLETE);
|
||||
|
|
|
@ -15,6 +15,7 @@ radiocom2000_LDADD = \
|
|||
$(top_builddir)/src/liboptions/liboptions.a \
|
||||
$(top_builddir)/src/libdebug/libdebug.a \
|
||||
$(top_builddir)/src/libmobile/libmobile.a \
|
||||
$(top_builddir)/src/libosmocc/libosmocc.a \
|
||||
$(top_builddir)/src/libdisplay/libdisplay.a \
|
||||
$(top_builddir)/src/libcompandor/libcompandor.a \
|
||||
$(top_builddir)/src/libjitter/libjitter.a \
|
||||
|
@ -26,7 +27,6 @@ radiocom2000_LDADD = \
|
|||
$(top_builddir)/src/libfm/libfm.a \
|
||||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libwave/libwave.a \
|
||||
$(top_builddir)/src/libmncc/libmncc.a \
|
||||
$(top_builddir)/src/libsample/libsample.a \
|
||||
$(top_builddir)/src/libg711/libg711.a \
|
||||
-lm
|
||||
|
|
|
@ -363,7 +363,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
r2000_check_channels();
|
||||
|
||||
main_mobile(&quit, latency, interval, NULL, station_id, 9);
|
||||
main_mobile("radiocom2000", &quit, latency, interval, NULL, station_id, 9);
|
||||
|
||||
fail:
|
||||
/* destroy transceiver instance */
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
#include <time.h>
|
||||
#include "../libsample/sample.h"
|
||||
#include "../libdebug/debug.h"
|
||||
#include "../libmncc/cause.h"
|
||||
#include "../libmobile/cause.h"
|
||||
#include "../libosmocc/message.h"
|
||||
#include "r2000.h"
|
||||
//#include "transaction.h"
|
||||
#include "frame.h"
|
||||
|
@ -45,10 +46,6 @@
|
|||
#define SUPER_TIME2 20.0 /* time to release after loosing supervisory signal */
|
||||
#define RELEASE_TIME 2.0 /* time to wait for release response */
|
||||
|
||||
/* Call reference for calls from station mobile to network
|
||||
This offset of 0x400000000 is required for MNCC interface. */
|
||||
static int new_callref = 0x40000000;
|
||||
|
||||
/* definition of bands and channels */
|
||||
#define CHANNEL_SPACING 0.0125
|
||||
|
||||
|
@ -900,20 +897,9 @@ static void tx_alert(r2000_t *r2000, frame_t *frame)
|
|||
|
||||
static int setup_call(r2000_t *r2000)
|
||||
{
|
||||
int callref = ++new_callref;
|
||||
int rc;
|
||||
|
||||
/* make call toward network */
|
||||
PDEBUG(DR2000, DEBUG_INFO, "Setup call to network.\n");
|
||||
/* must set callref, since MNCC may directly call call_down_answer to trigger recall, nested in call_up_setup */
|
||||
r2000->callref = callref;
|
||||
rc = call_up_setup(callref, subscriber2string(&r2000->subscriber), r2000->subscriber.dialing);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DR2000, DEBUG_NOTICE, "Call rejected (cause %d), releasing.\n", -rc);
|
||||
r2000->callref = 0;
|
||||
r2000_release(r2000);
|
||||
return rc;
|
||||
}
|
||||
r2000->callref = call_up_setup(subscriber2string(&r2000->subscriber), r2000->subscriber.dialing, OSMO_CC_NETWORK_R2000_NONE, "");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ tacs_LDADD = \
|
|||
$(top_builddir)/src/liboptions/liboptions.a \
|
||||
$(top_builddir)/src/libdebug/libdebug.a \
|
||||
$(top_builddir)/src/libmobile/libmobile.a \
|
||||
$(top_builddir)/src/libosmocc/libosmocc.a \
|
||||
$(top_builddir)/src/libdisplay/libdisplay.a \
|
||||
$(top_builddir)/src/libcompandor/libcompandor.a \
|
||||
$(top_builddir)/src/libgoertzel/libgoertzel.a \
|
||||
|
@ -26,7 +27,6 @@ tacs_LDADD = \
|
|||
$(top_builddir)/src/libfm/libfm.a \
|
||||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libwave/libwave.a \
|
||||
$(top_builddir)/src/libmncc/libmncc.a \
|
||||
$(top_builddir)/src/libsample/libsample.a \
|
||||
$(top_builddir)/src/libg711/libg711.a \
|
||||
-lm
|
||||
|
|
|
@ -11,5 +11,5 @@ int main(int argc, char *argv[])
|
|||
init_tones();
|
||||
init_outoforder();
|
||||
|
||||
return main_amps_tacs(argc, argv);
|
||||
return main_amps_tacs("tacs", argc, argv);
|
||||
}
|
||||
|
|
|
@ -58,6 +58,7 @@ test_dms_LDADD = \
|
|||
$(COMMON_LA) \
|
||||
$(top_builddir)/src/libdebug/libdebug.a \
|
||||
$(top_builddir)/src/libmobile/libmobile.a \
|
||||
$(top_builddir)/src/libosmocc/libosmocc.a \
|
||||
$(top_builddir)/src/liboptions/liboptions.a \
|
||||
$(top_builddir)/src/libdisplay/libdisplay.a \
|
||||
$(top_builddir)/src/nmt/libdmssms.a \
|
||||
|
@ -67,7 +68,6 @@ test_dms_LDADD = \
|
|||
$(top_builddir)/src/libemphasis/libemphasis.a \
|
||||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libwave/libwave.a \
|
||||
$(top_builddir)/src/libmncc/libmncc.a \
|
||||
$(top_builddir)/src/libsample/libsample.a \
|
||||
$(top_builddir)/src/libg711/libg711.a \
|
||||
-lm
|
||||
|
@ -94,6 +94,7 @@ test_sms_LDADD = \
|
|||
$(COMMON_LA) \
|
||||
$(top_builddir)/src/libdebug/libdebug.a \
|
||||
$(top_builddir)/src/libmobile/libmobile.a \
|
||||
$(top_builddir)/src/libosmocc/libosmocc.a \
|
||||
$(top_builddir)/src/liboptions/liboptions.a \
|
||||
$(top_builddir)/src/libdisplay/libdisplay.a \
|
||||
$(top_builddir)/src/nmt/libdmssms.a \
|
||||
|
@ -103,7 +104,6 @@ test_sms_LDADD = \
|
|||
$(top_builddir)/src/libemphasis/libemphasis.a \
|
||||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libwave/libwave.a \
|
||||
$(top_builddir)/src/libmncc/libmncc.a \
|
||||
$(top_builddir)/src/libsample/libsample.a \
|
||||
$(top_builddir)/src/libg711/libg711.a \
|
||||
-lm
|
||||
|
|
|
@ -13,6 +13,7 @@ zeitansage_LDADD = \
|
|||
$(top_builddir)/src/liboptions/liboptions.a \
|
||||
$(top_builddir)/src/libdebug/libdebug.a \
|
||||
$(top_builddir)/src/libmobile/libmobile.a \
|
||||
$(top_builddir)/src/libosmocc/libosmocc.a \
|
||||
$(top_builddir)/src/libdisplay/libdisplay.a \
|
||||
$(top_builddir)/src/libjitter/libjitter.a \
|
||||
$(top_builddir)/src/libtimer/libtimer.a \
|
||||
|
@ -22,7 +23,6 @@ zeitansage_LDADD = \
|
|||
$(top_builddir)/src/libfm/libfm.a \
|
||||
$(top_builddir)/src/libfilter/libfilter.a \
|
||||
$(top_builddir)/src/libwave/libwave.a \
|
||||
$(top_builddir)/src/libmncc/libmncc.a \
|
||||
$(top_builddir)/src/libsample/libsample.a \
|
||||
$(top_builddir)/src/libg711/libg711.a \
|
||||
$(ALSA_LIBS) \
|
||||
|
|
|
@ -93,7 +93,7 @@ int main(int argc, char *argv[])
|
|||
fm_init(fast_math);
|
||||
zeit_init(audio_level_dBm, alerting);
|
||||
|
||||
main_mobile(&quit, latency, interval, NULL, "1191", 4);
|
||||
main_mobile("zeitansage", &quit, latency, interval, NULL, "1191", 4);
|
||||
|
||||
//fail:
|
||||
/* exits */
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "../libsample/sample.h"
|
||||
#include "../libdebug/debug.h"
|
||||
#include "../libmobile/call.h"
|
||||
#include "../libmncc/cause.h"
|
||||
#include "../libmobile/cause.h"
|
||||
#include "zeitansage.h"
|
||||
|
||||
#define db2level(db) pow(10, (double)(db) / 20.0)
|
||||
|
|
Loading…
Reference in New Issue