P25 - Better Handling of Trunking ENC Call Lockout; Fix Duplicate Channel Listing in Multi Grant Updates;

This commit is contained in:
lwvmobile 2024-02-27 08:57:15 -05:00
parent 71d79ff45b
commit cb02c0328c
7 changed files with 222 additions and 30 deletions

View File

@ -1251,6 +1251,9 @@ void edacs(dsd_opts * opts, dsd_state * state);
unsigned long long int edacs_bch (unsigned long long int message);
void eot_cc(dsd_opts * opts, dsd_state * state); //end of TX return to CC
//Generic Tuning Functions
void return_to_cc (dsd_opts * opts, dsd_state * state);
//misc generic audio filtering for analog at 48k/1
void analog_deemph_filter(short * input, int len);
void analog_preemph_filter(short * input, int len);

View File

@ -411,3 +411,62 @@ int udp_socket_connectA(dsd_opts * opts, dsd_state * state)
}
}
void return_to_cc (dsd_opts * opts, dsd_state * state)
{
//extra safeguards due to sync issues with NXDN
memset (state->nxdn_sacch_frame_segment, 1, sizeof(state->nxdn_sacch_frame_segment));
memset (state->nxdn_sacch_frame_segcrc, 1, sizeof(state->nxdn_sacch_frame_segcrc));
memset (state->active_channel, 0, sizeof(state->active_channel));
//reset dmr blocks
dmr_reset_blocks (opts, state);
//zero out additional items
state->lasttg = 0;
state->lasttgR = 0;
state->lastsrc = 0;
state->lastsrcR = 0;
state->payload_algid = 0;
state->payload_algidR = 0;
state->payload_keyid = 0;
state->payload_keyidR = 0;
state->payload_mi = 0;
state->payload_miR = 0;
state->payload_miP = 0;
state->payload_miN = 0;
opts->p25_is_tuned = 0;
state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0;
//tune back to the control channel -- NOTE: Doesn't work correctly on EDACS Analog Voice
//RIGCTL
if (opts->p25_trunk == 1 && opts->use_rigctl == 1)
{
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, state->p25_cc_freq);
}
//rtl
#ifdef USE_RTLSDR
if (opts->p25_trunk == 1 && opts->audio_in_type == 3) rtl_dev_tune (opts, state->p25_cc_freq);
#endif
state->last_cc_sync_time = time(NULL);
//if P25p2 VCH and going back to P25p1 CC, flip symbolrate
if (state->p25_cc_is_tdma == 0)
{
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
}
//if P25p1 Data Revert on P25p2 TDMA CC, flip symbolrate
if (state->p25_cc_is_tdma == 1)
{
state->samplesPerSymbol = 8;
state->symbolCenter = 3;
}
// fprintf (stderr, "\n User Activated Return to CC; \n ");
}

View File

@ -25,6 +25,10 @@ long int process_channel_to_freq (dsd_opts * opts, dsd_state * state, int channe
(Channel Spacing) x (0.125 kHz).
*/
//return 0 if channel value is 0 or 0xFFFF
if (channel == 0) return 0;
if (channel == 0xFFFF) return 0;
//Note: Base Frequency is calculated as (Base Frequency) x (0.000005 MHz) from the IDEN_UP message.
long int freq = -1;

View File

@ -627,6 +627,47 @@ processLDU2 (dsd_opts * opts, dsd_state * state)
fprintf (stderr, "\n");
}
#define P25p1_ENC_LO //disable if this behavior is detremental
#ifdef P25p1_ENC_LO
//If trunking and tuning ENC calls is disabled, lock out and go back to CC
int enc_lo = 1; int ttg = state->lasttg; //checking to a valid TG will help make sure we have a good LDU1 LCW or HDU first
if (irrecoverable_errors == 0 && state->payload_algid != 0x80 && state->payload_algid != 0 && opts->p25_trunk == 1 && opts->p25_is_tuned == 1 && opts->trunk_tune_enc_calls == 0)
{
//NOTE: This may still cause an issue IF we havent' loaded the key yet from keyloader
if (state->payload_algid == 0xAA && state->R != 0) enc_lo = 0;
// else if (future condition) enc_lo = 0;
// else if (future condition) enc_lo = 0;
//if this is locked out by conditions above, then write it into the TG mode if we have a TG value assigned
if (enc_lo == 1 && ttg != 0)
{
int xx = 0; int enc_wr = 0;
for (xx = 0; xx < state->group_tally; xx++)
{
if (state->group_array[xx].groupNumber == ttg)
{
enc_wr = 1; //already in there, so no need to assign it
break;
}
}
//if not already in there, so save it there now
if (enc_wr == 0)
{
state->group_array[state->group_tally].groupNumber = ttg;
sprintf (state->group_array[state->group_tally].groupMode, "%s", "DE");
sprintf (state->group_array[state->group_tally].groupName, "%s", "ENC LO"); //was xx and not state->group_tally
state->group_tally++;
}
//return to the control channel
fprintf (stderr, " No Enc Following on P25p1 Trunking; Return to CC; \n");
return_to_cc (opts, state);
}
}
#endif //P25p1_ENC_LO
}
//LFSR code courtesy of https://github.com/mattames/LFSR/

