implement encryption flag reset when silence thresholds are met and silence frames are inserted; implement passthru support for some LDU LC LCOs [credit @ilyacodes for LCO discovery];

3.0-rcon_maint
Bryan Biedenkapp 3 years ago
parent dc95e7fd3e
commit 04736490a9

@ -262,7 +262,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
if (m_slot->m_rfState == RS_RF_AUDIO) { if (m_slot->m_rfState == RS_RF_AUDIO) {
m_lastRfN = 0U; 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); Sync::addDMRAudioSync(data + 2U, m_slot->m_duplex);
uint32_t errors = 0U; uint32_t errors = 0U;
@ -335,14 +335,14 @@ bool Voice::process(uint8_t* data, uint32_t len)
} }
if (errors > m_slot->m_silenceThreshold) { if (errors > m_slot->m_silenceThreshold) {
// Get the LCSS from the EMB // get the LCSS from the EMB
data::EMB emb; data::EMB emb;
emb.decode(data + 2U); emb.decode(data + 2U);
insertNullAudio(data + 2U); insertNullAudio(data + 2U);
m_fec.regenerateDMR(data + 2U); m_fec.regenerateDMR(data + 2U);
// Regenerate EMB // regenerate EMB
emb.encode(data + 2U); emb.encode(data + 2U);
LogWarning(LOG_RF, DMR_DT_VOICE ", exceeded lost audio threshold, filling in"); 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_rfTGHang.start();
m_slot->m_rfLastDstId = m_slot->m_rfLC->getDstId(); m_slot->m_rfLastDstId = m_slot->m_rfLC->getDstId();
// Get the LCSS from the EMB // get the LCSS from the EMB
data::EMB emb; data::EMB emb;
emb.decode(data + 2U); emb.decode(data + 2U);
uint8_t lcss = emb.getLCSS(); 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); bool ret = m_rfEmbeddedData[m_rfEmbeddedWriteN].addData(data + 2U, lcss);
if (ret) { if (ret) {
uint8_t flco = m_rfEmbeddedData[m_rfEmbeddedWriteN].getFLCO(); uint8_t flco = m_rfEmbeddedData[m_rfEmbeddedWriteN].getFLCO();
@ -566,10 +566,10 @@ bool Voice::process(uint8_t* data, uint32_t len)
return false; return false;
m_lastRfN = m_rfN; m_lastRfN = m_rfN;
// Regenerate the EMB // regenerate the EMB
emb.encode(data + 2U); emb.encode(data + 2U);
// Send the original audio frame out // send the original audio frame out
uint32_t errors = 0U; uint32_t errors = 0U;
uint8_t fid = m_slot->m_rfLC->getFID(); uint8_t fid = m_slot->m_rfLC->getFID();
if (fid == FID_ETSI || fid == FID_DMRA) { 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) { if (errors > m_slot->m_silenceThreshold) {
// Get the LCSS from the EMB // get the LCSS from the EMB
data::EMB emb; data::EMB emb;
emb.decode(data + 2U); emb.decode(data + 2U);
insertNullAudio(data + 2U); insertNullAudio(data + 2U);
m_fec.regenerateDMR(data + 2U); m_fec.regenerateDMR(data + 2U);
// Regenerate EMB // regenerate EMB
emb.encode(data + 2U); emb.encode(data + 2U);
LogWarning(LOG_RF, DMR_DT_VOICE ", exceeded lost audio threshold, filling in"); 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); emb.setColorCode(m_slot->m_colorCode);
for (uint32_t i = 0U; i < count; i++) { 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 (fid == FID_ETSI || fid == FID_DMRA) {
if (i > 0U) { if (i > 0U) {
::memcpy(data, DMR_SILENCE_DATA, DMR_FRAME_LENGTH_BYTES + 2U); ::memcpy(data, DMR_SILENCE_DATA, DMR_FRAME_LENGTH_BYTES + 2U);

@ -274,7 +274,7 @@ namespace p25
const uint8_t LC_GROUP_UPDT = 0x02U; // GRP VCH UPDT - Group Voice Channel Update 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_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_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_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_CALL_TERM = 0x0FU; // CALL TERM - Call Termination or Cancellation
const uint8_t LC_IDEN_UP = 0x18U; // IDEN UP - Channel Identifier Update const uint8_t LC_IDEN_UP = 0x18U; // IDEN UP - Channel Identifier Update

@ -12,7 +12,7 @@
// //
/* /*
* Copyright (C) 2016,2017 by Jonathan Naylor G4KLX * 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 * 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 * it under the terms of the GNU General Public License as published by
@ -76,6 +76,7 @@ LC::LC() :
m_encryptOverride(false), m_encryptOverride(false),
m_tsbkVendorSkip(false), m_tsbkVendorSkip(false),
m_callTimer(0U), m_callTimer(0U),
m_rsValue(0U),
m_mi(nullptr) m_mi(nullptr)
{ {
m_mi = new uint8_t[P25_MI_LENGTH_BYTES]; 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_callTimer = data.m_callTimer;
m_rsValue = data.m_rsValue;
m_algId = data.m_algId; m_algId = data.m_algId;
if (m_algId != P25_ALGO_UNENCRYPT) { if (m_algId != P25_ALGO_UNENCRYPT) {
delete[] m_mi; delete[] m_mi;
@ -569,6 +572,24 @@ bool LC::decodeLC(const uint8_t * rs)
m_protect = (rs[0U] & 0x80U) == 0x80U; // Protect Flag m_protect = (rs[0U] & 0x80U) == 0x80U; // Protect Flag
m_lco = rs[0U] & 0x3FU; // LCO 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 // standard P25 reference opcodes
switch (m_lco) { switch (m_lco) {
@ -680,6 +701,20 @@ void LC::encodeLC(uint8_t * rs)
break; 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 // split ulong64_t (8 byte) value into bytes
rs[1U] = (uint8_t)((rsValue >> 56) & 0xFFU); rs[1U] = (uint8_t)((rsValue >> 56) & 0xFFU);
rs[2U] = (uint8_t)((rsValue >> 48) & 0xFFU); rs[2U] = (uint8_t)((rsValue >> 48) & 0xFFU);

@ -12,7 +12,7 @@
// //
/* /*
* Copyright (C) 2016 by Jonathan Naylor G4KLX * 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 * 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 * it under the terms of the GNU General Public License as published by
@ -136,6 +136,8 @@ namespace p25
uint32_t m_callTimer; uint32_t m_callTimer;
ulong64_t m_rsValue; // used for certain transparent passthru LCOs
/** Encryption data */ /** Encryption data */
uint8_t* m_mi; uint8_t* m_mi;

@ -501,19 +501,19 @@ bool Voice::process(uint8_t* data, uint32_t len)
} }
} }
// Generate Sync // generate Sync
Sync::addP25Sync(data + 2U); Sync::addP25Sync(data + 2U);
// Generate NID // generate NID
m_p25->m_nid.encode(data + 2U, P25_DUID_LDU1); m_p25->m_nid.encode(data + 2U, P25_DUID_LDU1);
// Generate LDU1 Data // generate LDU1 Data
m_rfLC.encodeLDU1(data + 2U); m_rfLC.encodeLDU1(data + 2U);
// Generate Low Speed Data // generate Low Speed Data
m_rfLSD.process(data + 2U); m_rfLSD.process(data + 2U);
// Regenerate Audio // regenerate audio
uint32_t errors = m_audio.process(data + 2U); uint32_t errors = m_audio.process(data + 2U);
// replace audio with silence in cases where the error rate // 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"); 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 + 10U, 0U);
m_audio.encode(data + 2U, buffer + 26U, 1U); m_audio.encode(data + 2U, buffer + 26U, 1U);
m_audio.encode(data + 2U, buffer + 55U, 2U); 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 + 155U, 6U);
m_audio.encode(data + 2U, buffer + 180U, 7U); m_audio.encode(data + 2U, buffer + 180U, 7U);
m_audio.encode(data + 2U, buffer + 204U, 8U); 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_rfBits += 1233U;
m_rfErrs += errors; m_rfErrs += errors;
m_rfFrames++; m_rfFrames++;
// Add busy bits // add busy bits
P25Utils::addBusyBits(data + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true); P25Utils::addBusyBits(data + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true);
writeNetwork(data + 2U, P25_DUID_LDU1); writeNetwork(data + 2U, P25_DUID_LDU1);
@ -580,19 +589,19 @@ bool Voice::process(uint8_t* data, uint32_t len)
m_rfLastLDU2 = m_rfLC; m_rfLastLDU2 = m_rfLC;
} }
// Generate Sync // generate Sync
Sync::addP25Sync(data + 2U); Sync::addP25Sync(data + 2U);
// Generate NID // generate NID
m_p25->m_nid.encode(data + 2U, P25_DUID_LDU2); m_p25->m_nid.encode(data + 2U, P25_DUID_LDU2);
// Generate LDU2 data // generate LDU2 data
m_rfLC.encodeLDU2(data + 2U); m_rfLC.encodeLDU2(data + 2U);
// Generate Low Speed Data // generate Low Speed Data
m_rfLSD.process(data + 2U); m_rfLSD.process(data + 2U);
// Regenerate Audio // regenerate audio
uint32_t errors = m_audio.process(data + 2U); uint32_t errors = m_audio.process(data + 2U);
// replace audio with silence in cases where the error rate // 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"); 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 + 10U, 0U);
m_audio.encode(data + 2U, buffer + 26U, 1U); m_audio.encode(data + 2U, buffer + 26U, 1U);
m_audio.encode(data + 2U, buffer + 55U, 2U); 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 + 155U, 6U);
m_audio.encode(data + 2U, buffer + 180U, 7U); m_audio.encode(data + 2U, buffer + 180U, 7U);
m_audio.encode(data + 2U, buffer + 204U, 8U); 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_rfBits += 1233U;
m_rfErrs += errors; m_rfErrs += errors;
m_rfFrames++; m_rfFrames++;
// Add busy bits // add busy bits
P25Utils::addBusyBits(data + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true); P25Utils::addBusyBits(data + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true);
writeNetwork(data + 2U, P25_DUID_LDU2); writeNetwork(data + 2U, P25_DUID_LDU2);

Loading…
Cancel
Save

Powered by TurnKey Linux.