Files
dsd-fme/src/p25p2_xcch.c

954 lines
29 KiB
C

/*-------------------------------------------------------------------------------
* p25p2_xcch.c
* Phase 2 SACCH/FACCH/LCCH Handling
*
* LWVMOBILE
* 2022-09 DSD-FME Florida Man Edition
*-----------------------------------------------------------------------------*/
#include "dsd.h"
void process_SACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[180])
{
//Figure out which PDU we are looking at, see above info on 8.4.1
//reorganize bits into bytes and process accordingly
//new slot variable with flipped assignment for SACCH
uint8_t slot = (state->currentslot ^ 1) & 1;
unsigned long long int SMAC[24] = {0}; //22.5 bytes for SACCH MAC PDUs
int byte = 0;
int k = 0;
for (int j = 0; j < 22; j++)
{
for (int i = 0; i < 8; i++)
{
byte = byte << 1;
byte = byte | payload[k];
k++;
}
SMAC[j] = byte;
byte = 0; //reset byte
}
SMAC[22] = (payload[176] << 7) | (payload[177] << 6) | (payload[178] << 5) | (payload[179] << 4);
int opcode = 0;
opcode = (payload[0] << 2) | (payload[1] << 1) | (payload[2] << 0);
int mac_offset = 0;
mac_offset = (payload[3] << 2) | (payload[4] << 1) | (payload[5] << 0);
int res = (payload[6] << 1) | (payload[7] << 0);
int b = 9;
b = (payload[8] << 1) | (payload[9] << 0); //combined b1 and b2
int mco_a = 69;
//mco will tell us the number of octets to use in variable length MAC PDUs, need a table or something
mco_a = (payload[10] << 5) | (payload[11] << 4) | (payload[12] << 3) | (payload[13] << 2) | (payload[14] << 0) | (payload[15] << 0);
UNUSED3(mac_offset, b, mco_a);
//get the second mco after determining first message length, see what second mco is and plan accordingly
int mco_b = 69;
UNUSED(mco_b);
//attempt CRC12 check to validate or reject PDU
int err = -2;
if (state->p2_is_lcch == 0)
{
err = crc12_xb_bridge(payload, 180-12);
if (err != 0) //CRC Failure, warn or skip.
{
if (SMAC[1] == 0x0) //NULL PDU Check, pass if NULL type
{
//fprintf (stderr, " NULL ");
}
else
{
fprintf (stderr, " CRC12 ERR S");
//if (state->currentslot == 0) state->dmrburstL = 14;
//else state->dmrburstR = 14;
goto END_SMAC;
}
}
}
if (state->p2_is_lcch == 1)
{
int len = 0;
//int len = mac_msg_len[SMAC[1]] * 8;
//if (len > 164) len = 164; //prevent potential stack smash or other issue.
len = 164;
err = crc16_lb_bridge(payload, len);
if (err != 0) //CRC Failure, warn or skip.
{
if (SMAC[1] == 0x0) //NULL PDU Check, pass if NULL type
{
//fprintf (stderr, " NULL ");
state->p2_is_lcch = 0; //turn flag off here
goto END_SMAC;
}
else //permit MAC_SIGNAL on CRC ERR if -F option called
{
if (opts->aggressive_framesync == 1)
{
fprintf (stderr, " CRC16 ERR L");
state->p2_is_lcch = 0; //turn flag off here
//if (state->currentslot == 0) state->dmrburstL = 14;
//else state->dmrburstR = 14;
goto END_SMAC;
}
}
}
}
//remember, slots are inverted here, so set the opposite ones
//monitor, test, and remove these if they cause issues due to inversion
if (opcode == 0x0)
{
fprintf (stderr, " MAC_SIGNAL ");
//warn user instead of failing
if (err != 0)
{
fprintf (stderr, "%s", KRED);
fprintf (stderr, "CRC16 ERR ");
}
fprintf (stderr, "%s", KYEL);
process_MAC_VPDU(opts, state, 1, SMAC);
fprintf (stderr, "%s", KNRM);
}
//do not permit MAC_PTT with CRC errs, help prevent false positives on calls
if (opcode == 0x1 && err == 0)
{
fprintf (stderr, " MAC_PTT ");
fprintf (stderr, "%s", KGRN);
//remember, slots are inverted here, so set the opposite ones
if (state->currentslot == 1)
{
//reset fourv_counter and dropbyte on PTT
state->fourv_counter[0] = 0;
state->voice_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 20;
fprintf (stderr, "\n VCH 0 - ");
//check that src is not zero first, some harris and other patch systems may do this,
//but that also causes an issue in the new event logger if the active channel has a src, but mac_ptt has 0
uint32_t src = (SMAC[13] << 16) | (SMAC[14] << 8) | SMAC[15];
if (src != 0)
state->lastsrc = (SMAC[13] << 16) | (SMAC[14] << 8) | SMAC[15];
state->lasttg = (SMAC[16] << 8) | SMAC[17];
fprintf (stderr, "TG %d ", state->lasttg);
fprintf (stderr, "SRC %d ", src);
/*
When the talker radio is initiating an individual call (unit to unit or telephone interconnect), the reserved group ID of zero
is used in the group address portion of the MAC_PTT PDU and the source ID is that of the talker radio.
The outbound SACCH for the talker radio containing the talker ID information is required at the
talker radio site and optional at other sites. (So, if its from an external site, then it can be zero?)
*/
// if (state->lastsrc == 0) fprintf (stderr, "External ");
state->payload_algid = SMAC[10];
state->payload_keyid = (SMAC[11] << 8) | SMAC[12];
state->payload_miP = (SMAC[1] << 56) | (SMAC[2] << 48) | (SMAC[3] << 40) | (SMAC[4] << 32) |
(SMAC[5] << 24) | (SMAC[6] << 16) | (SMAC[7] << 8) | (SMAC[8] << 0);
if (state->payload_algid != 0x80 && state->payload_algid != 0x0)
{
fprintf (stderr, "%s", KYEL);
fprintf (stderr, "\n ALG ID: 0x%02X", state->payload_algid);
fprintf (stderr, " KEY ID: 0x%04X", state->payload_keyid);
fprintf (stderr, " MI: 0x%016llX", state->payload_miP);
fprintf(stderr, " MPTT");
if (state->R != 0 && state->payload_algid == 0xAA) fprintf (stderr, " Key 0x%010llX", state->R);
if (state->R != 0 && state->payload_algid == 0x81) fprintf (stderr, " Key 0x%016llX", state->R);
if ( (state->payload_algid == 0x84 || state->payload_algid == 0x89) && state->aes_key_loaded[0] == 1)
{
fprintf (stderr, "\n ");
fprintf (stderr, "Key: %016llX %016llX ", state->A1[0], state->A2[0]);
if (state->payload_algid == 0x84)
fprintf (stderr, "%016llX %016llX", state->A3[0], state->A4[0]);
// opts->unmute_encrypted_p25 = 1; //needed?
}
//expand 64-bit MI to 128-bit for AES
if (state->payload_algid == 0x84 || state->payload_algid == 0x89)
{
LFSR128(state);
// fprintf (stderr, "\n");
}
// fprintf (stderr, " %s", KRED);
// fprintf (stderr, "ENC");
}
//reset gain
if (opts->floating_point == 1)
state->aout_gain = opts->audio_gain;
}
if (state->currentslot == 0)
{
//reset fourv_counter and dropbyte on PTT
state->fourv_counter[1] = 0;
state->voice_counter[1] = 0;
state->dropR = 256;
state->payload_algidR = 0; //zero this out as well
state->dmrburstR = 20;
fprintf (stderr, "\n VCH 1 - ");
//check that src is not zero first, some harris and other patch systems may do this,
//but that also causes an issue in the new event logger if the active channel has a src, but mac_ptt has 0
uint32_t src = (SMAC[13] << 16) | (SMAC[14] << 8) | SMAC[15];
if (src != 0)
state->lastsrcR = (SMAC[13] << 16) | (SMAC[14] << 8) | SMAC[15];
state->lasttgR = (SMAC[16] << 8) | SMAC[17];
fprintf (stderr, "TG %d ", state->lasttgR);
fprintf (stderr, "SRC %d ", src);
// if (state->lastsrcR == 0) fprintf (stderr, "External ");
state->payload_algidR = SMAC[10];
state->payload_keyidR = (SMAC[11] << 8) | SMAC[12];
state->payload_miN = (SMAC[1] << 56) | (SMAC[2] << 48) | (SMAC[3] << 40) | (SMAC[4] << 32) |
(SMAC[5] << 24) | (SMAC[6] << 16) | (SMAC[7] << 8) | (SMAC[8] << 0);
if (state->payload_algidR != 0x80 && state->payload_algidR != 0x0)
{
fprintf (stderr, "%s", KYEL);
fprintf (stderr, "\n ALG ID: 0x%02X", state->payload_algidR);
fprintf (stderr, " KEY ID: 0x%04X", state->payload_keyidR);
fprintf (stderr, " MI: 0x%016llX", state->payload_miN);
fprintf(stderr, " MPTT");
if (state->RR != 0 && state->payload_algidR == 0xAA) fprintf (stderr, " Key 0x%010llX", state->RR);
if (state->RR != 0 && state->payload_algidR == 0x81) fprintf (stderr, " Key 0x%016llX", state->RR);
if ( (state->payload_algidR == 0x84 || state->payload_algidR == 0x89) && state->aes_key_loaded[1] == 1)
{
fprintf (stderr, "\n ");
fprintf (stderr, "Key: %016llX %016llX ", state->A1[1], state->A2[1]);
if (state->payload_algidR == 0x84)
fprintf (stderr, "%016llX %016llX", state->A3[1], state->A4[1]);
// opts->unmute_encrypted_p25 = 1; //needed?
}
//expand 64-bit MI to 128-bit for AES
if (state->payload_algidR == 0x84 || state->payload_algidR == 0x89)
{
LFSR128(state);
// fprintf (stderr, "\n");
}
// fprintf (stderr, " %s", KRED);
// fprintf (stderr, "ENC");
}
//reset gain
if (opts->floating_point == 1)
state->aout_gainR = opts->audio_gain;
}
if (opts->payload == 1)
{
fprintf (stderr, "\n MAC_PTT_PAYLOAD_S OFFSET: %d RES: %d \n ", mac_offset, res);
for (int i = 0; i < 24; i++)
{
if (i == 12) fprintf (stderr, "\n ");
fprintf (stderr, "[%02llX]", SMAC[i]);
}
}
//reset voice counter at MAC_PTT (inverted, triple check please)
if (state->currentslot == 1 && state->payload_algidR == 0x81)
state->DMRvcL = 0;
if (state->currentslot == 0 && state->payload_algid == 0x81)
state->DMRvcR = 0;
//reset voice counter after 2V (AES 256)
if (state->currentslot == 1 && state->payload_algidR == 0x84)
state->DMRvcL = 0;
if (state->currentslot == 0 && state->payload_algid == 0x84)
state->DMRvcR = 0;
//reset voice counter after 2V (AES 128)
if (state->currentslot == 1 && state->payload_algidR == 0x89)
state->DMRvcL = 0;
if (state->currentslot == 0 && state->payload_algid == 0x89)
state->DMRvcR = 0;
fprintf (stderr, "%s", KNRM);
}
//do not permit MAC_PTT_END with CRC errs, help prevent false positives on calls
if (opcode == 0x2 && err == 0)
{
fprintf (stderr, " MAC_END_PTT ");
fprintf (stderr, "%s", KRED);
//remember, slots are inverted here, so set the opposite ones
if (state->currentslot == 1)
{
state->fourv_counter[0] = 0;
state->voice_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 23;
state->payload_algid = 0;
state->payload_keyid = 0;
fprintf (stderr, "\n VCH 0 - ");
fprintf (stderr, "TG %d ", state->lasttg);
fprintf (stderr, "SRC %d ", state->lastsrc);
//print it and then zero out
state->lastsrc = 0;
state->lasttg = 0;
//close any open MBEout files
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
//blank the call string here -- slot variable is already flipped accordingly for sacch
sprintf (state->call_string[slot], "%s", " "); //21 spaces -- wrong placement!
//reset gain
if (opts->floating_point == 1)
state->aout_gain = opts->audio_gain;
}
if (state->currentslot == 0)
{
state->fourv_counter[1] = 0;
state->voice_counter[1] = 0;
state->dropR = 256;
state->dmrburstR = 23;
state->payload_algidR = 0;
state->payload_keyidR = 0;
fprintf (stderr, "\n VCH 1 - ");
fprintf (stderr, "TG %d ", state->lasttgR);
fprintf (stderr, "SRC %d ", state->lastsrcR);
//print it and then zero out
state->lastsrcR = 0;
state->lasttgR = 0;
//close any open MBEout files
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
//blank the call string here -- slot variable is already flipped accordingly for sacch
sprintf (state->call_string[slot], "%s", " "); //21 spaces -- wrong placement!
//reset gain
if (opts->floating_point == 1)
state->aout_gainR = opts->audio_gain;
}
//Return to CC on MAC_END_PTT if other slot is idle
//TODO: Look at the source address of the END_PTT, if it is 0xFFFFFF, then its from the FNE?
//if from the FNE, that may be when we know channel teardown will really occur vs using MAC_END_PTT directly
/*
Upon receipt of a MAC_END_PTT PDU on the assigned VCH, and having verified it contains the
correct color code, the SU shall return to the idle state on the control channel.
*/
//NOTE: Disable return later on if not desirable to use
//end_ptt in this slot, idle in the other slot (Normal Slots)
if ( ((state->currentslot == 0) && (state->dmrburstL == 24)) ||
((state->currentslot == 1) && (state->dmrburstR == 24)) )
{
if (opts->p25_trunk == 1 && opts->p25_is_tuned == 1)
{
//if P25p2 VCH and going back to P25p1 CC, flip symbolrate
if (state->p25_cc_is_tdma == 0)
{
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
//re-enable both slots
opts->slot1_on = 1;
opts->slot2_on = 1;
}
//rigctl
if (opts->use_rigctl == 1)
{
state->lasttg = 0;
state->lastsrc = 0;
state->lasttgR = 0;
state->lastsrcR = 0;
state->payload_algid = 0;
state->payload_keyid = 0;
state->payload_algidR = 0;
state->payload_keyidR = 0;
// state->payload_miP = 0;
//reset some strings
sprintf (state->call_string[0], "%s", " "); //21 spaces
sprintf (state->call_string[1], "%s", " "); //21 spaces
sprintf (state->active_channel[0], "%s", "");
sprintf (state->active_channel[1], "%s", "");
opts->p25_is_tuned = 0;
state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0;
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, state->p25_cc_freq);
}
//rtl
else if (opts->audio_in_type == 3)
{
#ifdef USE_RTLSDR
state->lasttg = 0;
state->lastsrc = 0;
state->lasttgR = 0;
state->lastsrcR = 0;
state->payload_algid = 0;
state->payload_keyid = 0;
state->payload_algidR = 0;
state->payload_keyidR = 0;
// state->payload_miP = 0;
//reset some strings
sprintf (state->call_string[0], "%s", " "); //21 spaces
sprintf (state->call_string[1], "%s", " "); //21 spaces
sprintf (state->active_channel[0], "%s", "");
sprintf (state->active_channel[1], "%s", "");
opts->p25_is_tuned = 0;
state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0;
rtl_dev_tune (opts, state->p25_cc_freq);
#endif
}
}
}
fprintf (stderr, "%s", KNRM);
}
if (opcode == 0x3 && err == 0)
{
if (state->currentslot == 1) state->dmrburstL = 24;
else state->dmrburstR = 24;
fprintf (stderr, " MAC_IDLE ");
fprintf (stderr, "%s", KYEL);
process_MAC_VPDU(opts, state, 1, SMAC);
fprintf (stderr, "%s", KNRM);
// if (opts->p25_trunk == 1 && opts->p25_is_tuned == 1)
// {
// if (state->currentslot == 1)
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
// }
//blank the call string here -- slot variable is already flipped accordingly for sacch
sprintf (state->call_string[slot], "%s", " "); //21 spaces
}
if (opcode == 0x4 && err == 0)
{
//disable to prevent blinking in ncurses terminal due to OSS preemption shim
#ifdef __CYGWIN__
if (opts->audio_out_type != 5)
{
if (state->currentslot == 1) state->dmrburstL = 21;
else state->dmrburstR = 21;
}
#else
if (state->currentslot == 1) state->dmrburstL = 21;
else state->dmrburstR = 21;
#endif
fprintf (stderr, " MAC_ACTIVE ");
fprintf (stderr, "%s", KYEL);
process_MAC_VPDU(opts, state, 1, SMAC);
fprintf (stderr, "%s", KNRM);
}
if (opcode == 0x6 && err == 0)
{
if (state->currentslot == 1)
{
state->dmrburstL = 22;
//close any open MBEout files
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
}
else
{
state->dmrburstR = 22;
//close any open MBEout files
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
}
fprintf (stderr, " MAC_HANGTIME ");
fprintf (stderr, "%s", KYEL);
process_MAC_VPDU(opts, state, 1, SMAC);
fprintf (stderr, "%s", KNRM);
}
END_SMAC:
if (1 == 2)
{
//CRC Failure!
}
}
void process_FACCH_MAC_PDU (dsd_opts * opts, dsd_state * state, int payload[156])
{
//Figure out which PDU we are looking at, see above info on 8.4.1
//reorganize bits into bytes and process accordingly
//new slot variable
uint8_t slot = state->currentslot;
unsigned long long int FMAC[24] = {0}; //19.5 bytes for FACCH MAC PDUs, add padding to end
int byte = 0;
int k = 0;
for (int j = 0; j < 19; j++)
{
for (int i = 0; i < 8; i++)
{
byte = byte << 1;
byte = byte | payload[k];
k++;
}
FMAC[j] = byte;
byte = 0; //reset byte
}
FMAC[19] = (payload[152] << 7) | (payload[153] << 6) | (payload[154] << 5) | (payload[155] << 4);
//add padding bytes so we can have a unified variable MAC PDU handler
for (int i = 0; i < 3; i++)
{
FMAC[i+20] = 0;
}
int opcode = 0;
opcode = (payload[0] << 2) | (payload[1] << 1) | (payload[2] << 0);
int mac_offset = 0;
mac_offset = (payload[3] << 2) | (payload[4] << 1) | (payload[5] << 0);
int res = (payload[6] << 1) | (payload[7] << 0);
UNUSED(mac_offset);
//attempt CRC check to validate or reject PDU
int err = -2;
if (state->p2_is_lcch == 0)
{
err = crc12_xb_bridge(payload, 156-12);
if (err != 0) //CRC Failure, warn or skip.
{
if (FMAC[1] == 0x0) //NULL PDU Check, pass if NULL
{
//fprintf (stderr, " NULL ");
}
else
{
fprintf (stderr, " CRC12 ERR F");
//if (state->currentslot == 0) state->dmrburstL = 14;
//else state->dmrburstR = 14;
goto END_FMAC;
}
}
}
//Not sure if a MAC Signal will come on a FACCH or not, so disable to prevent falsing
// if (opcode == 0x0)
// {
// fprintf (stderr, " MAC_SIGNAL ");
// fprintf (stderr, "%s", KYEL);
// process_MAC_VPDU(opts, state, 0, FMAC);
// fprintf (stderr, "%s", KNRM);
// }
if (opcode == 0x1 && err == 0)
{
fprintf (stderr, " MAC_PTT ");
fprintf (stderr, "%s", KGRN);
if (state->currentslot == 0)
{
//reset fourv_counter and dropbyte on PTT
state->fourv_counter[0] = 0;
state->voice_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 20;
fprintf (stderr, "\n VCH 0 - ");
//check that src is not zero first, some harris and other patch systems may do this,
//but that also causes an issue in the new event logger if the active channel has a src, but mac_ptt has 0
uint32_t src = (FMAC[13] << 16) | (FMAC[14] << 8) | FMAC[15];
if (src != 0)
state->lastsrc = (FMAC[13] << 16) | (FMAC[14] << 8) | FMAC[15];
state->lasttg = (FMAC[16] << 8) | FMAC[17];
fprintf (stderr, "TG %d ", state->lasttg);
fprintf (stderr, "SRC %d ", src);
// if (state->lastsrc == 0) fprintf (stderr, "External ");
state->payload_algid = FMAC[10];
state->payload_keyid = (FMAC[11] << 8) | FMAC[12];
state->payload_miP = (FMAC[1] << 56) | (FMAC[2] << 48) | (FMAC[3] << 40) | (FMAC[4] << 32) |
(FMAC[5] << 24) | (FMAC[6] << 16) | (FMAC[7] << 8) | (FMAC[8] << 0);
if (state->payload_algid != 0x80 && state->payload_algid != 0x0)
{
fprintf (stderr, "%s", KYEL);
fprintf (stderr, "\n ALG ID: 0x%02X", state->payload_algid);
fprintf (stderr, " KEY ID: 0x%04X", state->payload_keyid);
fprintf (stderr, " MI: 0x%016llX", state->payload_miP);
fprintf(stderr, " MPTT");
if (state->R != 0 && state->payload_algid == 0xAA) fprintf (stderr, " Key 0x%010llX", state->R);
if (state->R != 0 && state->payload_algid == 0x81) fprintf (stderr, " Key 0x%016llX", state->R);
if ( (state->payload_algid == 0x84 || state->payload_algid == 0x89) && state->aes_key_loaded[0] == 1)
{
fprintf (stderr, "\n ");
fprintf (stderr, "Key: %016llX %016llX ", state->A1[0], state->A2[0]);
if (state->payload_algid == 0x84)
fprintf (stderr, "%016llX %016llX", state->A3[0], state->A4[0]);
// opts->unmute_encrypted_p25 = 1; //needed?
}
//expand 64-bit MI to 128-bit for AES
if (state->payload_algid == 0x84 || state->payload_algid == 0x89)
{
LFSR128(state);
// fprintf (stderr, "\n");
}
// fprintf (stderr, " %s", KRED);
// fprintf (stderr, "ENC");
}
//reset gain
if (opts->floating_point == 1)
state->aout_gain = opts->audio_gain;
}
if (state->currentslot == 1)
{
//reset fourv_counter and dropbyte on PTT
state->fourv_counter[1] = 0;
state->voice_counter[1] = 0;
state->dropR = 256;
state->dmrburstR = 20;
fprintf (stderr, "\n VCH 1 - ");
//check that src is not zero first, some harris and other patch systems may do this,
//but that also causes an issue in the new event logger if the active channel has a src, but mac_ptt has 0
uint32_t src = (FMAC[13] << 16) | (FMAC[14] << 8) | FMAC[15];
if (src != 0)
state->lastsrcR = (FMAC[13] << 16) | (FMAC[14] << 8) | FMAC[15];
state->lasttgR = (FMAC[16] << 8) | FMAC[17];
fprintf (stderr, "TG %d ", state->lasttgR);
fprintf (stderr, "SRC %d ", src);
// if (state->lastsrcR == 0) fprintf (stderr, "External ");
state->payload_algidR = FMAC[10];
state->payload_keyidR = (FMAC[11] << 8) | FMAC[12];
state->payload_miN = (FMAC[1] << 56) | (FMAC[2] << 48) | (FMAC[3] << 40) | (FMAC[4] << 32) |
(FMAC[5] << 24) | (FMAC[6] << 16) | (FMAC[7] << 8) | (FMAC[8] << 0);
if (state->payload_algidR != 0x80 && state->payload_algidR != 0x0)
{
fprintf (stderr, "%s", KYEL);
fprintf (stderr, "\n ALG ID: 0x%02X", state->payload_algidR);
fprintf (stderr, " KEY ID: 0x%04X", state->payload_keyidR);
fprintf (stderr, " MI: 0x%016llX", state->payload_miN);
fprintf(stderr, " MPTT");
if (state->RR != 0 && state->payload_algidR == 0xAA) fprintf (stderr, " Key 0x%010llX", state->RR);
if (state->RR != 0 && state->payload_algidR == 0x81) fprintf (stderr, " Key 0x%016llX", state->RR);
if ( (state->payload_algidR == 0x84 || state->payload_algidR == 0x89) && state->aes_key_loaded[1] == 1)
{
fprintf (stderr, "\n ");
fprintf (stderr, "Key: %016llX %016llX ", state->A1[1], state->A2[1]);
if (state->payload_algidR == 0x84)
fprintf (stderr, "%016llX %016llX", state->A3[1], state->A4[1]);
// opts->unmute_encrypted_p25 = 1; //needed?
}
//expand 64-bit MI to 128-bit for AES
if (state->payload_algidR == 0x84 || state->payload_algidR == 0x89)
{
LFSR128(state);
// fprintf (stderr, "\n");
}
// fprintf (stderr, " %s", KRED);
// fprintf (stderr, "ENC");
}
//reset gain
if (opts->floating_point == 1)
state->aout_gainR = opts->audio_gain;
}
if (opts->payload == 1)
{
fprintf (stderr, "\n MAC_PTT_PAYLOAD_F OFFSET: %d RES: %d \n ", mac_offset, res);
for (int i = 0; i < 24; i++)
{
if (i == 12) fprintf (stderr, "\n ");
fprintf (stderr, "[%02llX]", FMAC[i]);
}
}
fprintf (stderr, "%s", KNRM);
//reset voice counter at MAC_PTT
if (state->currentslot == 0 && state->payload_algid == 0x81)
state->DMRvcL = 0;
if (state->currentslot == 1 && state->payload_algidR == 0x81)
state->DMRvcR = 0;
//reset voice counter after 2V (AES 256)
if (state->currentslot == 0 && state->payload_algid == 0x84)
state->DMRvcL = 0;
if (state->currentslot == 1 && state->payload_algidR == 0x84)
state->DMRvcR = 0;
//reset voice counter after 2V (AES 128)
if (state->currentslot == 0 && state->payload_algid == 0x89)
state->DMRvcL = 0;
if (state->currentslot == 1 && state->payload_algidR == 0x89)
state->DMRvcR = 0;
}
if (opcode == 0x2 && err == 0)
{
fprintf (stderr, " MAC_END_PTT ");
fprintf (stderr, "%s", KRED);
if (state->currentslot == 0)
{
state->fourv_counter[0] = 0;
state->voice_counter[0] = 0;
state->dropL = 256;
state->dmrburstL = 23;
state->payload_algid = 0; //zero this out as well
state->payload_keyid = 0;
fprintf (stderr, "\n VCH 0 - ");
fprintf (stderr, "TG %d ", state->lasttg);
fprintf (stderr, "SRC %d ", state->lastsrc);
//print it and then zero out
state->lastsrc = 0;
state->lasttg = 0;
//close any open MBEout files
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
//blank the call string here
sprintf (state->call_string[slot], "%s", " "); //21 spaces
//reset gain
if (opts->floating_point == 1)
state->aout_gain = opts->audio_gain; //reset
}
if (state->currentslot == 1)
{
state->fourv_counter[1] = 0;
state->voice_counter[1] = 0;
state->dropR = 256;
state->dmrburstR = 23;
state->payload_algidR = 0; //zero this out as well
state->payload_keyidR = 0;
fprintf (stderr, "\n VCH 1 - ");
fprintf (stderr, "TG %d ", state->lasttgR);
fprintf (stderr, "SRC %d ", state->lastsrcR);
//print it and then zero out
state->lastsrcR = 0;
state->lasttgR = 0;
//close any open MBEout files
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
//reset gain
if (opts->floating_point == 1)
state->aout_gainR = opts->audio_gain;
}
//Return to CC on MAC_END_PTT if other slot is idle
//NOTE: Disable return later on if not desirable to use
//end_ptt in this slot, idle in the other slot (Normal Slots)
if ( ((state->currentslot == 0) && (state->dmrburstR == 24)) ||
((state->currentslot == 1) && (state->dmrburstL == 24)) )
{
if (opts->p25_trunk == 1 && opts->p25_is_tuned == 1)
{
//if P25p2 VCH and going back to P25p1 CC, flip symbolrate
if (state->p25_cc_is_tdma == 0)
{
state->samplesPerSymbol = 10;
state->symbolCenter = 4;
//re-enable both slots
opts->slot1_on = 1;
opts->slot2_on = 1;
}
//rigctl
if (opts->use_rigctl == 1)
{
state->lasttg = 0;
state->lastsrc = 0;
state->lasttgR = 0;
state->lastsrcR = 0;
state->payload_algid = 0;
state->payload_keyid = 0;
state->payload_algidR = 0;
state->payload_keyidR = 0;
// state->payload_miP = 0;
//reset some strings
sprintf (state->call_string[0], "%s", " "); //21 spaces
sprintf (state->call_string[1], "%s", " "); //21 spaces
sprintf (state->active_channel[0], "%s", "");
sprintf (state->active_channel[1], "%s", "");
opts->p25_is_tuned = 0;
state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0;
if (opts->setmod_bw != 0 ) SetModulation(opts->rigctl_sockfd, opts->setmod_bw);
SetFreq(opts->rigctl_sockfd, state->p25_cc_freq);
}
//rtl
else if (opts->audio_in_type == 3)
{
#ifdef USE_RTLSDR
state->lasttg = 0;
state->lastsrc = 0;
state->lasttgR = 0;
state->lastsrcR = 0;
state->payload_algid = 0;
state->payload_keyid = 0;
state->payload_algidR = 0;
state->payload_keyidR = 0;
// state->payload_miP = 0;
//reset some strings
sprintf (state->call_string[0], "%s", " "); //21 spaces
sprintf (state->call_string[1], "%s", " "); //21 spaces
sprintf (state->active_channel[0], "%s", "");
sprintf (state->active_channel[1], "%s", "");
opts->p25_is_tuned = 0;
state->p25_vc_freq[0] = state->p25_vc_freq[1] = 0;
rtl_dev_tune (opts, state->p25_cc_freq);
#endif
}
}
}
fprintf (stderr, "%s", KNRM);
}
if (opcode == 0x3 && err == 0)
{
//what else should we zero out here?
//disable any of the lines below if issues are observed
if (state->currentslot == 0)
{
state->payload_algid = 0;
state->payload_keyid = 0;
state->dmrburstL = 24;
state->fourv_counter[0] = 0;
state->voice_counter[0] = 0;
state->lastsrc = 0;
state->lasttg = 0;
}
else
{
state->payload_algidR = 0;
state->payload_keyidR = 0;
state->dmrburstR = 24;
state->fourv_counter[1] = 0;
state->voice_counter[1] = 0;
state->lastsrcR = 0;
state->lasttgR = 0;
}
fprintf (stderr, " MAC_IDLE ");
fprintf (stderr, "%s", KYEL);
process_MAC_VPDU(opts, state, 0, FMAC);
fprintf (stderr, "%s", KNRM);
// if (opts->p25_trunk == 1 && opts->p25_is_tuned == 1)
// {
// if (state->currentslot == 0)
// {
// opts->slot1_on = 0;
// opts->slot2_on = 1;
// }
// else
// {
// opts->slot1_on = 1;
// opts->slot2_on = 0;
// }
// }
//blank the call string here
sprintf (state->call_string[slot], "%s", " "); //21 spaces
}
if (opcode == 0x4 && err == 0)
{
//disable to prevent blinking in ncurses terminal due to OSS preemption shim
#ifdef __CYGWIN__
if (opts->audio_out_type != 5)
{
if (state->currentslot == 0) state->dmrburstL = 21;
else state->dmrburstR = 21;
}
#else
if (state->currentslot == 0) state->dmrburstL = 21;
else state->dmrburstR = 21;
#endif
fprintf (stderr, " MAC_ACTIVE ");
fprintf (stderr, "%s", KYEL);
process_MAC_VPDU(opts, state, 0, FMAC);
fprintf (stderr, "%s", KNRM);
}
if (opcode == 0x6 && err == 0)
{
if (state->currentslot == 0)
{
state->dmrburstL = 22;
//close any open MBEout files
if (opts->mbe_out_f != NULL) closeMbeOutFile (opts, state);
}
else
{
state->dmrburstR = 22;
//close any open MBEout files
if (opts->mbe_out_fR != NULL) closeMbeOutFileR (opts, state);
}
fprintf (stderr, " MAC_HANGTIME ");
fprintf (stderr, "%s", KYEL);
process_MAC_VPDU(opts, state, 0, FMAC);
fprintf (stderr, "%s", KNRM);
}
END_FMAC:
if (1 == 2)
{
//CRC Failure!
}
}