diff --git a/src/dsd_ncurses.c b/src/dsd_ncurses.c index e680f2f..5ba4ee3 100644 --- a/src/dsd_ncurses.c +++ b/src/dsd_ncurses.c @@ -2263,8 +2263,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) printw ("\n"); printw ("| "); - printw ("TGT: [%05d] ", tgn); - printw ("SRC: [%05d] ", src); + printw ("TGT: [%5d] ", tgn); + printw ("SRC: [%5d] ", src); if (state->nxdn_alias_block_segment[0][0] > 0) { printw ("ALIAS: ["); @@ -2302,6 +2302,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) } if (state->nxdn_cipher_type == 0x2 && state->carrier == 1) { + attron(COLOR_PAIR(1)); printw ("IV: [%016llX] ", state->payload_miN); attron(COLOR_PAIR(2)); printw ("DES-OFB "); @@ -2310,6 +2311,7 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) } if (state->nxdn_cipher_type == 0x3 && state->carrier == 1) { + attron(COLOR_PAIR(1)); printw ("IV: [%016llX] ", state->payload_miN); attron(COLOR_PAIR(2)); printw ("AES-256 "); @@ -2908,8 +2910,8 @@ ncursesPrinter (dsd_opts * opts, dsd_state * state) if (lls == 28 || lls == 29) { printw ("RAN [%02lld] ", call_matrix[9-j][1]); - printw ("TG [%05lld] ", call_matrix[9-j][4]); - printw ("RID [%05lld] ", call_matrix[9-j][2]); + printw ("TG [%5lld] ", call_matrix[9-j][4]); + printw ("RID [%5lld] ", call_matrix[9-j][2]); } //dPMR if (lls == 20 || lls == 21 || lls == 22 || lls == 23 ||lls == 24 || lls == 25 || lls == 26 || lls == 27) diff --git a/src/nxdn_deperm.c b/src/nxdn_deperm.c index 8b4f104..72bed0b 100644 --- a/src/nxdn_deperm.c +++ b/src/nxdn_deperm.c @@ -42,7 +42,8 @@ static const int PARITY[] = { //decoding functions here void nxdn_descramble(uint8_t dibits[], int len) { - for (int i=0; i= len) break; dibits[scramble_t[i]] ^= 0x2; // invert sign of scrambled dibits @@ -119,7 +120,7 @@ void nxdn_deperm_facch(dsd_opts * opts, dsd_state * state, uint8_t bits[144]) } if (crc == check) NXDN_Elements_Content_decode(opts, state, 1, trellis_buf); - // else if (opts->payload == 1) NXDN_Elements_Content_decode(opts, state, 0, trellis_buf); + else if (opts->aggressive_framesync == 0) NXDN_Elements_Content_decode(opts, state, 0, trellis_buf); if (opts->payload == 1) { @@ -137,10 +138,16 @@ void nxdn_deperm_facch(dsd_opts * opts, dsd_state * state, uint8_t bits[144]) //new sacch void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60]) { - uint8_t deperm[60]; - uint8_t depunc[72]; - uint8_t trellis_buf[32]; - uint8_t answer[26]; + //see about initializing these variables + uint8_t deperm[60]; + uint8_t depunc[72]; + uint8_t trellis_buf[32]; + uint8_t answer[26]; + + memset (deperm, 0, sizeof(deperm)); + memset (depunc, 0, sizeof(depunc)); + memset (trellis_buf, 0, sizeof(trellis_buf)); + memset (answer, 0, sizeof(answer)); int o = 0; uint8_t crc = 0; //value computed by crc6 on payload uint8_t check = 0; //value pulled from last 6 bits @@ -186,7 +193,7 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60]) } CNXDNConvolution_start(); - for (int i = 0U; i < 40U; i++) + for (int i = 0U; i < 36U; i++) //40 { s0 = temp[(2*i)]; s1 = temp[(2*i)+1]; @@ -195,7 +202,7 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60]) } //stored as 5 bytes, will need to convert to trellis_buf after running - CNXDNConvolution_chainback(m_data, 36U); + CNXDNConvolution_chainback(m_data, 32U); //36 for(int i = 0; i < 4; i++) { @@ -230,6 +237,7 @@ void nxdn_deperm_sacch(dsd_opts * opts, dsd_state * state, uint8_t bits[60]) } if (crc == check) NXDN_Elements_Content_decode(opts, state, 1, nsf_sacch); + else if (opts->aggressive_framesync == 0) NXDN_Elements_Content_decode(opts, state, 0, nsf_sacch); if (opts->payload == 1) { @@ -398,6 +406,7 @@ void nxdn_deperm_facch2_udch(dsd_opts * opts, dsd_state * state, uint8_t bits[34 //NXDN_Elements_Content_decode(opts, state, 1, trellis_buf); NXDN_Elements_Content_decode(opts, state, 1, f2u_message_buffer); } + else if (opts->aggressive_framesync == 0) NXDN_Elements_Content_decode(opts, state, 0, f2u_message_buffer); if (opts->payload == 1) { @@ -495,6 +504,7 @@ void nxdn_deperm_cac(dsd_opts * opts, dsd_state * state, uint8_t bits[300]) fprintf (stderr, " CAC "); NXDN_Elements_Content_decode(opts, state, 1, cac_message_buffer); } + else if (opts->aggressive_framesync == 0) NXDN_Elements_Content_decode(opts, state, 0, cac_message_buffer); if (opts->payload == 1) { @@ -518,7 +528,7 @@ void nxdn_message_type (dsd_opts * opts, dsd_state * state, uint8_t MessageType) if (MessageType == 0x10) fprintf(stderr, " IDLE"); else if (MessageType == 0x11) fprintf(stderr, " DISC"); //disconnect else if (MessageType == 0x01) fprintf(stderr, " VCALL"); - else if (MessageType == 0x03) fprintf(stderr, " VCALL IV"); + else if (MessageType == 0x03) fprintf(stderr, " VCALL_IV"); else if (MessageType == 0x07) fprintf(stderr, " TX_REL_EX"); else if (MessageType == 0x08) fprintf(stderr, " TX_REL"); @@ -545,9 +555,8 @@ void nxdn_message_type (dsd_opts * opts, dsd_state * state, uint8_t MessageType) else fprintf(stderr, " Unknown M-%02X", MessageType); fprintf (stderr, "%s", KNRM); - //zero out stale values so they won't persist after a transmit release - //disable if random messages wipe out the alias - if (MessageType == 0x08 || MessageType == 0x10) //idle, tx_rel + //zero out stale values so they won't persist after a transmit release, idle, or disconnect + if (MessageType == 0x08 || MessageType == 0x10 || MessageType == 0x11) //tx_rel, idle, or disc { memset (state->nxdn_alias_block_segment, 0, sizeof(state->nxdn_alias_block_segment)); state->nxdn_last_rid = 0; diff --git a/src/nxdn_element.c b/src/nxdn_element.c index 53a1efc..c95f121 100644 --- a/src/nxdn_element.c +++ b/src/nxdn_element.c @@ -18,7 +18,7 @@ void NXDN_SACCH_Full_decode(dsd_opts * opts, dsd_state * state) uint32_t i; uint8_t CrcCorrect = 1; - /* Consider all SACCH CRC parts as corrects */ + /* Consider all SACCH CRC parts as correct */ CrcCorrect = 1; /* Reconstitute the full 72 bits SACCH */ @@ -33,6 +33,7 @@ void NXDN_SACCH_Full_decode(dsd_opts * opts, dsd_state * state) /* Decodes the element content */ // currently only going to run this if all four CRCs are good if (CrcCorrect == 1) NXDN_Elements_Content_decode(opts, state, CrcCorrect, SACCH); + else if (opts->aggressive_framesync == 0) NXDN_Elements_Content_decode(opts, state, 0, SACCH); } /* End NXDN_SACCH_Full_decode() */ @@ -272,13 +273,9 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa if (opts->p25_trunk == 1 && state->p25_cc_freq == 0) { long int ccfreq = 0; - if (state->trunk_chan_map[0] != 0) state->p25_cc_freq = state->trunk_chan_map[0]; - //we are assuming that the current channel is the control channel - //unsure whether or not control signalling is available on NXDN voice channels - - //if not available from the import file, then poll rigctl if its available - else if (opts->use_rigctl == 1) + //if not available, then poll rigctl if its available + if (opts->use_rigctl == 1) { ccfreq = GetCurrentFreq (opts->rigctl_sockfd); if (ccfreq != 0) state->p25_cc_freq = ccfreq; @@ -291,6 +288,7 @@ void NXDN_decode_VCALL_ASSGN(dsd_opts * opts, dsd_state * state, uint8_t * Messa } } + //run group/source analysis and tune if available/desired //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 @@ -459,31 +457,9 @@ void NXDN_decode_cch_info(dsd_opts * opts, dsd_state * state, uint8_t * Message) freq1 = nxdn_channel_to_frequency (opts, state, channel1); freq2 = nxdn_channel_to_frequency (opts, state, channel2); - //add handling for adding (or deleting?) frequencies to CC list - if (channel1sts & 0x20 || channel1sts & 0x8) //current or new only - { - if (freq1 != 0) state->p25_cc_freq = freq1; - //let's assume the frequency we are tuned to is the current control channel - else if (opts->use_rigctl == 1 && state->p25_cc_freq == 0) //if not set from channel map 0 or nxdn_channel_to_frequency and rigctl is available - { - freq1 = GetCurrentFreq (opts->rigctl_sockfd); - if (freq1 != 0) state->p25_cc_freq = freq1; - } - } - else if (channel1sts & 0x8) //Candidate Added - { - if (freq1 != 0) - { - //add to trunk_lcn_freq list? - for (int i = 0; i <= state->lcn_freq_count; i++) //<= pretty sure is correct here since we need to go through atleast one rep - { - if (freq1 == state->trunk_lcn_freq[i]) goto SKIP; - } - //assign if freq1 not found in array - state->trunk_lcn_freq[state->lcn_freq_count] = freq1; - state->lcn_freq_count++; - } - } + //removed code below, may have been causing issues with current CC frequency assignment + //removed code is unneccesary for trunking purposes + //if a delete, let's not bother trying to remove it from the list for now SKIP: ; //do nothing @@ -507,6 +483,25 @@ void NXDN_decode_srv_info(dsd_opts * opts, dsd_state * state, uint8_t * Message) nxdn_location_id_handler (state, location_id); fprintf (stderr, "%s", KNRM); + //poll for current frequency, will always be the control channel + //this PDU is constantly pumped out on the CC CAC Message + if (opts->p25_trunk == 1) + { + long int ccfreq = 0; + //if using rigctl, we can poll for the current frequency + if (opts->use_rigctl == 1) + { + ccfreq = GetCurrentFreq (opts->rigctl_sockfd); + if (ccfreq != 0) state->p25_cc_freq = ccfreq; + } + //if using rtl input, we can ask for the current frequency tuned + else if (opts->audio_in_type == 3) + { + ccfreq = (long int)opts->rtlsdr_center_freq; + if (ccfreq != 0) state->p25_cc_freq = ccfreq; + } + } + } //externalize the location handler to its own function @@ -596,31 +591,9 @@ void NXDN_decode_site_info(dsd_opts * opts, dsd_state * state, uint8_t * Message fprintf (stderr, "%s", KNRM); - //place the freqs into the array for hunting CC or - //rotating CCs without user LCN list - if (freq1 != 0) - { - for (int i = 0; i <= state->lcn_freq_count; i++) //<= pretty sure is correct here since we need to go through atleast one rep - { - if (freq1 == state->trunk_lcn_freq[i]) goto SKIP; - } - //assign if freq1 not found in array - state->trunk_lcn_freq[state->lcn_freq_count] = freq1; - state->lcn_freq_count++; - //shim here for main CC freq? - state->p25_cc_freq = freq1; - } + //removed code below, may have been causing issues with current CC frequency assignment + //removed code is unneccesary for trunking purposes - if (freq2 != 0) - { - for (int i = 0; i <= state->lcn_freq_count; i++) //<= pretty sure is correct here since we need to go through atleast one rep - { - if (freq2 == state->trunk_lcn_freq[i]) goto SKIP; - } - //assign if freq2 not found in array - state->trunk_lcn_freq[state->lcn_freq_count] = freq2; - state->lcn_freq_count++; - } SKIP: ; //do nothing @@ -703,11 +676,19 @@ void NXDN_decode_VCALL(dsd_opts * opts, dsd_state * state, uint8_t * Message) if (state->rkey_array[KeyID] != 0) state->R = state->rkey_array[KeyID]; else if (state->rkey_array[DestinationID] != 0) state->R = state->rkey_array[DestinationID]; - if (state->M == 1) - { - state->nxdn_cipher_type = 0x1; - CipherType = 0x1; - } + //consider removing code below, if we get this far (under good crc), + //then we will always have a correct cipher type and won't need to + //force it, its only needed on the vcall_assgn where no cipher is set + //dsd_mbe can also force the scrambler without triggering the settings here + + // if (state->M == 1) + // { + // state->nxdn_cipher_type = 0x1; + // CipherType = 0x1; + // } + + //debug + // if (CipherType > 0x1) state->R = 0; //don't use on manual key entry /* Print the "Cipher Type" */ if(CipherType != 0) diff --git a/src/nxdn_frame.c b/src/nxdn_frame.c index 157550a..8aeed50 100644 --- a/src/nxdn_frame.c +++ b/src/nxdn_frame.c @@ -45,40 +45,48 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state) int sr_structure; int sr_ran; - uint8_t lich_dibits[8] = {0}; - uint8_t sacch_bits[60] = {0}; - uint8_t facch_bits_a[144] = {0}; - uint8_t facch_bits_b[144] = {0}; - uint8_t cac_bits[300] = {0}; - uint8_t facch2_bits[348] = {0}; //facch2 or udch, same amount of bits + uint8_t lich_dibits[8]; + uint8_t sacch_bits[60]; + uint8_t facch_bits_a[144]; + uint8_t facch_bits_b[144]; + uint8_t cac_bits[300]; + uint8_t facch2_bits[348]; //facch2 or udch, same amount of bits //nxdn bit buffer, for easy assignment handling - int nxdn_bit_buffer[364] = {0}; - int nxdn_dibit_buffer[182] = {0}; + int nxdn_bit_buffer[364]; + int nxdn_dibit_buffer[182]; + //init all arrays memset (dbuf, 0, sizeof(dbuf)); + memset (answer, 0, sizeof(answer)); + memset (sacch_answer, 0, sizeof(sacch_answer)); + memset (lich_dibits, 0, sizeof(lich_dibits)); + memset (sacch_bits, 0, sizeof(sacch_bits)); + memset (facch_bits_b, 0, sizeof(facch_bits_b)); + memset (facch_bits_a, 0, sizeof(facch_bits_a)); + memset (cac_bits, 0, sizeof(cac_bits)); + memset (facch2_bits, 0, sizeof(facch2_bits)); + + memset (nxdn_bit_buffer, 0, sizeof(nxdn_bit_buffer)); + memset (nxdn_dibit_buffer, 0, sizeof(nxdn_dibit_buffer)); //collect lich bits first, if they are good, then we can collect the rest of them - for (int i = 0; i < 8; i++) - { - lich_dibits[i] = dbuf[i] = getDibit(opts, state); - } + for (int i = 0; i < 8; i++) lich_dibits[i] = dbuf[i] = getDibit(opts, state); nxdn_descramble (lich_dibits, 8); lich = 0; - for (int i=0; i<8; i++) - { - lich |= (lich_dibits[i] >> 1) << (7-i); - } + for (int i=0; i<8; i++) lich |= (lich_dibits[i] >> 1) << (7-i); lich_parity_received = lich & 1; lich_parity_computed = ((lich >> 7) + (lich >> 6) + (lich >> 5) + (lich >> 4)) & 1; lich = lich >> 1; if (lich_parity_received != lich_parity_computed) { - //fprintf(stderr, "NXDN lich parity error, ignoring frame \n"); - return; + // fprintf(stderr, "NXDN lich parity error, ignoring frame \n"); //debug + // state->lastsynctype = -1; //set to -1 so we don't jump back here too quickly + goto END; + // return; } voice = 0; @@ -92,6 +100,7 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state) if (lich % 2 == 0 && opts->p25_trunk == 1) { if (opts->payload == 1) fprintf(stderr, " Simplex/Inbound NXDN lich on trunking system - type 0x%02X\n", lich); + // state->lastsynctype = -1; //set to -1 so we don't jump back here too quickly goto END; } @@ -225,12 +234,18 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state) //vch frames stay inside dbuf, easier to assign that to ambe_fr frames //sacch needs extra handling depending on superframe or non-superframe variety - if (voice) + if (voice && !facch) //voice only, no facch steal { fprintf (stderr, "%s", KGRN); fprintf (stderr, " Voice "); fprintf (stderr, "%s", KNRM); } + else if (voice && facch) //voice with facch steal + { + fprintf (stderr, "%s", KGRN); + fprintf (stderr, " V%d+F%d ", 3 - facch, facch); //print which position on each + fprintf (stderr, "%s", KNRM); + } else { fprintf (stderr, "%s", KCYN); @@ -238,7 +253,7 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state) fprintf (stderr, "%s", KNRM); //roll the voice scrambler LFSR here if key available to advance seed (usually just needed on NXDN96) - if (state->nxdn_cipher_type == 0x1 && state->R != 0) //!voice, or voice == 0 + if (state->nxdn_cipher_type == 0x1 && state->R != 0) { char ambe_temp[49] = {0}; char ambe_d[49] = {0}; @@ -248,16 +263,38 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state) } } - } + } + + if (voice && facch == 1) //facch steal 1 -- before voice + { + //force scrambler here, but with unspecified key (just use what's loaded) + if (state->M == 1 && state->R != 0) state->nxdn_cipher_type = 0x1; + //roll the voice scrambler LFSR here if key available to advance seed -- half rotation on a facch steal + if (state->nxdn_cipher_type == 0x1 && state->R != 0) + { + char ambe_temp[49] = {0}; + char ambe_d[49] = {0}; + for (int i = 0; i < 2; i++) + { + LFSRN(ambe_temp, ambe_d, state); + } + } + } if (lich == 0x20 || lich == 0x21 || lich == 0x61 || lich == 0x40 || lich == 0x41) state->nxdn_sacch_non_superframe = TRUE; else state->nxdn_sacch_non_superframe = FALSE; - if (sacch)nxdn_deperm_sacch(opts, state, sacch_bits); - if (cac) nxdn_deperm_cac(opts, state, cac_bits); + if (sacch) nxdn_deperm_sacch(opts, state, sacch_bits); + if (cac) nxdn_deperm_cac(opts, state, cac_bits); if (facch2) nxdn_deperm_facch2_udch(opts, state, facch2_bits); - if (facch & 1) nxdn_deperm_facch(opts, state, facch_bits_a); - if (facch & 2) nxdn_deperm_facch(opts, state, facch_bits_b); + + //testing purposes -- don't run facch steals on enc -- causing issues with key loader (VCALL_ASSGN_DUP) + if (state->nxdn_cipher_type == 0 || state->R == 0) //!voice + { + if (facch & 1) nxdn_deperm_facch(opts, state, facch_bits_a); + if (facch & 2) nxdn_deperm_facch(opts, state, facch_bits_b); + } + if (voice) { //restore MBE file open here @@ -281,7 +318,22 @@ void nxdn_frame (dsd_opts * opts, dsd_state * state) } if (opts->frame_nxdn48 == 1) closeMbeOutFile (opts, state); //okay to close right away if nxdn48, no data/voice mixing } - } + } + + if (voice && facch == 2) //facch steal 2 -- after voice + { + //roll the voice scrambler LFSR here if key available to advance seed -- half rotation on a facch steal + if (state->nxdn_cipher_type == 0x1 && state->R != 0) + { + char ambe_temp[49] = {0}; + char ambe_d[49] = {0}; + for (int i = 0; i < 2; i++) + { + LFSRN(ambe_temp, ambe_d, state); + } + } + } + fprintf (stderr, "\n"); END: ; //do nothing