EDACS: support for EA system all-calls (#214)

* Refactor debug printing a bit

* Clean up group call logic

* Minor changes to debug printing

* EDACS EA: support for system all-calls

* EDACS: split out MT1 for TDMA call since we can't decode it anyway

* Refactor identifying call mode (digital/analog)

* Maintain consistent indentation for all MT1

* EDACS: Fix Compiler Error.

Had an extra right bracket on line 383

---------

Co-authored-by: lwvmobile <59371473+lwvmobile@users.noreply.github.com>
This commit is contained in:
ilyacodes 2024-03-21 21:02:53 -04:00 committed by GitHub
parent c85dd60399
commit de9127cfb4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 173 additions and 65 deletions

View File

@ -3450,6 +3450,9 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (call_matrix[i][2] > 100000)
// I-Call
printw (" TGT [%8lld] SRC [%8lld] I-Call", call_matrix[i][2] - 100000, call_matrix[i][3] );
else if (call_matrix[i][2] == -1)
// System all-call
printw (" TGT [ SYSTEM ] SRC [%8lld] All-Call", call_matrix[i][3] );
else
// Group call
printw (" TGT [%8lld] SRC [%8lld]", call_matrix[i][2], call_matrix[i][3] );
@ -3483,6 +3486,9 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (call_matrix[i][2] > 100000)
// I-Call
printw (" TGT [%8lld] SRC [%8lld] I-Call", call_matrix[i][2] - 100000, call_matrix[i][3] );
else if (call_matrix[i][2] == -1)
// System all-call
printw (" TGT [ SYSTEM ] SRC [%8lld] All-Call", call_matrix[i][3] );
else
// Group call
printw (" TGT [%8lld] SRC [%8lld]", call_matrix[i][2], call_matrix[i][3] );
@ -3616,6 +3622,9 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state)
if (call_matrix[j][2] > 100000)
// I-Call
printw ("Target [%8lld] Source [%8lld] I-Call", call_matrix[j][2] - 100000, call_matrix[j][3]);
else if (call_matrix[j][2] == -1)
// System all-call
printw ("Target [ SYSTEM ] Source [%8lld] All-Call", call_matrix[j][3]);
else
// Group call
printw ("Target [%8lld] Source [%8lld]", call_matrix[j][2], call_matrix[j][3]);

View File