View File

@ -386,7 +386,7 @@ void processTSBK(dsd_opts * opts, dsd_state * state)
if (opts->trunk_tune_group_calls == 0) goto SKIPCALL;
//Skip tuning encrypted calls if enc calls are disabled
if (opts->trunk_tune_enc_calls == 0) goto SKIPCALL;
// if (opts->trunk_tune_enc_calls == 0) goto SKIPCALL;
//tune if tuning available
if (opts->p25_trunk == 1 && (strcmp(mode, "DE") != 0) && (strcmp(mode, "B") != 0))

View File

@ -630,6 +630,70 @@ void process_ESS (dsd_opts * opts, dsd_state * state)
}
}
#define P25p2_ENC_LO //disable if this behavior is detremental
#ifdef P25p2_ENC_LO
//If trunking and tuning ENC calls is disabled, lock out and go back to CC
int enc_lo = 1;
int ttg = 0; //checking to a valid TG will help make sure we have a good MAC_PTT or SACCH Channel Update First
int alg = 0; //set alg and key based on current slot values
unsigned long long int key = 0;
if (state->currentslot == 0)
{
ttg = state->lasttg;
alg = state->payload_algid;
if (alg == 0xAA) key = state->R;
// else if (future condition) key = 1;
// else if (future condition) key = 1;
}
if (state->currentslot == 1)
{
ttg = state->lasttgR;
alg = state->payload_algidR;
if (alg == 0xAA) key = state->RR;
// else if (future condition) key = 1;
// else if (future condition) key = 1;
}
if (alg != 0 && opts->p25_trunk == 1 && opts->p25_is_tuned == 1 && opts->trunk_tune_enc_calls == 0)
{
//NOTE: This may still cause an issue IF we havent' loaded the key yet from keyloader
if (alg == 0xAA && key != 0) enc_lo = 0;
// else if (future condition) enc_lo = 0;
// else if (future condition) enc_lo = 0;
//if this is locked out by conditions above, then write it into the TG mode if we have a TG value assigned
if (enc_lo == 1 && ttg != 0)
{
int xx = 0; int enc_wr = 0;
for (xx = 0; xx < state->group_tally; xx++)
{
if (state->group_array[xx].groupNumber == ttg)
{
enc_wr = 1; //already in there, so no need to assign it
break;
}
}
//if not already in there, so save it there now
if (enc_wr == 0)
{
state->group_array[state->group_tally].groupNumber = ttg;
sprintf (state->group_array[state->group_tally].groupMode, "%s", "DE");
sprintf (state->group_array[state->group_tally].groupName, "%s", "ENC LO"); //was xx and not state->group_tally
state->group_tally++;
}
//return to the control channel -- NOTE: Disabled, just mark as lockout for now, return would require complex check of the other slot activity
// fprintf (stderr, " No Enc Following on P25p2 Trunking; Return to CC; \n");
// return_to_cc (opts, state);
}
}
#endif //P25p2_ENC_LO
}
if (ec == -1 || ec >= 15)
{

View File

@ -315,11 +315,16 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
fprintf (stderr, "\n MFID90 Group Regroup Channel Grant Update");
fprintf (stderr, "\n Channel 1 [%04X] Group 1 [%d][%04X]", channel1, group1, group1);
freq1 = process_channel_to_freq (opts, state, channel1);
fprintf (stderr, "\n Channel 2 [%04X] Group 2 [%d][%04X]", channel2, group2, group2);
freq2 = process_channel_to_freq (opts, state, channel2);
if (channel2 != channel1 && channel2 != 0 && channel2 != 0xFFFF)
{
fprintf (stderr, "\n Channel 2 [%04X] Group 2 [%d][%04X]", channel2, group2, group2);
freq2 = process_channel_to_freq (opts, state, channel2);
}
//add active channel to string for ncurses display
sprintf (state->active_channel[0], "MFID90 Active Ch: %04X SG: %d; Ch: %04X SG: %d; ", channel1, group1, channel2, group2);
if (channel2 != channel1 && channel2 != 0 && channel2 != 0xFFFF)
sprintf (state->active_channel[0], "MFID90 Active Ch: %04X SG: %d; Ch: %04X SG: %d; ", channel1, group1, channel2, group2);
else sprintf (state->active_channel[0], "MFID90 Active Ch: %04X SG: %d; ", channel1, group1);
state->last_active_time = time(NULL);
//Skip tuning group calls if group calls are disabled
@ -710,7 +715,7 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
if (opts->trunk_tune_private_calls == 0) goto SKIPCALL;
//Skip tuning encrypted calls if enc calls are disabled -- abb formats do not carry svc bits :(
if (opts->trunk_tune_enc_calls == 0) goto SKIPCALL; //enable, or disable?
// if (opts->trunk_tune_enc_calls == 0) goto SKIPCALL; //enable, or disable?
//unit to unit needs work, may fail under certain conditions (first blocked, second allowed, etc) (labels should still work though)
for (int i = 0; i < state->group_tally; i++)
@ -996,41 +1001,52 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
}
freq1 = process_channel_to_freq (opts, state, channel1);
fprintf (stderr, "\n Channel 2 [%04X] Group 2 [%d][%04X]", channel2, group2, group2);
if (so2 & 0x80) fprintf (stderr, " Emergency");
if (so2 & 0x40) fprintf (stderr, " Encrypted");
if (opts->payload == 1) //hide behind payload due to len
if (channel2 != channel1 && channel2 != 0 && channel2 != 0xFFFF)
{
if (so2 & 0x20) fprintf (stderr, " Duplex");
if (so2 & 0x10) fprintf (stderr, " Packet");
else fprintf (stderr, " Circuit");
if (so2 & 0x8) fprintf (stderr, " R"); //reserved bit is on
fprintf (stderr, " Priority %d", so2 & 0x7); //call priority
fprintf (stderr, "\n Channel 2 [%04X] Group 2 [%d][%04X]", channel2, group2, group2);
if (so2 & 0x80) fprintf (stderr, " Emergency");
if (so2 & 0x40) fprintf (stderr, " Encrypted");
if (opts->payload == 1) //hide behind payload due to len
{
if (so2 & 0x20) fprintf (stderr, " Duplex");
if (so2 & 0x10) fprintf (stderr, " Packet");
else fprintf (stderr, " Circuit");
if (so2 & 0x8) fprintf (stderr, " R"); //reserved bit is on
fprintf (stderr, " Priority %d", so2 & 0x7); //call priority
}
freq2 = process_channel_to_freq (opts, state, channel2);
}
freq2 = process_channel_to_freq (opts, state, channel2);
fprintf (stderr, "\n Channel 3 [%04X] Group 3 [%d][%04X]", channel3, group3, group3);
if (so3 & 0x80) fprintf (stderr, " Emergency");
if (so3 & 0x40) fprintf (stderr, " Encrypted");
if (opts->payload == 1) //hide behind payload due to len
if (channel3 != channel2 && channel3 != 0 && channel3 != 0xFFFF)
{
if (so3 & 0x20) fprintf (stderr, " Duplex");
if (so3 & 0x10) fprintf (stderr, " Packet");
else fprintf (stderr, " Circuit");
if (so3 & 0x8) fprintf (stderr, " R"); //reserved bit is on
fprintf (stderr, " Priority %d", so3 & 0x7); //call priority
fprintf (stderr, "\n Channel 3 [%04X] Group 3 [%d][%04X]", channel3, group3, group3);
if (so3 & 0x80) fprintf (stderr, " Emergency");
if (so3 & 0x40) fprintf (stderr, " Encrypted");
if (opts->payload == 1) //hide behind payload due to len
{
if (so3 & 0x20) fprintf (stderr, " Duplex");
if (so3 & 0x10) fprintf (stderr, " Packet");
else fprintf (stderr, " Circuit");
if (so3 & 0x8) fprintf (stderr, " R"); //reserved bit is on
fprintf (stderr, " Priority %d", so3 & 0x7); //call priority
}
freq3 = process_channel_to_freq (opts, state, channel3);
}
freq3 = process_channel_to_freq (opts, state, channel3);
//add active channel to string for ncurses display
sprintf (state->active_channel[0], "Active Ch: %04X TG: %d; Ch: %04X TG: %d; Ch: %04X TG: %d; ", channel1, group1, channel2, group2, channel3, group3);
//add active channel to string for ncurses display (multi check)
// if (channel3 != channel2 && channel2 != channel1 && channel3 != 0 && channel3 != 0xFFFF)
// sprintf (state->active_channel[0], "Active Ch: %04X TG: %d; Ch: %04X TG: %d; Ch: %04X TG: %d; ", channel1, group1, channel2, group2, channel3, group3);
state->last_active_time = time(NULL);
//Skip tuning group calls if group calls are disabled
if (opts->trunk_tune_group_calls == 0) goto SKIPCALL;
//Skip tuning encrypted calls if enc calls are disabled
if ( (so1 & 0x40) && (so2 & 0x40) && (so3 & 0x40) && opts->trunk_tune_enc_calls == 0) goto SKIPCALL;
if ( (so1 & 0x40) && (so2 & 0x40) && (so3 & 0x40) && opts->trunk_tune_enc_calls == 0) goto SKIPCALL; //this?
int loop = 3;
@ -1173,18 +1189,23 @@ void process_MAC_VPDU(dsd_opts * opts, dsd_state * state, int type, unsigned lon
fprintf (stderr, "\n Group Voice Channel Grant Update - Implicit");
fprintf (stderr, "\n Channel 1 [%04X] Group 1 [%d][%04X]", channel1, group1, group1);
freq1 = process_channel_to_freq (opts, state, channel1);
fprintf (stderr, "\n Channel 2 [%04X] Group 2 [%d][%04X]", channel2, group2, group2);
freq2 = process_channel_to_freq (opts, state, channel2);
if (channel2 != channel1 && channel2 != 0 && channel2 != 0xFFFF)
{
fprintf (stderr, "\n Channel 2 [%04X] Group 2 [%d][%04X]", channel2, group2, group2);
freq2 = process_channel_to_freq (opts, state, channel2);
}
//add active channel to string for ncurses display
sprintf (state->active_channel[0], "Active Ch: %04X TG: %d; Ch: %04X TG: %d; ", channel1, group1, channel2, group2);
if (channel2 != channel1 && channel2 != 0 && channel2 != 0xFFFF)
sprintf (state->active_channel[0], "Active Ch: %04X TG: %d; Ch: %04X TG: %d; ", channel1, group1, channel2, group2);
else sprintf (state->active_channel[0], "Active Ch: %04X TG: %d; ", channel1, group1);
state->last_active_time = time(NULL);
//Skip tuning group calls if group calls are disabled
if (opts->trunk_tune_group_calls == 0) goto SKIPCALL;
//Skip tuning encrypted calls if enc calls are disabled -- abb formats do not carry svc bits :(
if (opts->trunk_tune_enc_calls == 0) goto SKIPCALL; //enable, or disable?
// if (opts->trunk_tune_enc_calls == 0) goto SKIPCALL; //enable, or disable?
int loop = 1;
if (channel1 == channel2) loop = 1;