From c967e1500c5f20480576afd43a77892c8b418509 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 10:19:36 -0400 Subject: [PATCH 01/37] EDACS: Rename EDACS_IS_TESTCALL flag --- include/dsd.h | 2 +- src/dsd_ncurses.c | 16 ++++++++-------- src/edacs-fme.c | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/include/dsd.h b/include/dsd.h index fbe0a0d..7cf1e2e 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -770,7 +770,7 @@ typedef struct #define EDACS_IS_INDIVIDUAL 0x10 #define EDACS_IS_ALL_CALL 0x20 #define EDACS_IS_INTERCONNECT 0x40 - #define EDACS_IS_TESTCALL 0x100 + #define EDACS_IS_TEST_CALL 0x80 //trunking group and lcn freq list long int trunk_lcn_freq[26]; //max number on an EDACS system, should be enough on DMR too hopefully diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index f1e675d..201025d 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -3621,14 +3621,14 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) else if ((call_matrix[i][4] & EDACS_IS_INTERCONNECT) != 0) printw (" TGT [ SYSTEM ] SRC [%8lld] Interconnect", call_matrix[i][3] ); // Test call - else if ((call_matrix[i][4] & EDACS_IS_TESTCALL) != 0) + else if ((call_matrix[i][4] & EDACS_IS_TEST_CALL) != 0) printw (" TEST CALL"); // Unknown call else printw (" Unknown call type" ); // Call flags - if ((call_matrix[i][4] & EDACS_IS_TESTCALL) != 0) {} + if ((call_matrix[i][4] & EDACS_IS_TEST_CALL) != 0) {} else if ((call_matrix[i][4] & EDACS_IS_DIGITAL) == 0) printw (" [Ana]"); else printw (" [Dig]"); if ((call_matrix[i][4] & EDACS_IS_EMERGENCY) != 0) printw ("[EM]"); @@ -3655,14 +3655,14 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) else if ((call_matrix[i][4] & EDACS_IS_INTERCONNECT) != 0) printw (" TGT [ SYSTEM ] SRC [%5lld] Interconnect", call_matrix[i][3] ); // Test call - else if ((call_matrix[i][4] & EDACS_IS_TESTCALL) != 0) + else if ((call_matrix[i][4] & EDACS_IS_TEST_CALL) != 0) printw (" TEST CALL"); // Unknown call else printw (" Unknown call type" ); // Call flags - if ((call_matrix[i][4] & EDACS_IS_TESTCALL) != 0) {} + if ((call_matrix[i][4] & EDACS_IS_TEST_CALL) != 0) {} else if ((call_matrix[i][4] & EDACS_IS_DIGITAL) == 0) printw (" [Ana]"); else printw (" [Dig]"); if ((call_matrix[i][4] & EDACS_IS_EMERGENCY) != 0) printw ("[EM]"); @@ -3814,14 +3814,14 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) else if ((call_matrix[j][4] & EDACS_IS_INTERCONNECT) != 0) printw ("Target [ SYSTEM ] Source [%8lld] Interconnect", call_matrix[j][3]); // Test call - else if ((call_matrix[j][4] & EDACS_IS_TESTCALL) != 0) + else if ((call_matrix[j][4] & EDACS_IS_TEST_CALL) != 0) printw ("TEST CALL"); // Unknown call else printw ("Unknown call type"); // Call flags - if ((call_matrix[j][4] & EDACS_IS_TESTCALL) != 0) {} + if ((call_matrix[j][4] & EDACS_IS_TEST_CALL) != 0) {} else if ((call_matrix[j][4] & EDACS_IS_DIGITAL) == 0) printw (" [Ana]"); else printw (" [Dig]"); if ((call_matrix[j][4] & EDACS_IS_EMERGENCY) != 0) printw ("[EM]"); @@ -3853,14 +3853,14 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) else if ((call_matrix[j][4] & EDACS_IS_INTERCONNECT) != 0) printw ("Target [ SYSTEM ] Source [%5lld] Interconnect", call_matrix[j][3]); // Test call - else if ((call_matrix[i][4] & EDACS_IS_TESTCALL) != 0) + else if ((call_matrix[i][4] & EDACS_IS_TEST_CALL) != 0) printw (" TEST CALL"); // Unknown call else printw ("Unknown call type"); // Call flags - if ((call_matrix[i][4] & EDACS_IS_TESTCALL) != 0) {} + if ((call_matrix[i][4] & EDACS_IS_TEST_CALL) != 0) {} else if ((call_matrix[j][4] & EDACS_IS_DIGITAL) == 0) printw (" [Ana]"); else printw (" [Dig]"); if ((call_matrix[j][4] & EDACS_IS_EMERGENCY) != 0) printw ("[EM]"); diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 894b385..69752d3 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -625,7 +625,7 @@ void edacs(dsd_opts * opts, dsd_state * state) //and overwrite current values in the matrix state->lasttg = 999999999; state->lastsrc = 999999999; - state->edacs_vc_call_type = 0x101; //manually set to 0x101 to trigger voice call in ncurses, but no other flags + state->edacs_vc_call_type = EDACS_IS_TEST_CALL | EDACS_IS_VOICE; //manually set to trigger voice call in ncurses, but no other flags } //Adjacent Sites else if (mt2 == 0x1) @@ -1022,7 +1022,7 @@ void edacs(dsd_opts * opts, dsd_state * state) //and overwrite current values in the matrix state->lasttg = 999999999; state->lastsrc = 999999999; - state->edacs_vc_call_type = 0x101; //manually set to 0x101 to trigger voice call in ncurses, but no other flags + state->edacs_vc_call_type = EDACS_IS_TEST_CALL | EDACS_IS_VOICE; //manually set to trigger voice call in ncurses, but no other flags lcn = 0; //set to zero here, because this is not an actual call, so don't tune to it } else From c21aa9803476ffd4bc33db823174b71309ba6e35 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 10:20:53 -0400 Subject: [PATCH 02/37] EDACS: Fix incorrect indexer for test call --- src/dsd_ncurses.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 201025d..4a5fc44 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -3853,14 +3853,14 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) else if ((call_matrix[j][4] & EDACS_IS_INTERCONNECT) != 0) printw ("Target [ SYSTEM ] Source [%5lld] Interconnect", call_matrix[j][3]); // Test call - else if ((call_matrix[i][4] & EDACS_IS_TEST_CALL) != 0) + else if ((call_matrix[j][4] & EDACS_IS_TEST_CALL) != 0) printw (" TEST CALL"); // Unknown call else printw ("Unknown call type"); // Call flags - if ((call_matrix[i][4] & EDACS_IS_TEST_CALL) != 0) {} + if ((call_matrix[j][4] & EDACS_IS_TEST_CALL) != 0) {} else if ((call_matrix[j][4] & EDACS_IS_DIGITAL) == 0) printw (" [Ana]"); else printw (" [Dig]"); if ((call_matrix[j][4] & EDACS_IS_EMERGENCY) != 0) printw ("[EM]"); From a90a2dadd467084bf15a5179088c6d3860ac4654 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 10:24:10 -0400 Subject: [PATCH 03/37] EDACS: Prettier test call display --- src/dsd_ncurses.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 4a5fc44..3a76b67 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -3622,7 +3622,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw (" TGT [ SYSTEM ] SRC [%8lld] Interconnect", call_matrix[i][3] ); // Test call else if ((call_matrix[i][4] & EDACS_IS_TEST_CALL) != 0) - printw (" TEST CALL"); + printw (" TGT [ SYSTEM ] SRC [ SYSTEM ] Test Call"); // Unknown call else printw (" Unknown call type" ); @@ -3656,7 +3656,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw (" TGT [ SYSTEM ] SRC [%5lld] Interconnect", call_matrix[i][3] ); // Test call else if ((call_matrix[i][4] & EDACS_IS_TEST_CALL) != 0) - printw (" TEST CALL"); + printw (" TGT [ SYSTEM ] SRC [ SYS ] Test Call"); // Unknown call else printw (" Unknown call type" ); @@ -3815,7 +3815,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw ("Target [ SYSTEM ] Source [%8lld] Interconnect", call_matrix[j][3]); // Test call else if ((call_matrix[j][4] & EDACS_IS_TEST_CALL) != 0) - printw ("TEST CALL"); + printw ("Target [ SYSTEM ] Source [ SYSTEM ] Test Call"); // Unknown call else printw ("Unknown call type"); @@ -3854,7 +3854,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw ("Target [ SYSTEM ] Source [%5lld] Interconnect", call_matrix[j][3]); // Test call else if ((call_matrix[j][4] & EDACS_IS_TEST_CALL) != 0) - printw (" TEST CALL"); + printw ("Target [ SYSTEM ] Source [ SYS ] Test Call", call_matrix[j][3]); // Unknown call else printw ("Unknown call type"); From 7b2a2031a2116eb781b2e1a6ced26f9fe63f9ab6 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 10:25:22 -0400 Subject: [PATCH 04/37] EDACS: Consistency for Initiate Test Call message logging --- src/edacs-fme.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 69752d3..39701cc 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -607,17 +607,15 @@ void edacs(dsd_opts * opts, dsd_state * state) if (mt1 == 0x1F) { - //Test Call (not seen in the wild, see US patent US7546135B2, Figure 2b) - //Finally Captured in the wild, along with the "I-Call" with zero target and zero source + //Initiate Test Call (finally captured in the wild, along with the "I-Call" with zero target and zero source) if (mt2 == 0x0) { - // MSG_1 [F802180] MSG_2 [0000000] (MT1: 1F; MT2: 0) Initiate Test Call int cc_lcn = (msg_1 & 0x3E000) >> 13; //shifted to allow this example to be CC LCN 1, as was reported at the time of capture int wc_lcn = (msg_1 & 0xF80) >> 7; fprintf (stderr, "%s", KYEL); - fprintf (stderr, " Initiate Test Call :: CC LCN: %02d; WC LCN: %02d;", cc_lcn, wc_lcn); + fprintf (stderr, " Initiate Test Call :: CC LCN [%02d] WC LCN [%02d]", cc_lcn, wc_lcn); fprintf (stderr, "%s", KNRM); state->edacs_vc_lcn = wc_lcn; @@ -633,7 +631,7 @@ void edacs(dsd_opts * opts, dsd_state * state) int adj_lcn = (msg_1 & 0x1F000) >> 12; int adj_idx = (msg_1 & 0xF00) >> 8; //site 177 has 8 adj_sites, so this appears to be a 4-bit value int adj_site = (msg_1 & 0xFF); - + fprintf (stderr, "%s", KYEL); fprintf (stderr, " Adjacent Site"); if (adj_site > 0) From c073bc49c18a3a222d8e6eb9eb05f20dbe8aa500 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 10:25:38 -0400 Subject: [PATCH 05/37] EDACS: Consistency for CC LCN message logging --- src/edacs-fme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 39701cc..893551c 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -685,7 +685,7 @@ void edacs(dsd_opts * opts, dsd_state * state) { state->edacs_lcn_count = state->edacs_cc_lcn; } - fprintf (stderr, " :: System ID [%04X] Control Channel LCN [%d]%s", system, state->edacs_cc_lcn, get_lcn_status_string(lcn)); + fprintf (stderr, " :: System ID [%04X] Control Channel LCN [%02d]%s", system, state->edacs_cc_lcn, get_lcn_status_string(lcn)); //check for control channel lcn frequency if not provided in channel map or in the lcn list if (state->trunk_lcn_freq[state->edacs_cc_lcn-1] == 0) From 09b181449f30bc9db5f1d67021dfa48d7db3d901 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 10:27:37 -0400 Subject: [PATCH 06/37] EDACS: Differentiate test call from individual call on standard --- src/edacs-fme.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 893551c..412968a 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -1632,12 +1632,27 @@ void edacs(dsd_opts * opts, dsd_state * state) int target = (msg_1 & 0x3FFF); int source = (msg_2 & 0x3FFF); - fprintf (stderr, "%s", KCYN); - fprintf (stderr, " Individual Call Channel Assignment ::"); - if (is_digital == 0) fprintf (stderr, " Analog"); - else fprintf (stderr, " Digital"); - fprintf (stderr, " Callee [%05d] Caller [%05d] LCN [%02d]%s", target, source, lcn, get_lcn_status_string(lcn)); - if (is_tx_trunk == 0) fprintf (stderr, " [Message Trunking]"); + if (target == 0 && source == 0) + { + fprintf (stderr, "%s", KYEL); + fprintf (stderr, " Test Call Channel Assignment ::"); + fprintf (stderr, " LCN [%02d]%s", lcn, get_lcn_status_string(lcn)); + + state->edacs_vc_lcn = lcn; + //assign bogus values so that this will show up in ncurses terminal and overwrite current values in the matrix + state->lasttg = 999999999; + state->lastsrc = 999999999; + state->edacs_vc_call_type = EDACS_IS_TEST_CALL | EDACS_IS_VOICE; //manually set to trigger voice call in ncurses, but no other flags + lcn = 0; //set to zero here, because this is not an actual call, so don't tune to it + } + else { + fprintf (stderr, "%s", KCYN); + fprintf (stderr, " Voice Individual Channel Assignment ::"); + if (is_digital == 0) fprintf (stderr, " Analog"); + else fprintf (stderr, " Digital"); + fprintf (stderr, " Callee [%05d] Caller [%05d] LCN [%02d]%s", target, source, lcn, get_lcn_status_string(lcn)); + if (is_tx_trunk == 0) fprintf (stderr, " [Message Trunking]"); + } fprintf (stderr, "%s", KNRM); //LCNs >= 26 are reserved to indicate status (queued, busy, denied, etc) From bf62106953e2d389e5bc47d550c8036959378f4e Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 10:32:41 -0400 Subject: [PATCH 07/37] EDACS: Differentiate test call update from individual call update on standard --- src/edacs-fme.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 412968a..b5e7299 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -1479,6 +1479,7 @@ void edacs(dsd_opts * opts, dsd_state * state) } //Channel Updates (6.2.4.7) //Source/caller being present in individual call channel updates reverse engineered from Montreal STM system + //Test calls reverse engineered from HartLink system else if (mt_b == 0x3) { int mt_c = (msg_1 & 0x300000) >> 20; @@ -1492,6 +1493,9 @@ void edacs(dsd_opts * opts, dsd_state * state) //Abstract away to a target, and be sure to check whether it's an individual call later int target = (is_individual == 0) ? group : lid; + //Test calls are just individual calls with source and target of 0 + int is_test_call = (target == 0 && source == 0); + //Technically only MT-C 0x1 and 0x3 are defined in TSB 69.3 - using and extrapolating on legacy code int is_tx_trunk = (mt_c == 2 || mt_c == 3) ? 1 : 0; int is_digital = (mt_c == 1 || mt_c == 3) ? 1 : 0; @@ -1501,15 +1505,20 @@ void edacs(dsd_opts * opts, dsd_state * state) fprintf (stderr, "%s", KGRN); fprintf (stderr, " Voice Group Channel Update ::"); } - else + else if (is_test_call == 0) { fprintf (stderr, "%s", KCYN); fprintf (stderr, " Voice Individual Channel Update ::"); } + else + { + fprintf (stderr, "%s", KYEL); + fprintf (stderr, " Voice Test Channel Update ::"); + } if (is_digital == 0) fprintf (stderr, " Analog"); else fprintf (stderr, " Digital"); - if (is_individual == 0) fprintf (stderr, " Group [%04d]", target); - else fprintf (stderr, " Callee [%05d] Caller [%05d]", target, source); + if (is_individual == 0) fprintf (stderr, " Group [%04d]", target); + else if (is_test_call == 0) fprintf (stderr, " Callee [%05d] Caller [%05d]", target, source); fprintf (stderr, " LCN [%02d]%s", lcn, get_lcn_status_string(lcn)); if (is_tx_trunk == 0) fprintf (stderr, " [Message Trunking]"); if (is_emergency == 1) @@ -1624,6 +1633,7 @@ void edacs(dsd_opts * opts, dsd_state * state) } //Individual Call Channel Assignment (6.2.4.9) //Analog and digital flag reverse engineered from Montreal STM system + //Test calls reverse engineered from HartLink system else if (mt_b == 0x5) { int is_tx_trunk = (msg_1 & 0x200000) >> 21; From e237b5541b74fb77c12955ae9b505c23a5fb6bc0 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 10:38:39 -0400 Subject: [PATCH 08/37] EDACS: Test calls should be KMAG(enta) --- src/edacs-fme.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index b5e7299..59a3b74 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -569,7 +569,7 @@ void edacs(dsd_opts * opts, dsd_state * state) // - KYEL - system data // - KGRN - voice group calls // - KCYN - voice individual calls - // - KMAG - voice other calls (interconnect, all-call, etc) + // - KMAG - voice other calls (interconnect, all-call, test call, etc) // - KBLU - subscriber data // - KWHT - unknown/reserved @@ -1006,9 +1006,9 @@ void edacs(dsd_opts * opts, dsd_state * state) state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_INDIVIDUAL; if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; - fprintf (stderr, "%s", KCYN); if (target == 0 && source == 0) { + fprintf (stderr, "%s", KMAG); //this seems to be the continuation of the Initiate Test Call Command //normally, this appears as an "Analog I-Call", but with 0 tg and src, //its possible that those values could still be present, and that all @@ -1025,6 +1025,7 @@ void edacs(dsd_opts * opts, dsd_state * state) } else { + fprintf (stderr, "%s", KCYN); if (is_digital == 0) fprintf (stderr, " Analog I-Call"); else fprintf (stderr, " Digital I-Call"); if (is_update == 0) fprintf (stderr, " Assignment"); @@ -1644,7 +1645,7 @@ void edacs(dsd_opts * opts, dsd_state * state) if (target == 0 && source == 0) { - fprintf (stderr, "%s", KYEL); + fprintf (stderr, "%s", KMAG); fprintf (stderr, " Test Call Channel Assignment ::"); fprintf (stderr, " LCN [%02d]%s", lcn, get_lcn_status_string(lcn)); From b667d25f2a2484d23d15e6af24e2abcbbeecbca0 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 10:41:56 -0400 Subject: [PATCH 09/37] EDACS EA: cosmetic updates to I-Call/Test Call logging --- src/edacs-fme.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 59a3b74..eda3f2e 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -981,7 +981,7 @@ void edacs(dsd_opts * opts, dsd_state * state) } } - //I-Call Grant Update + //I-Call/Test Call Assignment/Update else if (mt1 == 0x10) { lcn = (msg_2 & 0x1F00000) >> 20; @@ -1006,15 +1006,14 @@ void edacs(dsd_opts * opts, dsd_state * state) state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_INDIVIDUAL; if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; + //Test calls are just I-Calls with source and target of 0 if (target == 0 && source == 0) { fprintf (stderr, "%s", KMAG); - //this seems to be the continuation of the Initiate Test Call Command - //normally, this appears as an "Analog I-Call", but with 0 tg and src, - //its possible that those values could still be present, and that all - //"Analog I-Call" is meant to be the assignment and update of the initiation - if (is_update) fprintf (stderr, " Test Call Update :: LCN: %02d;", lcn); - else fprintf (stderr, " Test Call Assignment :: LCN: %02d;", lcn); + fprintf (stderr, " Test Call"); + if (is_update == 0) fprintf (stderr, " Assignment"); + else fprintf (stderr, " Update"); + fprintf (stderr, " :: LCN [%02d]%s", lcn, get_lcn_status_string(lcn)); state->edacs_vc_lcn = lcn; //assign bogus values so that this will show up in ncurses terminal //and overwrite current values in the matrix From 832afa6c5a01e0d578f5a28ef90bb36b0588bb26 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 10:42:26 -0400 Subject: [PATCH 10/37] EDACS EA: comment --- src/edacs-fme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index eda3f2e..8e68c17 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -607,7 +607,7 @@ void edacs(dsd_opts * opts, dsd_state * state) if (mt1 == 0x1F) { - //Initiate Test Call (finally captured in the wild, along with the "I-Call" with zero target and zero source) + //Initiate Test Call (finally captured in the wild on SLERS EA, along with the "I-Call" with target and source of 0) if (mt2 == 0x0) { // MSG_1 [F802180] MSG_2 [0000000] (MT1: 1F; MT2: 0) Initiate Test Call From b577397d22a2c7895d925abbc242646a2355a302 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 10:44:37 -0400 Subject: [PATCH 11/37] EDACS ncurses: remove extra printf argument --- src/dsd_ncurses.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 3a76b67..86cded1 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -3854,7 +3854,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw ("Target [ SYSTEM ] Source [%5lld] Interconnect", call_matrix[j][3]); // Test call else if ((call_matrix[j][4] & EDACS_IS_TEST_CALL) != 0) - printw ("Target [ SYSTEM ] Source [ SYS ] Test Call", call_matrix[j][3]); + printw ("Target [ SYSTEM ] Source [ SYS ] Test Call"); // Unknown call else printw ("Unknown call type"); From d8e672f7962b08e5b995005e577d0ccafba4265b Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 10:47:40 -0400 Subject: [PATCH 12/37] EDACS EA: make System Dynamic Regroup KWHT so it doesn't conflict with test calls --- src/edacs-fme.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 8e68c17..750f0de 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -571,7 +571,7 @@ void edacs(dsd_opts * opts, dsd_state * state) // - KCYN - voice individual calls // - KMAG - voice other calls (interconnect, all-call, test call, etc) // - KBLU - subscriber data - // - KWHT - unknown/reserved + // - KWHT - unknown/reserved/special //Account for ESK, if any unsigned long long int fr_esk_mask = ((unsigned long long int)state->esk_mask) << 20; @@ -820,7 +820,7 @@ void edacs(dsd_opts * opts, dsd_state * state) int unk2 = (msg_2 & 0xF0000) >> 16; //unknown 4 bit value preceeding 20-bit target value of patch int target = (msg_2 & 0xFFFFF); //target group or individual ID (20-bit) to include in supergroup - fprintf (stderr, "%s", KMAG); //just make it stick out for now + fprintf (stderr, "%s", KWHT); //just make it stick out for now fprintf (stderr, " System Dynamic Regroup :: SSN: %03d; SGID: %05d; Target: %07d;", ssn, sgid, target); if (unk1) fprintf (stderr, " UNK1: %X;", unk1); //this value seems to always be zero if (unk2) fprintf (stderr, " UNK2: %X;", unk2); //this value seems to always be zero From 1ec8bb5c8bd275b0f5cd51dd00749e0de6ebc27d Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 10:51:04 -0400 Subject: [PATCH 13/37] ncurses: trim trailing whitespace --- src/dsd_ncurses.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 86cded1..8a712c8 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -951,7 +951,7 @@ void ncursesMenu (dsd_opts * opts, dsd_state * state) } - + TCP_END: ; //do nothing From a7d7cf1c2e4e4c5e2a54f66531ab2b5899e46ad4 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 10:56:51 -0400 Subject: [PATCH 14/37] EDACS EA: Dynamic Regroup log consistency --- src/edacs-fme.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 750f0de..dd0d2f2 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -821,9 +821,9 @@ void edacs(dsd_opts * opts, dsd_state * state) int target = (msg_2 & 0xFFFFF); //target group or individual ID (20-bit) to include in supergroup fprintf (stderr, "%s", KWHT); //just make it stick out for now - fprintf (stderr, " System Dynamic Regroup :: SSN: %03d; SGID: %05d; Target: %07d;", ssn, sgid, target); - if (unk1) fprintf (stderr, " UNK1: %X;", unk1); //this value seems to always be zero - if (unk2) fprintf (stderr, " UNK2: %X;", unk2); //this value seems to always be zero + fprintf (stderr, " System Dynamic Regroup :: SSN [%03d] SGID[%05d] Target [%07d]", ssn, sgid, target); + if (unk1) fprintf (stderr, " UNK1: [%X]", unk1); //this value seems to always be zero + if (unk2) fprintf (stderr, " UNK2: [%X]", unk2); //this value seems to always be zero fprintf (stderr, "%s", KNRM); } //Serial Number Request (not seen in the wild, see US patent 20030190923, Figure 2b) From a42dd9db8346bdebfbfb1242d075e8d4df735775 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 10:58:49 -0400 Subject: [PATCH 15/37] EDACS: update line telling user to specify EDACS type --- src/edacs-fme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index dd0d2f2..9055fd3 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -2092,7 +2092,7 @@ void edacs(dsd_opts * opts, dsd_state * state) //let users know they need to select an operational mode with the switches below else { - fprintf (stderr, " Detected: Use -fh, -fH, -fe, or -fE for std, esk, ea, or ea-esk;"); + fprintf (stderr, " Detected EDACS: Use -fh, -fH, -fe, or -fE for std, esk, ea, or ea-esk to specify the type"); fprintf (stderr, "\n"); fprintf (stderr, " MSG_1 [%07llX]", msg_1); fprintf (stderr, " MSG_2 [%07llX]", msg_2); From a78b88cb9067b03d46851a3e0f8491e141d02de3 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 14:19:10 -0400 Subject: [PATCH 16/37] EDACS EA: tiny log string change --- src/edacs-fme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 9055fd3..722e125 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -685,7 +685,7 @@ void edacs(dsd_opts * opts, dsd_state * state) { state->edacs_lcn_count = state->edacs_cc_lcn; } - fprintf (stderr, " :: System ID [%04X] Control Channel LCN [%02d]%s", system, state->edacs_cc_lcn, get_lcn_status_string(lcn)); + fprintf (stderr, " :: System ID [%04X] CC LCN [%02d]%s", system, state->edacs_cc_lcn, get_lcn_status_string(lcn)); //check for control channel lcn frequency if not provided in channel map or in the lcn list if (state->trunk_lcn_freq[state->edacs_cc_lcn-1] == 0) From db88bfff8d74eeb9bc924f327cbb49738a2d6840 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 14:48:32 -0400 Subject: [PATCH 17/37] EDACS: missing space --- src/edacs-fme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 722e125..8729e00 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -821,7 +821,7 @@ void edacs(dsd_opts * opts, dsd_state * state) int target = (msg_2 & 0xFFFFF); //target group or individual ID (20-bit) to include in supergroup fprintf (stderr, "%s", KWHT); //just make it stick out for now - fprintf (stderr, " System Dynamic Regroup :: SSN [%03d] SGID[%05d] Target [%07d]", ssn, sgid, target); + fprintf (stderr, " System Dynamic Regroup :: SSN [%03d] SGID [%05d] Target [%07d]", ssn, sgid, target); if (unk1) fprintf (stderr, " UNK1: [%X]", unk1); //this value seems to always be zero if (unk2) fprintf (stderr, " UNK2: [%X]", unk2); //this value seems to always be zero fprintf (stderr, "%s", KNRM); From 0208f6240c405c4906c74957c34854f11c925020 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 15:38:31 -0400 Subject: [PATCH 18/37] EDACS: Fix copypasta typo in new AFS logic --- src/edacs-fme.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 8729e00..00f26fc 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -464,15 +464,15 @@ void edacs(dsd_opts * opts, dsd_state * state) if (state->edacs_a_bits == 8) state->edacs_a_mask = 0xFF; if (state->edacs_a_bits == 9) state->edacs_a_mask = 0x1FF; - if (state->edacs_f_bits == 1) state->edacs_s_mask = 0x1; - if (state->edacs_f_bits == 2) state->edacs_s_mask = 0x3; - if (state->edacs_f_bits == 3) state->edacs_s_mask = 0x7; - if (state->edacs_f_bits == 4) state->edacs_s_mask = 0xF; - if (state->edacs_f_bits == 5) state->edacs_s_mask = 0x1F; - if (state->edacs_f_bits == 6) state->edacs_s_mask = 0x3F; - if (state->edacs_f_bits == 7) state->edacs_s_mask = 0x7F; - if (state->edacs_f_bits == 8) state->edacs_s_mask = 0xFF; - if (state->edacs_f_bits == 9) state->edacs_s_mask = 0x1FF; + if (state->edacs_f_bits == 1) state->edacs_f_mask = 0x1; + if (state->edacs_f_bits == 2) state->edacs_f_mask = 0x3; + if (state->edacs_f_bits == 3) state->edacs_f_mask = 0x7; + if (state->edacs_f_bits == 4) state->edacs_f_mask = 0xF; + if (state->edacs_f_bits == 5) state->edacs_f_mask = 0x1F; + if (state->edacs_f_bits == 6) state->edacs_f_mask = 0x3F; + if (state->edacs_f_bits == 7) state->edacs_f_mask = 0x7F; + if (state->edacs_f_bits == 8) state->edacs_f_mask = 0xFF; + if (state->edacs_f_bits == 9) state->edacs_f_mask = 0x1FF; if (state->edacs_s_bits == 1) state->edacs_s_mask = 0x1; if (state->edacs_s_bits == 2) state->edacs_s_mask = 0x3; From 4eb2e770c8270d11ec5a8d37448d44f84e502702 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Sat, 13 Apr 2024 16:19:52 -0400 Subject: [PATCH 19/37] EDACS: Redo Parts of EA Patch / Regroup Based on Newer Observations and Remove Overlapping Bit Range; --- src/edacs-fme.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 00f26fc..7f6c840 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -813,17 +813,16 @@ void edacs(dsd_opts * opts, dsd_state * state) int unk1 = (msg_1 & 0x70000) >> 20; //unknown 3 bit value preceeding the SGID int sgid = (msg_1 & 0xFFFF); //patched supergroup ID - //Note: SSN is the supergroup sequence number in P25 Harris lingo, but you would think this would be kind of redundant - //since the SGID is itself a unique number as well (waste of bits), but guess that's how their systems work - //that being said, the SSN is always the same for each SGID, so those values seem to go together here as well - int ssn = (msg_2 & 0xFF00000) >> 20; //this value seems to incrememnt based on SGID, so assigning 8-bit as the SSN - int unk2 = (msg_2 & 0xF0000) >> 16; //unknown 4 bit value preceeding 20-bit target value of patch - int target = (msg_2 & 0xFFFFF); //target group or individual ID (20-bit) to include in supergroup + //Updated Observation: The 'SSN' value may not be unique in this instance, so may be an entirely different value + //altogether. Its function is still unknown, but for the sake of displaying patches, is not required. - fprintf (stderr, "%s", KWHT); //just make it stick out for now - fprintf (stderr, " System Dynamic Regroup :: SSN [%03d] SGID [%05d] Target [%07d]", ssn, sgid, target); - if (unk1) fprintf (stderr, " UNK1: [%X]", unk1); //this value seems to always be zero - if (unk2) fprintf (stderr, " UNK2: [%X]", unk2); //this value seems to always be zero + int ssn = (msg_2 & 0xFF00000) >> 20; //this value seems to incrememnt based on SGID, so assigning 8-bit as the SSN + int target = (msg_2 & 0xFFFFF); //target group or individual ID (20-bit) to include in supergroup + + fprintf (stderr, "%s", KWHT); + fprintf (stderr, " System Dynamic Regroup :: SGID [%05d] Target [%07d]", sgid, target); + if (unk1) fprintf (stderr, " UNK1: [%01X]", unk1); //this value seems to always be zero + if (ssn) fprintf (stderr, " UNK2: [%02X]", ssn); //this may or may not be a unique value to each SGID fprintf (stderr, "%s", KNRM); } //Serial Number Request (not seen in the wild, see US patent 20030190923, Figure 2b) From 7e26b7b9020b279ed2ff86f01d1d87261a7906dd Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 16:22:52 -0400 Subject: [PATCH 20/37] EDACS: Show agency and fleet calls based on AFS --- include/dsd.h | 18 ++++++++++-------- src/dsd_ncurses.c | 6 +++++- src/edacs-fme.c | 19 ++++++++++++++++--- 3 files changed, 31 insertions(+), 12 deletions(-) diff --git a/include/dsd.h b/include/dsd.h index 7cf1e2e..be506ae 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -763,14 +763,16 @@ typedef struct int edacs_s_mask; //Calculated Mask for S Bits //flags for EDACS call type - #define EDACS_IS_VOICE 0x01 - #define EDACS_IS_DIGITAL 0x02 - #define EDACS_IS_EMERGENCY 0x04 - #define EDACS_IS_GROUP 0x08 - #define EDACS_IS_INDIVIDUAL 0x10 - #define EDACS_IS_ALL_CALL 0x20 - #define EDACS_IS_INTERCONNECT 0x40 - #define EDACS_IS_TEST_CALL 0x80 + #define EDACS_IS_VOICE 0x01 + #define EDACS_IS_DIGITAL 0x02 + #define EDACS_IS_EMERGENCY 0x04 + #define EDACS_IS_GROUP 0x08 + #define EDACS_IS_INDIVIDUAL 0x10 + #define EDACS_IS_ALL_CALL 0x20 + #define EDACS_IS_INTERCONNECT 0x40 + #define EDACS_IS_TEST_CALL 0x80 + #define EDACS_IS_AGENCY_CALL 0x100 + #define EDACS_IS_FLEET_CALL 0x200 //trunking group and lcn freq list long int trunk_lcn_freq[26]; //max number on an EDACS system, should be enough on DMR too hopefully diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 8a712c8..a2312b3 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -3665,6 +3665,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) if ((call_matrix[i][4] & EDACS_IS_TEST_CALL) != 0) {} else if ((call_matrix[i][4] & EDACS_IS_DIGITAL) == 0) printw (" [Ana]"); else printw (" [Dig]"); + if ((call_matrix[i][4] & EDACS_IS_AGENCY_CALL) != 0) printw ("[A]"); + if ((call_matrix[i][4] & EDACS_IS_FLEET_CALL) != 0) printw ("[F]"); if ((call_matrix[i][4] & EDACS_IS_EMERGENCY) != 0) printw ("[EM]"); } else @@ -3860,9 +3862,11 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw ("Unknown call type"); // Call flags - if ((call_matrix[j][4] & EDACS_IS_TEST_CALL) != 0) {} + if ((call_matrix[j][4] & EDACS_IS_TEST_CALL) != 0) {} else if ((call_matrix[j][4] & EDACS_IS_DIGITAL) == 0) printw (" [Ana]"); else printw (" [Dig]"); + if ((call_matrix[j][4] & EDACS_IS_AGENCY_CALL) != 0) printw ("[A]"); + if ((call_matrix[j][4] & EDACS_IS_FLEET_CALL) != 0) printw ("[F]"); if ((call_matrix[j][4] & EDACS_IS_EMERGENCY) != 0) printw ("[EM]"); } else diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 7f6c840..1939ce9 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -69,6 +69,17 @@ char* get_lcn_status_string(int lcn) return ""; } +int is_agency_call_group(int afs) +{ + int fs_mask = state->edacs_s_mask | (state->edacs_f_mask << state->edacs_f_shift); + return (afs & fs_mask) == 0 +} + +int is_fleet_call_group(int afs) +{ + return (afs & state->edacs_s_mask) == 0 +} + //Bitwise vote-compare the three copies of a message received. Note that fr_2 and fr_5 are transmitted inverted. unsigned long long int edacs_vote_fr(unsigned long long int fr_1_4, unsigned long long int fr_2_5, unsigned long long int fr_3_6) { @@ -1305,9 +1316,11 @@ void edacs(dsd_opts * opts, dsd_state * state) state->lastsrc = lid; //Call type for state - state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_GROUP; - if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; - if (is_emergency == 1) state->edacs_vc_call_type |= EDACS_IS_EMERGENCY; + state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_GROUP; + if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; + if (is_emergency == 1) state->edacs_vc_call_type |= EDACS_IS_EMERGENCY; + if (is_agency_call_group(group)) state->edacs_vc_call_type |= EDACS_IS_AGENCY_CALL; + if (is_fleet_call_group(group)) state->edacs_vc_call_type |= EDACS_IS_FLEET_CALL; char mode[8]; //allow, block, digital enc sprintf (mode, "%s", ""); From 834bd57ea6e96efb38a6bc31bd58b762b6fa6afc Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 16:23:32 -0400 Subject: [PATCH 21/37] EDACS: logging nit --- src/edacs-fme.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 1939ce9..3f93606 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -832,8 +832,8 @@ void edacs(dsd_opts * opts, dsd_state * state) fprintf (stderr, "%s", KWHT); fprintf (stderr, " System Dynamic Regroup :: SGID [%05d] Target [%07d]", sgid, target); - if (unk1) fprintf (stderr, " UNK1: [%01X]", unk1); //this value seems to always be zero - if (ssn) fprintf (stderr, " UNK2: [%02X]", ssn); //this may or may not be a unique value to each SGID + if (unk1) fprintf (stderr, " UNK1 [%01X]", unk1); //this value seems to always be zero + if (ssn) fprintf (stderr, " UNK2 [%02X]", ssn); //this may or may not be a unique value to each SGID fprintf (stderr, "%s", KNRM); } //Serial Number Request (not seen in the wild, see US patent 20030190923, Figure 2b) From 57c22b484d4cf54a635d0e5187821306a38150c1 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 16:30:36 -0400 Subject: [PATCH 22/37] EDACS: ugh have to pass state too --- src/edacs-fme.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 3f93606..f0fea6f 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -69,15 +69,15 @@ char* get_lcn_status_string(int lcn) return ""; } -int is_agency_call_group(int afs) +int is_agency_call_group(int afs, dsd_state * state) { int fs_mask = state->edacs_s_mask | (state->edacs_f_mask << state->edacs_f_shift); - return (afs & fs_mask) == 0 + return (afs & fs_mask) == 0; } -int is_fleet_call_group(int afs) +int is_fleet_call_group(int afs, dsd_state * state) { - return (afs & state->edacs_s_mask) == 0 + return (afs & state->edacs_s_mask) == 0; } //Bitwise vote-compare the three copies of a message received. Note that fr_2 and fr_5 are transmitted inverted. @@ -1316,11 +1316,11 @@ void edacs(dsd_opts * opts, dsd_state * state) state->lastsrc = lid; //Call type for state - state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_GROUP; - if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; - if (is_emergency == 1) state->edacs_vc_call_type |= EDACS_IS_EMERGENCY; - if (is_agency_call_group(group)) state->edacs_vc_call_type |= EDACS_IS_AGENCY_CALL; - if (is_fleet_call_group(group)) state->edacs_vc_call_type |= EDACS_IS_FLEET_CALL; + state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_GROUP; + if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; + if (is_emergency == 1) state->edacs_vc_call_type |= EDACS_IS_EMERGENCY; + if (is_agency_call_group(group, state)) state->edacs_vc_call_type |= EDACS_IS_AGENCY_CALL; + if (is_fleet_call_group(group, state)) state->edacs_vc_call_type |= EDACS_IS_FLEET_CALL; char mode[8]; //allow, block, digital enc sprintf (mode, "%s", ""); From b86cd1bc3cc551fec5449ec9704e7223ffcdf990 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 16:52:16 -0400 Subject: [PATCH 23/37] EDACS: agency call and fleet call are mutually-exclusive --- src/edacs-fme.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index f0fea6f..880f2de 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -77,6 +77,9 @@ int is_agency_call_group(int afs, dsd_state * state) int is_fleet_call_group(int afs, dsd_state * state) { + if (is_agency_call_group(afs, state)) + return 0; + return (afs & state->edacs_s_mask) == 0; } @@ -1316,11 +1319,11 @@ void edacs(dsd_opts * opts, dsd_state * state) state->lastsrc = lid; //Call type for state - state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_GROUP; - if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; - if (is_emergency == 1) state->edacs_vc_call_type |= EDACS_IS_EMERGENCY; - if (is_agency_call_group(group, state)) state->edacs_vc_call_type |= EDACS_IS_AGENCY_CALL; - if (is_fleet_call_group(group, state)) state->edacs_vc_call_type |= EDACS_IS_FLEET_CALL; + state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_GROUP; + if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; + if (is_emergency == 1) state->edacs_vc_call_type |= EDACS_IS_EMERGENCY; + if (is_agency_call_group(group, state)) state->edacs_vc_call_type |= EDACS_IS_AGENCY_CALL; + else if (is_fleet_call_group(group, state)) state->edacs_vc_call_type |= EDACS_IS_FLEET_CALL; char mode[8]; //allow, block, digital enc sprintf (mode, "%s", ""); From 33d8ee70d982fe8eed103f1bff356860617d3ea9 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sat, 13 Apr 2024 17:15:44 -0400 Subject: [PATCH 24/37] EDACS: compute AFS masks using math, not copy/paste --- src/edacs-fme.c | 34 ++++------------------------------ 1 file changed, 4 insertions(+), 30 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 880f2de..c7d42de 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -467,36 +467,10 @@ void edacs(dsd_opts * opts, dsd_state * state) state->edacs_a_shift = state->edacs_f_bits + state->edacs_s_bits; state->edacs_f_shift = state->edacs_s_bits; - //calculate masks via overkill copy and paste - if (state->edacs_a_bits == 1) state->edacs_a_mask = 0x1; - if (state->edacs_a_bits == 2) state->edacs_a_mask = 0x3; - if (state->edacs_a_bits == 3) state->edacs_a_mask = 0x7; - if (state->edacs_a_bits == 4) state->edacs_a_mask = 0xF; - if (state->edacs_a_bits == 5) state->edacs_a_mask = 0x1F; - if (state->edacs_a_bits == 6) state->edacs_a_mask = 0x3F; - if (state->edacs_a_bits == 7) state->edacs_a_mask = 0x7F; - if (state->edacs_a_bits == 8) state->edacs_a_mask = 0xFF; - if (state->edacs_a_bits == 9) state->edacs_a_mask = 0x1FF; - - if (state->edacs_f_bits == 1) state->edacs_f_mask = 0x1; - if (state->edacs_f_bits == 2) state->edacs_f_mask = 0x3; - if (state->edacs_f_bits == 3) state->edacs_f_mask = 0x7; - if (state->edacs_f_bits == 4) state->edacs_f_mask = 0xF; - if (state->edacs_f_bits == 5) state->edacs_f_mask = 0x1F; - if (state->edacs_f_bits == 6) state->edacs_f_mask = 0x3F; - if (state->edacs_f_bits == 7) state->edacs_f_mask = 0x7F; - if (state->edacs_f_bits == 8) state->edacs_f_mask = 0xFF; - if (state->edacs_f_bits == 9) state->edacs_f_mask = 0x1FF; - - if (state->edacs_s_bits == 1) state->edacs_s_mask = 0x1; - if (state->edacs_s_bits == 2) state->edacs_s_mask = 0x3; - if (state->edacs_s_bits == 3) state->edacs_s_mask = 0x7; - if (state->edacs_s_bits == 4) state->edacs_s_mask = 0xF; - if (state->edacs_s_bits == 5) state->edacs_s_mask = 0x1F; - if (state->edacs_s_bits == 6) state->edacs_s_mask = 0x3F; - if (state->edacs_s_bits == 7) state->edacs_s_mask = 0x7F; - if (state->edacs_s_bits == 8) state->edacs_s_mask = 0xFF; - if (state->edacs_s_bits == 9) state->edacs_s_mask = 0x1FF; + //calculate masks using bitwise math + state->edacs_a_mask = (1 << state->edacs_a_bits) - 1; + state->edacs_f_mask = (1 << state->edacs_f_bits) - 1; + state->edacs_s_mask = (1 << state->edacs_s_bits) - 1; char * timestr; //add timestr here, so we can assign it and also free it to prevent memory leak timestr = getTimeE(); From 8980207fd688df187fbb5401a976178bf2e58f51 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sun, 14 Apr 2024 09:12:01 -0400 Subject: [PATCH 25/37] EDACS: fix wrong comment --- src/dsd_ncurses.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index a2312b3..8ee6e91 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -3608,7 +3608,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) // Voice call if ((call_matrix[i][4] & EDACS_IS_VOICE) != 0) { - // System all-call + // Group call if ((call_matrix[i][4] & EDACS_IS_GROUP) != 0) printw (" TGT [%8lld] SRC [%8lld]", call_matrix[i][2], call_matrix[i][3] ); // I-Call From ad78373b435b98501901df98e43438e5cf445d11 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sun, 14 Apr 2024 09:12:26 -0400 Subject: [PATCH 26/37] EDACS: fix width of source for non-EA data calls --- src/dsd_ncurses.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index 8ee6e91..b47030a 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -3671,7 +3671,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) } else // Data call - printw (" TGT [ DATA ] SRC [%8lld] Data", call_matrix[i][3] ); + printw (" TGT [ DATA ] SRC [%5lld] Data", call_matrix[i][3] ); } for (int k = 0; k < state->group_tally; k++) { From d84136dc9283599dc9b435b2b3b2127c6d17b28a Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sun, 14 Apr 2024 09:40:03 -0400 Subject: [PATCH 27/37] EDACS: show agency/fleet call on channel updates too --- src/edacs-fme.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index c7d42de..eb82fca 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -1530,11 +1530,13 @@ void edacs(dsd_opts * opts, dsd_state * state) state->lastsrc = 0; //Call type for state - state->edacs_vc_call_type = EDACS_IS_VOICE; - if (is_individual == 0) state->edacs_vc_call_type |= EDACS_IS_GROUP; - else state->edacs_vc_call_type |= EDACS_IS_INDIVIDUAL; - if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; - if (is_emergency == 1) state->edacs_vc_call_type |= EDACS_IS_EMERGENCY; + state->edacs_vc_call_type = EDACS_IS_VOICE; + if (is_individual == 0) state->edacs_vc_call_type |= EDACS_IS_GROUP; + else state->edacs_vc_call_type |= EDACS_IS_INDIVIDUAL; + if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; + if (is_emergency == 1) state->edacs_vc_call_type |= EDACS_IS_EMERGENCY; + if (is_agency_call_group(group, state)) state->edacs_vc_call_type |= EDACS_IS_AGENCY_CALL; + else if (is_fleet_call_group(group, state)) state->edacs_vc_call_type |= EDACS_IS_FLEET_CALL; char mode[8]; //allow, block, digital enc sprintf (mode, "%s", ""); From ba41ba57f6bf7bd2c2fd6b9bea9253a905f0b989 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sun, 14 Apr 2024 09:42:43 -0400 Subject: [PATCH 28/37] EDACS: fix vc_call_type for EDACS_IS_TEST_CALL --- src/edacs-fme.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index eb82fca..d62d3e0 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -611,7 +611,7 @@ void edacs(dsd_opts * opts, dsd_state * state) //and overwrite current values in the matrix state->lasttg = 999999999; state->lastsrc = 999999999; - state->edacs_vc_call_type = EDACS_IS_TEST_CALL | EDACS_IS_VOICE; //manually set to trigger voice call in ncurses, but no other flags + state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_TEST_CALL; } //Adjacent Sites else if (mt2 == 0x1) @@ -990,7 +990,8 @@ void edacs(dsd_opts * opts, dsd_state * state) if (source != 0) state->lastsrc = source; //Call type for state - state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_INDIVIDUAL; + if (target == 0 && source == 0) state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_TEST_CALL; + else state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_INDIVIDUAL; if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; //Test calls are just I-Calls with source and target of 0 @@ -1006,7 +1007,6 @@ void edacs(dsd_opts * opts, dsd_state * state) //and overwrite current values in the matrix state->lasttg = 999999999; state->lastsrc = 999999999; - state->edacs_vc_call_type = EDACS_IS_TEST_CALL | EDACS_IS_VOICE; //manually set to trigger voice call in ncurses, but no other flags lcn = 0; //set to zero here, because this is not an actual call, so don't tune to it } else @@ -1643,7 +1643,6 @@ void edacs(dsd_opts * opts, dsd_state * state) //assign bogus values so that this will show up in ncurses terminal and overwrite current values in the matrix state->lasttg = 999999999; state->lastsrc = 999999999; - state->edacs_vc_call_type = EDACS_IS_TEST_CALL | EDACS_IS_VOICE; //manually set to trigger voice call in ncurses, but no other flags lcn = 0; //set to zero here, because this is not an actual call, so don't tune to it } else { @@ -1668,8 +1667,9 @@ void edacs(dsd_opts * opts, dsd_state * state) state->lastsrc = source; //Call type for state - state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_INDIVIDUAL; - if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; + if (target == 0 && source == 0) state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_TEST_CALL; + else state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_INDIVIDUAL; + if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; char mode[8]; //allow, block, digital enc sprintf (mode, "%s", ""); From b5a43031f963da261a1f0e4d27802fcd5166cc96 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sun, 14 Apr 2024 09:52:22 -0400 Subject: [PATCH 29/37] EDACS: rename functions to lowerCamelCase style It's, like, mildly more consistent... and is subtly shorter, which is handy for some cases. Though yeah we have functions with both styles in the same file. --- src/edacs-fme.c | 78 ++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index d62d3e0..9cd9438 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -53,7 +53,7 @@ char * getTimeE(void) //get pretty hhmmss timestamp return curr; } -char* get_lcn_status_string(int lcn) +char * getLcnStatusString(int lcn) { if (lcn == 26 || lcn == 27) return "[Reserved LCN Status]"; @@ -69,22 +69,22 @@ char* get_lcn_status_string(int lcn) return ""; } -int is_agency_call_group(int afs, dsd_state * state) +int isAgencyCallGroup(int afs, dsd_state * state) { int fs_mask = state->edacs_s_mask | (state->edacs_f_mask << state->edacs_f_shift); return (afs & fs_mask) == 0; } -int is_fleet_call_group(int afs, dsd_state * state) +int isFleetCallGroup(int afs, dsd_state * state) { - if (is_agency_call_group(afs, state)) + if (isAgencyCallGroup(afs, state)) return 0; return (afs & state->edacs_s_mask) == 0; } //Bitwise vote-compare the three copies of a message received. Note that fr_2 and fr_5 are transmitted inverted. -unsigned long long int edacs_vote_fr(unsigned long long int fr_1_4, unsigned long long int fr_2_5, unsigned long long int fr_3_6) +unsigned long long int edacsVoteFr(unsigned long long int fr_1_4, unsigned long long int fr_2_5, unsigned long long int fr_3_6) { fr_2_5 = (~fr_2_5) & 0xFFFFFFFFFF; @@ -516,8 +516,8 @@ void edacs(dsd_opts * opts, dsd_state * state) } //Take our 3 copies of the first and second message and vote them to extract the two "error-corrected" messages - unsigned long long int msg_1_ec = edacs_vote_fr(fr_1, fr_2, fr_3); - unsigned long long int msg_2_ec = edacs_vote_fr(fr_4, fr_5, fr_6); + unsigned long long int msg_1_ec = edacsVoteFr(fr_1, fr_2, fr_3); + unsigned long long int msg_2_ec = edacsVoteFr(fr_4, fr_5, fr_6); //Get just the 28-bit message portion unsigned long long int msg_1_ec_m = msg_1_ec >> 12; @@ -623,7 +623,7 @@ void edacs(dsd_opts * opts, dsd_state * state) fprintf (stderr, "%s", KYEL); fprintf (stderr, " Adjacent Site"); if (adj_site > 0) - fprintf (stderr, " :: Site ID [%02X][%03d] Index [%d] on CC LCN [%02d]%s", adj_site, adj_site, adj_idx, adj_lcn, get_lcn_status_string(lcn)); + fprintf (stderr, " :: Site ID [%02X][%03d] Index [%d] on CC LCN [%02d]%s", adj_site, adj_site, adj_idx, adj_lcn, getLcnStatusString(lcn)); else fprintf (stderr, " :: Total Indexed [%d]", adj_idx); //if site value is 0, then this tells us the total number of adjacent sites if (adj_site == 0 && adj_idx == 0) fprintf (stderr, " [Adjacency Table Reset]"); @@ -673,7 +673,7 @@ void edacs(dsd_opts * opts, dsd_state * state) { state->edacs_lcn_count = state->edacs_cc_lcn; } - fprintf (stderr, " :: System ID [%04X] CC LCN [%02d]%s", system, state->edacs_cc_lcn, get_lcn_status_string(lcn)); + fprintf (stderr, " :: System ID [%04X] CC LCN [%02d]%s", system, state->edacs_cc_lcn, getLcnStatusString(lcn)); //check for control channel lcn frequency if not provided in channel map or in the lcn list if (state->trunk_lcn_freq[state->edacs_cc_lcn-1] == 0) @@ -843,7 +843,7 @@ void edacs(dsd_opts * opts, dsd_state * state) int source = (msg_2 & 0xFFFFF); fprintf (stderr, "%s", KGRN); - fprintf (stderr, " TDMA Group Call :: Group [%05d] Source [%08d] LCN [%02d]%s", group, source, lcn, get_lcn_status_string(lcn)); + fprintf (stderr, " TDMA Group Call :: Group [%05d] Source [%08d] LCN [%02d]%s", group, source, lcn, getLcnStatusString(lcn)); fprintf (stderr, "%s", KNRM); } //Data Group Grant Update @@ -854,7 +854,7 @@ void edacs(dsd_opts * opts, dsd_state * state) int source = (msg_2 & 0xFFFFF); fprintf (stderr, "%s", KBLU); - fprintf (stderr, " Data Group Call :: Group [%05d] Source [%08d] LCN [%02d]%s", group, source, lcn, get_lcn_status_string(lcn)); + fprintf (stderr, " Data Group Call :: Group [%05d] Source [%08d] LCN [%02d]%s", group, source, lcn, getLcnStatusString(lcn)); fprintf (stderr, "%s", KNRM); } //Voice Call Grant Update @@ -893,7 +893,7 @@ void edacs(dsd_opts * opts, dsd_state * state) else fprintf (stderr, " Digital Group Call"); if (is_update == 0) fprintf (stderr, " Assignment"); else fprintf (stderr, " Update"); - fprintf (stderr, " :: Group [%05d] Source [%08d] LCN [%02d]%s", group, source, lcn, get_lcn_status_string(lcn)); + fprintf (stderr, " :: Group [%05d] Source [%08d] LCN [%02d]%s", group, source, lcn, getLcnStatusString(lcn)); //Trunking mode is correlated to (but not guaranteed to match) the type of call: // - emergency calls - usually message trunking @@ -1001,7 +1001,7 @@ void edacs(dsd_opts * opts, dsd_state * state) fprintf (stderr, " Test Call"); if (is_update == 0) fprintf (stderr, " Assignment"); else fprintf (stderr, " Update"); - fprintf (stderr, " :: LCN [%02d]%s", lcn, get_lcn_status_string(lcn)); + fprintf (stderr, " :: LCN [%02d]%s", lcn, getLcnStatusString(lcn)); state->edacs_vc_lcn = lcn; //assign bogus values so that this will show up in ncurses terminal //and overwrite current values in the matrix @@ -1017,7 +1017,7 @@ void edacs(dsd_opts * opts, dsd_state * state) if (is_update == 0) fprintf (stderr, " Assignment"); else fprintf (stderr, " Update"); - fprintf (stderr, " :: Target [%08d] Source [%08d] LCN [%02d]%s", target, source, lcn, get_lcn_status_string(lcn)); + fprintf (stderr, " :: Target [%08d] Source [%08d] LCN [%02d]%s", target, source, lcn, getLcnStatusString(lcn)); } fprintf (stderr, "%s", KNRM); @@ -1089,7 +1089,7 @@ void edacs(dsd_opts * opts, dsd_state * state) int source = (msg_2 & 0xFFFFF); fprintf (stderr, "%s", KBLU); - fprintf (stderr, " Channel Assignment (Unknown Data) :: Source [%08d] LCN [%02d]%s", source, lcn, get_lcn_status_string(lcn)); + fprintf (stderr, " Channel Assignment (Unknown Data) :: Source [%08d] LCN [%02d]%s", source, lcn, getLcnStatusString(lcn)); fprintf (stderr, "%s", KNRM); //LCNs greater than 26 are considered status values, "Busy, Queue, Deny, etc" @@ -1135,7 +1135,7 @@ void edacs(dsd_opts * opts, dsd_state * state) if (is_update == 0) fprintf (stderr, " Assignment"); else fprintf (stderr, " Update"); - fprintf (stderr, " :: Source [%08d] LCN [%02d]%s", source, lcn, get_lcn_status_string(lcn)); + fprintf (stderr, " :: Source [%08d] LCN [%02d]%s", source, lcn, getLcnStatusString(lcn)); fprintf (stderr, "%s", KNRM); char mode[8]; //allow, block, digital enc @@ -1272,7 +1272,7 @@ void edacs(dsd_opts * opts, dsd_state * state) fprintf (stderr, " Voice Group Channel Assignment ::"); if (is_digital == 0) fprintf (stderr, " Analog"); else fprintf (stderr, " Digital"); - fprintf (stderr, " Group [%04d] LID [%05d] LCN [%02d]%s", group, lid, lcn, get_lcn_status_string(lcn)); + fprintf (stderr, " Group [%04d] LID [%05d] LCN [%02d]%s", group, lid, lcn, getLcnStatusString(lcn)); if (is_tx_trunk == 0) fprintf (stderr, " [Message Trunking]"); if (is_emergency == 1) { @@ -1293,11 +1293,11 @@ void edacs(dsd_opts * opts, dsd_state * state) state->lastsrc = lid; //Call type for state - state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_GROUP; - if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; - if (is_emergency == 1) state->edacs_vc_call_type |= EDACS_IS_EMERGENCY; - if (is_agency_call_group(group, state)) state->edacs_vc_call_type |= EDACS_IS_AGENCY_CALL; - else if (is_fleet_call_group(group, state)) state->edacs_vc_call_type |= EDACS_IS_FLEET_CALL; + state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_GROUP; + if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; + if (is_emergency == 1) state->edacs_vc_call_type |= EDACS_IS_EMERGENCY; + if (isAgencyCallGroup(group, state)) state->edacs_vc_call_type |= EDACS_IS_AGENCY_CALL; + else if (isFleetCallGroup(group, state)) state->edacs_vc_call_type |= EDACS_IS_FLEET_CALL; char mode[8]; //allow, block, digital enc sprintf (mode, "%s", ""); @@ -1385,7 +1385,7 @@ void edacs(dsd_opts * opts, dsd_state * state) else fprintf (stderr, " Group [%04d]", target); if (is_from_lid == 1) fprintf (stderr, " -->"); else fprintf (stderr, " <--"); - fprintf (stderr, " Port [%02d] LCN [%02d]%s", port, lcn, get_lcn_status_string(lcn)); + fprintf (stderr, " Port [%02d] LCN [%02d]%s", port, lcn, getLcnStatusString(lcn)); fprintf (stderr, "%s", KNRM); //LCNs >= 26 are reserved to indicate status (queued, busy, denied, etc) @@ -1448,7 +1448,7 @@ void edacs(dsd_opts * opts, dsd_state * state) else fprintf (stderr, " Digital"); if (is_individual_id == 1) fprintf (stderr, " LID [%05d]", target); else fprintf (stderr, " Group [%04d]", target); - fprintf (stderr, " LCN [%02d]%s", lcn, get_lcn_status_string(lcn)); + fprintf (stderr, " LCN [%02d]%s", lcn, getLcnStatusString(lcn)); fprintf (stderr, "%s", KNRM); //LCNs >= 26 are reserved to indicate status (queued, busy, denied, etc) @@ -1508,7 +1508,7 @@ void edacs(dsd_opts * opts, dsd_state * state) else fprintf (stderr, " Digital"); if (is_individual == 0) fprintf (stderr, " Group [%04d]", target); else if (is_test_call == 0) fprintf (stderr, " Callee [%05d] Caller [%05d]", target, source); - fprintf (stderr, " LCN [%02d]%s", lcn, get_lcn_status_string(lcn)); + fprintf (stderr, " LCN [%02d]%s", lcn, getLcnStatusString(lcn)); if (is_tx_trunk == 0) fprintf (stderr, " [Message Trunking]"); if (is_emergency == 1) { @@ -1530,13 +1530,13 @@ void edacs(dsd_opts * opts, dsd_state * state) state->lastsrc = 0; //Call type for state - state->edacs_vc_call_type = EDACS_IS_VOICE; - if (is_individual == 0) state->edacs_vc_call_type |= EDACS_IS_GROUP; - else state->edacs_vc_call_type |= EDACS_IS_INDIVIDUAL; - if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; - if (is_emergency == 1) state->edacs_vc_call_type |= EDACS_IS_EMERGENCY; - if (is_agency_call_group(group, state)) state->edacs_vc_call_type |= EDACS_IS_AGENCY_CALL; - else if (is_fleet_call_group(group, state)) state->edacs_vc_call_type |= EDACS_IS_FLEET_CALL; + state->edacs_vc_call_type = EDACS_IS_VOICE; + if (is_individual == 0) state->edacs_vc_call_type |= EDACS_IS_GROUP; + else state->edacs_vc_call_type |= EDACS_IS_INDIVIDUAL; + if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; + if (is_emergency == 1) state->edacs_vc_call_type |= EDACS_IS_EMERGENCY; + if (isAgencyCallGroup(group, state)) state->edacs_vc_call_type |= EDACS_IS_AGENCY_CALL; + else if (isFleetCallGroup(group, state)) state->edacs_vc_call_type |= EDACS_IS_FLEET_CALL; char mode[8]; //allow, block, digital enc sprintf (mode, "%s", ""); @@ -1637,7 +1637,7 @@ void edacs(dsd_opts * opts, dsd_state * state) { fprintf (stderr, "%s", KMAG); fprintf (stderr, " Test Call Channel Assignment ::"); - fprintf (stderr, " LCN [%02d]%s", lcn, get_lcn_status_string(lcn)); + fprintf (stderr, " LCN [%02d]%s", lcn, getLcnStatusString(lcn)); state->edacs_vc_lcn = lcn; //assign bogus values so that this will show up in ncurses terminal and overwrite current values in the matrix @@ -1650,7 +1650,7 @@ void edacs(dsd_opts * opts, dsd_state * state) fprintf (stderr, " Voice Individual Channel Assignment ::"); if (is_digital == 0) fprintf (stderr, " Analog"); else fprintf (stderr, " Digital"); - fprintf (stderr, " Callee [%05d] Caller [%05d] LCN [%02d]%s", target, source, lcn, get_lcn_status_string(lcn)); + fprintf (stderr, " Callee [%05d] Caller [%05d] LCN [%02d]%s", target, source, lcn, getLcnStatusString(lcn)); if (is_tx_trunk == 0) fprintf (stderr, " [Message Trunking]"); } fprintf (stderr, "%s", KNRM); @@ -1733,7 +1733,7 @@ void edacs(dsd_opts * opts, dsd_state * state) fprintf (stderr, " Console "); if (is_drop == 0) fprintf (stderr, " Unkey"); else fprintf (stderr, " Drop"); - fprintf (stderr, " :: LID [%05d] LCN [%02d]%s", lid, lcn, get_lcn_status_string(lcn)); + fprintf (stderr, " :: LID [%05d] LCN [%02d]%s", lid, lcn, getLcnStatusString(lcn)); fprintf (stderr, "%s", KNRM); } //Use MT-D @@ -1757,7 +1757,7 @@ void edacs(dsd_opts * opts, dsd_state * state) int adj_site_id = (msg_1 & 0x1F0) >> 4; fprintf (stderr, "%s", KYEL); - fprintf (stderr, " Adjacent Site Control Channel :: Site ID [%02X][%03d] Index [%1d] LCN [%02d]%s", adj_site_id, adj_site_id, adj_site_index, adj_cc_lcn, get_lcn_status_string(adj_cc_lcn)); + fprintf (stderr, " Adjacent Site Control Channel :: Site ID [%02X][%03d] Index [%1d] LCN [%02d]%s", adj_site_id, adj_site_id, adj_site_index, adj_cc_lcn, getLcnStatusString(adj_cc_lcn)); if (adj_site_id == 0 && adj_site_index == 0) fprintf (stderr, " [Adjacency Table Reset]"); else if (adj_site_id != 0 && adj_site_index == 0) fprintf (stderr, " [Priority System Definition]"); else if (adj_site_id == 0 && adj_site_index != 0) fprintf (stderr, " [Adjacencies Table Length Definition]"); @@ -1838,7 +1838,7 @@ void edacs(dsd_opts * opts, dsd_state * state) int group = (msg_1 & 0x7FF); fprintf (stderr, "%s", KYEL); - fprintf (stderr, " Assignment to Auxiliary CC :: Group [%04d] Aux CC LCN [%02d]%s", group, aux_cc_lcn, get_lcn_status_string(aux_cc_lcn)); + fprintf (stderr, " Assignment to Auxiliary CC :: Group [%04d] Aux CC LCN [%02d]%s", group, aux_cc_lcn, getLcnStatusString(aux_cc_lcn)); fprintf (stderr, "%s", KNRM); } //Initiate Test Call Command (6.2.4.16) @@ -1877,7 +1877,7 @@ void edacs(dsd_opts * opts, dsd_state * state) int site_id = (msg_1 & 0x1F); fprintf (stderr, "%s", KYEL); - fprintf (stderr, " Standard/Networked :: Site ID [%02X][%03d] Priority [%1d] CC LCN [%02d]%s", site_id, site_id, priority, cc_lcn, get_lcn_status_string(cc_lcn)); + fprintf (stderr, " Standard/Networked :: Site ID [%02X][%03d] Priority [%1d] CC LCN [%02d]%s", site_id, site_id, priority, cc_lcn, getLcnStatusString(cc_lcn)); if (is_failsoft == 1) { fprintf (stderr, "%s", KRED); @@ -1946,7 +1946,7 @@ void edacs(dsd_opts * opts, dsd_state * state) fprintf (stderr, " ::"); if (is_digital == 0) fprintf (stderr, " Analog"); else fprintf (stderr, " Digital"); - fprintf (stderr, " LID [%05d] LCN [%02d]%s", lid, lcn, get_lcn_status_string(lcn)); + fprintf (stderr, " LID [%05d] LCN [%02d]%s", lid, lcn, getLcnStatusString(lcn)); if (is_tx_trunk == 0) fprintf (stderr, " [Message Trunking]"); fprintf (stderr, "%s", KNRM); From 0568475d59cefc0d1a599f990ceec4818cfba7c9 Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sun, 14 Apr 2024 08:23:14 -0400 Subject: [PATCH 30/37] EDACS: custom format for custom AFS patterns --- src/dsd_ncurses.c | 182 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 165 insertions(+), 17 deletions(-) diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index b47030a..e84ce89 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -315,6 +315,107 @@ char * getTimeC(time_t t) //get pretty hh:mm:ss timestamp return curr; } +int isCustomAfsString(dsd_state * state) { + return state->edacs_a_bits != 4 || state->edacs_f_bits != 4 || state->edacs_s_bits != 3; +} + +//Get the string length we need for an AFS string, math-style +int getAfsStringLength(dsd_state * state) { + if (!isCustomAfsString(state)) + return 6; + + int length = 0; + length += (state->edacs_a_bits + 2) / 3; + length += (state->edacs_f_bits + 2) / 3; + length += (state->edacs_s_bits + 2) / 3; + length += 2; //colon separators + + // This will be either 6 or 7 + return length; +} + +//Format the AFS string, Florida-style +int getAfsString(dsd_state * state, char * buffer, int a, int f, int s) { + if (!isCustomAfsString(state)) + { + sprintf(buffer, "%02d-%02d%01d", a, f, s); + return 6; + } + + int printed_chars = 0; + switch (state->edacs_a_bits) + { + case 1: + case 2: + case 3: + sprintf(buffer, "%01d:", a); + printed_chars += 1; + break; + case 4: + case 5: + case 6: + sprintf(buffer, "%02d:", a); + printed_chars += 2; + break; + case 7: + case 8: + case 9: + sprintf(buffer, "%03d:", a); + printed_chars += 3; + break; + } + + sprintf(buffer + printed_chars, ":"); + printed_chars++; + + switch (state->edacs_f_bits) { + case 1: + case 2: + case 3: + sprintf(buffer + printed_chars, "%01d", f); + printed_chars += 1; + break; + case 4: + case 5: + case 6: + sprintf(buffer + printed_chars, "%02d", f); + printed_chars += 2; + break; + case 7: + case 8: + case 9: + sprintf(buffer + printed_chars, "%03d", f); + printed_chars += 3; + break; + } + + sprintf(buffer + printed_chars, ":"); + printed_chars++; + + switch (state->edacs_s_bits) { + case 1: + case 2: + case 3: + sprintf(buffer + printed_chars, "%01d", s); + printed_chars += 1; + break; + case 4: + case 5: + case 6: + sprintf(buffer + printed_chars, "%02d", s); + printed_chars += 2; + break; + case 7: + case 8: + case 9: + sprintf(buffer + printed_chars, "%03d", s); + printed_chars += 3; + break; + } + + return printed_chars; +} + //testing a few things, going to put this into ncursesMenu #define WIDTH 36 #define HEIGHT 25 @@ -2608,7 +2709,12 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) int f = (state->tg_hold >> state->edacs_f_shift) & state->edacs_f_mask; int s = state->tg_hold & state->edacs_s_mask; if (state->ea_mode == 1) printw ("\n| \\TG HOLD: %d; ", state->tg_hold); - else printw ("\n| \\TG HOLD: %d [%02d-%02d%01d]; ", state->tg_hold, a, f, s); + else + { + char afs_str[8]; + getAfsString(state, afs_str, a, f, s); + printw ("\n| \\TG HOLD: %d [%s]; ", state->tg_hold, afs_str); + } } attron(COLOR_PAIR(4)); @@ -2649,7 +2755,12 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) int f = (state->tg_hold >> state->edacs_f_shift) & state->edacs_f_mask; int s = state->tg_hold & state->edacs_s_mask; if (state->ea_mode == 1) printw ("\n| \\TG HOLD: %d; ", state->tg_hold); - else printw ("\n| \\TG HOLD: %d [%02d-%02d%01d]; ", state->tg_hold, a, f, s); + else + { + char afs_str[8]; + getAfsString(state, afs_str, a, f, s); + printw ("\n| \\TG HOLD: %d [%s]; ", state->tg_hold, afs_str); + } } printw ("\n"); @@ -3644,19 +3755,35 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) { // Group call if ((call_matrix[i][4] & EDACS_IS_GROUP) != 0) - printw (" TGT [%6lld][%02d-%02d%01d] SRC [%5lld]", call_matrix[i][2], a, f, s, call_matrix[i][3] ); + { + char afs_str[8]; + getAfsString(state, afs_str, a, f, s); + printw (" TGT [%6lld][%s] SRC [%5lld]", call_matrix[i][2], afs_str, call_matrix[i][3] ); + } // I-Call else if ((call_matrix[i][4] & EDACS_IS_INDIVIDUAL) != 0) - printw (" TGT [%6lld][ UNIT ] SRC [%5lld] I-Call", call_matrix[i][2], call_matrix[i][3] ); + if (getAfsStringLength(state) == 6) + printw (" TGT [%6lld][ UNIT ] SRC [%5lld] I-Call", call_matrix[i][2], call_matrix[i][3] ); + else + printw (" TGT [%6lld][ UNIT ] SRC [%5lld] I-Call", call_matrix[i][2], call_matrix[i][3] ); // System all-call else if ((call_matrix[i][4] & EDACS_IS_ALL_CALL) != 0) - printw (" TGT [ SYSTEM ] SRC [%5lld] All-Call", call_matrix[i][3] ); + if (getAfsStringLength(state) == 6) + printw (" TGT [ SYSTEM ] SRC [%5lld] All-Call", call_matrix[i][3] ); + else + printw (" TGT [ SYSTEM ] SRC [%5lld] All-Call", call_matrix[i][3] ); // Interconnect call else if ((call_matrix[i][4] & EDACS_IS_INTERCONNECT) != 0) - printw (" TGT [ SYSTEM ] SRC [%5lld] Interconnect", call_matrix[i][3] ); + if (getAfsStringLength(state) == 6) + printw (" TGT [ SYSTEM ] SRC [%5lld] Interconnect", call_matrix[i][3] ); + else + printw (" TGT [ SYSTEM ] SRC [%5lld] Interconnect", call_matrix[i][3] ); // Test call else if ((call_matrix[i][4] & EDACS_IS_TEST_CALL) != 0) - printw (" TGT [ SYSTEM ] SRC [ SYS ] Test Call"); + if (getAfsStringLength(state) == 6) + printw (" TGT [ SYSTEM ] SRC [ SYS ] Test Call"); + else + printw (" TGT [ SYSTEM ] SRC [ SYS ] Test Call"); // Unknown call else printw (" Unknown call type" ); @@ -3669,9 +3796,12 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) if ((call_matrix[i][4] & EDACS_IS_FLEET_CALL) != 0) printw ("[F]"); if ((call_matrix[i][4] & EDACS_IS_EMERGENCY) != 0) printw ("[EM]"); } + // Data call else - // Data call - printw (" TGT [ DATA ] SRC [%5lld] Data", call_matrix[i][3] ); + if (getAfsStringLength(state) == 6) + printw (" TGT [ DATA ] SRC [%5lld] Data", call_matrix[i][3] ); + else + printw (" TGT [ DATA ] SRC [%5lld] Data", call_matrix[i][3] ); } for (int k = 0; k < state->group_tally; k++) { @@ -3843,20 +3973,35 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) int s = call_matrix[j][2] & state->edacs_s_mask; // Group call - if ((call_matrix[j][4] & EDACS_IS_GROUP) != 0) - printw ("Target [%6lld][%02d-%02d%01d] Source [%5lld]", call_matrix[j][2], a, f, s, call_matrix[j][3]); + if ((call_matrix[j][4] & EDACS_IS_GROUP) != 0) { + char afs_str[8]; + getAfsString(state, afs_str, a, f, s); + printw ("Target [%6lld][%s] Source [%5lld]", call_matrix[j][2], afs_str, call_matrix[j][3]); + } // I-Call else if ((call_matrix[j][4] & EDACS_IS_INDIVIDUAL) != 0) - printw ("Target [%6lld][ UNIT ] Source [%5lld] I-Call", call_matrix[j][2], call_matrix[j][3]); + if (getAfsStringLength(state) == 6) + printw ("Target [%6lld][ UNIT ] Source [%5lld] I-Call", call_matrix[j][2], call_matrix[j][3]); + else + printw ("Target [%6lld][ UNIT ] Source [%5lld] I-Call", call_matrix[j][2], call_matrix[j][3]); // System all-call else if ((call_matrix[j][4] & EDACS_IS_ALL_CALL) != 0) - printw ("Target [ SYSTEM ] Source [%5lld] All-Call", call_matrix[j][3]); + if (getAfsStringLength(state) == 6) + printw ("Target [ SYSTEM ] Source [%5lld] All-Call", call_matrix[j][3]); + else + printw ("Target [ SYSTEM ] Source [%5lld] All-Call", call_matrix[j][3]); // Interconnect else if ((call_matrix[j][4] & EDACS_IS_INTERCONNECT) != 0) - printw ("Target [ SYSTEM ] Source [%5lld] Interconnect", call_matrix[j][3]); + if (getAfsStringLength(state) == 6) + printw ("Target [ SYSTEM ] Source [%5lld] Interconnect", call_matrix[j][3]); + else + printw ("Target [ SYSTEM ] Source [%5lld] Interconnect", call_matrix[j][3]); // Test call else if ((call_matrix[j][4] & EDACS_IS_TEST_CALL) != 0) - printw ("Target [ SYSTEM ] Source [ SYS ] Test Call"); + if (getAfsStringLength(state) == 6) + printw ("Target [ SYSTEM ] Source [ SYS ] Test Call"); + else + printw ("Target [ SYSTEM ] Source [ SYS ] Test Call"); // Unknown call else printw ("Unknown call type"); @@ -3869,9 +4014,12 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) if ((call_matrix[j][4] & EDACS_IS_FLEET_CALL) != 0) printw ("[F]"); if ((call_matrix[j][4] & EDACS_IS_EMERGENCY) != 0) printw ("[EM]"); } + // Data call else - // Data call - printw ("Target [ DATA ] Source [%5lld] Data", call_matrix[j][3]); + if (getAfsStringLength(state) == 6) + printw ("Target [ DATA ] Source [%5lld] Data", call_matrix[j][3]); + else + printw ("Target [ DATA ] Source [%5lld] Data", call_matrix[j][3]); } //test for (int k = 0; k < state->group_tally; k++) From 8206a5f3f40fc13779386349fd04e9e8759d2d0e Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sun, 14 Apr 2024 10:00:46 -0400 Subject: [PATCH 31/37] EDACS: print agency/fleet calls in logs --- src/edacs-fme.c | 58 ++++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 25 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 9cd9438..60b02bf 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -1261,18 +1261,22 @@ void edacs(dsd_opts * opts, dsd_state * state) //Emergency Voice Group Channel Assignment (6.2.4.2) if (mt_a == 0x0 || mt_a == 0x1 || mt_a == 0x2 || mt_a == 0x3) { - int is_digital = (mt_a == 0x2 || mt_a == 0x3) ? 1 : 0; - int is_emergency = (mt_a == 0x1 || mt_a == 0x3) ? 1 : 0; - int lid = ((msg_1 & 0x1FC0000) >> 11) | ((msg_2 & 0xFE0000) >> 17); - int lcn = (msg_1 & 0x1F000) >> 12; - int is_tx_trunk = (msg_1 & 0x800) >> 11; - int group = (msg_1 & 0x7FF); + int is_digital = (mt_a == 0x2 || mt_a == 0x3) ? 1 : 0; + int is_emergency = (mt_a == 0x1 || mt_a == 0x3) ? 1 : 0; + int lid = ((msg_1 & 0x1FC0000) >> 11) | ((msg_2 & 0xFE0000) >> 17); + int lcn = (msg_1 & 0x1F000) >> 12; + int is_tx_trunk = (msg_1 & 0x800) >> 11; + int group = (msg_1 & 0x7FF); + int is_agency_call = isAgencyCallGroup(group, state); + int is_fleet_call = isFleetCallGroup(group, state); fprintf (stderr, "%s", KGRN); fprintf (stderr, " Voice Group Channel Assignment ::"); if (is_digital == 0) fprintf (stderr, " Analog"); else fprintf (stderr, " Digital"); fprintf (stderr, " Group [%04d] LID [%05d] LCN [%02d]%s", group, lid, lcn, getLcnStatusString(lcn)); + if (is_agency_call == 1) fprintf (stderr, " [Agency]"); + else if (is_agency_call == 1) fprintf (stderr, " [Fleet]"); if (is_tx_trunk == 0) fprintf (stderr, " [Message Trunking]"); if (is_emergency == 1) { @@ -1293,11 +1297,11 @@ void edacs(dsd_opts * opts, dsd_state * state) state->lastsrc = lid; //Call type for state - state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_GROUP; - if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; - if (is_emergency == 1) state->edacs_vc_call_type |= EDACS_IS_EMERGENCY; - if (isAgencyCallGroup(group, state)) state->edacs_vc_call_type |= EDACS_IS_AGENCY_CALL; - else if (isFleetCallGroup(group, state)) state->edacs_vc_call_type |= EDACS_IS_FLEET_CALL; + state->edacs_vc_call_type = EDACS_IS_VOICE | EDACS_IS_GROUP; + if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; + if (is_emergency == 1) state->edacs_vc_call_type |= EDACS_IS_EMERGENCY; + if (is_agency_call) state->edacs_vc_call_type |= EDACS_IS_AGENCY_CALL; + else if (is_fleet_call) state->edacs_vc_call_type |= EDACS_IS_FLEET_CALL; char mode[8]; //allow, block, digital enc sprintf (mode, "%s", ""); @@ -1471,13 +1475,15 @@ void edacs(dsd_opts * opts, dsd_state * state) //Test calls reverse engineered from HartLink system else if (mt_b == 0x3) { - int mt_c = (msg_1 & 0x300000) >> 20; - int lcn = (msg_1 & 0xF8000) >> 15; - int is_individual = (msg_1 & 0x4000) >> 14; - int is_emergency = (is_individual == 0) ? (msg_1 & 0x2000) >> 13 : 0; - int group = (msg_1 & 0x7FF); - int lid = (msg_1 & 0x3FFF); - int source = (msg_2 & 0x3FFF); //Source only present in individual calls + int mt_c = (msg_1 & 0x300000) >> 20; + int lcn = (msg_1 & 0xF8000) >> 15; + int is_individual = (msg_1 & 0x4000) >> 14; + int is_emergency = (is_individual == 0) ? (msg_1 & 0x2000) >> 13 : 0; + int group = (msg_1 & 0x7FF); + int lid = (msg_1 & 0x3FFF); + int source = (msg_2 & 0x3FFF); //Source only present in individual calls + int is_agency_call = is_individual == 0 && isAgencyCallGroup(group, state); + int is_fleet_call = is_individual == 0 && isFleetCallGroup(group, state); //Abstract away to a target, and be sure to check whether it's an individual call later int target = (is_individual == 0) ? group : lid; @@ -1509,6 +1515,8 @@ void edacs(dsd_opts * opts, dsd_state * state) if (is_individual == 0) fprintf (stderr, " Group [%04d]", target); else if (is_test_call == 0) fprintf (stderr, " Callee [%05d] Caller [%05d]", target, source); fprintf (stderr, " LCN [%02d]%s", lcn, getLcnStatusString(lcn)); + if (is_agency_call == 1) fprintf (stderr, " [Agency]"); + else if (is_fleet_call == 1) fprintf (stderr, " [Fleet]"); if (is_tx_trunk == 0) fprintf (stderr, " [Message Trunking]"); if (is_emergency == 1) { @@ -1530,13 +1538,13 @@ void edacs(dsd_opts * opts, dsd_state * state) state->lastsrc = 0; //Call type for state - state->edacs_vc_call_type = EDACS_IS_VOICE; - if (is_individual == 0) state->edacs_vc_call_type |= EDACS_IS_GROUP; - else state->edacs_vc_call_type |= EDACS_IS_INDIVIDUAL; - if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; - if (is_emergency == 1) state->edacs_vc_call_type |= EDACS_IS_EMERGENCY; - if (isAgencyCallGroup(group, state)) state->edacs_vc_call_type |= EDACS_IS_AGENCY_CALL; - else if (isFleetCallGroup(group, state)) state->edacs_vc_call_type |= EDACS_IS_FLEET_CALL; + state->edacs_vc_call_type = EDACS_IS_VOICE; + if (is_individual == 0) state->edacs_vc_call_type |= EDACS_IS_GROUP; + else state->edacs_vc_call_type |= EDACS_IS_INDIVIDUAL; + if (is_digital == 1) state->edacs_vc_call_type |= EDACS_IS_DIGITAL; + if (is_emergency == 1) state->edacs_vc_call_type |= EDACS_IS_EMERGENCY; + if (is_agency_call) state->edacs_vc_call_type |= EDACS_IS_AGENCY_CALL; + else if (is_fleet_call) state->edacs_vc_call_type |= EDACS_IS_FLEET_CALL; char mode[8]; //allow, block, digital enc sprintf (mode, "%s", ""); From 854b421235af946ab91f8e044f8dc1426f0b7e8b Mon Sep 17 00:00:00 2001 From: ilyacodes Date: Sun, 14 Apr 2024 10:47:34 -0400 Subject: [PATCH 32/37] EDACS: fix group patch shift size --- src/edacs-fme.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 60b02bf..dc81a32 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -798,7 +798,7 @@ void edacs(dsd_opts * opts, dsd_state * state) else if (mt2 == 0xC) { //Note: First 9 bits of msg_1 are the mt1 and mt2 bits - int unk1 = (msg_1 & 0x70000) >> 20; //unknown 3 bit value preceeding the SGID + int unk1 = (msg_1 & 0x70000) >> 16; //unknown 3 bit value preceeding the SGID int sgid = (msg_1 & 0xFFFF); //patched supergroup ID //Updated Observation: The 'SSN' value may not be unique in this instance, so may be an entirely different value @@ -806,11 +806,11 @@ void edacs(dsd_opts * opts, dsd_state * state) int ssn = (msg_2 & 0xFF00000) >> 20; //this value seems to incrememnt based on SGID, so assigning 8-bit as the SSN int target = (msg_2 & 0xFFFFF); //target group or individual ID (20-bit) to include in supergroup - + fprintf (stderr, "%s", KWHT); fprintf (stderr, " System Dynamic Regroup :: SGID [%05d] Target [%07d]", sgid, target); - if (unk1) fprintf (stderr, " UNK1 [%01X]", unk1); //this value seems to always be zero - if (ssn) fprintf (stderr, " UNK2 [%02X]", ssn); //this may or may not be a unique value to each SGID + if (unk1) fprintf (stderr, " UNK1 [%01X]", unk1); //this value seems to always be 7 for an active patch, 0 for a termination of a patch + if (ssn) fprintf (stderr, " UNK2 [%02X]", ssn); //this may or may not be a unique value to each SGID, is FE for termination of a patch fprintf (stderr, "%s", KNRM); } //Serial Number Request (not seen in the wild, see US patent 20030190923, Figure 2b) From d86c52050942ed6b2669e68a5a336be3ea5d0093 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Mon, 15 Apr 2024 07:17:07 -0400 Subject: [PATCH 33/37] EDACS: More WIP/Tests on EA Dynamic Regrouping; #252 --- src/edacs-fme.c | 76 ++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 66 insertions(+), 10 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index dc81a32..d4c93a2 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -794,23 +794,79 @@ void edacs(dsd_opts * opts, dsd_state * state) fprintf (stderr, "%s", KNRM); } - //Patch Groups / Dynamic Regroup -- Reverse Engineer WIP from observations and guesswork + //Patch Groups / Dynamic Regroup -- Current Code + // else if (mt2 == 0xC) + // { + // //Note: First 9 bits of msg_1 are the mt1 and mt2 bits + // int unk1 = (msg_1 & 0x70000) >> 16; //unknown 3 bit value preceeding the SGID + // int sgid = (msg_1 & 0xFFFF); //patched supergroup ID + + // //Updated Observation: The 'SSN' value may not be unique in this instance, so may be an entirely different value + // //altogether. Its function is still unknown, but for the sake of displaying patches, is not required. + + // int ssn = (msg_2 & 0xFF00000) >> 20; //this value seems to incrememnt based on SGID, so assigning 8-bit as the SSN + // int target = (msg_2 & 0xFFFFF); //target group or individual ID (20-bit) to include in supergroup + + // fprintf (stderr, "%s", KWHT); + // fprintf (stderr, " System Dynamic Regroup :: SGID [%05d] Target [%07d]", sgid, target); + // if (unk1) fprintf (stderr, " UNK1 [%01X]", unk1); //this value seems to always be 7 for an active patch, 0 for a termination of a patch + // if (ssn) fprintf (stderr, " UNK2 [%02X]", ssn); //this may or may not be a unique value to each SGID, is FE for termination of a patch + // fprintf (stderr, "%s", KNRM); + // } + + //Patch Groups / Dynamic Regroup -- Reverse Engineer WIP from observations, guesswork, and documented P25 MFID A4 regroup operations else if (mt2 == 0xC) { + + //Note: Due to the method used to reverse engineer this patch using conventions from a newer documented P25 source (MFID A4 L3Harris), + //its possible that the conventions, terminology, and bits signalled in this message are not entirely accurate, but are just speculation + //Note: First 9 bits of msg_1 are the mt1 and mt2 bits - int unk1 = (msg_1 & 0x70000) >> 16; //unknown 3 bit value preceeding the SGID - int sgid = (msg_1 & 0xFFFF); //patched supergroup ID + // FF80000 (visualization aide) + int tga = (msg_1 & 0x70000) >> 16; //unknown 3 bit value preceeding the SGID (TGA?) + int unk1 = (msg_1 & 0xFF00) >> 8; //unknown 8 bit value preceeding the TGA/Options + int sgid = (msg_1 & 0xFF); //patched supergroup ID expressed as an 8 bit value - //Updated Observation: The 'SSN' value may not be unique in this instance, so may be an entirely different value - //altogether. Its function is still unknown, but for the sake of displaying patches, is not required. - - int ssn = (msg_2 & 0xFF00000) >> 20; //this value seems to incrememnt based on SGID, so assigning 8-bit as the SSN + //Observation: The SSN value appears to be unique, but also different between sites, as in, each site + //has its own SSN for the same SGID patching, possibly a first come first serve pool value? + int ssn = (msg_2 & 0xF800000) >> 23; //this value seems to incrememnt based on SGID, 5-bit value + int unk2 = (msg_2 & 0x700000) >> 20; //unknown 3-bit value, possibly linked to TGA when patch is deleted int target = (msg_2 & 0xFFFFF); //target group or individual ID (20-bit) to include in supergroup + //Ilya, please don't nit fix my logging format for these, it breaks grep when parsing a bunch of these all at once fprintf (stderr, "%s", KWHT); - fprintf (stderr, " System Dynamic Regroup :: SGID [%05d] Target [%07d]", sgid, target); - if (unk1) fprintf (stderr, " UNK1 [%01X]", unk1); //this value seems to always be 7 for an active patch, 0 for a termination of a patch - if (ssn) fprintf (stderr, " UNK2 [%02X]", ssn); //this may or may not be a unique value to each SGID, is FE for termination of a patch + fprintf (stderr, " System Dynamic Regroup :: SP-WGID: %03d; Target: %07d;", sgid, target); + + //just a guess, but when target == sgid, then the unk2 value is 6 (as opposed to 7) + //so is this signalling the same TGA value, but the bit for activate is deactivated? + if (sgid == target) //or SSN == 0x1F + tga = unk2; + + //decode potential TGA values (assumming same as Harris P25) + if (tga & 4) fprintf (stderr, " One-Way"); //Simulselect + else fprintf (stderr, " Two-Way"); //Patch + if (tga & 2) fprintf (stderr, " Group"); + else fprintf (stderr, " Radio"); //Individual + fprintf (stderr, " Patch"); + if (tga & 1) fprintf (stderr, " Update"); + else fprintf (stderr, " Delete"); + + if (sgid != target) + { + fprintf (stderr, " TGA: %01X;", tga); //this value seems to always be 7 for an active patch, 0 for a termination of a patch (6 if assigned the unk2 value) + if (unk1) + fprintf (stderr, " UNK1: %01X;", unk1); + if (unk2) + fprintf (stderr, " UNK2: %02X;", unk2); + fprintf (stderr, " SSN: %02X;", ssn); //this may or may not be a unique value to each SGID, is 1F for termination of a patch + } + else + { + fprintf (stderr, " TGA: %01X;", tga); //this value seems to always be 7 for an active patch, 0 for a termination of a patch (6 if assigned the unk2 value) + if (unk1) + fprintf (stderr, " UNK1: %02X;", unk1); + } + fprintf (stderr, "%s", KNRM); } //Serial Number Request (not seen in the wild, see US patent 20030190923, Figure 2b) From e5d11c81f3efbf7bbc3b3981852734e599dbc0c5 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Mon, 15 Apr 2024 07:47:15 -0400 Subject: [PATCH 34/37] EDACS: More WIP/Tests on EA Dynamic Regrouping2; #252 --- src/edacs-fme.c | 41 ++++++++++++++++++++++++----------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index d4c93a2..9d7f50e 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -833,26 +833,27 @@ void edacs(dsd_opts * opts, dsd_state * state) int unk2 = (msg_2 & 0x700000) >> 20; //unknown 3-bit value, possibly linked to TGA when patch is deleted int target = (msg_2 & 0xFFFFF); //target group or individual ID (20-bit) to include in supergroup + //look at the 'zero' fields when on 'delete' + // MSG_1 [FE00045] MSG_2 [FE00045] + // FF80000 (visualization aide) + int unk3 = (msg_1 & 0x7FF00) >> 12; + int unk4 = (msg_2 & 0x7FF00) >> 12;; + //Ilya, please don't nit fix my logging format for these, it breaks grep when parsing a bunch of these all at once fprintf (stderr, "%s", KWHT); fprintf (stderr, " System Dynamic Regroup :: SP-WGID: %03d; Target: %07d;", sgid, target); - - //just a guess, but when target == sgid, then the unk2 value is 6 (as opposed to 7) - //so is this signalling the same TGA value, but the bit for activate is deactivated? - if (sgid == target) //or SSN == 0x1F - tga = unk2; - - //decode potential TGA values (assumming same as Harris P25) - if (tga & 4) fprintf (stderr, " One-Way"); //Simulselect - else fprintf (stderr, " Two-Way"); //Patch - if (tga & 2) fprintf (stderr, " Group"); - else fprintf (stderr, " Radio"); //Individual - fprintf (stderr, " Patch"); - if (tga & 1) fprintf (stderr, " Update"); - else fprintf (stderr, " Delete"); if (sgid != target) { + //decode potential TGA values (assumming same as Harris P25) + if (tga & 4) fprintf (stderr, " One-Way"); //Simulselect + else fprintf (stderr, " Two-Way"); //Patch + if (tga & 2) fprintf (stderr, " Group"); + else fprintf (stderr, " Radio"); //Individual + fprintf (stderr, " Patch"); + if (tga & 1) fprintf (stderr, " Active;"); + else fprintf (stderr, " Delete;"); + fprintf (stderr, " TGA: %01X;", tga); //this value seems to always be 7 for an active patch, 0 for a termination of a patch (6 if assigned the unk2 value) if (unk1) fprintf (stderr, " UNK1: %01X;", unk1); @@ -860,11 +861,17 @@ void edacs(dsd_opts * opts, dsd_state * state) fprintf (stderr, " UNK2: %02X;", unk2); fprintf (stderr, " SSN: %02X;", ssn); //this may or may not be a unique value to each SGID, is 1F for termination of a patch } + + //07:25:17 Sync: +EDACS MSG_1 [FE00045] MSG_2 [FE00045] (MT1: 1F; MT2: C) System Dynamic Regroup :: SP-WGID: 069; Target: 0000069; One-Way Group Patch Delete TGA: 6; + //Upon Reflection, thinking the same MT1 and MT2 values are in both messages, so appears to just be the SP-WGID here and a bunch of zeroes leading into it, and not a TGA value + else { - fprintf (stderr, " TGA: %01X;", tga); //this value seems to always be 7 for an active patch, 0 for a termination of a patch (6 if assigned the unk2 value) - if (unk1) - fprintf (stderr, " UNK1: %02X;", unk1); + fprintf (stderr, " Patch Delete;"); + if (unk3) + fprintf (stderr, " UNK3: %01X;", unk3); + if (unk3) + fprintf (stderr, " UNK4: %02X;", unk4); } fprintf (stderr, "%s", KNRM); From 5d205800aa7495a19ee75b78f8e4876610aa8050 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Mon, 15 Apr 2024 09:30:22 -0400 Subject: [PATCH 35/37] EDACS: Fix Bit Shift on EA Patch Info; Misc; #252 --- src/edacs-fme.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index 9d7f50e..b47980f 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -836,8 +836,8 @@ void edacs(dsd_opts * opts, dsd_state * state) //look at the 'zero' fields when on 'delete' // MSG_1 [FE00045] MSG_2 [FE00045] // FF80000 (visualization aide) - int unk3 = (msg_1 & 0x7FF00) >> 12; - int unk4 = (msg_2 & 0x7FF00) >> 12;; + int unk3 = (msg_1 & 0x7FF00) >> 8; + int unk4 = (msg_2 & 0x7FF00) >> 8; //Ilya, please don't nit fix my logging format for these, it breaks grep when parsing a bunch of these all at once fprintf (stderr, "%s", KWHT); @@ -846,15 +846,17 @@ void edacs(dsd_opts * opts, dsd_state * state) if (sgid != target) { //decode potential TGA values (assumming same as Harris P25) - if (tga & 4) fprintf (stderr, " One-Way"); //Simulselect - else fprintf (stderr, " Two-Way"); //Patch - if (tga & 2) fprintf (stderr, " Group"); - else fprintf (stderr, " Radio"); //Individual - fprintf (stderr, " Patch"); + //decided to disable the info presented below since I cannot confirm this + // if (tga & 4) fprintf (stderr, " One-Way"); //Simulselect + // else fprintf (stderr, " Two-Way"); //Patch + // if (tga & 2) fprintf (stderr, " Group"); + // else fprintf (stderr, " Radio"); //Individual + fprintf (stderr, " Patch"); if (tga & 1) fprintf (stderr, " Active;"); else fprintf (stderr, " Delete;"); - fprintf (stderr, " TGA: %01X;", tga); //this value seems to always be 7 for an active patch, 0 for a termination of a patch (6 if assigned the unk2 value) + //switched from using the TGA nomenclature to a more generic OPTion since I think this value is still a form of option + fprintf (stderr, " OPT: %01X;", tga); //this value seems to always be 7 for an active patch, 0 for a termination of a patch (6 if assigned the unk2 value) if (unk1) fprintf (stderr, " UNK1: %01X;", unk1); if (unk2) From dbc645e7b05ade09e56561bf1de848cc5a74bd0a Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Mon, 15 Apr 2024 09:40:53 -0400 Subject: [PATCH 36/37] EDACS: Fix Unk4 Value EA Dynamic Regrouping; #252 --- src/edacs-fme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/edacs-fme.c b/src/edacs-fme.c index b47980f..dcf6c3d 100644 --- a/src/edacs-fme.c +++ b/src/edacs-fme.c @@ -872,7 +872,7 @@ void edacs(dsd_opts * opts, dsd_state * state) fprintf (stderr, " Patch Delete;"); if (unk3) fprintf (stderr, " UNK3: %01X;", unk3); - if (unk3) + if (unk4) fprintf (stderr, " UNK4: %02X;", unk4); } From 3041713eb31ba4a6683f1621ac8f4782426ca448 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Tue, 16 Apr 2024 06:03:05 -0400 Subject: [PATCH 37/37] M17: Fix Compiler Error if librtlsdr not found / installed; --- src/m17.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/m17.c b/src/m17.c index 2fdb28e..b081967 100644 --- a/src/m17.c +++ b/src/m17.c @@ -1897,13 +1897,13 @@ void encodeM17STR(dsd_opts * opts, dsd_state * state) voice2[i] = sample; } } - + opts->rtl_rms = rtl_return_rms(); #endif } //read in RMS value for vox function; NOTE: will not work correctly SOCAT STDIO TCP due to blocking when no samples to read - if (opts->audio_in_type == 3) opts->rtl_rms = rtl_return_rms(); - else opts->rtl_rms = raw_rms(voice1, nsam, 1) / 2; //dividing by two so mic isn't so sensitive on vox + if (opts->audio_in_type != 3) + opts->rtl_rms = raw_rms(voice1, nsam, 1) / 2; //dividing by two so mic isn't so sensitive on vox //low pass filter if (opts->use_lpf == 1)