@ -374,10 +374,14 @@ void edacs_analog(dsd_opts * opts, dsd_state * state, int afs, unsigned char lcn
else fprintf(stderr, "%s", KRED);
fprintf (stderr, " Analog RMS: %04ld SQL: %ld", rms, sql);
if (afs != 0)
if (state->ea_mode == 0)
{
if (state->ea_mode == 0) fprintf (stderr, " AFS [%03d] [%02d-%03d] LCN [%02d]", afs, afs >> 7, afs & 0x7F, lcn);
else fprintf (stderr, " TG/TGT: [%d] LCN [%02d]", afs, lcn);
fprintf (stderr, " AFS [%03d] [%02d-%03d] LCN [%02d]", afs, afs >> 7, afs & 0x7F, lcn);
}
else
{
if (afs == -1) fprintf (stderr, " TGT [ SYSTEM ] LCN [%02d] All-Call", lcn);
else fprintf (stderr, " TGT [%08d] LCN [%02d]", afs, lcn);
}
//debug, view hit counter
@ -530,9 +534,18 @@ void edacs(dsd_opts * opts, dsd_state * state)
//Site ID
unsigned long long int site_id = 0; //we probably could just make this an int as well as the state variables
//add mt1 and mt2 for easy debug / decode
//Add raw payloads and MT1/MT2 for easy debug
if (opts->payload == 1)
fprintf (stderr, " MT1: %02X; MT2: %X; ", mt1, mt2);
{
fprintf (stderr, " FR_1 [%010llX]", fr_1t);
fprintf (stderr, " FR_4 [%010llX]", fr_4t);
fprintf (stderr, " (MT1: %02X", mt1);
// MT2 is meaningless if MT1 is not 0x1F
if (mt1 == 0x1F)
fprintf (stderr, "; MT2: %X)", mt2);
else
fprintf (stderr, ") ");
}
//MT1 of 0x1F indicates to use MT2 for the opcode. See US patent US7546135B2, Figure 2b.
if (mt1 == 0x1F)
@ -543,28 +556,6 @@ void edacs(dsd_opts * opts, dsd_state * state)
{
fprintf (stderr, " Initiate Test Call");
}
else if (mt2 == 0xA)
{
site_id = ((fr_1 & 0x1F000) >> 12) | ((fr_1 & 0x1F000000) >> 19);
fprintf (stderr, "%s", KYEL);
fprintf (stderr, " Site ID [%02llX][%03lld] Extended Addressing", site_id, site_id);
fprintf (stderr, "%s", KNRM);
state->edacs_site_id = site_id;
}
//Patch Groups
else if (mt2 == 0xC)
{
int patch_site = ((fr_4t & 0xFF00000000) >> 32); //is site info valid, 0 for all sites? else patch only good on site listed?
int sourcep = ((fr_1t & 0xFFFF000) >> 12);
int targetp = ((fr_4t & 0xFFFF000) >> 12);
fprintf (stderr, " Patch -- Site [%d] Source [%d] Target [%d] ", patch_site, sourcep, targetp);
}
//Serial Number Request (not seen in the wild, see US patent 20030190923, Figure 2b)
else if (mt2 == 0xD)
{
fprintf (stderr, " Serial Number Request");
}
//Adjacent Sites
else if (mt2 == 0x1)
{
@ -614,7 +605,15 @@ void edacs(dsd_opts * opts, dsd_state * state)
}
}
}
//Site ID
else if (mt2 == 0xA)
{
site_id = ((fr_1 & 0x1F000) >> 12) | ((fr_1 & 0x1F000000) >> 19);
fprintf (stderr, "%s", KYEL);
fprintf (stderr, " Site ID [%02llX][%03lld] Extended Addressing", site_id, site_id);
fprintf (stderr, "%s", KNRM);
state->edacs_site_id = site_id;
}
//disabling kick command, data looks like its just FFFF, no actual values, can't verify accuracy
// else if (mt2 == 0xB) //KICK LISTING for EA?? Unverified, but probably observed in Unitrunker way back when.
// {
@ -625,19 +624,52 @@ void edacs(dsd_opts * opts, dsd_state * state)
// fprintf (stderr, " FR_6 [%010llX]", fr_6);
// fprintf (stderr, " %08d REG/DEREG/AUTH?", kicked);
// }
// else //print frames for debug/analysis
if (opts->payload == 1)
//Patch Groups
else if (mt2 == 0xC)
{
fprintf (stderr, " FR_1 [%010llX]", fr_1t);
fprintf (stderr, " FR_4 [%010llX]", fr_4t);
int patch_site = ((fr_4t & 0xFF00000000) >> 32); //is site info valid, 0 for all sites? else patch only good on site listed?
int sourcep = ((fr_1t & 0xFFFF000) >> 12);
int targetp = ((fr_4t & 0xFFFF000) >> 12);
fprintf (stderr, " Patch -- Site [%d] Source [%d] Target [%d] ", patch_site, sourcep, targetp);
}
//Serial Number Request (not seen in the wild, see US patent 20030190923, Figure 2b)
else if (mt2 == 0xD)
{
fprintf (stderr, " Serial Number Request");
}
else
{
fprintf (stderr, " Unknown Command");
// Only print the payload if we haven't already printed it
if (opts->payload != 1)
{
fprintf (stderr, " FR_1 [%010llX]", fr_1t);
fprintf (stderr, " FR_4 [%010llX]", fr_4t);
}
}
}
//TDMA Group Grant Update (never observed, unknown if ever used on any EDACS system)
else if (mt1 == 0x1)
{
lcn = (fr_1t & 0x3E0000000) >> 29;
int group = (fr_1t & 0xFFFF000) >> 12;
int source = (fr_4t & 0xFFFFF000) >> 12;
fprintf (stderr, " Group [%05d] Source [%08d] LCN[%02d] Data Group Call", group, source, lcn);
}
//Data Group Grant Update
else if (mt1 == 0x2)
{
lcn = (fr_1t & 0x3E0000000) >> 29;
int group = (fr_1t & 0xFFFF000) >> 12;
int source = (fr_4t & 0xFFFFF000) >> 12;
fprintf (stderr, " Group [%05d] Source [%08d] LCN[%02d] TDMA Group Call", group, source, lcn);
}
//Voice Call Grant Update
// mt1 0x12 is analog group voice call, 0x3 is Digital group voice call, 0x2 Group Data Channel, 0x1 TDMA call
else if ((mt1 >= 0x1 && mt1 <= 0x3) || mt1 == 0x12)
// MT1 value determines the type of group call:
// - 0x03 digital group voice (ProVoice, standard on SLERS EA)
// - 0x12 analog group voice
else if (mt1 == 0x03 || mt1 == 0x12)
{
lcn = (fr_1t & 0x3E0000000) >> 29;
@ -647,19 +679,17 @@ void edacs(dsd_opts * opts, dsd_state * state)
state->edacs_lcn_count = lcn;
}
int is_digital = (mt1 == 0x3) ? 1 : 0;
int group = (fr_1t & 0xFFFF000) >> 12;
int source = (fr_4t & 0xFFFFF000) >> 12;
if (group != 0) state->lasttg = group;
state->lasttg = group; // 0 is a valid TG, it's the all-call for agency 0
if (source != 0) state->lastsrc = source;
if (lcn != 0) state->edacs_vc_lcn = lcn;
fprintf (stderr, "%s", KGRN);
fprintf (stderr, " Group [%05d] Source [%08d] LCN[%02d]", group, source, lcn);
if (mt1 == 0x1) fprintf (stderr, " TDMA Call"); //never observed, wonder if any EDACS systems ever carried a TDMA signal (X2-TDMA?)
else if (mt1 == 0x2) fprintf (stderr, " Group Data Call"); //Never Seen this one before
else if (mt1 == 0x3) fprintf (stderr, " Digital Call"); //ProVoice, this is what we always get on SLERS EA
else if (mt1 == 0x12) fprintf (stderr, " Analog Call"); //analog, to at least log that we recognize it
else fprintf (stderr, " Unknown Type");
if (is_digital == 0) fprintf (stderr, " Analog Group Call");
else fprintf (stderr, " Digital Group Call");
fprintf (stderr, "%s", KNRM);
char mode[8]; //allow, block, digital enc
@ -692,10 +722,10 @@ void edacs(dsd_opts * opts, dsd_state * state)
if (opts->dmr_stereo_wav == 1 && (opts->use_rigctl == 1 || opts->audio_in_type == 3))
{
sprintf (opts->wav_out_file, "./WAV/%s %s EDACS Site %lld TG %d SRC %d.wav", getDateE(), timestr, state->edacs_site_id, group, source);
if (mt1 != 0x12) //digital
if (is_digital == 1)
openWavOutFile (opts, state);
else //analog
openWavOutFile48k (opts, state); //
else
openWavOutFile48k (opts, state);
}
//do condition here, in future, will allow us to use tuning methods as well, or rtl_udp as well
@ -705,7 +735,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
SetFreq(opts->rigctl_sockfd, state->trunk_lcn_freq[lcn-1]); //minus one because the lcn index starts at zero
state->edacs_tuned_lcn = lcn;
opts->p25_is_tuned = 1;
if (mt1 == 0x12) //analog
if (is_digital == 0)
edacs_analog(opts, state, group, lcn);
}
@ -715,7 +745,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
rtl_dev_tune (opts, state->trunk_lcn_freq[lcn-1]);
state->edacs_tuned_lcn = lcn;
opts->p25_is_tuned = 1;
if (mt1 == 0x6) //analog
if (is_digital == 0)
edacs_analog(opts, state, group, lcn);
#endif
}
@ -735,26 +765,22 @@ void edacs(dsd_opts * opts, dsd_state * state)
state->edacs_lcn_count = lcn;
}
int is_digital = (fr_1t & 0x200000000) >> 33;
int target = (fr_1t & 0xFFFFF000) >> 12;
int source = (fr_4t & 0xFFFFF000) >> 12;
if (target != 0) state->lasttg = target + 100000; //Use IDs > 100000 to represent i-call targets to differentiate from TGs
if (source != 0) state->lastsrc = source;
if (lcn != 0) state->edacs_vc_lcn = lcn;
fprintf (stderr, "%s", KGRN);
fprintf (stderr, " I-Call Target [%08d] Source [%08d] LCN[%02d]", target, source, lcn);
fprintf (stderr, " Target [%08d] Source [%08d] LCN[%02d]", target, source, lcn);
//mt2 is 0x8 or 0xC when grant is first given, then 0xA or 0xE when call is in progress
if (mt2 == 0x8 || mt2 == 0xA) fprintf (stderr, " Analog Call");
else if (mt2 == 0xC || mt2 == 0xE) fprintf (stderr, " Digital Call");
else fprintf (stderr, " Unknown Type");
if (is_digital == 0) fprintf (stderr, " Analog I-Call");
else fprintf (stderr, " Digital I-Call");
fprintf (stderr, "%s", KNRM);
char mode[8]; //allow, block, digital enc
sprintf (mode, "%s", "");
//if we don't know what type of call it is, then write 'B' to mode for block - no point trying to tune to it
if (mt2 != 0x8 && mt2 != 0xA && mt2 != 0xC && mt2 != 0xE) sprintf (mode, "%s", "B");
//if we are using allow/whitelist mode, then write 'B' to mode for block - no allow/whitelist support for i-calls
if (opts->trunk_use_allow_list == 1) sprintf (mode, "%s", "B");
@ -767,10 +793,10 @@ void edacs(dsd_opts * opts, dsd_state * state)
if (opts->dmr_stereo_wav == 1 && (opts->use_rigctl == 1 || opts->audio_in_type == 3))
{
sprintf (opts->wav_out_file, "./WAV/%s %s EDACS Site %lld TGT %d SRC %d I-Call.wav", getDateE(), timestr, state->edacs_site_id, target, source);
if (mt2 == 0xC || mt2 == 0xE) //digital
if (is_digital == 1)
openWavOutFile (opts, state);
else //analog
openWavOutFile48k (opts, state); //
else
openWavOutFile48k (opts, state);
}
//do condition here, in future, will allow us to use tuning methods as well, or rtl_udp as well
@ -780,8 +806,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
SetFreq(opts->rigctl_sockfd, state->trunk_lcn_freq[lcn-1]); //minus one because the lcn index starts at zero
state->edacs_tuned_lcn = lcn;
opts->p25_is_tuned = 1;
//
if (mt2 == 0x8 || mt2 == 0xA) //analog
if (is_digital == 0)
edacs_analog(opts, state, target, lcn);
}
@ -791,8 +816,7 @@ void edacs(dsd_opts * opts, dsd_state * state)
rtl_dev_tune (opts, state->trunk_lcn_freq[lcn-1]);
state->edacs_tuned_lcn = lcn;
opts->p25_is_tuned = 1;
//
if (mt2 == 0x10)
if (is_digital == 0)
edacs_analog(opts, state, target, lcn);
#endif
}
@ -800,6 +824,76 @@ void edacs(dsd_opts * opts, dsd_state * state)
}
}
}
//System All-Call Grant Update
else if (mt1 == 0x16)
{
lcn = (fr_1t & 0x3E0000000) >> 29;
//LCNs greater than 26 are considered status values, "Busy, Queue, Deny, etc"
if (lcn > state->edacs_lcn_count && lcn < 26)
{
state->edacs_lcn_count = lcn;
}
int is_digital = (fr_1t & 0x10000000) >> 28;
int source = (fr_4t & 0xFFFFF000) >> 12;
state->lasttg = -1; // represent system all-call as TG -1 to differentiate from real TGs
if (source != 0) state->lastsrc = source;
if (lcn != 0) state->edacs_vc_lcn = lcn;
fprintf (stderr, "%s", KGRN);
fprintf (stderr, " Source [%08d] LCN[%02d]", source, lcn);
if (is_digital == 0) fprintf (stderr, " Analog System All-Call");
else fprintf (stderr, " Digital System All-Call");
fprintf (stderr, "%s", KNRM);
char mode[8]; //allow, block, digital enc
sprintf (mode, "%s", "");
//if we are using allow/whitelist mode, then write 'A' to mode for allow - always allow all-calls by default
if (opts->trunk_use_allow_list == 1) sprintf (mode, "%s", "A");
//this is working now with the new import setup
if (opts->trunk_tune_group_calls == 1 && opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0) ) //DE is digital encrypted, B is block
{
if (lcn > 0 && lcn < 26 && state->edacs_cc_lcn != 0 && state->trunk_lcn_freq[lcn-1] != 0) //don't tune if zero (not loaded or otherwise)
{
//openwav file and do per call right here, should probably check as well to make sure we have a valid trunking method active (rigctl, rtl)
if (opts->dmr_stereo_wav == 1 && (opts->use_rigctl == 1 || opts->audio_in_type == 3))
{
sprintf (opts->wav_out_file, "./WAV/%s %s EDACS Site %lld SRC %d All-Call.wav", getDateE(), timestr, state->edacs_site_id, source);
if (is_digital == 1)
openWavOutFile (opts, state);
else
openWavOutFile48k (opts, state);
}
//do condition here, in future, will allow us to use tuning methods as well, or rtl_udp as well
if (opts->use_rigctl == 1)
{
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, state->trunk_lcn_freq[lcn-1]); //minus one because the lcn index starts at zero
state->edacs_tuned_lcn = lcn;
opts->p25_is_tuned = 1;
if (is_digital == 0)
edacs_analog(opts, state, -1, lcn);
}
if (opts->audio_in_type == 3) //rtl dongle
{
#ifdef USE_RTLSDR
rtl_dev_tune (opts, state->trunk_lcn_freq[lcn-1]);
state->edacs_tuned_lcn = lcn;
opts->p25_is_tuned = 1;
if (is_digital == 0)
edacs_analog(opts, state, -1, lcn);
#endif
}
}
}
}
//Login
else if (mt1 == 0x19)
{
@ -807,11 +901,16 @@ void edacs(dsd_opts * opts, dsd_state * state)
int source = (fr_4t & 0xFFFFF000) >> 12;
fprintf (stderr, " Login Group [%05d] Source [%08d]", group, source);
}
else //print frames for debug/analysis
//Unknown command
else
{
fprintf (stderr, " FR_1 [%010llX]", fr_1t);
fprintf (stderr, " FR_4 [%010llX]", fr_4t);
fprintf (stderr, " Unknown Command");
// Only print the payload if we haven't already printed it
if (opts->payload != 1)
{
fprintf (stderr, " FR_1 [%010llX]", fr_1t);
fprintf (stderr, " FR_4 [%010llX]", fr_4t);
}
}
}