From cb02c0328c9b43e98dd9623e9c3b3e46b0aa5b08 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Tue, 27 Feb 2024 08:57:15 -0500 Subject: [PATCH] P25 - Better Handling of Trunking ENC Call Lockout; Fix Duplicate Channel Listing in Multi Grant Updates; --- include/dsd.h | 3 ++ src/dsd_rigctl.c | 59 +++++++++++++++++++++++++++++++++ src/p25_frequency.c | 4 +++ src/p25p1_ldu2.c | 41 +++++++++++++++++++++++ src/p25p1_tsbk.c | 2 +- src/p25p2_frame.c | 64 ++++++++++++++++++++++++++++++++++++ src/p25p2_vpdu.c | 79 ++++++++++++++++++++++++++++----------------- 7 files changed, 222 insertions(+), 30 deletions(-) diff --git a/include/dsd.h b/include/dsd.h index b2201dc..41a1252 100644 --- a/include/dsd.h +++ b/include/dsd.h @@ -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); diff --git a/src/dsd_rigctl.c b/src/dsd_rigctl.c index ee40b98..63667eb 100644 --- a/src/dsd_rigctl.c +++ b/src/dsd_rigctl.c @@ -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 "); +} diff --git a/src/p25_frequency.c b/src/p25_frequency.c index 4d2ba98..8993e27 100644 --- a/src/p25_frequency.c +++ b/src/p25_frequency.c @@ -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; diff --git a/src/p25p1_ldu2.c b/src/p25p1_ldu2.c index 52c01f7..dec7113 100644 --- a/src/p25p1_ldu2.c +++ b/src/p25p1_ldu2.c @@ -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/ diff --git a/src/p25p1_tsbk.c b/src/p25p1_tsbk.c index c801b7f..8ca5ce0 100644 --- a/src/p25p1_tsbk.c +++ b/src/p25p1_tsbk.c @@ -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)) diff --git a/src/p25p2_frame.c b/src/p25p2_frame.c index b27b79e..f7cc0f4 100644 --- a/src/p25p2_frame.c +++ b/src/p25p2_frame.c @@ -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) { diff --git a/src/p25p2_vpdu.c b/src/p25p2_vpdu.c index 468b71a..b7922cf 100644 --- a/src/p25p2_vpdu.c +++ b/src/p25p2_vpdu.c @@ -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;