C-Netz: Add capability of non-standard OgK channel(s)
This commit is contained in:
parent
4758f16324
commit
4930da8e0c
|
@ -159,6 +159,12 @@
|
||||||
|
|
||||||
#define CUT_OFF_EMPHASIS_CNETZ 796.0 /* 200 uS time constant */
|
#define CUT_OFF_EMPHASIS_CNETZ 796.0 /* 200 uS time constant */
|
||||||
|
|
||||||
|
/* OgK list of alternative channels, NOT including 131 */
|
||||||
|
cnetz_t *ogk_list[16];
|
||||||
|
int ogk_list_count = 0;
|
||||||
|
int ogk_list_index = 0;
|
||||||
|
|
||||||
|
|
||||||
/* Convert channel number to frequency number of base station.
|
/* Convert channel number to frequency number of base station.
|
||||||
Set 'unterband' to 1 to get frequency of mobile station. */
|
Set 'unterband' to 1 to get frequency of mobile station. */
|
||||||
double cnetz_kanal2freq(int kanal, int unterband)
|
double cnetz_kanal2freq(int kanal, int unterband)
|
||||||
|
@ -286,42 +292,38 @@ int cnetz_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create transceiver instance and link to a list. */
|
/* Create transceiver instance and link to a list. */
|
||||||
int cnetz_create(const char *kanal, enum cnetz_chan_type chan_type, const char *device, int use_sdr, enum demod_type demod, int samplerate, double rx_gain, double tx_gain, int challenge_valid, uint64_t challenge, int response_valid, uint64_t response, int warteschlange, int metering, double speech_deviation, int ms_power, int measure_speed, double clock_speed[2], int polarity, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, const char *read_tx_wave, int loopback)
|
int cnetz_create(const char *kanal_name, enum cnetz_chan_type chan_type, const char *device, int use_sdr, enum demod_type demod, int samplerate, double rx_gain, double tx_gain, int challenge_valid, uint64_t challenge, int response_valid, uint64_t response, int warteschlange, int metering, double speech_deviation, int ms_power, int measure_speed, double clock_speed[2], int polarity, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, const char *read_tx_wave, int loopback)
|
||||||
{
|
{
|
||||||
sender_t *sender;
|
sender_t *sender;
|
||||||
cnetz_t *cnetz;
|
cnetz_t *cnetz;
|
||||||
|
int kanal;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
if ((atoi(kanal) & 1) && (atoi(kanal) < 3 || atoi(kanal) > 1147)) {
|
kanal = atoi(kanal_name);
|
||||||
PDEBUG(DCNETZ, DEBUG_ERROR, "Channel ('Kanal') number %s invalid. For odd channel numbers, use channel 3 ... 1147.\n", kanal);
|
if ((kanal & 1) && (kanal < 3 || kanal > 1147)) {
|
||||||
|
PDEBUG(DCNETZ, DEBUG_ERROR, "Channel ('Kanal') number %d invalid. For odd channel numbers, use channel 3 ... 1147.\n", kanal);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if ((atoi(kanal) & 1) && atoi(kanal) > 947) {
|
if ((kanal & 1) && kanal > 947) {
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "You defined an extended frequency channel %s, only newer phones support this!\n", kanal);
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "You defined an extended frequency channel %d, only newer phones support this!\n", kanal);
|
||||||
}
|
}
|
||||||
if (!(atoi(kanal) & 1) && (atoi(kanal) < 4 || atoi(kanal) > 918)) {
|
if (!(kanal & 1) && (kanal < 4 || kanal > 918)) {
|
||||||
PDEBUG(DCNETZ, DEBUG_ERROR, "Channel ('Kanal') number %s invalid. For even channel numbers, use channel 4 ... 918.\n", kanal);
|
PDEBUG(DCNETZ, DEBUG_ERROR, "Channel ('Kanal') number %d invalid. For even channel numbers, use channel 4 ... 918.\n", kanal);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (!(atoi(kanal) & 1) && atoi(kanal) > 758) {
|
if (!(kanal & 1) && kanal > 758) {
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "You defined an extended frequency %s, only newer phones support this!\n", kanal);
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "You defined an extended frequency channel %d, only newer phones support this!\n", kanal);
|
||||||
}
|
|
||||||
|
|
||||||
/* OgK must be on channel 131 */
|
|
||||||
if ((chan_type == CHAN_TYPE_OGK || chan_type == CHAN_TYPE_OGK_SPK) && atoi(kanal) != CNETZ_OGK_KANAL) {
|
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "You must use channel %d for calling channel ('Orga-Kanal') or for combined calling + traffic channel!\n", CNETZ_OGK_KANAL);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SpK must be on channel other than 131 */
|
/* SpK must be on channel other than 131 */
|
||||||
if (chan_type == CHAN_TYPE_SPK && atoi(kanal) == CNETZ_OGK_KANAL) {
|
if (chan_type == CHAN_TYPE_SPK && kanal == CNETZ_STD_OGK_KANAL) {
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "You must not use channel %d for traffic channel!\n", CNETZ_OGK_KANAL);
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "You must not use channel %d for traffic channel!\n", CNETZ_STD_OGK_KANAL);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* warn if we combine SpK and OgK, this is not supported by standard */
|
/* warn if we combine SpK and OgK, this is not supported by standard */
|
||||||
if (chan_type == CHAN_TYPE_OGK_SPK) {
|
if (chan_type == CHAN_TYPE_OGK_SPK) {
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "You selected channel %d ('Orga-Kanal') for combined calling + traffic channel. Some phones will reject this.\n", CNETZ_OGK_KANAL);
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "You selected channel %d ('Orga-Kanal') for combined control + traffic channel. Some phones will reject this.\n", kanal);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (sender = sender_head; sender; sender = sender->next) {
|
for (sender = sender_head; sender; sender = sender->next) {
|
||||||
|
@ -338,11 +340,21 @@ int cnetz_create(const char *kanal, enum cnetz_chan_type chan_type, const char *
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
PDEBUG(DCNETZ, DEBUG_DEBUG, "Creating 'C-Netz' instance for 'Kanal' = %s (sample rate %d).\n", kanal, samplerate);
|
PDEBUG(DCNETZ, DEBUG_DEBUG, "Creating 'C-Netz' instance for 'Kanal' = %d (sample rate %d).\n", kanal, samplerate);
|
||||||
|
|
||||||
|
cnetz->kanal = kanal;
|
||||||
|
if ((chan_type == CHAN_TYPE_OGK || chan_type == CHAN_TYPE_OGK_SPK) && kanal != CNETZ_STD_OGK_KANAL) {
|
||||||
|
if (ogk_list_count == 16) {
|
||||||
|
PDEBUG(DCNETZ, DEBUG_ERROR, "No more than 16 non-standard OGK are allowed!\n");
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
ogk_list[ogk_list_count++] = cnetz;
|
||||||
|
}
|
||||||
|
|
||||||
/* init general part of transceiver */
|
/* init general part of transceiver */
|
||||||
/* do not enable emphasis, since it is done by cnetz code, not by common sender code */
|
/* do not enable emphasis, since it is done by cnetz code, not by common sender code */
|
||||||
rc = sender_create(&cnetz->sender, kanal, cnetz_kanal2freq(atoi(kanal), 0), cnetz_kanal2freq(atoi(kanal), 1), device, use_sdr, samplerate, rx_gain, tx_gain, 0, 0, write_rx_wave, write_tx_wave, read_rx_wave, read_tx_wave, loopback, PAGING_SIGNAL_NONE);
|
rc = sender_create(&cnetz->sender, kanal_name, cnetz_kanal2freq(kanal, 0), cnetz_kanal2freq(kanal, 1), device, use_sdr, samplerate, rx_gain, tx_gain, 0, 0, write_rx_wave, write_tx_wave, read_rx_wave, read_tx_wave, loopback, PAGING_SIGNAL_NONE);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to init transceiver process!\n");
|
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to init transceiver process!\n");
|
||||||
goto error;
|
goto error;
|
||||||
|
@ -403,13 +415,13 @@ int cnetz_create(const char *kanal, enum cnetz_chan_type chan_type, const char *
|
||||||
cnetz_go_idle(cnetz);
|
cnetz_go_idle(cnetz);
|
||||||
|
|
||||||
#ifdef DEBUG_SPK
|
#ifdef DEBUG_SPK
|
||||||
transaction_t *trans = create_transaction(cnetz, TRANS_DS, 2, 2, 22002, -1, -1);
|
transaction_t *trans = create_transaction(cnetz, TRANS_DS, 2, 2, 22002, -1, -1, NAN);
|
||||||
trans->mo_call = 1;
|
trans->mo_call = 1;
|
||||||
cnetz_set_sched_dsp_mode(cnetz, DSP_MODE_SPK_K, (cnetz->sched_ts + 2) & 31);
|
cnetz_set_sched_dsp_mode(cnetz, DSP_MODE_SPK_K, (cnetz->sched_ts + 2) & 31);
|
||||||
#else
|
#else
|
||||||
/* create transaction for speech channel loopback */
|
/* create transaction for speech channel loopback */
|
||||||
if (loopback && chan_type == CHAN_TYPE_SPK) {
|
if (loopback && chan_type == CHAN_TYPE_SPK) {
|
||||||
transaction_t *trans = create_transaction(cnetz, TRANS_VHQ_K, 2, 2, 22002, -1, -1);
|
transaction_t *trans = create_transaction(cnetz, TRANS_VHQ_K, 2, 2, 22002, -1, -1, NAN);
|
||||||
trans->mo_call = 1;
|
trans->mo_call = 1;
|
||||||
cnetz_set_dsp_mode(cnetz, DSP_MODE_SPK_K);
|
cnetz_set_dsp_mode(cnetz, DSP_MODE_SPK_K);
|
||||||
cnetz_set_sched_dsp_mode(cnetz, DSP_MODE_SPK_K, (cnetz->sched_ts + 1) & 31);
|
cnetz_set_sched_dsp_mode(cnetz, DSP_MODE_SPK_K, (cnetz->sched_ts + 1) & 31);
|
||||||
|
@ -419,20 +431,20 @@ int cnetz_create(const char *kanal, enum cnetz_chan_type chan_type, const char *
|
||||||
#if 0
|
#if 0
|
||||||
/* debug flushing transactions */
|
/* debug flushing transactions */
|
||||||
transaction_t *trans1, *trans2;
|
transaction_t *trans1, *trans2;
|
||||||
trans1 = create_transaction(cnetz, 99, 6, 2, 15784, -1, -1);
|
trans1 = create_transaction(cnetz, 99, 6, 2, 15784, -1, -1, NAN);
|
||||||
destroy_transaction(trans1);
|
destroy_transaction(trans1);
|
||||||
trans1 = create_transaction(cnetz, 99, 6, 2, 15784, -1, -1);
|
trans1 = create_transaction(cnetz, 99, 6, 2, 15784, -1, -1, NAN);
|
||||||
destroy_transaction(trans1);
|
destroy_transaction(trans1);
|
||||||
trans1 = create_transaction(cnetz, 99, 6, 2, 15784, -1, -1);
|
trans1 = create_transaction(cnetz, 99, 6, 2, 15784, -1, -1, NAN);
|
||||||
trans2 = create_transaction(cnetz, 99, 2, 2, 22002, -1, -1);
|
trans2 = create_transaction(cnetz, 99, 2, 2, 22002, -1, -1, NAN);
|
||||||
unlink_transaction(trans1);
|
unlink_transaction(trans1);
|
||||||
link_transaction(trans1, cnetz);
|
link_transaction(trans1, cnetz);
|
||||||
cnetz_flush_other_transactions(cnetz, trans1);
|
cnetz_flush_other_transactions(cnetz, trans1);
|
||||||
trans2 = create_transaction(cnetz, 99, 2, 2, 22002, -1, -1);
|
trans2 = create_transaction(cnetz, 99, 2, 2, 22002, -1, -1, NAN);
|
||||||
cnetz_flush_other_transactions(cnetz, trans2);
|
cnetz_flush_other_transactions(cnetz, trans2);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Created 'Kanal' #%s of type '%s' = %s\n", kanal, chan_type_short_name(chan_type), chan_type_long_name(chan_type));
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "Created 'Kanal' #%d of type '%s' = %s\n", kanal, chan_type_short_name(chan_type), chan_type_long_name(chan_type));
|
||||||
const char *name, *station;
|
const char *name, *station;
|
||||||
name = get_station_name(si.fuz_nat, si.fuz_fuvst, si.fuz_rest, &station);
|
name = get_station_name(si.fuz_nat, si.fuz_fuvst, si.fuz_rest, &station);
|
||||||
PDEBUG(DNMT, DEBUG_NOTICE, " -> Using cell ID: Nat=%d FuVst=%d Rest=%d Name='%s' (%s)\n", si.fuz_nat, si.fuz_fuvst, si.fuz_rest, name, station);
|
PDEBUG(DNMT, DEBUG_NOTICE, " -> Using cell ID: Nat=%d FuVst=%d Rest=%d Name='%s' (%s)\n", si.fuz_nat, si.fuz_fuvst, si.fuz_rest, name, station);
|
||||||
|
@ -473,9 +485,9 @@ static cnetz_t *search_free_spk(int extended)
|
||||||
cnetz = (cnetz_t *) sender;
|
cnetz = (cnetz_t *) sender;
|
||||||
/* ignore extended frequency, if not supported */
|
/* ignore extended frequency, if not supported */
|
||||||
if (!extended) {
|
if (!extended) {
|
||||||
if ((atoi(sender->kanal) & 1) && atoi(sender->kanal) > 947)
|
if ((cnetz->kanal & 1) && cnetz->kanal > 947)
|
||||||
continue;
|
continue;
|
||||||
if (!(atoi(sender->kanal) & 1) && atoi(sender->kanal) > 758)
|
if (!(cnetz->kanal & 1) && cnetz->kanal > 758)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* ignore busy channel */
|
/* ignore busy channel */
|
||||||
|
@ -492,7 +504,7 @@ static cnetz_t *search_free_spk(int extended)
|
||||||
return ogk_spk;
|
return ogk_spk;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cnetz_t *search_ogk(void)
|
static cnetz_t *search_ogk(int kanal)
|
||||||
{
|
{
|
||||||
sender_t *sender;
|
sender_t *sender;
|
||||||
cnetz_t *cnetz;
|
cnetz_t *cnetz;
|
||||||
|
@ -502,6 +514,8 @@ static cnetz_t *search_ogk(void)
|
||||||
/* ignore busy channel */
|
/* ignore busy channel */
|
||||||
if (cnetz->state != CNETZ_IDLE)
|
if (cnetz->state != CNETZ_IDLE)
|
||||||
continue;
|
continue;
|
||||||
|
if (cnetz->kanal != kanal)
|
||||||
|
continue;
|
||||||
if (cnetz->chan_type == CHAN_TYPE_OGK)
|
if (cnetz->chan_type == CHAN_TYPE_OGK)
|
||||||
return cnetz;
|
return cnetz;
|
||||||
if (cnetz->chan_type == CHAN_TYPE_OGK_SPK)
|
if (cnetz->chan_type == CHAN_TYPE_OGK_SPK)
|
||||||
|
@ -514,7 +528,6 @@ static cnetz_t *search_ogk(void)
|
||||||
/* Abort connection, if any and send idle broadcast */
|
/* Abort connection, if any and send idle broadcast */
|
||||||
void cnetz_go_idle(cnetz_t *cnetz)
|
void cnetz_go_idle(cnetz_t *cnetz)
|
||||||
{
|
{
|
||||||
cnetz_t *ogk;
|
|
||||||
transaction_t *trans;
|
transaction_t *trans;
|
||||||
|
|
||||||
if (cnetz->state == CNETZ_IDLE)
|
if (cnetz->state == CNETZ_IDLE)
|
||||||
|
@ -533,18 +546,17 @@ void cnetz_go_idle(cnetz_t *cnetz)
|
||||||
/* set scheduler to OgK or turn off SpK */
|
/* set scheduler to OgK or turn off SpK */
|
||||||
if (cnetz->dsp_mode == DSP_MODE_SPK_K || cnetz->dsp_mode == DSP_MODE_SPK_V) {
|
if (cnetz->dsp_mode == DSP_MODE_SPK_K || cnetz->dsp_mode == DSP_MODE_SPK_V) {
|
||||||
/* switch next frame after distributed signaling boundary (multiple of 8 slots) */
|
/* switch next frame after distributed signaling boundary (multiple of 8 slots) */
|
||||||
cnetz_set_sched_dsp_mode(cnetz, (atoi(cnetz->sender.kanal) == CNETZ_OGK_KANAL) ? DSP_MODE_OGK : DSP_MODE_OFF, (cnetz->sched_ts + 8) & 24);
|
cnetz_set_sched_dsp_mode(cnetz, (cnetz->chan_type == CHAN_TYPE_OGK || cnetz->chan_type == CHAN_TYPE_OGK_SPK) ? DSP_MODE_OGK : DSP_MODE_OFF, (cnetz->sched_ts + 8) & 24);
|
||||||
} else {
|
} else {
|
||||||
/* switch next frame */
|
/* switch next frame */
|
||||||
cnetz_set_sched_dsp_mode(cnetz, (atoi(cnetz->sender.kanal) == CNETZ_OGK_KANAL) ? DSP_MODE_OGK : DSP_MODE_OFF, (cnetz->sched_ts + 1) & 31);
|
cnetz_set_sched_dsp_mode(cnetz, (cnetz->chan_type == CHAN_TYPE_OGK || cnetz->chan_type == CHAN_TYPE_OGK_SPK) ? DSP_MODE_OGK : DSP_MODE_OFF, (cnetz->sched_ts + 1) & 31);
|
||||||
cnetz_set_dsp_mode(cnetz, (atoi(cnetz->sender.kanal) == CNETZ_OGK_KANAL) ? DSP_MODE_OGK : DSP_MODE_OFF);
|
cnetz_set_dsp_mode(cnetz, (cnetz->chan_type == CHAN_TYPE_OGK || cnetz->chan_type == CHAN_TYPE_OGK_SPK) ? DSP_MODE_OGK : DSP_MODE_OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for first phone in queue and trigger completion of call (becoming idle means that SpK is now available) */
|
/* check for first phone in queue and trigger completion of call (becoming idle means that SpK is now available) */
|
||||||
ogk = search_ogk();
|
trans = search_transaction_queue();
|
||||||
trans = search_transaction(ogk, TRANS_MT_QUEUE | TRANS_MO_QUEUE);
|
|
||||||
if (trans) {
|
if (trans) {
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Now channel available for queued subscriber '%s'.\n", transaction2rufnummer(trans));
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "Now channel is available for queued subscriber '%s'.\n", transaction2rufnummer(trans));
|
||||||
trans_new_state(trans, (trans->state == TRANS_MT_QUEUE) ? TRANS_MT_DELAY : TRANS_MO_DELAY);
|
trans_new_state(trans, (trans->state == TRANS_MT_QUEUE) ? TRANS_MT_DELAY : TRANS_MO_DELAY);
|
||||||
timer_stop(&trans->timer);
|
timer_stop(&trans->timer);
|
||||||
timer_start(&trans->timer, 2.0);
|
timer_start(&trans->timer, 2.0);
|
||||||
|
@ -585,14 +597,14 @@ void call_down_clock(void) {}
|
||||||
|
|
||||||
int call_down_setup(int callref, const char __attribute__((unused)) *caller_id, enum number_type __attribute__((unused)) caller_type, const char *dialing)
|
int call_down_setup(int callref, const char __attribute__((unused)) *caller_id, enum number_type __attribute__((unused)) caller_type, const char *dialing)
|
||||||
{
|
{
|
||||||
sender_t *sender;
|
cnetz_t *ogk, *spk;
|
||||||
cnetz_t *cnetz, *spk;
|
|
||||||
int rc;
|
int rc;
|
||||||
int extended;
|
int extended;
|
||||||
transaction_t *trans;
|
transaction_t *trans;
|
||||||
uint8_t futln_nat;
|
uint8_t futln_nat;
|
||||||
uint8_t futln_fuvst;
|
uint8_t futln_fuvst;
|
||||||
int futln_rest; /* use int for checking size > 65535 */
|
int futln_rest; /* use int for checking size > 65535 */
|
||||||
|
int ogk_kanal;
|
||||||
|
|
||||||
/* 1. split number into elements */
|
/* 1. split number into elements */
|
||||||
futln_nat = dialing[0] - '0';
|
futln_nat = dialing[0] - '0';
|
||||||
|
@ -605,28 +617,22 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 2. check if the subscriber is attached */
|
/* 2. check if the subscriber is attached */
|
||||||
rc = find_db(futln_nat, futln_fuvst, futln_rest, NULL, &extended);
|
rc = find_db(futln_nat, futln_fuvst, futln_rest, &ogk_kanal, NULL, &extended);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call to not attached subscriber, rejecting!\n");
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call to not attached subscriber, rejecting!\n");
|
||||||
return -CAUSE_OUTOFORDER;
|
return -CAUSE_OUTOFORDER;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 3. check if given number is already in a call, return BUSY */
|
/* 3. check if given number is already in a call, return BUSY */
|
||||||
for (sender = sender_head; sender; sender = sender->next) {
|
trans = search_transaction_number_global(futln_nat, futln_fuvst, futln_rest);
|
||||||
cnetz = (cnetz_t *) sender;
|
if (trans) {
|
||||||
/* search transaction for this number */
|
|
||||||
trans = search_transaction_number(cnetz, futln_nat, futln_fuvst, futln_rest);
|
|
||||||
if (trans)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (sender) {
|
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call to busy number, rejecting!\n");
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call to busy number, rejecting!\n");
|
||||||
return -CAUSE_BUSY;
|
return -CAUSE_BUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 4. check if we have no OgK, return NOCHANNEL */
|
/* 4. check if we have no OgK, return NOCHANNEL */
|
||||||
cnetz = search_ogk();
|
ogk = search_ogk(ogk_kanal);
|
||||||
if (!cnetz) {
|
if (!ogk) {
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call, but OgK is currently busy, rejecting!\n");
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call, but OgK is currently busy, rejecting!\n");
|
||||||
return -CAUSE_NOCHANNEL;
|
return -CAUSE_NOCHANNEL;
|
||||||
}
|
}
|
||||||
|
@ -634,17 +640,17 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id,
|
||||||
/* 5. check if all senders are busy, return NOCHANNEL */
|
/* 5. check if all senders are busy, return NOCHANNEL */
|
||||||
spk = search_free_spk(extended);
|
spk = search_free_spk(extended);
|
||||||
if (!spk) {
|
if (!spk) {
|
||||||
if (!cnetz->warteschlange) {
|
if (!ogk->warteschlange) {
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call, but no free channel, rejecting!\n");
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call, but no free channel, rejecting!\n");
|
||||||
return -CAUSE_NOCHANNEL;
|
return -CAUSE_NOCHANNEL;
|
||||||
} else
|
} else
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call, but no free channel, queuing call!\n");
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call, but no free channel, queuing call!\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Call to mobile station, paging station id '%s'\n", dialing);
|
PDEBUG(DCNETZ, DEBUG_INFO, "Call to mobile station, paging station id '%s'\n", dialing);
|
||||||
|
|
||||||
/* 6. trying to page mobile station */
|
/* 6. trying to page mobile station */
|
||||||
trans = create_transaction(cnetz, (spk) ? TRANS_VAK : TRANS_WSK, futln_nat, futln_fuvst, futln_rest, -1, -1);
|
trans = create_transaction(ogk, (spk) ? TRANS_VAK : TRANS_WSK, futln_nat, futln_fuvst, futln_rest, -1, -1, NAN);
|
||||||
if (!trans) {
|
if (!trans) {
|
||||||
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
|
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
|
||||||
return -CAUSE_TEMPFAIL;
|
return -CAUSE_TEMPFAIL;
|
||||||
|
@ -750,17 +756,17 @@ void call_down_release(int callref, int cause)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int cnetz_meldeaufruf(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest)
|
int cnetz_meldeaufruf(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int ogk_kanal)
|
||||||
{
|
{
|
||||||
cnetz_t *cnetz;
|
cnetz_t *cnetz;
|
||||||
transaction_t *trans;
|
transaction_t *trans;
|
||||||
|
|
||||||
cnetz = search_ogk();
|
cnetz = search_ogk(ogk_kanal);
|
||||||
if (!cnetz) {
|
if (!cnetz) {
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "'Meldeaufruf', but OgK is currently busy!\n");
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "'Meldeaufruf', but OgK is currently busy!\n");
|
||||||
return -CAUSE_NOCHANNEL;
|
return -CAUSE_NOCHANNEL;
|
||||||
}
|
}
|
||||||
trans = create_transaction(cnetz, TRANS_MA, futln_nat, futln_fuvst, futln_rest, -1, -1);
|
trans = create_transaction(cnetz, TRANS_MA, futln_nat, futln_fuvst, futln_rest, -1, -1, NAN);
|
||||||
if (!trans) {
|
if (!trans) {
|
||||||
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
|
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
|
||||||
return -CAUSE_TEMPFAIL;
|
return -CAUSE_TEMPFAIL;
|
||||||
|
@ -992,7 +998,7 @@ const telegramm_t *cnetz_transmit_telegramm_rufblock(cnetz_t *cnetz)
|
||||||
telegramm.grenzwert_fuer_umschalten = si.grenz_umschalten;
|
telegramm.grenzwert_fuer_umschalten = si.grenz_umschalten;
|
||||||
telegramm.grenze_fuer_ausloesen = si.grenz_ausloesen;
|
telegramm.grenze_fuer_ausloesen = si.grenz_ausloesen;
|
||||||
|
|
||||||
trans = search_transaction(cnetz, TRANS_EM | TRANS_UM | TRANS_WBN | TRANS_WBP | TRANS_VAG | TRANS_VAK | TRANS_ATQ | TRANS_VA | TRANS_WSK);
|
trans = search_transaction(cnetz, TRANS_EM | TRANS_UM | TRANS_WBN | TRANS_WBP | TRANS_VAG | TRANS_VAK | TRANS_ATQ | TRANS_ATQ_IDLE | TRANS_VA | TRANS_WSK);
|
||||||
if (trans) {
|
if (trans) {
|
||||||
telegramm.futln_nationalitaet = trans->futln_nat;
|
telegramm.futln_nationalitaet = trans->futln_nat;
|
||||||
telegramm.futln_heimat_fuvst_nr = trans->futln_fuvst;
|
telegramm.futln_heimat_fuvst_nr = trans->futln_fuvst;
|
||||||
|
@ -1057,14 +1063,14 @@ vak:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (spk == cnetz) {
|
if (spk == cnetz) {
|
||||||
PDEBUG(DCNETZ, DEBUG_INFO, "Staying on combined calling + traffic channel %s\n", spk->sender.kanal);
|
PDEBUG(DCNETZ, DEBUG_INFO, "Staying on combined control + traffic channel %s\n", spk->sender.kanal);
|
||||||
} else {
|
} else {
|
||||||
PDEBUG(DCNETZ, DEBUG_INFO, "Assigning phone to traffic channel %s\n", spk->sender.kanal);
|
PDEBUG(DCNETZ, DEBUG_INFO, "Assigning phone to traffic channel %s\n", spk->sender.kanal);
|
||||||
/* sync RX time to current OgK time */
|
/* sync RX time to current OgK time */
|
||||||
fsk_copy_sync(&spk->fsk_demod, &cnetz->fsk_demod);
|
fsk_copy_sync(&spk->fsk_demod, &cnetz->fsk_demod);
|
||||||
}
|
}
|
||||||
/* set channel */
|
/* set channel */
|
||||||
telegramm.frequenz_nr = atoi(spk->sender.kanal);
|
telegramm.frequenz_nr = spk->kanal;
|
||||||
/* change state to busy */
|
/* change state to busy */
|
||||||
cnetz_new_state(spk, CNETZ_BUSY);
|
cnetz_new_state(spk, CNETZ_BUSY);
|
||||||
/* schedule switching two slots ahead */
|
/* schedule switching two slots ahead */
|
||||||
|
@ -1076,6 +1082,7 @@ vak:
|
||||||
cnetz_flush_other_transactions(spk, trans);
|
cnetz_flush_other_transactions(spk, trans);
|
||||||
break;
|
break;
|
||||||
case TRANS_ATQ:
|
case TRANS_ATQ:
|
||||||
|
case TRANS_ATQ_IDLE:
|
||||||
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending acknowledgment 'Quittung fuer Ausloesen des FuTelG im OgK-Betrieb' to release request.\n");
|
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending acknowledgment 'Quittung fuer Ausloesen des FuTelG im OgK-Betrieb' to release request.\n");
|
||||||
telegramm.opcode = OPCODE_ATQ_R;
|
telegramm.opcode = OPCODE_ATQ_R;
|
||||||
destroy_transaction(trans);
|
destroy_transaction(trans);
|
||||||
|
@ -1117,7 +1124,13 @@ const telegramm_t *cnetz_transmit_telegramm_meldeblock(cnetz_t *cnetz)
|
||||||
telegramm.ogk_verkehrsanteil = 0; /* must be 0 or phone might not respond to messages in different slot */
|
telegramm.ogk_verkehrsanteil = 0; /* must be 0 or phone might not respond to messages in different slot */
|
||||||
telegramm.teilnehmergruppensperre = si.teilnehmergruppensperre;
|
telegramm.teilnehmergruppensperre = si.teilnehmergruppensperre;
|
||||||
telegramm.anzahl_gesperrter_teilnehmergruppen = si.anzahl_gesperrter_teilnehmergruppen;
|
telegramm.anzahl_gesperrter_teilnehmergruppen = si.anzahl_gesperrter_teilnehmergruppen;
|
||||||
telegramm.ogk_vorschlag = CNETZ_OGK_KANAL;
|
if (ogk_list_count) {
|
||||||
|
/* if we have alternative OGKs, we cycle through the list and indicate their channels */
|
||||||
|
telegramm.ogk_vorschlag = ogk_list[ogk_list_index]->kanal;
|
||||||
|
if (++ogk_list_index == ogk_list_count)
|
||||||
|
ogk_list_index = 0;
|
||||||
|
} else
|
||||||
|
telegramm.ogk_vorschlag = CNETZ_STD_OGK_KANAL;
|
||||||
telegramm.fuz_rest_nr = si.fuz_rest;
|
telegramm.fuz_rest_nr = si.fuz_rest;
|
||||||
|
|
||||||
trans = search_transaction(cnetz, TRANS_VWG | TRANS_MA);
|
trans = search_transaction(cnetz, TRANS_VWG | TRANS_MA);
|
||||||
|
@ -1171,11 +1184,12 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Ignoring Attachment from subscriber '%s', because we are busy becoming SpK.\n", rufnummer);
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "Ignoring Attachment from subscriber '%s', because we are busy becoming SpK.\n", rufnummer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
trans = create_transaction(cnetz, TRANS_EM, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, telegramm->chipkarten_futelg_bit, telegramm->erweitertes_frequenzbandbit);
|
trans = create_transaction(cnetz, TRANS_EM, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, telegramm->chipkarten_futelg_bit, telegramm->erweitertes_frequenzbandbit, cnetz->rf_level_db);
|
||||||
if (!trans) {
|
if (!trans) {
|
||||||
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
|
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
cnetz = trans->cnetz; /* cnetz may change, due to stronger reception on different OgK */
|
||||||
valid_frame = 1;
|
valid_frame = 1;
|
||||||
break;
|
break;
|
||||||
case OPCODE_UM_R:
|
case OPCODE_UM_R:
|
||||||
|
@ -1192,11 +1206,12 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Ignoring Roaming from subscriber '%s', because we are busy becoming SpK.\n", rufnummer);
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "Ignoring Roaming from subscriber '%s', because we are busy becoming SpK.\n", rufnummer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
trans = create_transaction(cnetz, TRANS_UM, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, telegramm->chipkarten_futelg_bit, telegramm->erweitertes_frequenzbandbit);
|
trans = create_transaction(cnetz, TRANS_UM, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, telegramm->chipkarten_futelg_bit, telegramm->erweitertes_frequenzbandbit, cnetz->rf_level_db);
|
||||||
if (!trans) {
|
if (!trans) {
|
||||||
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
|
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
cnetz = trans->cnetz; /* cnetz may change, due to stronger reception on different OgK */
|
||||||
valid_frame = 1;
|
valid_frame = 1;
|
||||||
break;
|
break;
|
||||||
case OPCODE_UWG_R:
|
case OPCODE_UWG_R:
|
||||||
|
@ -1208,29 +1223,33 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo
|
||||||
break;
|
break;
|
||||||
case OPCODE_VWG_R:
|
case OPCODE_VWG_R:
|
||||||
case OPCODE_SRG_R:
|
case OPCODE_SRG_R:
|
||||||
|
case OPCODE_NUG_R:
|
||||||
if (!match_fuz(telegramm))
|
if (!match_fuz(telegramm))
|
||||||
break;
|
break;
|
||||||
rufnummer = telegramm2rufnummer(telegramm);
|
rufnummer = telegramm2rufnummer(telegramm);
|
||||||
if (opcode == OPCODE_VWG_R)
|
if (opcode == OPCODE_VWG_R)
|
||||||
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received outgoing Call 'Verbindungswunsch gehend' message from Subscriber '%s'\n", rufnummer);
|
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received outgoing Call 'Verbindungswunsch gehend' message from Subscriber '%s'\n", rufnummer);
|
||||||
else
|
else if (opcode == OPCODE_SRG_R)
|
||||||
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received outgoing emergency Call 'Sonderruf gehend' message from Subscriber '%s'\n", rufnummer);
|
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received outgoing emergency Call 'Sonderruf gehend' message from Subscriber '%s'\n", rufnummer);
|
||||||
|
else
|
||||||
|
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received outgoing Call 'Verbindungswunsch gehend bei Nachbarschaftsunterstuetzung' message from Subscriber '%s'\n", rufnummer);
|
||||||
if (cnetz->state != CNETZ_IDLE) {
|
if (cnetz->state != CNETZ_IDLE) {
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Ignoring Call from subscriber '%s', because we are busy becoming SpK.\n", rufnummer);
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "Ignoring Call from subscriber '%s', because we are busy becoming SpK.\n", rufnummer);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
trans = create_transaction(cnetz, TRANS_VWG, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, -1, telegramm->erweitertes_frequenzbandbit);
|
trans = create_transaction(cnetz, TRANS_VWG, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, -1, telegramm->erweitertes_frequenzbandbit, cnetz->rf_level_db);
|
||||||
if (!trans) {
|
if (!trans) {
|
||||||
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
|
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
cnetz = trans->cnetz; /* cnetz may change, due to stronger reception on different OgK */
|
||||||
trans->try = 1;
|
trans->try = 1;
|
||||||
valid_frame = 1;
|
valid_frame = 1;
|
||||||
break;
|
break;
|
||||||
case OPCODE_WUE_M:
|
case OPCODE_WUE_M:
|
||||||
trans = search_transaction(cnetz, TRANS_WAF | TRANS_WBP | TRANS_VAG | TRANS_MO_QUEUE);
|
trans = search_transaction(cnetz, TRANS_WAF | TRANS_WBP | TRANS_VAG | TRANS_MO_QUEUE);
|
||||||
if (!trans) {
|
if (!trans) {
|
||||||
PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received dialing digits 'Wahluebertragung' message without transaction, ignoring!\n");
|
PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received dialing digits 'Wahluebertragung' message without transaction (on this OgK), ignoring!\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rufnummer = transaction2rufnummer(trans);
|
rufnummer = transaction2rufnummer(trans);
|
||||||
|
@ -1246,17 +1265,30 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo
|
||||||
break;
|
break;
|
||||||
rufnummer = telegramm2rufnummer(telegramm);
|
rufnummer = telegramm2rufnummer(telegramm);
|
||||||
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received release 'Ausloesen des FuTelG im OgK-Betrieb bei WS' message from Subscriber '%s'\n", rufnummer);
|
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received release 'Ausloesen des FuTelG im OgK-Betrieb bei WS' message from Subscriber '%s'\n", rufnummer);
|
||||||
trans = search_transaction_number(cnetz, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr);
|
trans = search_transaction_number_global(telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr);
|
||||||
if (!trans) {
|
if (!trans) {
|
||||||
|
PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "There is no transaction, so we assume that the phone did not receive previous release.\n");
|
||||||
/* create transaction, in case the phone repeats the release after we have acked it */
|
/* create transaction, in case the phone repeats the release after we have acked it */
|
||||||
trans = create_transaction(cnetz, TRANS_ATQ, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, -1, -1);
|
trans = create_transaction(cnetz, TRANS_ATQ_IDLE, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, -1, -1, cnetz->rf_level_db);
|
||||||
if (!trans) {
|
if (!trans) {
|
||||||
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
|
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
cnetz = trans->cnetz; /* cnetz may change, due to stronger reception on different OgK */
|
||||||
} else {
|
} else {
|
||||||
timer_stop(&trans->timer);
|
if (cnetz == trans->cnetz) {
|
||||||
trans_new_state(trans, TRANS_ATQ);
|
timer_stop(&trans->timer);
|
||||||
|
trans_new_state(trans, TRANS_ATQ);
|
||||||
|
} else
|
||||||
|
if (trans->state == TRANS_ATQ_IDLE) {
|
||||||
|
trans = create_transaction(cnetz, TRANS_ATQ_IDLE, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr, -1, -1, cnetz->rf_level_db);
|
||||||
|
if (!trans) {
|
||||||
|
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cnetz = trans->cnetz; /* cnetz may change, due to stronger reception on different OgK */
|
||||||
|
} else
|
||||||
|
PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received release 'Ausloesen des FuTelG im OgK-Betrieb bei WS' message without transaction (on this OgK), ignoring!\n");
|
||||||
}
|
}
|
||||||
valid_frame = 1;
|
valid_frame = 1;
|
||||||
break;
|
break;
|
||||||
|
@ -1265,7 +1297,7 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo
|
||||||
break;
|
break;
|
||||||
trans = search_transaction_number(cnetz, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr);
|
trans = search_transaction_number(cnetz, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr);
|
||||||
if (!trans) {
|
if (!trans) {
|
||||||
PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received acknowledge 'Meldung Funktelefonteilnehmer' message without transaction, ignoring!\n");
|
PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received acknowledge 'Meldung Funktelefonteilnehmer' message without transaction (on this OgK), ignoring!\n");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
rufnummer = transaction2rufnummer(trans);
|
rufnummer = transaction2rufnummer(trans);
|
||||||
|
@ -1295,7 +1327,9 @@ const telegramm_t *cnetz_transmit_telegramm_spk_k(cnetz_t *cnetz)
|
||||||
{
|
{
|
||||||
static telegramm_t telegramm;
|
static telegramm_t telegramm;
|
||||||
transaction_t *trans = cnetz->trans_list;
|
transaction_t *trans = cnetz->trans_list;
|
||||||
|
int ogk_kanal;
|
||||||
cnetz_t *ogk;
|
cnetz_t *ogk;
|
||||||
|
int rc;
|
||||||
|
|
||||||
if (!trans)
|
if (!trans)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -1311,7 +1345,7 @@ const telegramm_t *cnetz_transmit_telegramm_spk_k(cnetz_t *cnetz)
|
||||||
telegramm.futln_nationalitaet = trans->futln_nat;
|
telegramm.futln_nationalitaet = trans->futln_nat;
|
||||||
telegramm.futln_heimat_fuvst_nr = trans->futln_fuvst;
|
telegramm.futln_heimat_fuvst_nr = trans->futln_fuvst;
|
||||||
telegramm.futln_rest_nr = trans->futln_rest;
|
telegramm.futln_rest_nr = trans->futln_rest;
|
||||||
telegramm.frequenz_nr = atoi(cnetz->sender.kanal);
|
telegramm.frequenz_nr = cnetz->kanal;
|
||||||
telegramm.bedingte_genauigkeit_der_fufst = si.genauigkeit;
|
telegramm.bedingte_genauigkeit_der_fufst = si.genauigkeit;
|
||||||
telegramm.zufallszahl = cnetz->challenge;
|
telegramm.zufallszahl = cnetz->challenge;
|
||||||
|
|
||||||
|
@ -1426,9 +1460,15 @@ no_auth:
|
||||||
/* idle channel */
|
/* idle channel */
|
||||||
cnetz_go_idle(cnetz);
|
cnetz_go_idle(cnetz);
|
||||||
/* alloc ogk again */
|
/* alloc ogk again */
|
||||||
ogk = search_ogk();
|
rc = find_db(trans->futln_nat, trans->futln_fuvst, trans->futln_rest, &ogk_kanal, NULL, NULL);
|
||||||
|
if (rc < 0) {
|
||||||
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "Cannot find subscriber in database anymore, releasing!\n");
|
||||||
|
goto no_ogk;
|
||||||
|
}
|
||||||
|
ogk = search_ogk(ogk_kanal);
|
||||||
if (!ogk) {
|
if (!ogk) {
|
||||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Cannot retry, because currently no OgK available (busy)\n");
|
PDEBUG(DCNETZ, DEBUG_NOTICE, "Cannot retry, because currently no OgK available (busy)\n");
|
||||||
|
no_ogk:
|
||||||
cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH);
|
cnetz_release(trans, CNETZ_CAUSE_FUNKTECHNISCH);
|
||||||
if (trans->callref)
|
if (trans->callref)
|
||||||
call_up_release(trans->callref, CAUSE_NOCHANNEL);
|
call_up_release(trans->callref, CAUSE_NOCHANNEL);
|
||||||
|
@ -1634,7 +1674,7 @@ const telegramm_t *cnetz_transmit_telegramm_spk_v(cnetz_t *cnetz)
|
||||||
telegramm.futln_nationalitaet = trans->futln_nat;
|
telegramm.futln_nationalitaet = trans->futln_nat;
|
||||||
telegramm.futln_heimat_fuvst_nr = trans->futln_fuvst;
|
telegramm.futln_heimat_fuvst_nr = trans->futln_fuvst;
|
||||||
telegramm.futln_rest_nr = trans->futln_rest;
|
telegramm.futln_rest_nr = trans->futln_rest;
|
||||||
telegramm.frequenz_nr = atoi(cnetz->sender.kanal);
|
telegramm.frequenz_nr = cnetz->kanal;
|
||||||
telegramm.entfernung = si.entfernung;
|
telegramm.entfernung = si.entfernung;
|
||||||
telegramm.bedingte_genauigkeit_der_fufst = si.genauigkeit;
|
telegramm.bedingte_genauigkeit_der_fufst = si.genauigkeit;
|
||||||
telegramm.gueltigkeit_des_gebuehrenstandes = 0;
|
telegramm.gueltigkeit_des_gebuehrenstandes = 0;
|
||||||
|
|
|
@ -6,7 +6,7 @@ typedef struct cnetz cnetz_t;
|
||||||
#include "fsk_demod.h"
|
#include "fsk_demod.h"
|
||||||
#include "transaction.h"
|
#include "transaction.h"
|
||||||
|
|
||||||
#define CNETZ_OGK_KANAL 131
|
#define CNETZ_STD_OGK_KANAL 131
|
||||||
|
|
||||||
/* dsp modes of transmission */
|
/* dsp modes of transmission */
|
||||||
enum dsp_mode {
|
enum dsp_mode {
|
||||||
|
@ -66,6 +66,7 @@ struct clock_speed {
|
||||||
/* instance of cnetz sender */
|
/* instance of cnetz sender */
|
||||||
struct cnetz {
|
struct cnetz {
|
||||||
sender_t sender;
|
sender_t sender;
|
||||||
|
int kanal; /* channel number */
|
||||||
enum cnetz_chan_type chan_type; /* channel type */
|
enum cnetz_chan_type chan_type; /* channel type */
|
||||||
scrambler_t scrambler_tx; /* mirror what we transmit to MS */
|
scrambler_t scrambler_tx; /* mirror what we transmit to MS */
|
||||||
scrambler_t scrambler_rx; /* mirror what we receive from MS */
|
scrambler_t scrambler_rx; /* mirror what we receive from MS */
|
||||||
|
@ -99,6 +100,7 @@ struct cnetz {
|
||||||
|
|
||||||
/* dsp states */
|
/* dsp states */
|
||||||
enum dsp_mode dsp_mode; /* current mode: audio, "Telegramm", .... */
|
enum dsp_mode dsp_mode; /* current mode: audio, "Telegramm", .... */
|
||||||
|
double rf_level_db; /* current RF level or nan, if not applicable */
|
||||||
iir_filter_t lp; /* low pass filter to eliminate noise above 5280 Hz */
|
iir_filter_t lp; /* low pass filter to eliminate noise above 5280 Hz */
|
||||||
fsk_fm_demod_t fsk_demod; /* demod process */
|
fsk_fm_demod_t fsk_demod; /* demod process */
|
||||||
double fsk_deviation; /* deviation of FSK signal on sound card */
|
double fsk_deviation; /* deviation of FSK signal on sound card */
|
||||||
|
@ -144,7 +146,7 @@ int cnetz_create(const char *kanal, enum cnetz_chan_type chan_type, const char *
|
||||||
void cnetz_destroy(sender_t *sender);
|
void cnetz_destroy(sender_t *sender);
|
||||||
void cnetz_go_idle(cnetz_t *cnetz);
|
void cnetz_go_idle(cnetz_t *cnetz);
|
||||||
void cnetz_sync_frame(cnetz_t *cnetz, double sync, int ts);
|
void cnetz_sync_frame(cnetz_t *cnetz, double sync, int ts);
|
||||||
int cnetz_meldeaufruf(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest);
|
int cnetz_meldeaufruf(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int ogk_kanal);
|
||||||
const struct telegramm *cnetz_transmit_telegramm_rufblock(cnetz_t *cnetz);
|
const struct telegramm *cnetz_transmit_telegramm_rufblock(cnetz_t *cnetz);
|
||||||
const struct telegramm *cnetz_transmit_telegramm_meldeblock(cnetz_t *cnetz);
|
const struct telegramm *cnetz_transmit_telegramm_meldeblock(cnetz_t *cnetz);
|
||||||
void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, struct telegramm *telegramm, int block);
|
void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, struct telegramm *telegramm, int block);
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
typedef struct cnetz_database {
|
typedef struct cnetz_database {
|
||||||
|
|
||||||
struct cnetz_database *next;
|
struct cnetz_database *next;
|
||||||
|
int ogk_kanal; /* available on which channel */
|
||||||
uint8_t futln_nat; /* who ... */
|
uint8_t futln_nat; /* who ... */
|
||||||
uint8_t futln_fuvst;
|
uint8_t futln_fuvst;
|
||||||
uint16_t futln_rest;
|
uint16_t futln_rest;
|
||||||
|
@ -81,7 +82,7 @@ static void db_timeout(struct timer *timer)
|
||||||
|
|
||||||
PDEBUG(DDB, DEBUG_INFO, "Check, if subscriber '%d,%d,%05d' is still available.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
|
PDEBUG(DDB, DEBUG_INFO, "Check, if subscriber '%d,%d,%05d' is still available.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
|
||||||
|
|
||||||
rc = cnetz_meldeaufruf(db->futln_nat, db->futln_fuvst, db->futln_rest);
|
rc = cnetz_meldeaufruf(db->futln_nat, db->futln_fuvst, db->futln_rest, db->ogk_kanal);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
/* OgK is used for speech, but this never happens in a real
|
/* OgK is used for speech, but this never happens in a real
|
||||||
* network. We just assume that the phone has responded and
|
* network. We just assume that the phone has responded and
|
||||||
|
@ -93,7 +94,7 @@ static void db_timeout(struct timer *timer)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create/update db entry */
|
/* create/update db entry */
|
||||||
int update_db(cnetz_t __attribute__((unused)) *cnetz, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *futelg_bit, int *extended, int busy, int failed)
|
int update_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int ogk_kanal, int *futelg_bit, int *extended, int busy, int failed)
|
||||||
{
|
{
|
||||||
cnetz_db_t *db, **dbp;
|
cnetz_db_t *db, **dbp;
|
||||||
|
|
||||||
|
@ -128,6 +129,9 @@ int update_db(cnetz_t __attribute__((unused)) *cnetz, uint8_t futln_nat, uint8_t
|
||||||
PDEBUG(DDB, DEBUG_INFO, "Adding subscriber '%d,%d,%05d' to database.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
|
PDEBUG(DDB, DEBUG_INFO, "Adding subscriber '%d,%d,%05d' to database.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ogk_kanal)
|
||||||
|
db->ogk_kanal = ogk_kanal;
|
||||||
|
|
||||||
if (futelg_bit && *futelg_bit >= 0)
|
if (futelg_bit && *futelg_bit >= 0)
|
||||||
db->futelg_bit = *futelg_bit;
|
db->futelg_bit = *futelg_bit;
|
||||||
|
|
||||||
|
@ -136,17 +140,17 @@ int update_db(cnetz_t __attribute__((unused)) *cnetz, uint8_t futln_nat, uint8_t
|
||||||
|
|
||||||
db->busy = busy;
|
db->busy = busy;
|
||||||
if (busy) {
|
if (busy) {
|
||||||
PDEBUG(DDB, DEBUG_INFO, "Subscriber '%d,%d,%05d' busy now.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
|
PDEBUG(DDB, DEBUG_INFO, "Subscriber '%d,%d,%05d' on OGK channel #%d is busy now.\n", db->futln_nat, db->futln_fuvst, db->futln_rest, db->ogk_kanal);
|
||||||
timer_stop(&db->timer);
|
timer_stop(&db->timer);
|
||||||
} else if (!failed) {
|
} else if (!failed) {
|
||||||
PDEBUG(DDB, DEBUG_INFO, "Subscriber '%d,%d,%05d' idle now.\n", db->futln_nat, db->futln_fuvst, db->futln_rest);
|
PDEBUG(DDB, DEBUG_INFO, "Subscriber '%d,%d,%05d' on OGK channel #%d is idle now.\n", db->futln_nat, db->futln_fuvst, db->futln_rest, db->ogk_kanal);
|
||||||
timer_start(&db->timer, MELDE_INTERVAL); /* when to check avaiability (again) */
|
timer_start(&db->timer, MELDE_INTERVAL); /* when to check avaiability (again) */
|
||||||
db->retry = 0;
|
db->retry = 0;
|
||||||
db->eingebucht = 1;
|
db->eingebucht = 1;
|
||||||
db->last_seen = get_time();
|
db->last_seen = get_time();
|
||||||
} else {
|
} else {
|
||||||
db->retry++;
|
db->retry++;
|
||||||
PDEBUG(DDB, DEBUG_NOTICE, "Paging subscriber '%d,%d,%05d' failed (try %d of %d).\n", db->futln_nat, db->futln_fuvst, db->futln_rest, db->retry, MELDE_MAXIMAL);
|
PDEBUG(DDB, DEBUG_NOTICE, "Paging subscriber '%d,%d,%05d' on OGK channel #%d failed (try %d of %d).\n", db->futln_nat, db->futln_fuvst, db->futln_rest, db->ogk_kanal, db->retry, MELDE_MAXIMAL);
|
||||||
if (db->retry == MELDE_MAXIMAL) {
|
if (db->retry == MELDE_MAXIMAL) {
|
||||||
PDEBUG(DDB, DEBUG_INFO, "Marking subscriber as gone.\n");
|
PDEBUG(DDB, DEBUG_INFO, "Marking subscriber as gone.\n");
|
||||||
db->eingebucht = 0;
|
db->eingebucht = 0;
|
||||||
|
@ -162,7 +166,7 @@ int update_db(cnetz_t __attribute__((unused)) *cnetz, uint8_t futln_nat, uint8_t
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int find_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *futelg_bit, int *extended)
|
int find_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *ogk_kanal, int *futelg_bit, int *extended)
|
||||||
{
|
{
|
||||||
cnetz_db_t *db = cnetz_db_head;
|
cnetz_db_t *db = cnetz_db_head;
|
||||||
|
|
||||||
|
@ -171,6 +175,8 @@ int find_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *fu
|
||||||
&& db->futln_nat == futln_nat
|
&& db->futln_nat == futln_nat
|
||||||
&& db->futln_fuvst == futln_fuvst
|
&& db->futln_fuvst == futln_fuvst
|
||||||
&& db->futln_rest == futln_rest) {
|
&& db->futln_rest == futln_rest) {
|
||||||
|
if (ogk_kanal)
|
||||||
|
*ogk_kanal = db->ogk_kanal;
|
||||||
if (futelg_bit)
|
if (futelg_bit)
|
||||||
*futelg_bit = db->futelg_bit;
|
*futelg_bit = db->futelg_bit;
|
||||||
if (extended)
|
if (extended)
|
||||||
|
@ -193,6 +199,7 @@ void dump_db(void)
|
||||||
cnetz_db_t *db = cnetz_db_head;
|
cnetz_db_t *db = cnetz_db_head;
|
||||||
double now = get_time();
|
double now = get_time();
|
||||||
int last;
|
int last;
|
||||||
|
char attached[16];
|
||||||
|
|
||||||
PDEBUG(DDB, DEBUG_NOTICE, "Dump of subscriber database:\n");
|
PDEBUG(DDB, DEBUG_NOTICE, "Dump of subscriber database:\n");
|
||||||
if (!db) {
|
if (!db) {
|
||||||
|
@ -204,7 +211,8 @@ void dump_db(void)
|
||||||
PDEBUG(DDB, DEBUG_NOTICE, "-------------------------------------------------------------------------------\n");
|
PDEBUG(DDB, DEBUG_NOTICE, "-------------------------------------------------------------------------------\n");
|
||||||
while (db) {
|
while (db) {
|
||||||
last = (db->busy) ? 0 : (uint32_t)(now - db->last_seen);
|
last = (db->busy) ? 0 : (uint32_t)(now - db->last_seen);
|
||||||
PDEBUG(DDB, DEBUG_NOTICE, "%d,%d,%05d\t%s\t\t%s\t\t%02d:%02d:%02d \t%d/%d\n", db->futln_nat, db->futln_fuvst, db->futln_rest, (db->eingebucht) ? "YES" : "-no-", (db->busy) ? "YES" : "-no-", last / 3600, (last / 60) % 60, last % 60, db->retry, MELDE_MAXIMAL);
|
sprintf(attached, "YES (OGK %d)", db->ogk_kanal);
|
||||||
|
PDEBUG(DDB, DEBUG_NOTICE, "%d,%d,%05d\t%s\t%s\t\t%02d:%02d:%02d \t%d/%d\n", db->futln_nat, db->futln_fuvst, db->futln_rest, (db->eingebucht) ? attached : "-no-\t", (db->busy) ? "YES" : "-no-", last / 3600, (last / 60) % 60, last % 60, db->retry, MELDE_MAXIMAL);
|
||||||
db = db->next;
|
db = db->next;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
int update_db(cnetz_t *cnetz, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *futelg_bit, int *extended, int busy, int failed);
|
int update_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int ogk_kanal, int *futelg_bit, int *extended, int busy, int failed);
|
||||||
int find_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *futelg_bit, int *extended);
|
int find_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int *ogk_kanal, int *futelg_bit, int *extended);
|
||||||
void flush_db(void);
|
void flush_db(void);
|
||||||
void dump_db(void);
|
void dump_db(void);
|
||||||
|
|
||||||
|
|
|
@ -568,10 +568,12 @@ static int fsk_distributed_encode(cnetz_t *cnetz, const char *bits)
|
||||||
/* decode samples and hut for bit changes
|
/* decode samples and hut for bit changes
|
||||||
* use deviation to find greatest slope of the signal (bit change)
|
* use deviation to find greatest slope of the signal (bit change)
|
||||||
*/
|
*/
|
||||||
void sender_receive(sender_t *sender, sample_t *samples, int length, double __attribute__((unused)) rf_level_db)
|
void sender_receive(sender_t *sender, sample_t *samples, int length, double rf_level_db)
|
||||||
{
|
{
|
||||||
cnetz_t *cnetz = (cnetz_t *) sender;
|
cnetz_t *cnetz = (cnetz_t *) sender;
|
||||||
|
|
||||||
|
cnetz->rf_level_db = rf_level_db;
|
||||||
|
|
||||||
/* measure rx sample speed */
|
/* measure rx sample speed */
|
||||||
calc_clock_speed(cnetz, length, 0, 0);
|
calc_clock_speed(cnetz, length, 0, 0);
|
||||||
|
|
||||||
|
|
|
@ -82,6 +82,10 @@ void print_help(const char *arg0)
|
||||||
/* - - */
|
/* - - */
|
||||||
printf(" -T --channel-type <channel type> | list\n");
|
printf(" -T --channel-type <channel type> | list\n");
|
||||||
printf(" Give channel type, use 'list' to get a list. (default = '%s')\n", chan_type_short_name(chan_type[0]));
|
printf(" Give channel type, use 'list' to get a list. (default = '%s')\n", chan_type_short_name(chan_type[0]));
|
||||||
|
printf(" You must define at least one OgK at channel 131. This channel may be a\n");
|
||||||
|
printf(" a combined OgK+SpK channel, but this works with older phones only.\n");
|
||||||
|
printf(" You must define additionally one or more SpK, in order to make calls.\n");
|
||||||
|
printf(" You may define alternative OgK, the phones will attach to it then.\n");
|
||||||
printf(" -M --measure-speed\n");
|
printf(" -M --measure-speed\n");
|
||||||
printf(" Measures clock speed. THIS IS REQUIRED! See documentation!\n");
|
printf(" Measures clock speed. THIS IS REQUIRED! See documentation!\n");
|
||||||
printf(" -C --clock-speed <rx ppm>,<tx ppm>\n");
|
printf(" -C --clock-speed <rx ppm>,<tx ppm>\n");
|
||||||
|
@ -524,7 +528,7 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!num_kanal) {
|
if (!num_kanal) {
|
||||||
printf("No channel (\"Kanal\") is specified, I suggest channel %d.\n\n", CNETZ_OGK_KANAL);
|
printf("No channel (\"Kanal\") is specified, I suggest channel %d.\n\n", CNETZ_STD_OGK_KANAL);
|
||||||
mandatory = 1;
|
mandatory = 1;
|
||||||
}
|
}
|
||||||
if (use_sdr) {
|
if (use_sdr) {
|
||||||
|
@ -585,7 +589,7 @@ int main(int argc, char *argv[])
|
||||||
init_coding();
|
init_coding();
|
||||||
cnetz_init();
|
cnetz_init();
|
||||||
|
|
||||||
/* check for mandatory OgK */
|
/* check for mandatory standard OgK */
|
||||||
for (i = 0; i < num_kanal; i++) {
|
for (i = 0; i < num_kanal; i++) {
|
||||||
if (chan_type[i] == CHAN_TYPE_OGK || chan_type[i] == CHAN_TYPE_OGK_SPK)
|
if (chan_type[i] == CHAN_TYPE_OGK || chan_type[i] == CHAN_TYPE_OGK_SPK)
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -1499,10 +1499,9 @@ void cnetz_decode_telegramm(cnetz_t *cnetz, const char *bits, double level, doub
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PDEBUG_CHAN(DDSP, DEBUG_INFO, "RF level: %.1f dB RX Level: %.0f%% Standard deviation: %.0f%% Sync Time: %.2f (TS %.2f) %s\n", cnetz->rf_level_db, fabs(level) / cnetz->fsk_deviation * 100.0, stddev / fabs(level) * 100.0, sync_time, sync_time / 396.0, (level < 0) ? "NEGATIVE (phone's mode)" : "POSITIVE (base station's mode)");
|
||||||
if (bit_errors)
|
if (bit_errors)
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: %.0f%% Standard deviation: %.0f%% Sync Time: %.2f (TS %.2f) Bit errors: %d %s\n", fabs(level) / cnetz->fsk_deviation * 100.0, stddev / fabs(level) * 100.0, sync_time, sync_time / 396.0, bit_errors, (level < 0) ? "NEGATIVE (phone's mode)" : "POSITIVE (base station's mode)");
|
PDEBUG_CHAN(DDSP, DEBUG_INFO, " -> Frame has %d bit errors.\n", bit_errors);
|
||||||
else
|
|
||||||
PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: %.0f%% Standard deviation: %.0f%% Sync Time: %.2f (TS %.2f) %s\n", fabs(level) / cnetz->fsk_deviation * 100.0, stddev / fabs(level) * 100.0, sync_time, sync_time / 396.0, (level < 0) ? "NEGATIVE (phone's mode)" : "POSITIVE (base station's mode)");
|
|
||||||
|
|
||||||
disassemble_telegramm(&telegramm, bits, si.authentifikationsbit);
|
disassemble_telegramm(&telegramm, bits, si.authentifikationsbit);
|
||||||
opcode = telegramm.opcode;
|
opcode = telegramm.opcode;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <math.h>
|
||||||
#include "../libsample/sample.h"
|
#include "../libsample/sample.h"
|
||||||
#include "../libdebug/debug.h"
|
#include "../libdebug/debug.h"
|
||||||
#include "../libmobile/call.h"
|
#include "../libmobile/call.h"
|
||||||
|
@ -28,6 +29,8 @@
|
||||||
#include "telegramm.h"
|
#include "telegramm.h"
|
||||||
#include "database.h"
|
#include "database.h"
|
||||||
|
|
||||||
|
static int new_cueue_position = 0;
|
||||||
|
|
||||||
const char *transaction2rufnummer(transaction_t *trans)
|
const char *transaction2rufnummer(transaction_t *trans)
|
||||||
{
|
{
|
||||||
static char rufnummer[32]; /* make GCC happy (overflow check) */
|
static char rufnummer[32]; /* make GCC happy (overflow check) */
|
||||||
|
@ -38,24 +41,34 @@ const char *transaction2rufnummer(transaction_t *trans)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* create transaction */
|
/* create transaction */
|
||||||
transaction_t *create_transaction(cnetz_t *cnetz, uint64_t state, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int futelg_bit, int extended)
|
transaction_t *create_transaction(cnetz_t *cnetz, uint64_t state, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int futelg_bit, int extended, double rf_level_db)
|
||||||
{
|
{
|
||||||
sender_t *sender;
|
transaction_t *trans;
|
||||||
transaction_t *trans = NULL;
|
|
||||||
cnetz_t *search_cnetz;
|
|
||||||
|
|
||||||
/* search transaction for this subscriber */
|
trans = search_transaction_number_global(futln_nat, futln_fuvst, futln_rest);
|
||||||
for (sender = sender_head; sender; sender = sender->next) {
|
|
||||||
search_cnetz = (cnetz_t *) sender;
|
|
||||||
/* search transaction for this callref */
|
|
||||||
trans = search_transaction_number(search_cnetz, futln_nat, futln_fuvst, futln_rest);
|
|
||||||
if (trans)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (trans) {
|
if (trans) {
|
||||||
const char *rufnummer = transaction2rufnummer(trans);
|
const char *rufnummer = transaction2rufnummer(trans);
|
||||||
int old_callref = trans->callref;
|
int old_callref = trans->callref;
|
||||||
cnetz_t *old_cnetz = trans->cnetz;
|
cnetz_t *old_cnetz = trans->cnetz;
|
||||||
|
/* both states must be the same and one of the give selection */
|
||||||
|
if ((trans->state & state & (TRANS_EM | TRANS_UM | TRANS_VWG | TRANS_ATQ_IDLE))) {
|
||||||
|
if (!isnan(trans->rf_level_db) && !isnan(rf_level_db) && trans->cnetz->kanal != cnetz->kanal) {
|
||||||
|
if (rf_level_db > trans->rf_level_db) {
|
||||||
|
PDEBUG(DTRANS, DEBUG_NOTICE, "Found already pending transaction for subscriber '%s' on channel #%d, but this message on channel #%d is stronger, so we move to that channel!\n", rufnummer, trans->cnetz->kanal, cnetz->kanal);
|
||||||
|
trans->rf_level_db = rf_level_db;
|
||||||
|
unlink_transaction(trans);
|
||||||
|
link_transaction(trans, cnetz);
|
||||||
|
update_db(trans->futln_nat, trans->futln_fuvst, trans->futln_rest, cnetz->kanal, NULL, NULL, 1, 0);
|
||||||
|
return trans;
|
||||||
|
}
|
||||||
|
if (rf_level_db < trans->rf_level_db) {
|
||||||
|
PDEBUG(DTRANS, DEBUG_NOTICE, "Found already pending transaction for subscriber '%s' on channel #%d, but this message on channel #%d is weaker, so we ignore that channel!\n", rufnummer, trans->cnetz->kanal, cnetz->kanal);
|
||||||
|
return trans;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PDEBUG(DTRANS, DEBUG_NOTICE, "Found already pending transaction for subscriber '%s' on channel #%d, but this message on channel #%d is also received. Try to avoid multiple OgK channels!\n", rufnummer, trans->cnetz->kanal, cnetz->kanal);
|
||||||
|
return trans;
|
||||||
|
}
|
||||||
PDEBUG(DTRANS, DEBUG_NOTICE, "Found already pending transaction for subscriber '%s', deleting!\n", rufnummer);
|
PDEBUG(DTRANS, DEBUG_NOTICE, "Found already pending transaction for subscriber '%s', deleting!\n", rufnummer);
|
||||||
destroy_transaction(trans);
|
destroy_transaction(trans);
|
||||||
if (old_cnetz) /* should be... */
|
if (old_cnetz) /* should be... */
|
||||||
|
@ -88,10 +101,12 @@ transaction_t *create_transaction(cnetz_t *cnetz, uint64_t state, uint8_t futln_
|
||||||
link_transaction(trans, cnetz);
|
link_transaction(trans, cnetz);
|
||||||
|
|
||||||
/* update database: now busy */
|
/* update database: now busy */
|
||||||
update_db(cnetz, futln_nat, futln_fuvst, futln_rest, &futelg_bit, &extended, 1, 0);
|
update_db(futln_nat, futln_fuvst, futln_rest, cnetz->kanal, &futelg_bit, &extended, 1, 0);
|
||||||
trans->futelg_bit = futelg_bit;
|
trans->futelg_bit = futelg_bit;
|
||||||
trans->extended = extended;
|
trans->extended = extended;
|
||||||
|
|
||||||
|
trans->rf_level_db = rf_level_db;
|
||||||
|
|
||||||
return trans;
|
return trans;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +114,7 @@ transaction_t *create_transaction(cnetz_t *cnetz, uint64_t state, uint8_t futln_
|
||||||
void destroy_transaction(transaction_t *trans)
|
void destroy_transaction(transaction_t *trans)
|
||||||
{
|
{
|
||||||
/* update database: now idle */
|
/* update database: now idle */
|
||||||
update_db(trans->cnetz, trans->futln_nat, trans->futln_fuvst, trans->futln_rest, NULL, NULL, 0, trans->page_failed);
|
update_db(trans->futln_nat, trans->futln_fuvst, trans->futln_rest, 0, NULL, NULL, 0, trans->page_failed);
|
||||||
|
|
||||||
unlink_transaction(trans);
|
unlink_transaction(trans);
|
||||||
|
|
||||||
|
@ -182,6 +197,23 @@ transaction_t *search_transaction_number(cnetz_t *cnetz, uint8_t futln_nat, uint
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
transaction_t *search_transaction_number_global(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest)
|
||||||
|
{
|
||||||
|
sender_t *sender;
|
||||||
|
cnetz_t *cnetz;
|
||||||
|
transaction_t *trans = NULL;
|
||||||
|
|
||||||
|
/* search transaction for this subscriber */
|
||||||
|
for (sender = sender_head; sender; sender = sender->next) {
|
||||||
|
cnetz = (cnetz_t *) sender;
|
||||||
|
/* search transaction for this callref */
|
||||||
|
trans = search_transaction_number(cnetz, futln_nat, futln_fuvst, futln_rest);
|
||||||
|
if (trans)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return trans;
|
||||||
|
}
|
||||||
transaction_t *search_transaction_callref(cnetz_t *cnetz, int callref)
|
transaction_t *search_transaction_callref(cnetz_t *cnetz, int callref)
|
||||||
{
|
{
|
||||||
transaction_t *trans = cnetz->trans_list;
|
transaction_t *trans = cnetz->trans_list;
|
||||||
|
@ -201,6 +233,42 @@ transaction_t *search_transaction_callref(cnetz_t *cnetz, int callref)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* get oldest transaction in queue:
|
||||||
|
*
|
||||||
|
* oldest means that the queue number is the smallest.
|
||||||
|
* all candidates (transactions) must be in queue state.
|
||||||
|
*/
|
||||||
|
transaction_t *search_transaction_queue(void)
|
||||||
|
{
|
||||||
|
sender_t *sender;
|
||||||
|
transaction_t *trans, *found = NULL;
|
||||||
|
cnetz_t *cnetz;
|
||||||
|
int queue_max = 0;
|
||||||
|
|
||||||
|
for (sender = sender_head; sender; sender = sender->next) {
|
||||||
|
cnetz = (cnetz_t *) sender;
|
||||||
|
trans = cnetz->trans_list;
|
||||||
|
while (trans) {
|
||||||
|
if ((trans->state & (TRANS_MO_QUEUE | TRANS_MT_QUEUE))) {
|
||||||
|
/* select if first or lower number */
|
||||||
|
if (!found || trans->queue_position < queue_max) {
|
||||||
|
queue_max = trans->queue_position;
|
||||||
|
found = trans;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trans = trans->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
const char *rufnummer = transaction2rufnummer(found);
|
||||||
|
PDEBUG(DTRANS, DEBUG_DEBUG, "Found oldest transaction in queue for subscriber '%s'\n", rufnummer);
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
static const char *trans_state_name(uint64_t state)
|
static const char *trans_state_name(uint64_t state)
|
||||||
{
|
{
|
||||||
switch (state) {
|
switch (state) {
|
||||||
|
@ -252,6 +320,8 @@ static const char *trans_state_name(uint64_t state)
|
||||||
return "AT";
|
return "AT";
|
||||||
case TRANS_ATQ:
|
case TRANS_ATQ:
|
||||||
return "ATQ";
|
return "ATQ";
|
||||||
|
case TRANS_ATQ_IDLE:
|
||||||
|
return "ATQ_IDLE";
|
||||||
case TRANS_MO_QUEUE:
|
case TRANS_MO_QUEUE:
|
||||||
return "MO_QUEUE";
|
return "MO_QUEUE";
|
||||||
case TRANS_MT_QUEUE:
|
case TRANS_MT_QUEUE:
|
||||||
|
@ -301,6 +371,7 @@ const char *trans_short_state_name(uint64_t state)
|
||||||
case TRANS_AF:
|
case TRANS_AF:
|
||||||
case TRANS_AT:
|
case TRANS_AT:
|
||||||
case TRANS_ATQ:
|
case TRANS_ATQ:
|
||||||
|
case TRANS_ATQ_IDLE:
|
||||||
return "RELEASE";
|
return "RELEASE";
|
||||||
case TRANS_MO_QUEUE:
|
case TRANS_MO_QUEUE:
|
||||||
case TRANS_MO_DELAY:
|
case TRANS_MO_DELAY:
|
||||||
|
@ -317,6 +388,9 @@ void trans_new_state(transaction_t *trans, uint64_t state)
|
||||||
{
|
{
|
||||||
PDEBUG(DTRANS, DEBUG_INFO, "Transaction (%s) state %s -> %s\n", transaction2rufnummer(trans), trans_state_name(trans->state), trans_state_name(state));
|
PDEBUG(DTRANS, DEBUG_INFO, "Transaction (%s) state %s -> %s\n", transaction2rufnummer(trans), trans_state_name(trans->state), trans_state_name(state));
|
||||||
trans->state = state;
|
trans->state = state;
|
||||||
|
/* in case of a queue, set new positon */
|
||||||
|
if (!trans->queue_position && (state == TRANS_MO_QUEUE || state == TRANS_MT_QUEUE))
|
||||||
|
trans->queue_position = ++new_cueue_position;
|
||||||
cnetz_display_status();
|
cnetz_display_status();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,11 +29,12 @@
|
||||||
#define TRANS_AF (1 << 20) /* release connection by base station (SpK) */
|
#define TRANS_AF (1 << 20) /* release connection by base station (SpK) */
|
||||||
#define TRANS_AT (1 << 21) /* release connection by mobile station */
|
#define TRANS_AT (1 << 21) /* release connection by mobile station */
|
||||||
#define TRANS_ATQ (1 << 22) /* acknowledge release of MO call in queue */
|
#define TRANS_ATQ (1 << 22) /* acknowledge release of MO call in queue */
|
||||||
|
#define TRANS_ATQ_IDLE (1 << 23) /* repeat, if call has been released already (mobile sends again) */
|
||||||
/* queue */
|
/* queue */
|
||||||
#define TRANS_MO_QUEUE (1 << 23) /* MO queue */
|
#define TRANS_MO_QUEUE (1 << 24) /* MO queue */
|
||||||
#define TRANS_MT_QUEUE (1 << 24) /* MT queue */
|
#define TRANS_MT_QUEUE (1 << 25) /* MT queue */
|
||||||
#define TRANS_MO_DELAY (1 << 25) /* delay to be sure the channel is free again */
|
#define TRANS_MO_DELAY (1 << 26) /* delay to be sure the channel is free again */
|
||||||
#define TRANS_MT_DELAY (1 << 26)
|
#define TRANS_MT_DELAY (1 << 27)
|
||||||
|
|
||||||
typedef struct transaction {
|
typedef struct transaction {
|
||||||
struct transaction *next; /* pointer to next node in list */
|
struct transaction *next; /* pointer to next node in list */
|
||||||
|
@ -54,16 +55,20 @@ typedef struct transaction {
|
||||||
int mt_call; /* flags a moile terminating call */
|
int mt_call; /* flags a moile terminating call */
|
||||||
int page_failed; /* failed to get a response from MS */
|
int page_failed; /* failed to get a response from MS */
|
||||||
double call_start; /* when did the call start? (used for metering) */
|
double call_start; /* when did the call start? (used for metering) */
|
||||||
|
int queue_position; /* to find next transaction in queue */
|
||||||
|
double rf_level_db; /* level of first contact, so we can detect correct channel at multiple receptions */
|
||||||
} transaction_t;
|
} transaction_t;
|
||||||
|
|
||||||
const char *transaction2rufnummer(transaction_t *trans);
|
const char *transaction2rufnummer(transaction_t *trans);
|
||||||
transaction_t *create_transaction(cnetz_t *cnetz, uint64_t state, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int futelg_bit, int extended);
|
transaction_t *create_transaction(cnetz_t *cnetz, uint64_t state, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, int futelg_bit, int extended, double rf_level_db);
|
||||||
void destroy_transaction(transaction_t *trans);
|
void destroy_transaction(transaction_t *trans);
|
||||||
void link_transaction(transaction_t *trans, cnetz_t *cnetz);
|
void link_transaction(transaction_t *trans, cnetz_t *cnetz);
|
||||||
void unlink_transaction(transaction_t *trans);
|
void unlink_transaction(transaction_t *trans);
|
||||||
transaction_t *search_transaction(cnetz_t *cnetz, uint64_t state_mask);
|
transaction_t *search_transaction(cnetz_t *cnetz, uint64_t state_mask);
|
||||||
transaction_t *search_transaction_number(cnetz_t *cnetz, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest);
|
transaction_t *search_transaction_number(cnetz_t *cnetz, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest);
|
||||||
|
transaction_t *search_transaction_number_global(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest);
|
||||||
transaction_t *search_transaction_callref(cnetz_t *cnetz, int callref);
|
transaction_t *search_transaction_callref(cnetz_t *cnetz, int callref);
|
||||||
|
transaction_t *search_transaction_queue(void);
|
||||||
void trans_new_state(transaction_t *trans, uint64_t state);
|
void trans_new_state(transaction_t *trans, uint64_t state);
|
||||||
void cnetz_flush_other_transactions(cnetz_t *cnetz, transaction_t *trans);
|
void cnetz_flush_other_transactions(cnetz_t *cnetz, transaction_t *trans);
|
||||||
void transaction_timeout(struct timer *timer);
|
void transaction_timeout(struct timer *timer);
|
||||||
|
|
Loading…
Reference in New Issue