From d52c2b6426f6e64a47859b22a35ca32635ff50e6 Mon Sep 17 00:00:00 2001 From: lwvmobile Date: Tue, 26 Sep 2023 16:54:17 -0400 Subject: [PATCH] P25 -- Add MFID90 GRG Call Grant TSBK/MPDU; --- src/p25p1_mdpu.c | 113 +++++++++++++++++++++++-- src/p25p1_tsbk.c | 209 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 307 insertions(+), 15 deletions(-) diff --git a/src/p25p1_mdpu.c b/src/p25p1_mdpu.c index 4c0a6d6..f271cba 100644 --- a/src/p25p1_mdpu.c +++ b/src/p25p1_mdpu.c @@ -478,8 +478,8 @@ void processMPDU(dsd_opts * opts, dsd_state * state) } } - //look at Harris Opcodes and payload portion of TSBK - else if (MFID == 0xA4) + //look at Harris Opcodes and payload portion of MPDU + else if (MFID == 0xA4) { //TODO: Add Known Opcodes from Manual (all one of them) fprintf (stderr, "%s",KCYN); @@ -489,15 +489,110 @@ void processMPDU(dsd_opts * opts, dsd_state * state) fprintf (stderr, " %s",KNRM); } - //look at Motorola Opcodes and payload portion of TSBK + //look at Motorola Opcodes and payload portion of MPDU else if (MFID == 0x90) { - //TODO: Add Known Opcodes from Manual - fprintf (stderr, "%s",KCYN); - fprintf (stderr, "\n MFID 90 (Moto); Opcode: %02X; ", mpdu_byte[0] & 0x3F); - for (i = 0; i < (12*(blks+1)%37); i++) - fprintf (stderr, "%02X", mpdu_byte[i]); - fprintf (stderr, " %s",KNRM); + //TIA-102.AABH + if (opcode == 0x02) + { + int svc = mpdu_byte[8]; //Just the Res, P-bit, and more res bits + int channelt = (mpdu_byte[12] << 8) | mpdu_byte[13]; + int channelr = (mpdu_byte[14] << 8) | mpdu_byte[15]; + long int source = (mpdu_byte[3] << 16) |(mpdu_byte[4] << 8) | mpdu_byte[5]; + int group = (mpdu_byte[16] << 8) | mpdu_byte[17]; + long int freq1 = 0; + long int freq2 = 0; + UNUSED2(source, freq2); + fprintf (stderr, "%s\n ",KYEL); + + //unsure if this follows for GRG + // if (svc & 0x80) fprintf (stderr, " Emergency"); + + if (svc & 0x40) fprintf (stderr, " Encrypted"); //P-bit + + //unsure if this follows for GRG + // if (opts->payload == 1) //hide behind payload due to len + // { + // if (svc & 0x20) fprintf (stderr, " Duplex"); + // if (svc & 0x10) fprintf (stderr, " Packet"); + // else fprintf (stderr, " Circuit"); + // if (svc & 0x8) fprintf (stderr, " R"); //reserved bit is on + // fprintf (stderr, " Priority %d", svc & 0x7); //call priority + // } + + fprintf (stderr, " MFID90 Group Regroup Channel Grant - Explicit"); + fprintf (stderr, "\n SVC [%02X] CHAN-T [%04X] CHAN-R [%04X] SG [%d][%04X]", svc, channelt, channelr, group, group); + freq1 = process_channel_to_freq (opts, state, channelt); + freq2 = process_channel_to_freq (opts, state, channelr); + + //add active channel to string for ncurses display + sprintf (state->active_channel[0], "MFID90 Ch: %04X SG: %d ", channelt, group); + state->last_active_time = time(NULL); + + for (int i = 0; i < state->group_tally; i++) + { + if (state->group_array[i].groupNumber == group) + { + fprintf (stderr, " [%s]", state->group_array[i].groupName); + strcpy (mode, state->group_array[i].groupMode); + break; + } + } + + + //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 ( (svc & 0x40) && 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)) + { + //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot + if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && freq1 != 0) //if we aren't already on a VC and have a valid frequency + { + + //changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK + if (1 == 1) + { + if (state->p25_chan_tdma[channelt >> 12] == 1) + { + state->samplesPerSymbol = 8; + state->symbolCenter = 3; + } + } + //rigctl + if (opts->use_rigctl == 1) + { + if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw); + SetFreq(opts->rigctl_sockfd, freq1); + state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1; + opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + state->last_vc_sync_time = time(NULL); + } + //rtl + else if (opts->audio_in_type == 3) + { + #ifdef USE_RTLSDR + rtl_dev_tune (opts, freq1); + state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1; + opts->p25_is_tuned = 1; + state->last_vc_sync_time = time(NULL); + #endif + } + } + } + } + + else + { + fprintf (stderr, "%s",KCYN); + fprintf (stderr, "\n MFID 90 (Moto); Opcode: %02X; ", mpdu_byte[0] & 0x3F); + for (i = 0; i < (12*(blks+1)%37); i++) + fprintf (stderr, "%02X", mpdu_byte[i]); + fprintf (stderr, " %s",KNRM); + } } else diff --git a/src/p25p1_tsbk.c b/src/p25p1_tsbk.c index f9167d3..ce02992 100644 --- a/src/p25p1_tsbk.c +++ b/src/p25p1_tsbk.c @@ -167,12 +167,209 @@ void processTSBK(dsd_opts * opts, dsd_state * state) //look at Motorola Opcodes and payload portion of TSBK else if (MFID == 0x90 && protectbit == 0 && err == 0) { - //TODO: Add Known Opcodes from Manual -- will probably want to add the voice grants - fprintf (stderr, "%s",KCYN); - fprintf (stderr, "\n MFID 90 (Moto); Opcode: %02X; ", tsbk_byte[0] & 0x3F); - for (i = 2; i < 10; i++) - fprintf (stderr, "%02X", tsbk_byte[i]); - fprintf (stderr, " %s",KNRM); + //group list mode so we can look and see if we need to block tuning any groups, etc + char mode[8]; //allow, block, digital, enc, etc + sprintf (mode, "%s", ""); + + //MFID 90 Group Regroup Channel Grant (MOT_GRG_CN_GRANT) TIA-102.AABH + if ( (tsbk_byte[0] & 0x3F) == 0x02 ) + { + int svc = tsbk_byte[2]; //Just the Res, P-bit, and more res bits + int channel = (tsbk_byte[3] << 8) | tsbk_byte[4]; + long int source = (tsbk_byte[7] << 16) |(tsbk_byte[8] << 8) | tsbk_byte[9]; + int group = (tsbk_byte[5] << 8) | tsbk_byte[6]; + long int freq1 = 0; + UNUSED(source); + fprintf (stderr, "%s\n ",KYEL); + + //unsure if this follows for GRG + // if (svc & 0x80) fprintf (stderr, " Emergency"); + + if (svc & 0x40) fprintf (stderr, " Encrypted"); //P-bit + + //unsure if this follows for GRG + // if (opts->payload == 1) //hide behind payload due to len + // { + // if (svc & 0x20) fprintf (stderr, " Duplex"); + // if (svc & 0x10) fprintf (stderr, " Packet"); + // else fprintf (stderr, " Circuit"); + // if (svc & 0x8) fprintf (stderr, " R"); //reserved bit is on + // fprintf (stderr, " Priority %d", svc & 0x7); //call priority + // } + + fprintf (stderr, " MFID90 Group Regroup Channel Grant"); + fprintf (stderr, "\n SVC [%02X] CHAN [%04X] SG [%d][%04X]", svc, channel, group, group); + freq1 = process_channel_to_freq (opts, state, channel); + + //add active channel to string for ncurses display + sprintf (state->active_channel[0], "MFID90 Ch: %04X SG: %d ", channel, group); + state->last_active_time = time(NULL); + + if (opts->trunk_use_allow_list == 1) sprintf (mode, "%s", "B"); + + for (int i = 0; i < state->group_tally; i++) + { + if (state->group_array[i].groupNumber == group) + { + fprintf (stderr, " [%s]", state->group_array[i].groupName); + strcpy (mode, state->group_array[i].groupMode); + break; + } + } + + //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 ( (svc & 0x40) && 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)) + { + //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot + if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && freq1 != 0) //if we aren't already on a VC and have a valid frequency + { + + //changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK + if (1 == 1) + { + if (state->p25_chan_tdma[channel >> 12] == 1) + { + state->samplesPerSymbol = 8; + state->symbolCenter = 3; + } + } + //rigctl + if (opts->use_rigctl == 1) + { + if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw); + SetFreq(opts->rigctl_sockfd, freq1); + state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1; + opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + state->last_vc_sync_time = time(NULL); + } + //rtl + else if (opts->audio_in_type == 3) + { + #ifdef USE_RTLSDR + rtl_dev_tune (opts, freq1); + state->p25_vc_freq[0] = state->p25_vc_freq[1] = freq1; + opts->p25_is_tuned = 1; + state->last_vc_sync_time = time(NULL); + #endif + } + } + } + } + + else if ( (tsbk_byte[0] & 0x3F) == 0x03 ) + { + //MFID 90 Group Regroup Channel Update (MOT_GRG_CN_GRANT_UPDT) TIA-102.AABH + int channel1 = (tsbk_byte[2] << 8) | tsbk_byte[3]; + int group1 = (tsbk_byte[4] << 8) | tsbk_byte[5]; + int channel2 = (tsbk_byte[6] << 8) | tsbk_byte[7]; + int group2 = (tsbk_byte[8] << 8) | tsbk_byte[9]; + + long int freq1 = 0; + long int freq2 = 0; + + int tempg = 0; //temp group + int tempc = 0; //temp chan + long int tempf = 0; //temp freq + + fprintf (stderr, "%s\n ",KYEL); + fprintf (stderr, " MFID90 Group Regroup Channel Grant Update"); + fprintf (stderr, "\n CHAN1 [%04X] SG [%d][%04X] CHAN2 [%04X] SG [%d][%04X]", channel1, group1, group1, channel2, group2, group2); + freq1 = process_channel_to_freq (opts, state, channel1); + freq2 = process_channel_to_freq (opts, state, channel2); + + //add active channel to string for ncurses display + sprintf (state->active_channel[0], "MFID90 Ch: %04X SG: %d; Ch: %04X SG: %d ", channel1, group1, channel2, group2); + state->last_active_time = time(NULL); + + tempf = freq1; + tempc = channel1; + tempg = group1; + + for (int j = 0; j < 2; j++) + { + if (j == 1) + { + tempf = freq2; + tempc = channel2; + tempg = group2; + } + + if (opts->trunk_use_allow_list == 1) sprintf (mode, "%s", "B"); + + for (int i = 0; i < state->group_tally; i++) + { + if (state->group_array[i].groupNumber == tempg) + { + fprintf (stderr, " [%s]", state->group_array[i].groupName); + strcpy (mode, state->group_array[i].groupMode); + break; + } + } + + + //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 (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)) + { + //reworked to set freq once on any call to process_channel_to_freq, and tune on that, independent of slot + if (state->p25_cc_freq != 0 && opts->p25_is_tuned == 0 && tempf != 0) //if we aren't already on a VC and have a valid frequency + { + + //changed to allow symbol rate change on C4FM Phase 2 systems as well as QPSK + if (1 == 1) + { + if (state->p25_chan_tdma[tempc >> 12] == 1) + { + state->samplesPerSymbol = 8; + state->symbolCenter = 3; + } + } + //rigctl + if (opts->use_rigctl == 1) + { + if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw); + SetFreq(opts->rigctl_sockfd, tempf); + state->p25_vc_freq[0] = state->p25_vc_freq[1] = tempf; + opts->p25_is_tuned = 1; //set to 1 to set as currently tuned so we don't keep tuning nonstop + state->last_vc_sync_time = time(NULL); + } + //rtl + else if (opts->audio_in_type == 3) + { + #ifdef USE_RTLSDR + rtl_dev_tune (opts, tempf); + state->p25_vc_freq[0] = state->p25_vc_freq[1] = tempf; + opts->p25_is_tuned = 1; + state->last_vc_sync_time = time(NULL); + #endif + } + } + } + } + + } + else + { + fprintf (stderr, "%s",KCYN); + fprintf (stderr, "\n MFID 90 (Moto); Opcode: %02X; ", tsbk_byte[0] & 0x3F); + for (i = 2; i < 10; i++) + fprintf (stderr, "%02X", tsbk_byte[i]); + fprintf (stderr, " %s",KNRM); + } + + SKIPCALL: ; //do nothing + } //set our WACN and SYSID here now that we have valid ec and crc/checksum