C-Netz: Work on system informations, metering and call queues
- Make system informations configurable - Simulate call mertering - Support for call queues on busy voice channels
This commit is contained in:
parent
3bfba37fff
commit
dfdad21e3f
|
@ -311,7 +311,7 @@ dsp.c:218 notice : Clock: RX=19.44 TX=19.49; Signal: RX=19.35 TX=19.43 ppm
|
|||
<p>
|
||||
One can see that the measured clock from the sound card (sample rate) differs about +19.45 PPM.
|
||||
Because I did not do any correction to the signal processing, the same error applies to the signal processing.
|
||||
Use command line option '-S 19.45,19.45' or '--clock-speed 19.45,19.45' to compensate the clock error by adjusting the signal processor.
|
||||
Use command line option '-C 19.45,19.45' or '--clock-speed 19.45,19.45' to compensate the clock error by adjusting the signal processor.
|
||||
Let it run again for one hour and you will see that clock deviation of the signal is below 1 PPM.
|
||||
</p>
|
||||
|
||||
|
@ -384,7 +384,7 @@ To run the base station I the following command line options:
|
|||
|
||||
<pre>
|
||||
|
||||
# cnetz -k 131 -p -d -S 19.25,19.25
|
||||
# cnetz -k 131 -p -d -C 19.25,19.25
|
||||
...
|
||||
cnetz.c:142 notice : You selected channel 131 ('Orga-Kanal') for combined callin
|
||||
g + traffic channel. Some phones will reject this.
|
||||
|
|
|
@ -39,6 +39,12 @@
|
|||
* created. The transaction is linked to OgK. When the scheduler schedules
|
||||
* VAK(R), the SpK is allocated and the transaction is linked to it.
|
||||
*
|
||||
* If no SpK is available, the call is rejected. If queue (Warteschlange) is
|
||||
* enabled, WSK(R) is scheduled. After transmission, the state changes to
|
||||
* TRANS_MT_QUEUE. Upon timeout (no channel becomes available), the call is
|
||||
* rejected by scheduling VA(R). Upon available channel the call proceeeds with
|
||||
* VAK(R) as described above.
|
||||
*
|
||||
* If an MO (mobile originating) call is made (received VWG(K)), a transaction
|
||||
* with callref is created. The transaction is linked to OgK. When the
|
||||
* scheduler schedules WAF(M), the process waits for WUE(M). If not received,
|
||||
|
@ -47,6 +53,12 @@
|
|||
* then schedules VAG(R), the SpK is allocated and the transaction is linked to
|
||||
* it.
|
||||
*
|
||||
* If no SpK is available, the call is rejected by scheduling WBN(R). If queue
|
||||
* (Warteschlange) is enabled, WWBP(R) is scheduled. After transmission, the
|
||||
* state is changed to TRANS_MO_QUEUE. Upon timeout (no channel becomes
|
||||
* available), the call is rejected by scheduling VA(R). Upon available channel
|
||||
* the call proceeeds with VAG(R) as described above.
|
||||
*
|
||||
* Switching to SpK is performed two time slots after transmitting VAK(R) or
|
||||
* VAG(R). The timer is started. The schedulers schedules 8 times BQ(K) and
|
||||
* awaits at least one BEL(K). If BEK(K) is received, the timer is stoped. If
|
||||
|
@ -129,6 +141,7 @@
|
|||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <inttypes.h>
|
||||
#include "../common/sample.h"
|
||||
#include "../common/debug.h"
|
||||
#include "../common/timer.h"
|
||||
|
@ -231,7 +244,7 @@ int cnetz_init(void)
|
|||
}
|
||||
|
||||
/* Create transceiver instance and link to a list. */
|
||||
int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *audiodev, int use_sdr, enum demod_type demod, int samplerate, double rx_gain, int auth, 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(int kanal, enum cnetz_chan_type chan_type, const char *audiodev, int use_sdr, enum demod_type demod, int samplerate, double rx_gain, int auth, int warteschlange, int metering, 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;
|
||||
cnetz_t *cnetz;
|
||||
|
@ -313,6 +326,8 @@ int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *audiodev
|
|||
|
||||
cnetz->chan_type = chan_type;
|
||||
cnetz->auth = auth;
|
||||
cnetz->warteschlange = warteschlange;
|
||||
cnetz->metering = metering;
|
||||
cnetz->ms_power = ms_power;
|
||||
|
||||
switch (polarity) {
|
||||
|
@ -409,63 +424,7 @@ void cnetz_destroy(sender_t *sender)
|
|||
free(cnetz);
|
||||
}
|
||||
|
||||
/* Abort connection, if any and send idle broadcast */
|
||||
void cnetz_go_idle(cnetz_t *cnetz)
|
||||
{
|
||||
if (cnetz->state == CNETZ_IDLE)
|
||||
return;
|
||||
|
||||
if (cnetz->trans_list) {
|
||||
PDEBUG(DCNETZ, DEBUG_ERROR, "Releasing but still having transaction, please fix!\n");
|
||||
if (cnetz->trans_list->callref)
|
||||
call_in_release(cnetz->trans_list->callref, CAUSE_NORMAL);
|
||||
destroy_transaction(cnetz->trans_list);
|
||||
}
|
||||
|
||||
PDEBUG(DCNETZ, DEBUG_INFO, "Entering IDLE state on channel %d.\n", cnetz->sender.kanal);
|
||||
cnetz_new_state(cnetz, CNETZ_IDLE);
|
||||
|
||||
/* set scheduler to OgK or turn off SpK */
|
||||
if (cnetz->dsp_mode == DSP_MODE_SPK_K || cnetz->dsp_mode == DSP_MODE_SPK_V) {
|
||||
/* go idle after next frame/slot */
|
||||
cnetz_set_sched_dsp_mode(cnetz, (cnetz->sender.kanal == CNETZ_OGK_KANAL) ? DSP_MODE_OGK : DSP_MODE_OFF, 1);
|
||||
} else {
|
||||
cnetz_set_sched_dsp_mode(cnetz, (cnetz->sender.kanal == CNETZ_OGK_KANAL) ? DSP_MODE_OGK : DSP_MODE_OFF, 0);
|
||||
cnetz_set_dsp_mode(cnetz, (cnetz->sender.kanal == CNETZ_OGK_KANAL) ? DSP_MODE_OGK : DSP_MODE_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
/* Initiate release connection on speech channel */
|
||||
static void cnetz_release(transaction_t *trans, uint8_t cause)
|
||||
{
|
||||
trans_new_state(trans, TRANS_AF);
|
||||
trans->repeat = 0;
|
||||
trans->release_cause = cause;
|
||||
trans->cnetz->sched_switch_mode = 0;
|
||||
timer_stop(&trans->timer);
|
||||
}
|
||||
|
||||
/* Receive audio from call instance. */
|
||||
void call_rx_audio(int callref, sample_t *samples, int count)
|
||||
{
|
||||
sender_t *sender;
|
||||
cnetz_t *cnetz;
|
||||
|
||||
for (sender = sender_head; sender; sender = sender->next) {
|
||||
cnetz = (cnetz_t *) sender;
|
||||
if (cnetz->trans_list && cnetz->trans_list->callref == callref)
|
||||
break;
|
||||
}
|
||||
if (!sender)
|
||||
return;
|
||||
|
||||
if (cnetz->dsp_mode == DSP_MODE_SPK_V) {
|
||||
/* store as is, since we convert rate when processing FSK frames */
|
||||
jitter_save(&cnetz->sender.dejitter, samples, count);
|
||||
}
|
||||
}
|
||||
|
||||
cnetz_t *search_free_spk(int extended)
|
||||
static cnetz_t *search_free_spk(int extended)
|
||||
{
|
||||
sender_t *sender;
|
||||
cnetz_t *cnetz, *ogk_spk = NULL;
|
||||
|
@ -493,7 +452,7 @@ cnetz_t *search_free_spk(int extended)
|
|||
return ogk_spk;
|
||||
}
|
||||
|
||||
cnetz_t *search_ogk(void)
|
||||
static cnetz_t *search_ogk(void)
|
||||
{
|
||||
sender_t *sender;
|
||||
cnetz_t *cnetz;
|
||||
|
@ -512,10 +471,80 @@ cnetz_t *search_ogk(void)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
int call_out_setup(int callref, const char __attribute__((unused)) *caller_id, enum number_type __attribute__((unused)) caller_type, const char *dialing)
|
||||
/* Abort connection, if any and send idle broadcast */
|
||||
void cnetz_go_idle(cnetz_t *cnetz)
|
||||
{
|
||||
cnetz_t *ogk;
|
||||
transaction_t *trans;
|
||||
|
||||
if (cnetz->state == CNETZ_IDLE)
|
||||
return;
|
||||
|
||||
if (cnetz->trans_list) {
|
||||
PDEBUG(DCNETZ, DEBUG_ERROR, "Releasing but still having transaction, please fix!\n");
|
||||
if (cnetz->trans_list->callref)
|
||||
call_in_release(cnetz->trans_list->callref, CAUSE_NORMAL);
|
||||
destroy_transaction(cnetz->trans_list);
|
||||
}
|
||||
|
||||
PDEBUG(DCNETZ, DEBUG_INFO, "Entering IDLE state on channel %d.\n", cnetz->sender.kanal);
|
||||
cnetz_new_state(cnetz, CNETZ_IDLE);
|
||||
|
||||
/* set scheduler to OgK or turn off SpK */
|
||||
if (cnetz->dsp_mode == DSP_MODE_SPK_K || cnetz->dsp_mode == DSP_MODE_SPK_V) {
|
||||
/* go idle after next frame/slot */
|
||||
cnetz_set_sched_dsp_mode(cnetz, (cnetz->sender.kanal == CNETZ_OGK_KANAL) ? DSP_MODE_OGK : DSP_MODE_OFF, 1);
|
||||
} else {
|
||||
cnetz_set_sched_dsp_mode(cnetz, (cnetz->sender.kanal == CNETZ_OGK_KANAL) ? DSP_MODE_OGK : DSP_MODE_OFF, 0);
|
||||
cnetz_set_dsp_mode(cnetz, (cnetz->sender.kanal == CNETZ_OGK_KANAL) ? 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) */
|
||||
ogk = search_ogk();
|
||||
trans = search_transaction(ogk, TRANS_MT_QUEUE | TRANS_MO_QUEUE);
|
||||
if (trans) {
|
||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Now channel available for queued subscriber '%s'.\n", transaction2rufnummer(trans));
|
||||
trans_new_state(trans, (trans->state == TRANS_MT_QUEUE) ? TRANS_MT_DELAY : TRANS_MO_DELAY);
|
||||
timer_stop(&trans->timer);
|
||||
timer_start(&trans->timer, 2.0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Initiate release connection on speech channel */
|
||||
static void cnetz_release(transaction_t *trans, uint8_t cause)
|
||||
{
|
||||
trans_new_state(trans, (trans->cnetz->dsp_mode == DSP_MODE_OGK) ? TRANS_VA : TRANS_AF);
|
||||
trans->repeat = 0;
|
||||
trans->release_cause = cause;
|
||||
trans->cnetz->sched_switch_mode = 0;
|
||||
timer_stop(&trans->timer);
|
||||
}
|
||||
|
||||
/* Receive audio from call instance. */
|
||||
void call_rx_audio(int callref, sample_t *samples, int count)
|
||||
{
|
||||
sender_t *sender;
|
||||
cnetz_t *cnetz;
|
||||
|
||||
for (sender = sender_head; sender; sender = sender->next) {
|
||||
cnetz = (cnetz_t *) sender;
|
||||
if (cnetz->trans_list && cnetz->trans_list->callref == callref)
|
||||
break;
|
||||
}
|
||||
if (!sender)
|
||||
return;
|
||||
|
||||
if (cnetz->dsp_mode == DSP_MODE_SPK_V) {
|
||||
/* store as is, since we convert rate when processing FSK frames */
|
||||
jitter_save(&cnetz->sender.dejitter, samples, count);
|
||||
}
|
||||
}
|
||||
|
||||
int call_out_setup(int callref, const char __attribute__((unused)) *caller_id, enum number_type __attribute__((unused)) caller_type, const char *dialing)
|
||||
{
|
||||
sender_t *sender;
|
||||
cnetz_t *cnetz, *spk;
|
||||
int extended;
|
||||
transaction_t *trans;
|
||||
uint8_t futln_nat;
|
||||
uint8_t futln_fuvst;
|
||||
|
@ -544,7 +573,8 @@ inval:
|
|||
futln_rest = atoi(dialing + 2);
|
||||
|
||||
/* 2. check if the subscriber is attached */
|
||||
if (!find_db(futln_nat, futln_fuvst, futln_rest)) {
|
||||
extended = find_db(futln_nat, futln_fuvst, futln_rest);
|
||||
if (extended < 0) {
|
||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call to not attached subscriber, rejecting!\n");
|
||||
return -CAUSE_OUTOFORDER;
|
||||
}
|
||||
|
@ -562,23 +592,27 @@ inval:
|
|||
return -CAUSE_BUSY;
|
||||
}
|
||||
|
||||
/* 4. check if all senders are busy, return NOCHANNEL */
|
||||
if (!search_free_spk(1)) { // FIXME: maybe lookup database for extended frequency band before calling subscriber
|
||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call, but no free channel, rejecting!\n");
|
||||
return -CAUSE_NOCHANNEL;
|
||||
}
|
||||
|
||||
/* 5. check if we have no OgK, return NOCHANNEL */
|
||||
/* 4. check if we have no OgK, return NOCHANNEL */
|
||||
cnetz = search_ogk();
|
||||
if (!cnetz) {
|
||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call, but OgK is currently busy, rejecting!\n");
|
||||
return -CAUSE_NOCHANNEL;
|
||||
}
|
||||
|
||||
/* 5. check if all senders are busy, return NOCHANNEL */
|
||||
spk = search_free_spk(extended);
|
||||
if (!spk) {
|
||||
if (!cnetz->warteschlange) {
|
||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Outgoing call, but no free channel, rejecting!\n");
|
||||
return -CAUSE_NOCHANNEL;
|
||||
} else
|
||||
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);
|
||||
|
||||
/* 6. trying to page mobile station */
|
||||
trans = create_transaction(cnetz, TRANS_VAK, dialing[0] - '0', dialing[1] - '0', atoi(dialing + 2), -1);
|
||||
trans = create_transaction(cnetz, (spk) ? TRANS_VAK : TRANS_WSK, dialing[0] - '0', dialing[1] - '0', atoi(dialing + 2), -1);
|
||||
if (!trans) {
|
||||
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
|
||||
return -CAUSE_TEMPFAIL;
|
||||
|
@ -632,8 +666,13 @@ void call_out_disconnect(int callref, int cause)
|
|||
default:
|
||||
PDEBUG(DCNETZ, DEBUG_INFO, "Call control disconnects on organisation channel, removing transaction.\n");
|
||||
call_in_release(callref, cause);
|
||||
destroy_transaction(trans);
|
||||
cnetz_go_idle(cnetz);
|
||||
trans->callref = 0;
|
||||
if (trans->state == TRANS_MT_QUEUE || trans->state == TRANS_MT_DELAY) {
|
||||
cnetz_release(trans, cnetz_cause_isdn2cnetz(cause));
|
||||
} else {
|
||||
destroy_transaction(trans);
|
||||
cnetz_go_idle(cnetz);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -670,8 +709,12 @@ void call_out_release(int callref, int cause)
|
|||
break;
|
||||
default:
|
||||
PDEBUG(DCNETZ, DEBUG_INFO, "Call control releases on organisation channel, removing transaction.\n");
|
||||
destroy_transaction(trans);
|
||||
cnetz_go_idle(cnetz);
|
||||
if (trans->state == TRANS_MT_QUEUE) {
|
||||
cnetz_release(trans, cnetz_cause_isdn2cnetz(cause));
|
||||
} else {
|
||||
destroy_transaction(trans);
|
||||
cnetz_go_idle(cnetz);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -767,6 +810,22 @@ void transaction_timeout(struct timer *timer)
|
|||
trans->try++;
|
||||
trans_new_state(trans, TRANS_VWG);
|
||||
break;
|
||||
case TRANS_MT_QUEUE:
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Phone in queue, but still no channel available, releasing call!\n");
|
||||
call_in_release(trans->callref, CAUSE_NOCHANNEL);
|
||||
trans->callref = 0;
|
||||
cnetz_release(trans, CNETZ_CAUSE_GASSENBESETZT);
|
||||
break;
|
||||
case TRANS_MO_QUEUE:
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Phone in queue, but still no channel available, releasing!\n");
|
||||
cnetz_release(trans, CNETZ_CAUSE_GASSENBESETZT);
|
||||
break;
|
||||
case TRANS_MT_DELAY:
|
||||
trans_new_state(trans, TRANS_VAK);
|
||||
break;
|
||||
case TRANS_MO_DELAY:
|
||||
trans_new_state(trans, TRANS_VAG);
|
||||
break;
|
||||
case TRANS_BQ:
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "No response after channel allocation 'Belegung Quittung'\n");
|
||||
trans_new_state(trans, TRANS_AF);
|
||||
|
@ -808,7 +867,7 @@ void transaction_timeout(struct timer *timer)
|
|||
destroy_transaction(trans);
|
||||
break;
|
||||
default:
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_ERROR, "Timeout unhandled in state %d\n", trans->state);
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_ERROR, "Timeout unhandled in state %" PRIu64 "\n", trans->state);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -869,13 +928,13 @@ const telegramm_t *cnetz_transmit_telegramm_rufblock(cnetz_t *cnetz)
|
|||
telegramm.zeitschlitz_nr = cnetz->sched_ts;
|
||||
telegramm.grenzwert_fuer_einbuchen_und_umbuchen = si[cnetz->cell_nr].grenz_einbuchen;
|
||||
telegramm.authentifikationsbit = cnetz->auth;
|
||||
telegramm.vermittlungstechnische_sperren = si[cnetz->cell_nr].sperre;
|
||||
telegramm.ws_kennung = 0;
|
||||
telegramm.vermittlungstechnische_sperren = si[cnetz->cell_nr].vermittlungstechnische_sperren;
|
||||
telegramm.ws_kennung = si[cnetz->cell_nr].ws_kennung;
|
||||
telegramm.reduzierungsfaktor = si[cnetz->cell_nr].reduzierung;
|
||||
telegramm.fuz_nationalitaet = si[cnetz->cell_nr].fuz_nat;
|
||||
telegramm.fuz_fuvst_nr = si[cnetz->cell_nr].fuz_fuvst;
|
||||
telegramm.fuz_rest_nr = si[cnetz->cell_nr].fuz_rest;
|
||||
telegramm.kennung_fufst = si[cnetz->cell_nr].fufst_prio;
|
||||
telegramm.kennung_fufst = si[cnetz->cell_nr].kennung_fufst;
|
||||
telegramm.nachbarschafts_prioritaets_bit = si[cnetz->cell_nr].nachbar_prio;
|
||||
telegramm.bewertung_nach_pegel_und_entfernung = si[cnetz->cell_nr].bewertung;
|
||||
telegramm.entfernungsangabe_der_fufst = si[cnetz->cell_nr].entfernung;
|
||||
|
@ -884,11 +943,12 @@ const telegramm_t *cnetz_transmit_telegramm_rufblock(cnetz_t *cnetz)
|
|||
telegramm.grenzwert_fuer_umschalten = si[cnetz->cell_nr].grenz_umschalten;
|
||||
telegramm.grenze_fuer_ausloesen = si[cnetz->cell_nr].grenz_ausloesen;
|
||||
|
||||
trans = search_transaction(cnetz, TRANS_EM | TRANS_UM | TRANS_WBN | TRANS_WBP | TRANS_VAG | TRANS_VAK);
|
||||
trans = search_transaction(cnetz, TRANS_EM | TRANS_UM | TRANS_WBN | TRANS_WBP | TRANS_VAG | TRANS_VAK | TRANS_ATQ | TRANS_VA | TRANS_WSK);
|
||||
if (trans) {
|
||||
telegramm.futln_nationalitaet = trans->futln_nat;
|
||||
telegramm.futln_heimat_fuvst_nr = trans->futln_fuvst;
|
||||
telegramm.futln_rest_nr = trans->futln_rest;
|
||||
telegramm.ausloesegrund = trans->release_cause;
|
||||
switch (trans->state) {
|
||||
case TRANS_EM:
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending acknowledgment 'Einbuchquittung' to Attachment request.\n");
|
||||
|
@ -909,16 +969,26 @@ wbn:
|
|||
break;
|
||||
case TRANS_WBP:
|
||||
spk = search_free_spk(trans->extended);
|
||||
if (!spk) {
|
||||
/* Accept call if channel available, otherwise reject or queue call */
|
||||
if (spk) {
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending call accept 'Wahlbestaetigung positiv'.\n");
|
||||
telegramm.opcode = OPCODE_WBP_R;
|
||||
trans_new_state(trans, TRANS_VAG);
|
||||
} else if (cnetz->warteschlange) {
|
||||
/* queue call if no channel is available, but queue allowed */
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "No free channel, sending call accept in queue 'Wahlbestaetigung positiv in Warteschlage'.\n");
|
||||
telegramm.opcode = OPCODE_WWBP_R;
|
||||
trans_new_state(trans, TRANS_MO_QUEUE);
|
||||
timer_start(&trans->timer, T_VAG2); /* Maximum time to hold queue */
|
||||
} else {
|
||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "No free channel anymore, rejecting call!\n");
|
||||
trans_new_state(trans, TRANS_WBN);
|
||||
goto wbn;
|
||||
}
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending call accept 'Wahlbestaetigung positiv'.\n");
|
||||
telegramm.opcode = OPCODE_WBP_R;
|
||||
trans_new_state(trans, TRANS_VAG);
|
||||
break;
|
||||
case TRANS_VAG:
|
||||
case TRANS_VAK:
|
||||
vak:
|
||||
if (trans->state == TRANS_VAG) {
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending channel assignment 'Verbindungsaufbau gehend'.\n");
|
||||
telegramm.opcode = OPCODE_VAG_R;
|
||||
|
@ -956,6 +1026,28 @@ wbn:
|
|||
/* flush all other transactions, if any (in case of OgK/SpK) */
|
||||
cnetz_flush_other_transactions(spk, trans);
|
||||
break;
|
||||
case TRANS_ATQ:
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending acknowledgment 'Quittung fuer Ausloesen des FuTelG im OgK-Betrieb' to release request.\n");
|
||||
telegramm.opcode = OPCODE_ATQ_R;
|
||||
destroy_transaction(trans);
|
||||
break;
|
||||
case TRANS_VA:
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Sending 'Vorzeitiges Ausloesen' to queued mobile station\n");
|
||||
telegramm.opcode = OPCODE_VA_R;
|
||||
destroy_transaction(trans);
|
||||
break;
|
||||
case TRANS_WSK:
|
||||
spk = search_free_spk(trans->extended);
|
||||
/* if channel becomes free before we send the queue information, we proceed with channel assignment */
|
||||
if (spk) {
|
||||
trans_new_state(trans, TRANS_VAK);
|
||||
goto vak;
|
||||
}
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "No free channel, sending incoming call in queue 'Warteschglange kommend'.\n");
|
||||
telegramm.opcode = OPCODE_WSK_R;
|
||||
trans_new_state(trans, TRANS_MT_QUEUE);
|
||||
timer_start(&trans->timer, T_VAK); /* Maximum time to hold queue */
|
||||
call_in_alerting(trans->callref);
|
||||
default:
|
||||
; /* LR */
|
||||
}
|
||||
|
@ -974,8 +1066,8 @@ const telegramm_t *cnetz_transmit_telegramm_meldeblock(cnetz_t *cnetz)
|
|||
telegramm.opcode = OPCODE_MLR_M;
|
||||
telegramm.max_sendeleistung = cnetz->ms_power;
|
||||
telegramm.ogk_verkehrsanteil = 0; /* must be 0 or phone might not respond to messages in different slot */
|
||||
telegramm.teilnehmersperre = 0;
|
||||
telegramm.anzahl_gesperrter_teilnehmergruppen = 0;
|
||||
telegramm.teilnehmergruppensperre = si[cnetz->cell_nr].teilnehmergruppensperre;
|
||||
telegramm.anzahl_gesperrter_teilnehmergruppen = si[cnetz->cell_nr].anzahl_gesperrter_teilnehmergruppen;
|
||||
telegramm.ogk_vorschlag = CNETZ_OGK_KANAL;
|
||||
telegramm.fuz_rest_nr = si[cnetz->cell_nr].fuz_rest;
|
||||
|
||||
|
@ -1014,7 +1106,6 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo
|
|||
int valid_frame = 0;
|
||||
transaction_t *trans;
|
||||
const char *rufnummer;
|
||||
cnetz_t *spk;
|
||||
|
||||
switch (opcode) {
|
||||
case OPCODE_EM_R:
|
||||
|
@ -1059,6 +1150,13 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo
|
|||
}
|
||||
valid_frame = 1;
|
||||
break;
|
||||
case OPCODE_UWG_R:
|
||||
case OPCODE_UWK_R:
|
||||
if (!match_fuz(cnetz, telegramm, cnetz->cell_nr))
|
||||
break;
|
||||
rufnummer = telegramm2rufnummer(telegramm);
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received Roaming request 'Umbuchantrag' message from Subscriber '%s' on queue\n", rufnummer);
|
||||
break;
|
||||
case OPCODE_VWG_R:
|
||||
case OPCODE_SRG_R:
|
||||
if (!match_fuz(cnetz, telegramm, cnetz->cell_nr))
|
||||
|
@ -1075,16 +1173,10 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo
|
|||
break;
|
||||
}
|
||||
trans->try = 1;
|
||||
spk = search_free_spk(trans->extended);
|
||||
if (!spk) {
|
||||
PDEBUG(DCNETZ, DEBUG_NOTICE, "Rejecting call from subscriber '%s', because we have no free channel. (or not supported by phone)\n", rufnummer);
|
||||
trans_new_state(trans, TRANS_WBN);
|
||||
break;
|
||||
}
|
||||
valid_frame = 1;
|
||||
break;
|
||||
case OPCODE_WUE_M:
|
||||
trans = search_transaction(cnetz, TRANS_WAF | TRANS_WBP | TRANS_VAG);
|
||||
trans = search_transaction(cnetz, TRANS_WAF | TRANS_WBP | TRANS_VAG | TRANS_MO_QUEUE);
|
||||
if (!trans) {
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received dialing digits 'Wahluebertragung' message without transaction, ignoring!\n");
|
||||
break;
|
||||
|
@ -1097,7 +1189,28 @@ void cnetz_receive_telegramm_ogk(cnetz_t *cnetz, telegramm_t *telegramm, int blo
|
|||
trans->try = 1; /* try */
|
||||
valid_frame = 1;
|
||||
break;
|
||||
case OPCODE_ATO_R:
|
||||
if (!match_fuz(cnetz, telegramm, cnetz->cell_nr))
|
||||
break;
|
||||
rufnummer = telegramm2rufnummer(telegramm);
|
||||
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);
|
||||
if (!trans) {
|
||||
/* 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, telegramm->erweitertes_frequenzbandbit);
|
||||
if (!trans) {
|
||||
PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to create transaction\n");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
timer_stop(&trans->timer);
|
||||
trans_new_state(trans, TRANS_ATQ);
|
||||
}
|
||||
valid_frame = 1;
|
||||
break;
|
||||
case OPCODE_MFT_M:
|
||||
if (!match_fuz(cnetz, telegramm, cnetz->cell_nr))
|
||||
break;
|
||||
trans = search_transaction_number(cnetz, telegramm->futln_nationalitaet, telegramm->futln_heimat_fuvst_nr, telegramm->futln_rest_nr);
|
||||
if (!trans) {
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_NOTICE, "Received acknowledge 'Meldung Funktelefonteilnehmer' message without transaction, ignoring!\n");
|
||||
|
@ -1392,15 +1505,23 @@ const telegramm_t *cnetz_transmit_telegramm_spk_v(cnetz_t *cnetz)
|
|||
{
|
||||
static telegramm_t telegramm;
|
||||
transaction_t *trans = cnetz->trans_list;
|
||||
int meter = 0;
|
||||
|
||||
memset(&telegramm, 0, sizeof(telegramm));
|
||||
if (!trans)
|
||||
return &telegramm;
|
||||
|
||||
if (cnetz->metering) {
|
||||
double now = get_time();
|
||||
if (!trans->call_start)
|
||||
trans->call_start = now;
|
||||
meter = (now - trans->call_start) / (double)cnetz->metering + 1;
|
||||
}
|
||||
|
||||
telegramm.max_sendeleistung = cnetz->ms_power;
|
||||
telegramm.sendeleistungsanpassung = 1;
|
||||
telegramm.ankuendigung_gespraechsende = 0;
|
||||
telegramm.gebuehren_stand = 0;
|
||||
telegramm.gebuehren_stand = meter;
|
||||
telegramm.fuz_nationalitaet = si[cnetz->cell_nr].fuz_nat;
|
||||
telegramm.fuz_fuvst_nr = si[cnetz->cell_nr].fuz_fuvst;
|
||||
telegramm.fuz_rest_nr = si[cnetz->cell_nr].fuz_rest;
|
||||
|
@ -1456,6 +1577,8 @@ void cnetz_receive_telegramm_spk_v(cnetz_t *cnetz, telegramm_t *telegramm)
|
|||
|
||||
switch (opcode) {
|
||||
case OPCODE_VH_V:
|
||||
case OPCODE_USAI_V:
|
||||
case OPCODE_USAE_V:
|
||||
if (!match_fuz(cnetz, telegramm, cnetz->cell_nr)) {
|
||||
break;
|
||||
}
|
||||
|
@ -1465,7 +1588,17 @@ void cnetz_receive_telegramm_spk_v(cnetz_t *cnetz, telegramm_t *telegramm)
|
|||
if (trans->state != TRANS_VHQ)
|
||||
break;
|
||||
timer_start(&trans->timer, 0.6 * F_VHQ); /* F_VHQ frames */
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received supervisory frame 'Verbindung halten' message.\n");
|
||||
switch (opcode) {
|
||||
case OPCODE_VH_V:
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received supervisory frame 'Verbindung halten' message%s.\n", (telegramm->test_telefonteilnehmer_geraet) ? ", phone is a test-phone" : "");
|
||||
break;
|
||||
case OPCODE_USAI_V:
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received internal handover request frame 'Umschaltantrag intern' message%s.\n", (telegramm->test_telefonteilnehmer_geraet) ? ", phone is a test-phone" : "");
|
||||
break;
|
||||
case OPCODE_USAE_V:
|
||||
PDEBUG_CHAN(DCNETZ, DEBUG_INFO, "Received external handover request frame 'Umschaltantrag extern' message%s.\n", (telegramm->test_telefonteilnehmer_geraet) ? ", phone is a test-phone" : "");
|
||||
break;
|
||||
}
|
||||
valid_frame = 1;
|
||||
cnetz->scrambler = telegramm->betriebs_art;
|
||||
break;
|
||||
|
|
|
@ -37,6 +37,8 @@ enum cnetz_state {
|
|||
#define N_AFKT 6 /* number of release frames to send during concentrated signaling */
|
||||
#define N_AFV 4 /* number of release frames to send during distributed signaling */
|
||||
#define N 3 /* now many times we repeat a message on OgK */
|
||||
#define T_VAG2 180 /* time on outgoing queue */
|
||||
#define T_VAK 60 /* time on incoming queue */
|
||||
|
||||
/* clear causes */
|
||||
#define CNETZ_CAUSE_GASSENBESETZT 0 /* network congested */
|
||||
|
@ -71,6 +73,8 @@ typedef struct cnetz {
|
|||
/* cell config */
|
||||
int ms_power; /* power level of MS, use 0..3 */
|
||||
int auth; /* authentication support of the cell */
|
||||
int warteschlange; /* use queue */
|
||||
int metering; /* use metering pulses in seconds 0 = off */
|
||||
|
||||
/* all cnetz states */
|
||||
enum cnetz_state state; /* main state of sender */
|
||||
|
@ -127,7 +131,7 @@ int cnetz_channel_by_short_name(const char *short_name);
|
|||
const char *chan_type_short_name(enum cnetz_chan_type chan_type);
|
||||
const char *chan_type_long_name(enum cnetz_chan_type chan_type);
|
||||
int cnetz_init(void);
|
||||
int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *audiodev, int use_sdr, enum demod_type demod, int samplerate, double rx_gain, int auth, 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(int kanal, enum cnetz_chan_type chan_type, const char *audiodev, int use_sdr, enum demod_type demod, int samplerate, double rx_gain, int auth, int warteschlange, int metering, 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);
|
||||
void cnetz_destroy(sender_t *sender);
|
||||
void cnetz_go_idle(cnetz_t *cnetz);
|
||||
void cnetz_sync_frame(cnetz_t *cnetz, double sync, int ts);
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#define MELDE_MAXIMAL 3
|
||||
|
||||
typedef struct cnetz_database {
|
||||
|
||||
struct cnetz_database *next;
|
||||
uint8_t futln_nat; /* who ... */
|
||||
uint8_t futln_fuvst;
|
||||
|
@ -154,10 +155,10 @@ int find_db(uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest)
|
|||
if (db->futln_nat == futln_nat
|
||||
&& db->futln_fuvst == futln_fuvst
|
||||
&& db->futln_rest == futln_rest)
|
||||
return 1;
|
||||
return db->extended;
|
||||
db = db->next;
|
||||
}
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void flush_db(void)
|
||||
|
|
243
src/cnetz/main.c
243
src/cnetz/main.c
|
@ -47,7 +47,27 @@ int set_clock_speed = 0;
|
|||
const char *flip_polarity = "auto";
|
||||
int ms_power = 0; /* 0..3 */
|
||||
int auth = 0;
|
||||
int warteschlange = 1;
|
||||
uint8_t fuz_nat = 1;
|
||||
uint8_t fuz_fuvst = 1;
|
||||
uint8_t fuz_rest = 38;
|
||||
uint8_t kennung_fufst = 1; /* normal prio */
|
||||
uint8_t ws_kennung = 0; /* no queue */
|
||||
uint8_t fuvst_sperren = 0; /* no blocking registration/calls */
|
||||
uint8_t grenz_einbuchen = 1; /* > 15 SNR */
|
||||
uint8_t grenz_umschalten = 15; /* < 18 SNR */
|
||||
uint8_t grenz_ausloesen = 15; /* < 18 SNR */
|
||||
uint8_t mittel_umschalten = 5; /* 64 Frames */
|
||||
uint8_t mittel_ausloesen = 5; /* 64 Frames */
|
||||
uint8_t genauigkeit = 1; /* limited accuracy */
|
||||
uint8_t bewertung = 1; /* rating by level */
|
||||
uint8_t entfernung = 3; /* 3km */
|
||||
uint8_t reduzierung = 0; /* factor 4 */
|
||||
uint8_t nachbar_prio = 0;
|
||||
int8_t futln_sperre_start = -1; /* no blocking */
|
||||
int8_t futln_sperre_end = -1; /* no range */
|
||||
enum demod_type demod = FSK_DEMOD_AUTO;
|
||||
int metering = 20;
|
||||
|
||||
void print_help(const char *arg0)
|
||||
{
|
||||
|
@ -57,7 +77,7 @@ void print_help(const char *arg0)
|
|||
printf(" Give channel type, use 'list' to get a list. (default = '%s')\n", chan_type_short_name(chan_type[0]));
|
||||
printf(" -M --measure-speed\n");
|
||||
printf(" Measures clock speed. THIS IS REQUIRED! See documentation!\n");
|
||||
printf(" -S --clock-speed <rx ppm>,<tx ppm>\n");
|
||||
printf(" -C --clock-speed <rx ppm>,<tx ppm>\n");
|
||||
printf(" Correct speed of sound card's clock. Use '-M' to measure speed for\n");
|
||||
printf(" some hours after temperature has settled. The use these results to\n");
|
||||
printf(" correct signal processing speed. After adjustment, the clock must match\n");
|
||||
|
@ -69,6 +89,7 @@ void print_help(const char *arg0)
|
|||
printf(" base station generates two virtual base stations with both polarities.\n");
|
||||
printf(" Once a mobile registers, the correct polarity is selected and used.\n");
|
||||
printf(" (default = %s)\n", flip_polarity);
|
||||
printf(" Note: This has no effect with SDR.\n");
|
||||
printf(" -P --ms-power <power level>\n");
|
||||
printf(" Give power level of the mobile station 0..3. (default = '%d')\n", ms_power);
|
||||
printf(" 0 = 50-125 mW; 1 = 0.5-1 W; 2 = 4-8 W; 3 = 10-20 W\n");
|
||||
|
@ -76,6 +97,90 @@ void print_help(const char *arg0)
|
|||
printf(" Enable authentication on the base station. Since we cannot\n");
|
||||
printf(" authenticate, because we don't know the secret key and the algorithm,\n");
|
||||
printf(" we just accept any card. With this we get the vendor IDs of the phone.\n");
|
||||
printf(" -Q --queue | --warteschlange 1 | 0\n");
|
||||
printf(" Enable queue support. If no channel is available, calls will be kept\n");
|
||||
printf(" in a queue for maximum of 60 seconds. (default = %d)\n", warteschlange);
|
||||
printf(" -G --gebuehren <seconds> | 0\n");
|
||||
printf(" Increment metering counter every given number of seconds.\n");
|
||||
printf(" To turn off, use 0. (default = %d)\n", metering);
|
||||
printf(" -S --sysinfo fuz-nat=<nat>\n");
|
||||
printf(" Set country ID of base station. All IDs were used inside Germany only.\n");
|
||||
printf(" (default = %d)\n", fuz_nat);
|
||||
printf(" -S --sysinfo fuz-fuvst=<id>\n");
|
||||
printf(" Set switching center ID of base station. (default = %d)\n", fuz_fuvst);
|
||||
printf(" -S --sysinfo fuz-rest=<id>\n");
|
||||
printf(" Set cell ID of base station. (default = %d)\n", fuz_rest);
|
||||
printf(" -S --sysinfo kennung-fufst=<id>\n");
|
||||
printf(" Set priority for selecting base station. (default = %d)\n", kennung_fufst);
|
||||
printf(" 0 = Test (Only special mobile stations may register.)\n");
|
||||
printf(" 1 = Normal priority base station.\n");
|
||||
printf(" 2 = Higher priority base station.\n");
|
||||
printf(" 3 = Highest priority base station.\n");
|
||||
printf(" Note: Priority has no effect, because there is only one base station.\n");
|
||||
printf(" -S --sysinfo ws-kennung=<value>\n");
|
||||
printf(" Queue setting of base station. (default = %d)\n", ws_kennung);
|
||||
printf(" 0 = No queue, calls will be handled directly.\n");
|
||||
printf(" 1 = Queue on outgoing calls.\n");
|
||||
printf(" 2 = Queue blocked, no calls allowed.\n");
|
||||
printf(" 3 = Reserved, don't use!\n");
|
||||
printf(" -S --sysinfo fuvst-sperren=<value>\n");
|
||||
printf(" Blocking registration and outgoing calls. (default = %d)\n", fuvst_sperren);
|
||||
printf(" 0 = Registration and outgoing calls allowed.\n");
|
||||
printf(" 1 = Only registration alloweed.\n");
|
||||
printf(" 2 = Only outgoing calls allowed. (Cannot work without registration!)\n");
|
||||
printf(" 3 = No registration and no outgoing calls allowed.\n");
|
||||
printf(" -S --sysinfo grenz-einbuchen=<value>\n");
|
||||
printf(" Minimum SNR to allow registration of mobile (default = %d)\n", grenz_einbuchen);
|
||||
printf(" 0 = No limit; 1 = >15 dB; 2 = >17 dB; 3 = >19 dB\n");
|
||||
printf(" 4 = >21 dB; 5 = >25 dB; 6 = >28 dB; 7 = >32 dB\n");
|
||||
printf(" -S --sysinfo grenz-umschalten=<value>\n");
|
||||
printf(" Minimum SNR before phone requests handover (default = %d)\n", grenz_umschalten);
|
||||
printf(" 15 = 18 dB ... 0 = 26 dB (external)\n");
|
||||
printf(" 13 = 16 dB ... 0 = 22 dB (internal)\n");
|
||||
printf(" -S --sysinfo grenz-ausloesen=<value>\n");
|
||||
printf(" Minimum SNR before phone releases of call (default = %d)\n", grenz_ausloesen);
|
||||
printf(" 15 = 18 dB ... 0 = 26 dB\n");
|
||||
printf(" -S --sysinfo mittel-umschalten=<value>\n");
|
||||
printf(" Number of frames to measure for handover criterium (default = %d)\n", mittel_umschalten);
|
||||
printf(" 0 = 2 measurements; 1 = 4 measurements; 2 = 8 measurememnts\n");
|
||||
printf(" 3 = 16 measurements; 4 = 32 measurements; 5 = 64 measurememnts\n");
|
||||
printf(" -S --sysinfo mittel-ausloesen=<value>\n");
|
||||
printf(" Number of frames to measure for release criterium (default = %d)\n", mittel_ausloesen);
|
||||
printf(" 0 = 2 measurements; 1 = 4 measurements; 2 = 8 measurememnts\n");
|
||||
printf(" 3 = 16 measurements; 4 = 32 measurements; 5 = 64 measurememnts\n");
|
||||
printf(" -S --sysinfo genauigkeit=<value>\n");
|
||||
printf(" Accuracy of base station (default = %d)\n", genauigkeit);
|
||||
printf(" 0 = full accuracy; 1 = limited accuracy\n");
|
||||
printf(" Note: This has no effect, because there is only one base station.\n");
|
||||
printf(" -S --sysinfo bewertung=<value>\n");
|
||||
printf(" Rating of base station (default = %d)\n", bewertung);
|
||||
printf(" 0 = by relative distance; 1 = by received level\n");
|
||||
printf(" Note: This has no effect, because there is only one base station.\n");
|
||||
printf(" -S --sysinfo entfernung=<value>\n");
|
||||
printf(" Base station size (default = %d)\n", entfernung);
|
||||
printf(" 0 = 1.5km; 1 = 2km; 2 = 2.5km; 3 = 3km; 4 = 5km; 5 = 5km\n");
|
||||
printf(" 6 = 6km; 7 = 7km; 8 = 8km; 9 = 10km; 10 = 12km; 11 = 14km\n");
|
||||
printf(" 12 = 16km; 13 = 17km; 14 = 23km; 15 = 30km\n");
|
||||
printf(" Note: This has no effect, because there is only one base station.\n");
|
||||
printf(" -S --sysinfo reduzierung=<value>\n");
|
||||
printf(" See specs value 'y' (default = %d)\n", reduzierung);
|
||||
printf(" 0 = 4; 1 = 3; 2 = 2; 3 = 1\n");
|
||||
printf(" Note: This has no effect, because there is only one base station.\n");
|
||||
printf(" -S --sysinfo nachbar-prio=<value>\n");
|
||||
printf(" See specs value 'g' (default = %d)\n", nachbar_prio);
|
||||
printf(" Note: This has no effect, because there is only one base station.\n");
|
||||
printf(" -S --sysinfo futln-sperre=<value>[-<value>]\n");
|
||||
printf(" Blocking registration and outgoing calls for selected mobile stations.\n");
|
||||
printf(" The 4 least significant bits of the subscriber number can be given to\n");
|
||||
printf(" block all matching phones. Alternatively the phone number may be given\n");
|
||||
printf(" here, so that the 4 bits get calculated automatically. The optional\n");
|
||||
printf(" second value can be given, to define a range - in the same way.\n");
|
||||
if (futln_sperre_start < 0)
|
||||
printf(" (default = no value given)\n");
|
||||
else if (futln_sperre_end < 0)
|
||||
printf(" (default = %d)\n", futln_sperre_start);
|
||||
else
|
||||
printf(" (default = %d-%d)\n", futln_sperre_start, futln_sperre_end);
|
||||
printf(" -D --demod auto | slope | level\n");
|
||||
printf(" Adjust demodulation algorithm. Use 'slope' to detect a level change\n");
|
||||
printf(" by finding the highest slope of a bit transition. It is useful, if\n");
|
||||
|
@ -91,6 +196,27 @@ void print_help(const char *arg0)
|
|||
printf("Press 'i' key to dump list of currently attached subscribers.\n");
|
||||
}
|
||||
|
||||
static int atoi_limit(const char *p, int l1, int l2)
|
||||
{
|
||||
int value = atoi(p);
|
||||
|
||||
if (l1 < l2) {
|
||||
if (value < l1)
|
||||
value = l1;
|
||||
if (value > l2)
|
||||
value = l2;
|
||||
} else {
|
||||
if (value < l2)
|
||||
value = l2;
|
||||
if (value > l1)
|
||||
value = l1;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
#define OPT_WARTESCHLANGE 256
|
||||
|
||||
static int handle_options(int argc, char **argv)
|
||||
{
|
||||
int skip_args = 0;
|
||||
|
@ -100,15 +226,19 @@ static int handle_options(int argc, char **argv)
|
|||
static struct option long_options_special[] = {
|
||||
{"channel-type", 1, 0, 'T'},
|
||||
{"measure-speed", 0, 0, 'M'},
|
||||
{"clock-speed", 1, 0, 'S'},
|
||||
{"clock-speed", 1, 0, 'C'},
|
||||
{"flip-polarity", 1, 0, 'F'},
|
||||
{"ms-power", 1, 0, 'P'},
|
||||
{"authentication", 0, 0, 'A'},
|
||||
{"queue", 1, 0, 'Q'},
|
||||
{"warteschlange", 1, 0, OPT_WARTESCHLANGE},
|
||||
{"gebuehren", 1, 0, 'G'},
|
||||
{"sysinfo", 1, 0, 'S'},
|
||||
{"demod", 1, 0, 'D'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
|
||||
set_options_common("T:MS:F:N:P:AD:", long_options_special);
|
||||
set_options_common("T:MC:F:P:AQ:G:S:D:", long_options_special);
|
||||
|
||||
while (1) {
|
||||
int option_index = 0, c;
|
||||
|
@ -136,7 +266,7 @@ static int handle_options(int argc, char **argv)
|
|||
measure_speed = 1;
|
||||
skip_args++;
|
||||
break;
|
||||
case 'S':
|
||||
case 'C':
|
||||
p = strchr(optarg, ',');
|
||||
if (!p) {
|
||||
fprintf(stderr, "Illegal clock speed, use two values, seperated by comma and no spaces!\n");
|
||||
|
@ -161,17 +291,97 @@ static int handle_options(int argc, char **argv)
|
|||
skip_args += 2;
|
||||
break;
|
||||
case 'P':
|
||||
ms_power = atoi(optarg);
|
||||
if (ms_power > 3)
|
||||
ms_power = 3;
|
||||
if (ms_power < 0)
|
||||
ms_power = 0;
|
||||
ms_power = atoi_limit(optarg, 0, 3);
|
||||
skip_args += 2;
|
||||
break;
|
||||
case 'A':
|
||||
auth = 1;
|
||||
skip_args += 1;
|
||||
break;
|
||||
case 'Q':
|
||||
case OPT_WARTESCHLANGE:
|
||||
warteschlange = atoi_limit(optarg, 0, 1);;
|
||||
skip_args += 2;
|
||||
break;
|
||||
case 'G':
|
||||
metering = atoi(optarg);
|
||||
skip_args += 2;
|
||||
break;
|
||||
case 'S':
|
||||
p = strchr(optarg, '=');
|
||||
if (!p) {
|
||||
fprintf(stderr, "Given sysinfo parameter '%s' requires '=' character to set value, see help!\n", optarg);
|
||||
exit(0);
|
||||
}
|
||||
p++;
|
||||
if (!strncasecmp(optarg, "fuz-nat=", p - optarg)) {
|
||||
fuz_nat = atoi_limit(p, 0, 7);
|
||||
} else
|
||||
if (!strncasecmp(optarg, "fuz-fuvst=", p - optarg)) {
|
||||
fuz_fuvst = atoi_limit(p, 0, 32);
|
||||
} else
|
||||
if (!strncasecmp(optarg, "fuz-rest=", p - optarg)) {
|
||||
fuz_rest = atoi_limit(p, 0, 255);
|
||||
} else
|
||||
if (!strncasecmp(optarg, "kennung-fufst=", p - optarg)) {
|
||||
kennung_fufst = atoi_limit(p, 0, 3);
|
||||
} else
|
||||
if (!strncasecmp(optarg, "ws-kennung=", p - optarg)) {
|
||||
ws_kennung = atoi_limit(p, 0, 3);
|
||||
} else
|
||||
if (!strncasecmp(optarg, "fuvst-sperren=", p - optarg)) {
|
||||
fuvst_sperren = atoi_limit(p, 0, 3);
|
||||
} else
|
||||
if (!strncasecmp(optarg, "grenz-einbuchen=", p - optarg)) {
|
||||
grenz_einbuchen = atoi_limit(p, 0, 7);
|
||||
} else
|
||||
if (!strncasecmp(optarg, "grenz-umschalten=", p - optarg)) {
|
||||
grenz_umschalten = atoi_limit(p, 0, 15);
|
||||
} else
|
||||
if (!strncasecmp(optarg, "grenz-ausloesen=", p - optarg)) {
|
||||
grenz_ausloesen = atoi_limit(p, 0, 15);
|
||||
} else
|
||||
if (!strncasecmp(optarg, "mittel-umschalten=", p - optarg)) {
|
||||
mittel_umschalten = atoi_limit(p, 0, 5);
|
||||
} else
|
||||
if (!strncasecmp(optarg, "mittel-ausloesen=", p - optarg)) {
|
||||
mittel_ausloesen = atoi_limit(p, 0, 5);
|
||||
} else
|
||||
if (!strncasecmp(optarg, "genauigkeit=", p - optarg)) {
|
||||
genauigkeit = atoi_limit(p, 0, 1);
|
||||
} else
|
||||
if (!strncasecmp(optarg, "bewertung=", p - optarg)) {
|
||||
bewertung = atoi_limit(p, 0, 1);
|
||||
} else
|
||||
if (!strncasecmp(optarg, "entfernung=", p - optarg)) {
|
||||
entfernung = atoi_limit(p, 0, 15);
|
||||
} else
|
||||
if (!strncasecmp(optarg, "nachbar-prio=", p - optarg)) {
|
||||
nachbar_prio = atoi_limit(p, 0, 1);
|
||||
} else
|
||||
if (!strncasecmp(optarg, "futln-sperre=", p - optarg)) {
|
||||
char value[128], *v, *q;
|
||||
strncpy(value, p, sizeof(value) - 1);
|
||||
value[sizeof(value) - 1] = '\0';
|
||||
v = value;
|
||||
q = strchr(value, '-');
|
||||
if (q)
|
||||
*q++ = '\0';
|
||||
if (strlen(v) > 5)
|
||||
v += strlen(v) - 5;
|
||||
futln_sperre_start = atoi(v) & 0xf;
|
||||
if (q) {
|
||||
if (strlen(q) > 5)
|
||||
q += strlen(q) - 5;
|
||||
futln_sperre_end = atoi(q) & 0xf;
|
||||
}
|
||||
} else
|
||||
{
|
||||
fprintf(stderr, "Given sysinfo parameter '%s' unknown, see help!\n", optarg);
|
||||
exit(0);
|
||||
}
|
||||
skip_args += 2;
|
||||
break;
|
||||
case 'D':
|
||||
if (!strcasecmp(optarg, "auto"))
|
||||
demod = FSK_DEMOD_AUTO;
|
||||
|
@ -202,6 +412,8 @@ int main(int argc, char *argv[])
|
|||
const char *station_id = "";
|
||||
int mandatory = 0;
|
||||
int polarity;
|
||||
int teilnehmergruppensperre = 0;
|
||||
int anzahl_gesperrter_teilnehmergruppen = 0;
|
||||
int i;
|
||||
|
||||
/* init common tones */
|
||||
|
@ -266,7 +478,16 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* init functions */
|
||||
scrambler_init();
|
||||
init_sysinfo();
|
||||
if (futln_sperre_start >= 0) {
|
||||
teilnehmergruppensperre = futln_sperre_start;
|
||||
if (futln_sperre_end >= 0)
|
||||
anzahl_gesperrter_teilnehmergruppen = ((futln_sperre_end - futln_sperre_start) & 0xf) + 1;
|
||||
else
|
||||
anzahl_gesperrter_teilnehmergruppen = 1;
|
||||
}
|
||||
if (anzahl_gesperrter_teilnehmergruppen)
|
||||
printf("Blocked subscriber with number's last 4 bits from 0x%x to 0x%x\n", teilnehmergruppensperre, (teilnehmergruppensperre + anzahl_gesperrter_teilnehmergruppen - 1) & 0xf);
|
||||
init_sysinfo(fuz_nat, fuz_fuvst, fuz_rest, kennung_fufst, ws_kennung, fuvst_sperren, grenz_einbuchen, grenz_umschalten, grenz_ausloesen, mittel_umschalten, mittel_ausloesen, genauigkeit, bewertung, entfernung, reduzierung, nachbar_prio, teilnehmergruppensperre, anzahl_gesperrter_teilnehmergruppen);
|
||||
dsp_init();
|
||||
rc = init_telegramm();
|
||||
if (rc < 0) {
|
||||
|
@ -336,7 +557,7 @@ int main(int argc, char *argv[])
|
|||
|
||||
/* create transceiver instance */
|
||||
for (i = 0; i < num_kanal; i++) {
|
||||
rc = cnetz_create(kanal[i], chan_type[i], audiodev[i], use_sdr, demod, samplerate, rx_gain, auth, ms_power, (i == 0) ? measure_speed : 0, clock_speed, polarity, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, read_tx_wave, loopback);
|
||||
rc = cnetz_create(kanal[i], chan_type[i], audiodev[i], use_sdr, demod, samplerate, rx_gain, auth, warteschlange, metering, ms_power, (i == 0) ? measure_speed : 0, clock_speed, polarity, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, read_tx_wave, loopback);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Failed to create \"Sender\" instance. Quitting!\n");
|
||||
goto fail;
|
||||
|
|
|
@ -4,61 +4,57 @@
|
|||
|
||||
cnetz_si si[2];
|
||||
|
||||
void init_sysinfo(void)
|
||||
void init_sysinfo(uint8_t fuz_nat, uint8_t fuz_fuvst, uint8_t fuz_rest, uint8_t kennung_fufst, uint8_t ws_kennung, uint8_t vermittlungstechnische_sperren, uint8_t grenz_einbuchen, uint8_t grenz_umschalten, uint8_t grenz_ausloesen, uint8_t mittel_umschalten, uint8_t mittel_ausloesen, uint8_t genauigkeit, uint8_t bewertung, uint8_t entfernung, uint8_t reduzierung, uint8_t nachbar_prio, int8_t teilnehmergruppensperre, uint8_t anzahl_gesperrter_teilnehmergruppen)
|
||||
{
|
||||
memset(&si, 0, sizeof(si));
|
||||
memset(&si[0], 0, sizeof(cnetz_si));
|
||||
|
||||
/* polarity of TX signal */
|
||||
si[0].flip_polarity = 0;
|
||||
|
||||
/* ID of base station */
|
||||
si[0].fuz_nat = fuz_nat;
|
||||
si[0].fuz_fuvst = fuz_fuvst;
|
||||
si[0].fuz_rest = fuz_rest;
|
||||
|
||||
/* a low value causes quicker measurement results */
|
||||
si[0].mittel_umschalten = mittel_umschalten; /* 0..5 */
|
||||
|
||||
/* a high value is tollerant to bad quality */
|
||||
si[0].grenz_umschalten = grenz_umschalten; /* 0..15 */
|
||||
|
||||
/* a low value causes quicker measurement results */
|
||||
si[0].mittel_ausloesen = mittel_ausloesen; /* 0..5 */
|
||||
|
||||
/* a high value is tollerant to bad quality */
|
||||
si[0].grenz_ausloesen = grenz_ausloesen; /* 0..15 */
|
||||
|
||||
si[0].vermittlungstechnische_sperren = vermittlungstechnische_sperren;
|
||||
|
||||
si[0].genauigkeit = genauigkeit; /* 1 = bedingte Genauigkeit */
|
||||
|
||||
si[0].entfernung = entfernung;
|
||||
|
||||
/* a low value is tollerant to bad quality */
|
||||
si[0].grenz_einbuchen = grenz_einbuchen; /* 1..7 */
|
||||
|
||||
si[0].kennung_fufst = kennung_fufst;
|
||||
|
||||
si[0].ws_kennung = ws_kennung;
|
||||
|
||||
si[0].nachbar_prio = nachbar_prio;
|
||||
|
||||
si[0].bewertung = bewertung; /* 0 = relative entfernung, 1 = pegel */
|
||||
|
||||
si[0].reduzierung = reduzierung;
|
||||
|
||||
/* deny group of subscribers. (used to balance subscribers between base stations) */
|
||||
si[0].teilnehmergruppensperre = teilnehmergruppensperre;
|
||||
si[0].anzahl_gesperrter_teilnehmergruppen = anzahl_gesperrter_teilnehmergruppen;
|
||||
|
||||
/* second cell uses flipped polarity. different station ID is used to
|
||||
* detect what cell (and what polarity) the mobile responses to. */
|
||||
memcpy(&si[1], &si[0], sizeof(cnetz_si));
|
||||
si[1].flip_polarity = 1;
|
||||
|
||||
si[0].fuz_nat = 1;
|
||||
si[1].fuz_nat = 1;
|
||||
|
||||
si[0].fuz_fuvst = 1;
|
||||
si[1].fuz_fuvst = 1;
|
||||
|
||||
si[0].fuz_rest = 38;
|
||||
si[1].fuz_rest = 39;
|
||||
|
||||
/* a low value causes quicker measurement results */
|
||||
si[0].mittel_umschalten = 5; /* 0..5 */
|
||||
si[1].mittel_umschalten = 5;
|
||||
|
||||
/* a low value is tollerant to bad quality */
|
||||
si[0].grenz_umschalten = 0; /* 0..13 */
|
||||
si[1].grenz_umschalten = 0; /* 0..13 */
|
||||
|
||||
/* a low value causes quicker measurement results */
|
||||
si[0].mittel_ausloesen = 5; /* 0..5 */
|
||||
si[1].mittel_ausloesen = 5;
|
||||
|
||||
/* a low value is tollerant to bad quality */
|
||||
si[0].grenz_ausloesen = 0; /* 0..13 */
|
||||
si[1].grenz_ausloesen = 0; /* 0..13 */
|
||||
|
||||
si[0].sperre = 0;
|
||||
si[1].sperre = 0;
|
||||
|
||||
si[0].genauigkeit = 1; /* bedingte Genauigkeit */
|
||||
si[1].genauigkeit = 1; /* bedingte Genauigkeit */
|
||||
|
||||
si[0].entfernung = 3;
|
||||
si[1].entfernung = 3;
|
||||
|
||||
/* a low value is tollerant to bad quality */
|
||||
si[0].grenz_einbuchen = 1; /* 1..7 */
|
||||
si[1].grenz_einbuchen = 1;
|
||||
|
||||
si[0].fufst_prio = 1; /* normal pio */
|
||||
si[1].fufst_prio = 1; /* normal pio */
|
||||
|
||||
si[0].nachbar_prio = 0;
|
||||
si[1].nachbar_prio = 0;
|
||||
|
||||
si[0].bewertung = 1; /* pegel */
|
||||
si[1].bewertung = 1; /* pegel */
|
||||
|
||||
si[0].reduzierung = 0;
|
||||
si[1].reduzierung = 0;
|
||||
si[1].fuz_rest = si[0].fuz_rest + 1;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,17 +8,20 @@ typedef struct system_information {
|
|||
uint8_t grenz_umschalten;
|
||||
uint8_t mittel_ausloesen;
|
||||
uint8_t grenz_ausloesen;
|
||||
uint8_t sperre;
|
||||
uint8_t vermittlungstechnische_sperren;
|
||||
uint8_t genauigkeit;
|
||||
uint8_t entfernung;
|
||||
uint8_t grenz_einbuchen;
|
||||
uint8_t fufst_prio; /* prio of base station */
|
||||
uint8_t kennung_fufst; /* prio of base station */
|
||||
uint8_t ws_kennung; /* queue setting sof base station */
|
||||
uint8_t nachbar_prio;
|
||||
uint8_t bewertung;
|
||||
uint8_t reduzierung;
|
||||
int8_t teilnehmergruppensperre;
|
||||
int8_t anzahl_gesperrter_teilnehmergruppen;
|
||||
} cnetz_si;
|
||||
|
||||
extern cnetz_si si[];
|
||||
|
||||
void init_sysinfo(void);
|
||||
void init_sysinfo(uint8_t fuz_nat, uint8_t fuz_fuvst, uint8_t fuz_rest, uint8_t kennung_fufst, uint8_t ws_kennung, uint8_t vermittlungstechnische_sperren, uint8_t grenz_einbuchen, uint8_t grenz_umschalten, uint8_t grenz_ausloesen, uint8_t mittel_umschalten, uint8_t mittel_ausloesen, uint8_t genauigkeit, uint8_t bewertung, uint8_t entfernung, uint8_t reduzierung, uint8_t nachbar_prio, int8_t teilnehmergruppensperre, uint8_t anzahl_gesperrter_teilnehmergruppen);
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ static const char *param_genauigkeit[] = {
|
|||
};
|
||||
|
||||
static const char *param_grenzwert[] = {
|
||||
"Illegaler Parameter 0",
|
||||
"No limit",
|
||||
"> 15 dB S/N",
|
||||
"> 17 dB S/N",
|
||||
"> 19 dB S/N",
|
||||
|
@ -272,7 +272,7 @@ static struct definition_parameter {
|
|||
{ 'U',"FuTln-Heimmat FuVSt-Nr.", 5, NULL },
|
||||
{ 'V',"Sicherungs-Code", 16, NULL },
|
||||
{ 'W',"WS-Kennung", 2, param_wskennung },
|
||||
{ 'X',"Wahlziffer beliebig 16 Ziffer", 64, NULL },
|
||||
{ 'X',"Wahlziffer beliebig 16 Ziffern", 64, NULL },
|
||||
{ 'Z',"Zeitschlitz-Nr.", 5, NULL },
|
||||
{ 'a',"Grenzert fuer Ausloesen", 4, param_ausloesen },
|
||||
{ 'b',"Chipkarten-FuTelG-Bit", 1, param_chipkarte },
|
||||
|
@ -363,7 +363,7 @@ static struct definition_opcode {
|
|||
{ "________________________________________________________________", NULL, "opcode 34",BLOCK_I,"Illegaler Opcode" },
|
||||
{ "PPdZZZZZ----------------IIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "EBQ(R)", BLOCK_R,"Einbuchquittung" },
|
||||
{ "PPdZZZZZ----------------IIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "UBQ(R)", BLOCK_R,"Umbuchquittung" },
|
||||
{ "PPdZZZZZ----------------IIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "WSK(R)", BLOCK_R,"Wartescglange kommend" },
|
||||
{ "PPdZZZZZ----------------IIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "WSK(R)", BLOCK_R,"Warteschglange kommend" },
|
||||
{ "PP-MMMMMDDDDEEEE------HHHHHHHHHHFFFFFFFF------------------------", NULL, "MLR(M)", BLOCK_M,"Melde-Leer-Ruf" },
|
||||
{ "PPdZZZZZffflvvWW------yyIIIAAAAAFFFFFFFFkkgprrrrmmmmnnnnuuuuaaaa", NULL, "LR(R)", BLOCK_R,"Leer-Ruf" },
|
||||
{ "PPdZZZZZ----------------IIIAAAAAFFFFFFFFNNNUUUUUTTTTTTTTTTTTTTTT", NULL, "ATQ(R)", BLOCK_R,"Quittung fuer Ausloesen des FuTelG im OgK-Betrieb" },
|
||||
|
@ -655,7 +655,7 @@ static char *assemble_telegramm(const telegramm_t *telegramm, int debug)
|
|||
value = telegramm->ankuendigung_gespraechsende;
|
||||
break;
|
||||
case 'D':
|
||||
value = telegramm->teilnehmersperre;
|
||||
value = telegramm->teilnehmergruppensperre;
|
||||
break;
|
||||
case 'E':
|
||||
value = telegramm->anzahl_gesperrter_teilnehmergruppen;
|
||||
|
@ -868,7 +868,7 @@ static void disassemble_telegramm(telegramm_t *telegramm, const char *bits, int
|
|||
telegramm->ankuendigung_gespraechsende = value;
|
||||
break;
|
||||
case 'D':
|
||||
telegramm->teilnehmersperre = value;
|
||||
telegramm->teilnehmergruppensperre = value;
|
||||
break;
|
||||
case 'E':
|
||||
telegramm->anzahl_gesperrter_teilnehmergruppen = value;
|
||||
|
@ -1533,7 +1533,7 @@ selected:
|
|||
nr = 1;
|
||||
goto selected;
|
||||
} else {
|
||||
PDEBUG(DFRAME, DEBUG_NOTICE, "Received Telegramm with no cell number, ignoring!\n");
|
||||
PDEBUG(DFRAME, DEBUG_NOTICE, "Received Telegramm with unknown cell number, ignoring!\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ typedef struct telegramm {
|
|||
uint8_t fuz_fuvst_nr;
|
||||
uint8_t betriebs_art;
|
||||
uint8_t ankuendigung_gespraechsende;
|
||||
uint8_t teilnehmersperre;
|
||||
uint8_t teilnehmergruppensperre;
|
||||
uint8_t anzahl_gesperrter_teilnehmergruppen;
|
||||
uint8_t fuz_rest_nr;
|
||||
uint16_t gebuehren_stand;
|
||||
|
|
|
@ -39,7 +39,7 @@ const char *transaction2rufnummer(transaction_t *trans)
|
|||
}
|
||||
|
||||
/* create transaction */
|
||||
transaction_t *create_transaction(cnetz_t *cnetz, uint32_t state, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, 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 extended)
|
||||
{
|
||||
sender_t *sender;
|
||||
transaction_t *trans = NULL;
|
||||
|
@ -80,7 +80,7 @@ transaction_t *create_transaction(cnetz_t *cnetz, uint32_t state, uint8_t futln_
|
|||
|
||||
if (state == TRANS_VWG)
|
||||
trans->mo_call = 1;
|
||||
if (state == TRANS_VAK)
|
||||
if (state == TRANS_VAK || state == TRANS_WSK)
|
||||
trans->mt_call = 1;
|
||||
|
||||
const char *rufnummer = transaction2rufnummer(trans);
|
||||
|
@ -147,7 +147,7 @@ void unlink_transaction(transaction_t *trans)
|
|||
cnetz_display_status();
|
||||
}
|
||||
|
||||
transaction_t *search_transaction(cnetz_t *cnetz, uint32_t state_mask)
|
||||
transaction_t *search_transaction(cnetz_t *cnetz, uint64_t state_mask)
|
||||
{
|
||||
transaction_t *trans = cnetz->trans_list;
|
||||
|
||||
|
@ -200,7 +200,7 @@ transaction_t *search_transaction_callref(cnetz_t *cnetz, int callref)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static const char *trans_state_name(int state)
|
||||
static const char *trans_state_name(uint64_t state)
|
||||
{
|
||||
switch (state) {
|
||||
case 0:
|
||||
|
@ -223,6 +223,8 @@ static const char *trans_state_name(int state)
|
|||
return "WBN";
|
||||
case TRANS_VAG:
|
||||
return "VAG";
|
||||
case TRANS_WSK:
|
||||
return "WSK";
|
||||
case TRANS_VAK:
|
||||
return "VAK";
|
||||
case TRANS_BQ:
|
||||
|
@ -235,16 +237,28 @@ static const char *trans_state_name(int state)
|
|||
return "DS";
|
||||
case TRANS_AHQ:
|
||||
return "AHQ";
|
||||
case TRANS_VA:
|
||||
return "VA";
|
||||
case TRANS_AF:
|
||||
return "AF";
|
||||
case TRANS_AT:
|
||||
return "AT";
|
||||
case TRANS_ATQ:
|
||||
return "ATQ";
|
||||
case TRANS_MO_QUEUE:
|
||||
return "MO_QUEUE";
|
||||
case TRANS_MT_QUEUE:
|
||||
return "MT_QUEUE";
|
||||
case TRANS_MO_DELAY:
|
||||
return "MO_DELAY";
|
||||
case TRANS_MT_DELAY:
|
||||
return "MT_DELAY";
|
||||
default:
|
||||
return "<invald transaction state>";
|
||||
}
|
||||
}
|
||||
|
||||
const char *trans_short_state_name(int state)
|
||||
const char *trans_short_state_name(uint64_t state)
|
||||
{
|
||||
switch (state) {
|
||||
case 0:
|
||||
|
@ -279,9 +293,9 @@ const char *trans_short_state_name(int state)
|
|||
}
|
||||
}
|
||||
|
||||
void trans_new_state(transaction_t *trans, int state)
|
||||
void trans_new_state(transaction_t *trans, uint64_t state)
|
||||
{
|
||||
PDEBUG(DTRANS, DEBUG_INFO, "Transaction state %s -> %s\n", 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;
|
||||
cnetz_display_status();
|
||||
}
|
||||
|
|
|
@ -13,16 +13,24 @@
|
|||
#define TRANS_WBN (1 << 7) /* dialing received, waiting for time slot to reject call */
|
||||
#define TRANS_VAG (1 << 8) /* establishment of call sent, switching channel */
|
||||
/* mobile terminated call */
|
||||
#define TRANS_VAK (1 << 9) /* establishment of call sent, switching channel */
|
||||
#define TRANS_WSK (1 << 9) /* incomming call in queue */
|
||||
#define TRANS_VAK (1 << 10) /* establishment of call sent, switching channel */
|
||||
/* traffic channel */
|
||||
#define TRANS_BQ (1 << 10) /* accnowledge channel */
|
||||
#define TRANS_VHQ (1 << 11) /* hold call */
|
||||
#define TRANS_RTA (1 << 12) /* hold call and make the phone ring */
|
||||
#define TRANS_DS (1 << 13) /* establish speech connection */
|
||||
#define TRANS_AHQ (1 << 14) /* establish speech connection after answer */
|
||||
#define TRANS_BQ (1 << 11) /* accnowledge channel */
|
||||
#define TRANS_VHQ (1 << 12) /* hold call */
|
||||
#define TRANS_RTA (1 << 13) /* hold call and make the phone ring */
|
||||
#define TRANS_DS (1 << 14) /* establish speech connection */
|
||||
#define TRANS_AHQ (1 << 15) /* establish speech connection after answer */
|
||||
/* release */
|
||||
#define TRANS_AF (1 << 15) /* release connection by base station */
|
||||
#define TRANS_AT (1 << 16) /* release connection by mobile station */
|
||||
#define TRANS_VA (1 << 16) /* release call in queue by base station (OgK) */
|
||||
#define TRANS_AF (1 << 17) /* release connection by base station (SpK) */
|
||||
#define TRANS_AT (1 << 18) /* release connection by mobile station */
|
||||
#define TRANS_ATQ (1 << 19) /* acknowledge release of MO call in queue */
|
||||
/* queue */
|
||||
#define TRANS_MO_QUEUE (1 << 20) /* MO queue */
|
||||
#define TRANS_MT_QUEUE (1 << 21) /* MT queue */
|
||||
#define TRANS_MO_DELAY (1 << 22) /* delay to be sure the channel is free again */
|
||||
#define TRANS_MT_DELAY (1 << 23)
|
||||
|
||||
typedef struct transaction {
|
||||
struct transaction *next; /* pointer to next node in list */
|
||||
|
@ -33,7 +41,7 @@ typedef struct transaction {
|
|||
uint16_t futln_rest;
|
||||
int extended; /* extended frequency capability */
|
||||
char dialing[17]; /* number dialed by the phone */
|
||||
int32_t state; /* state of transaction */
|
||||
int64_t state; /* state of transaction */
|
||||
int8_t release_cause; /* reason for release, (c-netz coding) */
|
||||
int try; /* counts resending messages */
|
||||
int repeat; /* counts repeating messages */
|
||||
|
@ -41,18 +49,19 @@ typedef struct transaction {
|
|||
int mo_call; /* flags a moile originating call */
|
||||
int mt_call; /* flags a moile terminating call */
|
||||
int page_failed; /* failed to get a response from MS */
|
||||
double call_start; /* when did the call start? (used for metering) */
|
||||
} transaction_t;
|
||||
|
||||
const char *transaction2rufnummer(transaction_t *trans);
|
||||
transaction_t *create_transaction(cnetz_t *cnetz, uint32_t state, uint8_t futln_nat, uint8_t futln_fuvst, uint16_t futln_rest, 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 extended);
|
||||
void destroy_transaction(transaction_t *trans);
|
||||
void link_transaction(transaction_t *trans, cnetz_t *cnetz);
|
||||
void unlink_transaction(transaction_t *trans);
|
||||
transaction_t *search_transaction(cnetz_t *cnetz, uint32_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_callref(cnetz_t *cnetz, int callref);
|
||||
void trans_new_state(transaction_t *trans, int state);
|
||||
void trans_new_state(transaction_t *trans, uint64_t state);
|
||||
void cnetz_flush_other_transactions(cnetz_t *cnetz, transaction_t *trans);
|
||||
void transaction_timeout(struct timer *timer);
|
||||
const char *trans_short_state_name(int state);
|
||||
const char *trans_short_state_name(uint64_t state);
|
||||
|
||||
|
|
Loading…
Reference in New Issue