From 2dcf10b1b165cda744ee171d219d68a7d36765b0 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sat, 27 Jan 2024 22:53:24 +0100 Subject: [PATCH] Add metering information from osmo-cc to B-Netz and C-Netz Untested! --- src/amps/amps.c | 2 +- src/amps/esn.c | 1 + src/anetz/anetz.c | 2 +- src/bnetz/bnetz.c | 61 +++++++++++++++++++++++++++++++------ src/bnetz/bnetz.h | 1 + src/bnetz/main.c | 2 ++ src/cnetz/cnetz.c | 41 +++++++++++++++++++++---- src/cnetz/cnetz.h | 2 +- src/cnetz/main.c | 4 ++- src/cnetz/transaction.h | 4 ++- src/eurosignal/eurosignal.c | 2 +- src/fuenf/fuenf.c | 2 +- src/fuvst/fuvst.c | 2 +- src/fuvst/sniffer.c | 2 +- src/golay/golay.c | 2 +- src/imts/imts.c | 2 +- src/jolly/jolly.c | 2 +- src/libmobile/call.c | 12 ++++++-- src/libmobile/call.h | 2 +- src/mpt1327/mpt1327.c | 2 +- src/nmt/nmt.c | 2 +- src/pocsag/pocsag.c | 2 +- src/r2000/r2000.c | 2 +- src/zeitansage/zeitansage.c | 2 +- 24 files changed, 122 insertions(+), 36 deletions(-) diff --git a/src/amps/amps.c b/src/amps/amps.c index 7af7539..33d3beb 100644 --- a/src/amps/amps.c +++ b/src/amps/amps.c @@ -990,7 +990,7 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id, return 0; } -void call_down_answer(int __attribute__((unused)) callref) +void call_down_answer(int __attribute__((unused)) callref, struct timeval __attribute__((unused)) *tv_meter) { } diff --git a/src/amps/esn.c b/src/amps/esn.c index 5f3cbab..93bcb70 100644 --- a/src/amps/esn.c +++ b/src/amps/esn.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "../libsample/sample.h" #include "../liblogging/logging.h" #include "../libmobile/call.h" diff --git a/src/anetz/anetz.c b/src/anetz/anetz.c index 06e257b..6ae1441 100644 --- a/src/anetz/anetz.c +++ b/src/anetz/anetz.c @@ -433,7 +433,7 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id, return 0; } -void call_down_answer(int __attribute__((unused)) callref) +void call_down_answer(int __attribute__((unused)) callref, struct timeval __attribute__((unused)) *tv_meter) { } diff --git a/src/bnetz/bnetz.c b/src/bnetz/bnetz.c index 1cd758f..7beb9c9 100644 --- a/src/bnetz/bnetz.c +++ b/src/bnetz/bnetz.c @@ -48,7 +48,7 @@ #define TRENN_COUNT 5 /* min. 720 ms release 'Trennsignal' (according to FTZ 1727 Pfl 32 Clause 3.2.2.2.6) */ -#define METERING_DURATION 0,140000 /* duration of metering pulse (according to FTZ 1727 Pfl 32 Clause 3.2.6.6.1) */ +#define METERING_DURATION_US 140000 /* duration of metering pulse (according to FTZ 1727 Pfl 32 Clause 3.2.6.6.1) */ #define METERING_START 1,0 /* start metering 1 second after call start */ const char *bnetz_state_name(enum bnetz_state state) @@ -419,9 +419,12 @@ void bnetz_receive_tone(bnetz_t *bnetz, int bit) osmo_timer_del(&bnetz->timer); bnetz_new_state(bnetz, BNETZ_GESPRAECH); bnetz_set_dsp_mode(bnetz, DSP_MODE_AUDIO); - /* start metering pulses if forced */ - if (bnetz->metering < 0) + /* start metering pulses, if forced (mobile terminating call) */ + if (bnetz->metering < 0) { + bnetz->metering_tv.tv_sec = abs(bnetz->metering); + bnetz->metering_tv.tv_usec = 0; osmo_timer_schedule(&bnetz->timer, METERING_START); + } call_up_answer(bnetz->callref, bnetz->station_id); break; } @@ -584,9 +587,6 @@ void bnetz_receive_telegramm(bnetz_t *bnetz, uint16_t telegramm) osmo_timer_del(&bnetz->timer); bnetz_set_dsp_mode(bnetz, DSP_MODE_AUDIO); bnetz_new_state(bnetz, BNETZ_GESPRAECH); - /* start metering pulses if enabled and supported by phone or if forced */ - if (bnetz->metering < 0 || (bnetz->metering > 0 && (bnetz->dial_type == DIAL_TYPE_METER || bnetz->dial_type == DIAL_TYPE_METER_MUENZ))) - osmo_timer_schedule(&bnetz->timer, METERING_START); /* setup call */ LOGP(DBNETZ, LOGL_INFO, "Setup call to network.\n"); @@ -635,6 +635,7 @@ lets see, if noise will not generate a release signal.... static void bnetz_timeout(void *data) { bnetz_t *bnetz = data; + int to_sec, to_usec; switch (bnetz->state) { case BNETZ_WAHLABRUF: @@ -673,12 +674,21 @@ static void bnetz_timeout(void *data) case DSP_MODE_AUDIO: /* turn on merting pulse */ bnetz_set_dsp_mode(bnetz, DSP_MODE_AUDIO_METER); - osmo_timer_schedule(&bnetz->timer, METERING_DURATION); + osmo_timer_schedule(&bnetz->timer, 0, METERING_DURATION_US); break; case DSP_MODE_AUDIO_METER: /* turn off and wait given seconds for next metering cycle */ bnetz_set_dsp_mode(bnetz, DSP_MODE_AUDIO); - osmo_timer_schedule(&bnetz->timer, (double)abs(bnetz->metering) - METERING_DURATION); + /* if metering has been disabled due to disconnect (must be at least 1s) */ + if (!bnetz->metering_tv.tv_sec) + break; + to_sec = bnetz->metering_tv.tv_sec; + to_usec = bnetz->metering_tv.tv_usec - METERING_DURATION_US; + if (to_usec < 0) { + to_usec += 1000000; + to_sec--; + } + osmo_timer_schedule(&bnetz->timer, to_sec, to_usec); break; default: break; @@ -726,8 +736,35 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id, return 0; } -void call_down_answer(int __attribute__((unused)) callref) +void call_down_answer(int callref, struct timeval *tv_meter) { + sender_t *sender; + bnetz_t *bnetz; + + LOGP(DBNETZ, LOGL_INFO, "Call has been answered by network.\n"); + + for (sender = sender_head; sender; sender = sender->next) { + bnetz = (bnetz_t *) sender; + if (bnetz->callref == callref) + break; + } + if (!sender) { + LOGP(DBNETZ, LOGL_NOTICE, "Incoming answer, but no callref!\n"); + return; + } + + /* At least tone second! */ + if (tv_meter->tv_sec) { + LOGP(DBNETZ, LOGL_INFO, "Network starts metering pulses every %lu.%03lu seconds.\n", tv_meter->tv_sec, tv_meter->tv_usec / 1000); + memcpy(&bnetz->metering_tv, tv_meter, sizeof(bnetz->metering_tv)); + osmo_timer_schedule(&bnetz->timer, METERING_START); + } else if (bnetz->metering < 0 || (bnetz->metering > 0 && (bnetz->dial_type == DIAL_TYPE_METER || bnetz->dial_type == DIAL_TYPE_METER_MUENZ))) { + /* start metering pulses if enabled and supported by phone or if forced (mobile origninating call) */ + LOGP(DBNETZ, LOGL_INFO, "Command line options starts metering pulses every %d seconds.\n", abs(bnetz->metering)); + bnetz->metering_tv.tv_sec = abs(bnetz->metering); + bnetz->metering_tv.tv_usec = 0; + osmo_timer_schedule(&bnetz->timer, METERING_START); + } } /* Call control sends disconnect (with tones). @@ -753,8 +790,12 @@ void call_down_disconnect(int callref, int cause) } /* Release when not active */ - if (bnetz->state == BNETZ_GESPRAECH) + if (bnetz->state == BNETZ_GESPRAECH) { + /* stop metering */ + bnetz->metering_tv.tv_sec = 0; + bnetz->metering_tv.tv_usec = 0; return; + } switch (bnetz->state) { case BNETZ_SELEKTIVRUF_EIN: case BNETZ_SELEKTIVRUF_AUS: diff --git a/src/bnetz/bnetz.h b/src/bnetz/bnetz.h index 3995744..b0220f3 100644 --- a/src/bnetz/bnetz.h +++ b/src/bnetz/bnetz.h @@ -56,6 +56,7 @@ typedef struct bnetz { /* system info */ int gfs; /* 'Gruppenfreisignal' */ int metering; /* use metering pulses in seconds 0 = off, < 0 = force */ + struct timeval metering_tv; /* time to repeat metering pulse (current call) */ /* switch sender to channel 19 */ char paging_file[256]; /* if set, write to given file to switch to channel 19 or back */ diff --git a/src/bnetz/main.c b/src/bnetz/main.c index 0a5fa4f..e78fdf3 100644 --- a/src/bnetz/main.c +++ b/src/bnetz/main.c @@ -58,6 +58,8 @@ void print_help(const char *arg0) printf(" Pulses will be sent on outgoing calls only and only if mobile station\n"); printf(" requests it. Use negative value to force metering pulses for all calls.\n"); printf(" (default = %d)\n", metering); + printf(" If metering pulses are sent via Osmo-CC interface, pulses are always\n"); + printf(" sent, if mobile station requests it. This overrides this option.\n"); printf(" -P --paging tone | notone | positive | negative | =:\n"); printf(" Send a tone, give a signal or write to a file when switching to\n"); printf(" channel 19. (paging the phone).\n"); diff --git a/src/cnetz/cnetz.c b/src/cnetz/cnetz.c index 0d959a9..51ede65 100644 --- a/src/cnetz/cnetz.c +++ b/src/cnetz/cnetz.c @@ -667,8 +667,35 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id, return 0; } -void call_down_answer(int __attribute__((unused)) callref) +void call_down_answer(int callref, struct timeval *tv_meter) { + sender_t *sender; + cnetz_t *cnetz; + transaction_t *trans; + + LOGP(DCNETZ, LOGL_INFO, "Call has been answered by network.\n"); + + for (sender = sender_head; sender; sender = sender->next) { + cnetz = (cnetz_t *) sender; + trans = search_transaction_callref(cnetz, callref); + if (trans) + break; + } + if (!sender) { + LOGP(DCNETZ, LOGL_NOTICE, "Incoming answer, but no callref!\n"); + return; + } + + /* At least tone second! */ + if (tv_meter->tv_sec) { + LOGP(DCNETZ, LOGL_INFO, "Network starts metering pulses every %lu.%03lu seconds.\n", tv_meter->tv_sec, tv_meter->tv_usec / 1000); + trans->meter_start = get_time(); + trans->metering_time = (double)tv_meter->tv_sec + (double)tv_meter->tv_usec / 1000000.0; + } else if (cnetz->metering) { + LOGP(DCNETZ, LOGL_INFO, "Command line options starts metering pulses every %d seconds.\n", cnetz->metering); + trans->meter_start = get_time(); + trans->metering_time = (double)cnetz->metering; + } } /* Call control sends disconnect (with tones). @@ -700,6 +727,8 @@ void call_down_disconnect(int callref, int cause) switch (cnetz->dsp_mode) { case DSP_MODE_SPK_V: + /* stop metering */ + trans->meter_end = get_time(); return; case DSP_MODE_SPK_K: LOGP(DCNETZ, LOGL_INFO, "Call control disconnects on speech channel, releasing towards mobile station.\n"); @@ -1667,11 +1696,11 @@ const telegramm_t *cnetz_transmit_telegramm_spk_v(cnetz_t *cnetz) memset(&telegramm, 0, sizeof(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; + if (trans->metering_time) { + /* get end time. if not set, use current time. (still running) */ + double end = (trans->meter_end) ? : get_time(); + /* add one unit, because when metering is started, the first unit is counted. */ + meter = (end - trans->meter_start) / (double)trans->metering_time + 1.0; } telegramm.max_sendeleistung = cnetz_power2bits(cnetz->ms_power); diff --git a/src/cnetz/cnetz.h b/src/cnetz/cnetz.h index 5cba73a..b9bbafe 100644 --- a/src/cnetz/cnetz.h +++ b/src/cnetz/cnetz.h @@ -82,7 +82,7 @@ struct cnetz { int response_valid; /* expect authorizaton response */ uint64_t response; /* authorization response */ int warteschlange; /* use queue */ - int metering; /* use metering pulses in seconds 0 = off */ + int metering; /* send metering units in seconds 0 = off */ /* all cnetz states */ enum cnetz_state state; /* main state of sender */ diff --git a/src/cnetz/main.c b/src/cnetz/main.c index dd4e663..f3b58c7 100644 --- a/src/cnetz/main.c +++ b/src/cnetz/main.c @@ -122,8 +122,10 @@ void print_help(const char *arg0) 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 | 0\n"); - printf(" Increment metering counter every given number of seconds.\n"); + printf(" Increment metering counter every given number of seconds.\n"); printf(" To turn off, use 0. (default = %d)\n", metering); + printf(" If metering pulses are sent via Osmo-CC interface, pulses are always\n"); + printf(" increment metering counter. This overrides this option.\n"); printf(" -V --voice-deviation <2400..4000 Hz>\n"); printf(" It is unclear what the actual voice deviation is. Please increase, if\n"); printf(" mobile's earpiece is too quiet and the microphone is too loud.\n"); diff --git a/src/cnetz/transaction.h b/src/cnetz/transaction.h index a0189a4..4a5d70b 100644 --- a/src/cnetz/transaction.h +++ b/src/cnetz/transaction.h @@ -54,7 +54,9 @@ 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) */ + double metering_time; /* time between units (0.0 if no metering set) */ + double meter_start; /* when did the metering start? (0.0 if not yet started) */ + double meter_end; /* when did the metering end? (0.0 if not yet ended) */ 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; diff --git a/src/eurosignal/eurosignal.c b/src/eurosignal/eurosignal.c index e09b91c..f88a3ae 100644 --- a/src/eurosignal/eurosignal.c +++ b/src/eurosignal/eurosignal.c @@ -684,7 +684,7 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id, return 0; } -void call_down_answer(int __attribute__((unused)) callref) +void call_down_answer(int __attribute__((unused)) callref, struct timeval __attribute__((unused)) *tv_meter) { euro_call_t *call; diff --git a/src/fuenf/fuenf.c b/src/fuenf/fuenf.c index 1fb66a6..be5f8bc 100644 --- a/src/fuenf/fuenf.c +++ b/src/fuenf/fuenf.c @@ -347,7 +347,7 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id, return 0; } -void call_down_answer(int __attribute__((unused)) callref) +void call_down_answer(int __attribute__((unused)) callref, struct timeval __attribute__((unused)) *tv_meter) { } diff --git a/src/fuvst/fuvst.c b/src/fuvst/fuvst.c index bf6c60f..bac0f86 100755 --- a/src/fuvst/fuvst.c +++ b/src/fuvst/fuvst.c @@ -1360,7 +1360,7 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id, return 0; } -void call_down_answer(int callref) +void call_down_answer(int callref, struct timeval __attribute__((unused)) *tv_meter) { transaction_t *trans; uint8_t opcode, *data; diff --git a/src/fuvst/sniffer.c b/src/fuvst/sniffer.c index 90e1e07..3f7ee2a 100644 --- a/src/fuvst/sniffer.c +++ b/src/fuvst/sniffer.c @@ -263,7 +263,7 @@ void call_down_clock(void) {} int call_down_setup(int __attribute__((unused)) callref, const char __attribute__((unused)) *caller_id, enum number_type __attribute__((unused)) caller_type, const char __attribute__((unused)) *dialing) { return 0; } -void call_down_answer(int __attribute__((unused)) callref) { } +void call_down_answer(int __attribute__((unused)) callref, struct timeval __attribute__((unused)) *tv_meter) { } void call_down_disconnect(int __attribute__((unused)) callref, int __attribute__((unused)) cause) { } diff --git a/src/golay/golay.c b/src/golay/golay.c index c79a9dc..6094caf 100644 --- a/src/golay/golay.c +++ b/src/golay/golay.c @@ -845,7 +845,7 @@ int call_down_setup(int __attribute__((unused)) callref, const char *caller_id, return -CAUSE_NORMAL; } -void call_down_answer(int __attribute__((unused)) callref) +void call_down_answer(int __attribute__((unused)) callref, struct timeval __attribute__((unused)) *tv_meter) { } diff --git a/src/imts/imts.c b/src/imts/imts.c index c96447c..337a528 100644 --- a/src/imts/imts.c +++ b/src/imts/imts.c @@ -1203,7 +1203,7 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id, return 0; } -void call_down_answer(int __attribute__((unused)) callref) +void call_down_answer(int __attribute__((unused)) callref, struct timeval __attribute__((unused)) *tv_meter) { } diff --git a/src/jolly/jolly.c b/src/jolly/jolly.c index 48e47db..bea372b 100644 --- a/src/jolly/jolly.c +++ b/src/jolly/jolly.c @@ -513,7 +513,7 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id, return 0; } -void call_down_answer(int __attribute__((unused)) callref) +void call_down_answer(int __attribute__((unused)) callref, struct timeval __attribute__((unused)) *tv_meter) { } diff --git a/src/libmobile/call.c b/src/libmobile/call.c index e848881..69478fe 100644 --- a/src/libmobile/call.c +++ b/src/libmobile/call.c @@ -660,9 +660,10 @@ void ll_msg_cb(osmo_cc_endpoint_t __attribute__((unused)) *ep, uint32_t callref, { process_t *process; uint8_t coding, location, progress, isdn_cause, socket_cause; - uint16_t sip_cause; + uint16_t sip_cause, metering_connect_units, metering_unit_period_decisecs; uint8_t type, plan, present, screen, caller_type; char caller_id[33], number[33]; + struct timeval tv_meter = {}; const char *suffix, *invalid; int rc; @@ -704,6 +705,13 @@ void ll_msg_cb(osmo_cc_endpoint_t __attribute__((unused)) *ep, uint32_t callref, return; } + /* get metering information */ + rc = osmo_cc_get_ie_metering(msg, 0, &metering_connect_units, &metering_unit_period_decisecs); + if (rc >= 0) { + tv_meter.tv_sec = metering_unit_period_decisecs / 10; + tv_meter.tv_usec = (metering_unit_period_decisecs % 10) / 10; + } + switch(msg->type) { case OSMO_CC_MSG_SETUP_REQ: { @@ -852,7 +860,7 @@ void ll_msg_cb(osmo_cc_endpoint_t __attribute__((unused)) *ep, uint32_t callref, goto nego_failed; new_state_process(callref, PROCESS_CONNECT); LOGP(DCALL, LOGL_INFO, "Call answered\n"); - call_down_answer(callref); + call_down_answer(callref, &tv_meter); indicate_answer_ack(callref); break; case OSMO_CC_MSG_DISC_REQ: diff --git a/src/libmobile/call.h b/src/libmobile/call.h index fe26161..997917f 100644 --- a/src/libmobile/call.h +++ b/src/libmobile/call.h @@ -31,7 +31,7 @@ void call_tone_recall(int callref, int on); /* send messages */ int call_down_setup(int callref, const char *caller_id, enum number_type caller_type, const char *dialing); -void call_down_answer(int callref); +void call_down_answer(int callref, struct timeval *tv_meter); void call_down_disconnect(int callref, int cause); void call_down_release(int callref, int cause); diff --git a/src/mpt1327/mpt1327.c b/src/mpt1327/mpt1327.c index 5161e1a..7ef0288 100755 --- a/src/mpt1327/mpt1327.c +++ b/src/mpt1327/mpt1327.c @@ -1598,7 +1598,7 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id, return 0; } -void call_down_answer(int __attribute__((unused)) callref) +void call_down_answer(int __attribute__((unused)) callref, struct timeval __attribute__((unused)) *tv_meter) { } diff --git a/src/nmt/nmt.c b/src/nmt/nmt.c index e8f9174..08357e9 100644 --- a/src/nmt/nmt.c +++ b/src/nmt/nmt.c @@ -1869,7 +1869,7 @@ int sms_out_setup(char *dialing, const char *caller_id, enum number_type caller_ return _out_setup(0, caller_id, caller_type, dialing, sms); } -void call_down_answer(int __attribute__((unused)) callref) +void call_down_answer(int __attribute__((unused)) callref, struct timeval __attribute__((unused)) *tv_meter) { } diff --git a/src/pocsag/pocsag.c b/src/pocsag/pocsag.c index 4689387..29d3416 100644 --- a/src/pocsag/pocsag.c +++ b/src/pocsag/pocsag.c @@ -541,7 +541,7 @@ void pocsag_msg_done(pocsag_t *pocsag) pocsag_scan_or_loopback(pocsag); } -void call_down_answer(int __attribute__((unused)) callref) +void call_down_answer(int __attribute__((unused)) callref, struct timeval __attribute__((unused)) *tv_meter) { } diff --git a/src/r2000/r2000.c b/src/r2000/r2000.c index cad6916..839b02a 100644 --- a/src/r2000/r2000.c +++ b/src/r2000/r2000.c @@ -1434,7 +1434,7 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id, } /* Call control answers call toward station mobile. */ -void call_down_answer(int callref) +void call_down_answer(int callref, struct timeval __attribute__((unused)) *tv_meter) { sender_t *sender; r2000_t *r2000; diff --git a/src/zeitansage/zeitansage.c b/src/zeitansage/zeitansage.c index a251721..f41359f 100644 --- a/src/zeitansage/zeitansage.c +++ b/src/zeitansage/zeitansage.c @@ -358,7 +358,7 @@ int call_down_setup(int callref, const char __attribute__((unused)) *caller_id, return 0; } -void call_down_answer(int __attribute__((unused)) callref) +void call_down_answer(int __attribute__((unused)) callref, struct timeval __attribute__((unused)) *tv_meter) { }