diff --git a/dmr/packet/Voice.cpp b/dmr/packet/Voice.cpp index ec50d32f..c7b78014 100644 --- a/dmr/packet/Voice.cpp +++ b/dmr/packet/Voice.cpp @@ -262,7 +262,7 @@ bool Voice::process(uint8_t* data, uint32_t len) if (m_slot->m_rfState == RS_RF_AUDIO) { m_lastRfN = 0U; - // Convert the Audio Sync to be from the BS or MS as needed + // convert the Audio Sync to be from the BS or MS as needed Sync::addDMRAudioSync(data + 2U, m_slot->m_duplex); uint32_t errors = 0U; @@ -335,14 +335,14 @@ bool Voice::process(uint8_t* data, uint32_t len) } if (errors > m_slot->m_silenceThreshold) { - // Get the LCSS from the EMB + // get the LCSS from the EMB data::EMB emb; emb.decode(data + 2U); insertNullAudio(data + 2U); m_fec.regenerateDMR(data + 2U); - // Regenerate EMB + // regenerate EMB emb.encode(data + 2U); LogWarning(LOG_RF, DMR_DT_VOICE ", exceeded lost audio threshold, filling in"); @@ -357,12 +357,12 @@ bool Voice::process(uint8_t* data, uint32_t len) m_slot->m_rfTGHang.start(); m_slot->m_rfLastDstId = m_slot->m_rfLC->getDstId(); - // Get the LCSS from the EMB + // get the LCSS from the EMB data::EMB emb; emb.decode(data + 2U); uint8_t lcss = emb.getLCSS(); - // Dump any interesting Embedded Data + // dump any interesting Embedded Data bool ret = m_rfEmbeddedData[m_rfEmbeddedWriteN].addData(data + 2U, lcss); if (ret) { uint8_t flco = m_rfEmbeddedData[m_rfEmbeddedWriteN].getFLCO(); @@ -566,10 +566,10 @@ bool Voice::process(uint8_t* data, uint32_t len) return false; m_lastRfN = m_rfN; - // Regenerate the EMB + // regenerate the EMB emb.encode(data + 2U); - // Send the original audio frame out + // send the original audio frame out uint32_t errors = 0U; uint8_t fid = m_slot->m_rfLC->getFID(); if (fid == FID_ETSI || fid == FID_DMRA) { @@ -580,14 +580,14 @@ bool Voice::process(uint8_t* data, uint32_t len) } if (errors > m_slot->m_silenceThreshold) { - // Get the LCSS from the EMB + // get the LCSS from the EMB data::EMB emb; emb.decode(data + 2U); insertNullAudio(data + 2U); m_fec.regenerateDMR(data + 2U); - // Regenerate EMB + // regenerate EMB emb.encode(data + 2U); LogWarning(LOG_RF, DMR_DT_VOICE ", exceeded lost audio threshold, filling in"); @@ -1259,7 +1259,7 @@ void Voice::insertSilence(uint32_t count) emb.setColorCode(m_slot->m_colorCode); for (uint32_t i = 0U; i < count; i++) { - // Only use our silence frame if its AMBE audio data + // only use our silence frame if its AMBE audio data if (fid == FID_ETSI || fid == FID_DMRA) { if (i > 0U) { ::memcpy(data, DMR_SILENCE_DATA, DMR_FRAME_LENGTH_BYTES + 2U); diff --git a/p25/P25Defines.h b/p25/P25Defines.h index 0f2bfcec..b341d814 100644 --- a/p25/P25Defines.h +++ b/p25/P25Defines.h @@ -274,7 +274,7 @@ namespace p25 const uint8_t LC_GROUP_UPDT = 0x02U; // GRP VCH UPDT - Group Voice Channel Update const uint8_t LC_PRIVATE = 0x03U; // UU VCH USER - Unit-to-Unit Voice Channel User const uint8_t LC_UU_ANS_REQ = 0x05U; // UU ANS REQ - Unit to Unit Answer Request - const uint8_t LC_TEL_INT_VCH_USER = 0x06U; // TEL INT VCH USER - Telephone Interconnect Voice Channel User + const uint8_t LC_TEL_INT_VCH_USER = 0x06U; // TEL INT VCH USER - Telephone Interconnect Voice Channel User / MOT GPS DATA - Motorola In-Band GPS Data const uint8_t LC_TEL_INT_ANS_RQST = 0x07U; // TEL INT ANS RQST - Telephone Interconnect Answer Request const uint8_t LC_CALL_TERM = 0x0FU; // CALL TERM - Call Termination or Cancellation const uint8_t LC_IDEN_UP = 0x18U; // IDEN UP - Channel Identifier Update diff --git a/p25/lc/LC.cpp b/p25/lc/LC.cpp index 8e91a180..31315154 100644 --- a/p25/lc/LC.cpp +++ b/p25/lc/LC.cpp @@ -12,7 +12,7 @@ // /* * Copyright (C) 2016,2017 by Jonathan Naylor G4KLX -* Copyright (C) 2017-2022 by Bryan Biedenkapp N2PLL +* Copyright (C) 2017-2023 by Bryan Biedenkapp N2PLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -76,6 +76,7 @@ LC::LC() : m_encryptOverride(false), m_tsbkVendorSkip(false), m_callTimer(0U), + m_rsValue(0U), m_mi(nullptr) { m_mi = new uint8_t[P25_MI_LENGTH_BYTES]; @@ -519,6 +520,8 @@ void LC::copy(const LC& data) m_callTimer = data.m_callTimer; + m_rsValue = data.m_rsValue; + m_algId = data.m_algId; if (m_algId != P25_ALGO_UNENCRYPT) { delete[] m_mi; @@ -569,6 +572,24 @@ bool LC::decodeLC(const uint8_t * rs) m_protect = (rs[0U] & 0x80U) == 0x80U; // Protect Flag m_lco = rs[0U] & 0x3FU; // LCO + + m_mfId = rs[1U]; // Mfg Id. + + // Motorola P25 vendor opcodes (these are just detected for passthru) + if (m_mfId == P25_MFG_MOT) { + switch (m_lco) { + case LC_TEL_INT_VCH_USER: // MOT GPS DATA + m_rsValue = rsValue; + break; + default: + LogError(LOG_P25, "LC::decodeLC(), unknown LC value, mfId = $%02X, lco = $%02X", m_mfId, m_lco); + break; + } + + if (m_mfId == P25_MFG_MOT) { + return true; + } + } // standard P25 reference opcodes switch (m_lco) { @@ -680,6 +701,20 @@ void LC::encodeLC(uint8_t * rs) break; } + // Motorola P25 vendor opcodes (these are just detected for passthru) + if (m_mfId == P25_MFG_MOT) { + rsValue = 0U; + + switch (m_lco) { + case LC_TEL_INT_VCH_USER: // MOT GPS DATA + rsValue = m_rsValue; + break; + default: + LogError(LOG_P25, "LC::encodeLC(), unknown LC value, mfId = $%02X, lco = $%02X", m_mfId, m_lco); + break; + } + } + // split ulong64_t (8 byte) value into bytes rs[1U] = (uint8_t)((rsValue >> 56) & 0xFFU); rs[2U] = (uint8_t)((rsValue >> 48) & 0xFFU); diff --git a/p25/lc/LC.h b/p25/lc/LC.h index 5cfce141..da02be0f 100644 --- a/p25/lc/LC.h +++ b/p25/lc/LC.h @@ -12,7 +12,7 @@ // /* * Copyright (C) 2016 by Jonathan Naylor G4KLX -* Copyright (C) 2017-2022 by Bryan Biedenkapp N2PLL +* Copyright (C) 2017-2023 by Bryan Biedenkapp N2PLL * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -136,6 +136,8 @@ namespace p25 uint32_t m_callTimer; + ulong64_t m_rsValue; // used for certain transparent passthru LCOs + /** Encryption data */ uint8_t* m_mi; diff --git a/p25/packet/Voice.cpp b/p25/packet/Voice.cpp index 8d3e4e71..490feee9 100644 --- a/p25/packet/Voice.cpp +++ b/p25/packet/Voice.cpp @@ -501,19 +501,19 @@ bool Voice::process(uint8_t* data, uint32_t len) } } - // Generate Sync + // generate Sync Sync::addP25Sync(data + 2U); - // Generate NID + // generate NID m_p25->m_nid.encode(data + 2U, P25_DUID_LDU1); - // Generate LDU1 Data + // generate LDU1 Data m_rfLC.encodeLDU1(data + 2U); - // Generate Low Speed Data + // generate Low Speed Data m_rfLSD.process(data + 2U); - // Regenerate Audio + // regenerate audio uint32_t errors = m_audio.process(data + 2U); // replace audio with silence in cases where the error rate @@ -527,7 +527,7 @@ bool Voice::process(uint8_t* data, uint32_t len) LogWarning(LOG_RF, P25_LDU1_STR ", exceeded lost audio threshold, filling in"); - // Add the Audio + // add the audio m_audio.encode(data + 2U, buffer + 10U, 0U); m_audio.encode(data + 2U, buffer + 26U, 1U); m_audio.encode(data + 2U, buffer + 55U, 2U); @@ -537,13 +537,22 @@ bool Voice::process(uint8_t* data, uint32_t len) m_audio.encode(data + 2U, buffer + 155U, 6U); m_audio.encode(data + 2U, buffer + 180U, 7U); m_audio.encode(data + 2U, buffer + 204U, 8U); + + // reset the encryption flags if necessary + if (m_rfLC.getEncrypted()) { + m_rfLC.setEncrypted(false); + m_rfLC.setAlgId(P25_ALGO_UNENCRYPT); + + // regenerate LDU1 data + m_rfLC.encodeLDU1(data + 2U); + } } m_rfBits += 1233U; m_rfErrs += errors; m_rfFrames++; - // Add busy bits + // add busy bits P25Utils::addBusyBits(data + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true); writeNetwork(data + 2U, P25_DUID_LDU1); @@ -580,19 +589,19 @@ bool Voice::process(uint8_t* data, uint32_t len) m_rfLastLDU2 = m_rfLC; } - // Generate Sync + // generate Sync Sync::addP25Sync(data + 2U); - // Generate NID + // generate NID m_p25->m_nid.encode(data + 2U, P25_DUID_LDU2); - // Generate LDU2 data + // generate LDU2 data m_rfLC.encodeLDU2(data + 2U); - // Generate Low Speed Data + // generate Low Speed Data m_rfLSD.process(data + 2U); - // Regenerate Audio + // regenerate audio uint32_t errors = m_audio.process(data + 2U); // replace audio with silence in cases where the error rate @@ -606,7 +615,7 @@ bool Voice::process(uint8_t* data, uint32_t len) LogWarning(LOG_RF, P25_LDU2_STR ", exceeded lost audio threshold, filling in"); - // Add the Audio + // add the Audio m_audio.encode(data + 2U, buffer + 10U, 0U); m_audio.encode(data + 2U, buffer + 26U, 1U); m_audio.encode(data + 2U, buffer + 55U, 2U); @@ -616,13 +625,22 @@ bool Voice::process(uint8_t* data, uint32_t len) m_audio.encode(data + 2U, buffer + 155U, 6U); m_audio.encode(data + 2U, buffer + 180U, 7U); m_audio.encode(data + 2U, buffer + 204U, 8U); + + // reset the encryption flags if necessary + if (m_rfLC.getEncrypted()) { + m_rfLC.setEncrypted(false); + m_rfLC.setAlgId(P25_ALGO_UNENCRYPT); + + // regenerate LDU2 data + m_rfLC.encodeLDU2(data + 2U); + } } m_rfBits += 1233U; m_rfErrs += errors; m_rfFrames++; - // Add busy bits + // add busy bits P25Utils::addBusyBits(data + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true); writeNetwork(data + 2U, P25_DUID_LDU2);