fix issue where ACL wouldn't blacklist RIDs when ACLs were disabled (blacklisting should always work); refactor TSBK decode/encode classes to better support raw and non-trellis data output/input; more fixes making P25T VOC more reliable; implement more DFSI LC handling;

pull/12/head
Bryan Biedenkapp 4 years ago
parent bb61b5e157
commit 8b2771274e

@ -65,6 +65,11 @@ bool AccessControl::validateSrcId(uint32_t id)
{ {
// check if RID ACLs are enabled // check if RID ACLs are enabled
if (m_ridLookup->getACL() == false) { if (m_ridLookup->getACL() == false) {
RadioId rid = m_ridLookup->find(id);
if (!rid.radioDefault() && !rid.radioEnabled()) {
return false;
}
return true; return true;
} }

@ -103,6 +103,7 @@ namespace p25
const uint32_t P25_PDU_FEC_LENGTH_BITS = P25_PDU_FEC_LENGTH_BYTES * 8U - 4U; // Trellis is actually 196 bits const uint32_t P25_PDU_FEC_LENGTH_BITS = P25_PDU_FEC_LENGTH_BYTES * 8U - 4U; // Trellis is actually 196 bits
const uint32_t P25_MI_LENGTH_BYTES = 9U; const uint32_t P25_MI_LENGTH_BYTES = 9U;
const uint32_t P25_RAW_IMBE_LENGTH_BYTES = 11U;
const uint32_t P25_SS0_START = 70U; const uint32_t P25_SS0_START = 70U;
const uint32_t P25_SS1_START = 71U; const uint32_t P25_SS1_START = 71U;

@ -1530,7 +1530,7 @@ void TrunkPacket::writeRF_TSDU_SBF(bool noNetwork, bool clearBeforeWrite, bool f
// Generate TSBK block // Generate TSBK block
m_rfTSBK.setLastBlock(true); // always set last block -- this a Single Block TSDU m_rfTSBK.setLastBlock(true); // always set last block -- this a Single Block TSDU
m_rfTSBK.encode(data + 2U, true); m_rfTSBK.encode(data + 2U);
if (m_debug) { if (m_debug) {
Utils::dump(1U, "!!! *TSDU (SBF) TSBK Block Data", data + P25_PREAMBLE_LENGTH_BYTES + 2U, P25_TSBK_FEC_LENGTH_BYTES); Utils::dump(1U, "!!! *TSDU (SBF) TSBK Block Data", data + P25_PREAMBLE_LENGTH_BYTES + 2U, P25_TSBK_FEC_LENGTH_BYTES);
@ -1602,7 +1602,7 @@ void TrunkPacket::writeRF_TSDU_MBF(bool clearBeforeWrite)
if (m_mbfCnt + 1U == TSBK_MBF_CNT) { if (m_mbfCnt + 1U == TSBK_MBF_CNT) {
// Generate TSBK block // Generate TSBK block
m_rfTSBK.setLastBlock(true); // set last block m_rfTSBK.setLastBlock(true); // set last block
m_rfTSBK.encode(tsbk, false); m_rfTSBK.encode(tsbk, true);
if (m_debug) { if (m_debug) {
Utils::dump(1U, "!!! *TSDU MBF Last TSBK Block", tsbk, P25_TSBK_FEC_LENGTH_BYTES); Utils::dump(1U, "!!! *TSDU MBF Last TSBK Block", tsbk, P25_TSBK_FEC_LENGTH_BYTES);
@ -1666,7 +1666,7 @@ void TrunkPacket::writeRF_TSDU_MBF(bool clearBeforeWrite)
// Generate TSBK block // Generate TSBK block
m_rfTSBK.setLastBlock(false); // clear last block m_rfTSBK.setLastBlock(false); // clear last block
m_rfTSBK.encode(tsbk, false); m_rfTSBK.encode(tsbk, true);
if (m_debug) { if (m_debug) {
Utils::dump(1U, "!!! *TSDU MBF Block Data", tsbk, P25_TSBK_FEC_LENGTH_BYTES); Utils::dump(1U, "!!! *TSDU MBF Block Data", tsbk, P25_TSBK_FEC_LENGTH_BYTES);
@ -2410,7 +2410,7 @@ void TrunkPacket::writeNet_TSDU_From_RF(uint8_t* data)
// Regenerate TSDU Data // Regenerate TSDU Data
m_rfTSBK.setLastBlock(true); // always set last block -- this a Single Block TSDU m_rfTSBK.setLastBlock(true); // always set last block -- this a Single Block TSDU
m_rfTSBK.encode(data, true); m_rfTSBK.encode(data);
// Add busy bits // Add busy bits
m_p25->addBusyBits(data, P25_TSDU_FRAME_LENGTH_BYTES, true, false); m_p25->addBusyBits(data, P25_TSDU_FRAME_LENGTH_BYTES, true, false);
@ -2485,7 +2485,7 @@ void TrunkPacket::writeNet_TSDU()
// Regenerate TSDU Data // Regenerate TSDU Data
m_netTSBK.setLastBlock(true); // always set last block -- this a Single Block TSDU m_netTSBK.setLastBlock(true); // always set last block -- this a Single Block TSDU
m_netTSBK.encode(buffer + 2U, true); m_netTSBK.encode(buffer + 2U);
// Add busy bits // Add busy bits
m_p25->addBusyBits(buffer + 2U, P25_TSDU_FRAME_LENGTH_BYTES, true, false); m_p25->addBusyBits(buffer + 2U, P25_TSDU_FRAME_LENGTH_BYTES, true, false);

@ -729,6 +729,18 @@ bool VoicePacket::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, d
m_netLastLDU1 = control; m_netLastLDU1 = control;
if (m_p25->m_netState == RS_NET_IDLE) {
// are we interrupting a running CC?
if (m_p25->m_ccRunning) {
g_interruptP25Control = true;
}
// single-channel trunking or voice on control support?
if (m_p25->m_control && m_p25->m_voiceOnControl) {
m_p25->m_ccRunning = false; // otherwise the grant will be bundled with other packets
}
}
checkNet_LDU2(control, lsd); checkNet_LDU2(control, lsd);
if (m_p25->m_netState != RS_NET_IDLE) { if (m_p25->m_netState != RS_NET_IDLE) {
writeNet_LDU1(control, lsd); writeNet_LDU1(control, lsd);
@ -779,17 +791,9 @@ bool VoicePacket::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, d
count += 16U; count += 16U;
if (m_p25->m_netState == RS_NET_IDLE) { if (m_p25->m_netState == RS_NET_IDLE) {
// are we interrupting a running CC? if (!m_p25->m_voiceOnControl) {
if (m_p25->m_ccRunning) { m_p25->m_modem->clearP25Data();
g_interruptP25Control = true;
}
// single-channel trunking or voice on control support?
if (m_p25->m_control && m_p25->m_voiceOnControl) {
m_p25->m_ccRunning = false; // otherwise the grant will be bundled with other packets
} }
m_p25->m_modem->clearP25Data();
m_p25->m_queue.clear(); m_p25->m_queue.clear();
resetRF(); resetRF();

@ -65,6 +65,11 @@ bool AccessControl::validateSrcId(uint32_t id)
{ {
// check if RID ACLs are enabled // check if RID ACLs are enabled
if (m_ridLookup->getACL() == false) { if (m_ridLookup->getACL() == false) {
RadioId rid = m_ridLookup->find(id);
if (!rid.radioDefault() && !rid.radioEnabled()) {
return false;
}
return true; return true;
} }

@ -73,6 +73,8 @@ namespace p25
const uint32_t P25_DFSI_TSBK_FRAME_LENGTH_BYTES = 25U; const uint32_t P25_DFSI_TSBK_FRAME_LENGTH_BYTES = 25U;
const uint8_t P25_DFSI_STATUS = 0x02U; //
const uint8_t P25_DFSI_RT_ENABLED = 0x02U; // const uint8_t P25_DFSI_RT_ENABLED = 0x02U; //
const uint8_t P25_DFSI_RT_DISABLED = 0x04U; // const uint8_t P25_DFSI_RT_DISABLED = 0x04U; //

@ -54,9 +54,11 @@ LC::LC() :
m_source(P25_DFSI_DEF_SOURCE), m_source(P25_DFSI_DEF_SOURCE),
m_control(), m_control(),
m_tsbk(), m_tsbk(),
m_lsd() m_lsd(),
m_mi(NULL)
{ {
/* stub */ m_mi = new uint8_t[P25_MI_LENGTH_BYTES];
::memset(m_mi, 0x00U, P25_MI_LENGTH_BYTES);
} }
/// <summary> /// <summary>
@ -64,7 +66,7 @@ LC::LC() :
/// </summary> /// </summary>
LC::~LC() LC::~LC()
{ {
/* stub */ delete[] m_mi;
} }
/// <summary> /// <summary>
@ -87,6 +89,13 @@ LC& LC::operator=(const LC& data)
m_control = data.m_control; m_control = data.m_control;
m_tsbk = data.m_tsbk; m_tsbk = data.m_tsbk;
m_lsd = data.m_lsd; m_lsd = data.m_lsd;
delete[] m_mi;
uint8_t* mi = new uint8_t[P25_MI_LENGTH_BYTES];
::memcpy(mi, data.m_mi, P25_MI_LENGTH_BYTES);
m_mi = mi;
} }
return *this; return *this;
@ -135,6 +144,11 @@ bool LC::decodeVHDR1(const uint8_t* data)
assert(data != NULL); assert(data != NULL);
m_frameType = data[0U]; // Frame Type m_frameType = data[0U]; // Frame Type
if (m_frameType != P25_DFSI_VHDR1) {
LogError(LOG_P25, "LC::decodeVHDR1(), invalid frametype, frameType = $%02X", m_frameType);
return false;
}
if (!decodeStart(data + 1U)) { if (!decodeStart(data + 1U)) {
LogError(LOG_P25, "LC::decodeVHDR1(), failed to decode start record"); LogError(LOG_P25, "LC::decodeVHDR1(), failed to decode start record");
return false; return false;
@ -157,7 +171,7 @@ void LC::encodeVHDR1(uint8_t* data)
uint8_t rawFrame[P25_DFSI_VHDR1_FRAME_LENGTH_BYTES]; uint8_t rawFrame[P25_DFSI_VHDR1_FRAME_LENGTH_BYTES];
::memset(rawFrame, 0x00U, P25_DFSI_VHDR1_FRAME_LENGTH_BYTES); ::memset(rawFrame, 0x00U, P25_DFSI_VHDR1_FRAME_LENGTH_BYTES);
rawFrame[0U] = m_frameType; // Frame Type rawFrame[0U] = P25_DFSI_VHDR1; // Frame Type
// encode start record // encode start record
encodeStart(rawFrame + 1U); encodeStart(rawFrame + 1U);
@ -179,6 +193,10 @@ bool LC::decodeVHDR2(const uint8_t* data)
m_control = lc::LC(); m_control = lc::LC();
m_frameType = data[0U]; // Frame Type m_frameType = data[0U]; // Frame Type
if (m_frameType != P25_DFSI_VHDR2) {
LogError(LOG_P25, "LC::decodeVHDR2(), invalid frametype, frameType = $%02X", m_frameType);
return false;
}
uint32_t dstId = (data[1U] << 16) | (data[2U] << 8) | (data[3U] << 0); uint32_t dstId = (data[1U] << 16) | (data[2U] << 8) | (data[3U] << 0);
m_control.setDstId(dstId); // Talkgroup Address m_control.setDstId(dstId); // Talkgroup Address
@ -194,16 +212,17 @@ void LC::encodeVHDR2(uint8_t* data)
{ {
assert(data != NULL); assert(data != NULL);
uint8_t rawFrame[P25_DFSI_VHDR2_FRAME_LENGTH_BYTES]; uint8_t dfsiFrame[P25_DFSI_VHDR2_FRAME_LENGTH_BYTES];
::memset(rawFrame, 0x00U, P25_DFSI_VHDR2_FRAME_LENGTH_BYTES); ::memset(dfsiFrame, 0x00U, P25_DFSI_VHDR2_FRAME_LENGTH_BYTES);
rawFrame[0U] = m_frameType; // Frame Type dfsiFrame[0U] = P25_DFSI_VHDR2; // Frame Type
rawFrame[1U] = (m_control.getDstId() >> 16) & 0xFFU; // Talkgroup Address uint32_t dstId = m_control.getDstId();
rawFrame[2U] = (m_control.getDstId() >> 8) & 0xFFU; dfsiFrame[1U] = (dstId >> 16) & 0xFFU; // Talkgroup Address
rawFrame[3U] = (m_control.getDstId() >> 0) & 0xFFU; dfsiFrame[2U] = (dstId >> 8) & 0xFFU;
dfsiFrame[3U] = (dstId >> 0) & 0xFFU;
::memcpy(data, rawFrame, P25_DFSI_VHDR2_FRAME_LENGTH_BYTES); ::memcpy(data, dfsiFrame, P25_DFSI_VHDR2_FRAME_LENGTH_BYTES);
} }
/// <summary> /// <summary>
@ -214,7 +233,87 @@ void LC::encodeVHDR2(uint8_t* data)
/// <returns>True, if decoded, otherwise false.</returns> /// <returns>True, if decoded, otherwise false.</returns>
bool LC::decodeLDU1(const uint8_t* data, uint8_t* imbe) bool LC::decodeLDU1(const uint8_t* data, uint8_t* imbe)
{ {
// TODO TODO TODO assert(data != NULL);
assert(imbe != NULL);
m_frameType = data[0U]; // Frame Type
// different frame types mean different things
switch (m_frameType)
{
case P25_DFSI_LDU1_VOICE1:
{
m_control = p25::lc::LC();
m_lsd = p25::data::LowSpeedData();
decodeStart(data + 1U); // Start Record
m_icwFlag = data[5U]; // ICW Flag
m_rssi = data[6U]; // RSSI
::memcpy(imbe, data + 10U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
m_source = data[21U]; // Source
}
break;
case P25_DFSI_LDU1_VOICE2:
{
::memcpy(imbe, data + 1U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
m_source = data[12U]; // Source
}
break;
case P25_DFSI_LDU1_VOICE3:
{
m_control.setLCO(data[1U]); // LCO
m_control.setMFId(data[2U]); // MFId
uint8_t serviceOptions = (uint8_t)(data[3U]); // Service Options
m_control.setEmergency((serviceOptions & 0x80U) == 0x80U);
m_control.setEncrypted((serviceOptions & 0x40U) == 0x40U);
m_control.setPriority((serviceOptions & 0x07U));
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
case P25_DFSI_LDU1_VOICE4:
{
uint32_t dstId = (data[1U] << 16) | (data[2U] << 8) | (data[3U] << 0);
m_control.setDstId(dstId); // Talkgroup Address
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
case P25_DFSI_LDU1_VOICE5:
{
uint32_t srcId = (data[1U] << 16) | (data[2U] << 8) | (data[3U] << 0);
m_control.setSrcId(srcId); // Source Address
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
case P25_DFSI_LDU1_VOICE6:
{
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
case P25_DFSI_LDU1_VOICE7:
{
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
case P25_DFSI_LDU1_VOICE8:
{
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
case P25_DFSI_LDU1_VOICE9:
{
m_lsd.setLSD1(data[1U]); // LSD MSB
m_lsd.setLSD2(data[2U]); // LSD LSB
::memcpy(imbe, data + 4U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
default:
{
LogError(LOG_P25, "LC::decodeLDU1(), invalid frametype, frameType = $%02X", m_frameType);
return false;
}
break;
}
return true; return true;
} }
@ -226,11 +325,20 @@ bool LC::decodeLDU1(const uint8_t* data, uint8_t* imbe)
void LC::encodeLDU1(uint8_t* data, const uint8_t* imbe) void LC::encodeLDU1(uint8_t* data, const uint8_t* imbe)
{ {
assert(data != NULL); assert(data != NULL);
assert(imbe != NULL);
uint8_t serviceOptions =
(m_control.getEmergency() ? 0x80U : 0x00U) +
(m_control.getEncrypted() ? 0x40U : 0x00U) +
(m_control.getPriority() & 0x07U);
// determine the LDU1 DFSI frame length, its variable // determine the LDU1 DFSI frame length, its variable
uint32_t frameLength = P25_DFSI_LDU1_VOICE1_FRAME_LENGTH_BYTES; uint32_t frameLength = P25_DFSI_LDU1_VOICE1_FRAME_LENGTH_BYTES;
switch (m_frameType) switch (m_frameType)
{ {
case P25_DFSI_LDU1_VOICE1:
frameLength = P25_DFSI_LDU1_VOICE1_FRAME_LENGTH_BYTES;
break;
case P25_DFSI_LDU1_VOICE2: case P25_DFSI_LDU1_VOICE2:
frameLength = P25_DFSI_LDU1_VOICE2_FRAME_LENGTH_BYTES; frameLength = P25_DFSI_LDU1_VOICE2_FRAME_LENGTH_BYTES;
break; break;
@ -255,61 +363,96 @@ void LC::encodeLDU1(uint8_t* data, const uint8_t* imbe)
case P25_DFSI_LDU1_VOICE9: case P25_DFSI_LDU1_VOICE9:
frameLength = P25_DFSI_LDU1_VOICE9_FRAME_LENGTH_BYTES; frameLength = P25_DFSI_LDU1_VOICE9_FRAME_LENGTH_BYTES;
break; break;
case P25_DFSI_LDU1_VOICE1:
default: default:
frameLength = P25_DFSI_LDU1_VOICE1_FRAME_LENGTH_BYTES; {
LogError(LOG_P25, "LC::encodeLDU1(), invalid frametype, frameType = $%02X", m_frameType);
return;
}
break; break;
} }
uint8_t rawFrame[frameLength]; uint8_t dfsiFrame[frameLength];
::memset(rawFrame, 0x00U, frameLength); ::memset(dfsiFrame, 0x00U, frameLength);
rawFrame[0U] = m_frameType; // Frame Type dfsiFrame[0U] = m_frameType; // Frame Type
// different frame types mean different things // different frame types mean different things
switch (m_frameType) switch (m_frameType)
{ {
case P25_DFSI_LDU1_VOICE2: case P25_DFSI_LDU1_VOICE2:
// TODO TODO TODO {
::memcpy(dfsiFrame + 1U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
dfsiFrame[12U] = m_source; // Source
}
break; break;
case P25_DFSI_LDU1_VOICE3: case P25_DFSI_LDU1_VOICE3:
// TODO TODO TODO {
dfsiFrame[1U] = m_control.getLCO(); // LCO
dfsiFrame[2U] = m_control.getMFId(); // MFId
dfsiFrame[3U] = serviceOptions; // Service Options
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
dfsiFrame[16U] = P25_DFSI_STATUS; // Status
}
break; break;
case P25_DFSI_LDU1_VOICE4: case P25_DFSI_LDU1_VOICE4:
// TODO TODO TODO {
uint32_t dstId = m_control.getDstId();
dfsiFrame[1U] = (dstId >> 16) & 0xFFU; // Target Address
dfsiFrame[2U] = (dstId >> 8) & 0xFFU;
dfsiFrame[3U] = (dstId >> 0) & 0xFFU;
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
dfsiFrame[16U] = P25_DFSI_STATUS; // Status
}
break; break;
case P25_DFSI_LDU1_VOICE5: case P25_DFSI_LDU1_VOICE5:
// TODO TODO TODO {
uint32_t srcId = m_control.getSrcId();
dfsiFrame[1U] = (srcId >> 16) & 0xFFU; // Source Address
dfsiFrame[2U] = (srcId >> 8) & 0xFFU;
dfsiFrame[3U] = (srcId >> 0) & 0xFFU;
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
dfsiFrame[16U] = P25_DFSI_STATUS; // Status
}
break; break;
case P25_DFSI_LDU1_VOICE6: case P25_DFSI_LDU1_VOICE6:
// TODO TODO TODO {
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
dfsiFrame[16U] = P25_DFSI_STATUS; // Status
}
break; break;
case P25_DFSI_LDU1_VOICE7: case P25_DFSI_LDU1_VOICE7:
// TODO TODO TODO {
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
dfsiFrame[16U] = P25_DFSI_STATUS; // Status
}
break; break;
case P25_DFSI_LDU1_VOICE8: case P25_DFSI_LDU1_VOICE8:
// TODO TODO TODO {
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
dfsiFrame[16U] = P25_DFSI_STATUS; // Status
}
break; break;
case P25_DFSI_LDU1_VOICE9: case P25_DFSI_LDU1_VOICE9:
// TODO TODO TODO {
dfsiFrame[1U] = m_lsd.getLSD1(); // LSD MSB
dfsiFrame[2U] = m_lsd.getLSD2(); // LSD LSB
::memcpy(dfsiFrame + 4U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
}
break; break;
case P25_DFSI_LDU1_VOICE1: case P25_DFSI_LDU1_VOICE1:
default: default:
{ {
// encode start record encodeStart(dfsiFrame + 1U); // Start Record
encodeStart(rawFrame + 1U); dfsiFrame[5U] = m_icwFlag; // ICW Flag
dfsiFrame[6U] = m_rssi; // RSSI
rawFrame[5U] = m_icwFlag; // ICW Flag ::memcpy(dfsiFrame + 10U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
rawFrame[6U] = m_rssi; // RSSI dfsiFrame[21U] = m_source; // Source
// TODO TODO TODO
} }
break; break;
} }
::memcpy(data, rawFrame, frameLength); ::memcpy(data, dfsiFrame, frameLength);
} }
/// <summary> /// <summary>
@ -320,7 +463,89 @@ void LC::encodeLDU1(uint8_t* data, const uint8_t* imbe)
/// <returns>True, if decoded, otherwise false.</returns> /// <returns>True, if decoded, otherwise false.</returns>
bool LC::decodeLDU2(const uint8_t* data, uint8_t* imbe) bool LC::decodeLDU2(const uint8_t* data, uint8_t* imbe)
{ {
// TODO TODO TODO assert(data != NULL);
assert(imbe != NULL);
m_frameType = data[0U]; // Frame Type
// different frame types mean different things
switch (m_frameType)
{
case P25_DFSI_LDU2_VOICE10:
{
::memset(m_mi, 0x00U, P25_MI_LENGTH_BYTES);
m_lsd = p25::data::LowSpeedData();
decodeStart(data + 1U); // Start Record
m_icwFlag = data[5U]; // ICW Flag
m_rssi = data[6U]; // RSSI
::memcpy(imbe, data + 10U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
m_source = data[21U]; // Source
}
break;
case P25_DFSI_LDU2_VOICE11:
{
::memcpy(imbe, data + 1U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
case P25_DFSI_LDU2_VOICE12:
{
m_mi[0U] = data[1U]; // Message Indicator
m_mi[1U] = data[2U];
m_mi[2U] = data[3U];
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
case P25_DFSI_LDU2_VOICE13:
{
m_mi[3U] = data[1U]; // Message Indicator
m_mi[4U] = data[2U];
m_mi[5U] = data[3U];
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
case P25_DFSI_LDU2_VOICE14:
{
m_mi[6U] = data[1U]; // Message Indicator
m_mi[7U] = data[2U];
m_mi[8U] = data[3U];
m_control.setMI(m_mi);
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
case P25_DFSI_LDU2_VOICE15:
{
m_control.setAlgId(data[1U]); // Algorithm ID
uint32_t kid = (data[2U] << 8) | (data[3U] << 0); // Key ID
m_control.setKId(kid);
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
case P25_DFSI_LDU2_VOICE16:
{
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
case P25_DFSI_LDU2_VOICE17:
{
::memcpy(imbe, data + 5U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
case P25_DFSI_LDU2_VOICE18:
{
m_lsd.setLSD1(data[1U]); // LSD MSB
m_lsd.setLSD2(data[2U]); // LSD LSB
::memcpy(imbe, data + 4U, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
}
break;
default:
{
LogError(LOG_P25, "LC::decodeLDU1(), invalid frametype, frameType = $%02X", m_frameType);
return false;
}
break;
}
return true; return true;
} }
@ -332,11 +557,19 @@ bool LC::decodeLDU2(const uint8_t* data, uint8_t* imbe)
void LC::encodeLDU2(uint8_t* data, const uint8_t* imbe) void LC::encodeLDU2(uint8_t* data, const uint8_t* imbe)
{ {
assert(data != NULL); assert(data != NULL);
assert(imbe != NULL);
// generate MI data
uint8_t mi[p25::P25_MI_LENGTH_BYTES];
m_control.getMI(mi);
// determine the LDU2 DFSI frame length, its variable // determine the LDU2 DFSI frame length, its variable
uint32_t frameLength = P25_DFSI_LDU2_VOICE10_FRAME_LENGTH_BYTES; uint32_t frameLength = P25_DFSI_LDU2_VOICE10_FRAME_LENGTH_BYTES;
switch (m_frameType) switch (m_frameType)
{ {
case P25_DFSI_LDU2_VOICE10:
frameLength = P25_DFSI_LDU2_VOICE10_FRAME_LENGTH_BYTES;
break;
case P25_DFSI_LDU2_VOICE11: case P25_DFSI_LDU2_VOICE11:
frameLength = P25_DFSI_LDU2_VOICE11_FRAME_LENGTH_BYTES; frameLength = P25_DFSI_LDU2_VOICE11_FRAME_LENGTH_BYTES;
break; break;
@ -361,76 +594,138 @@ void LC::encodeLDU2(uint8_t* data, const uint8_t* imbe)
case P25_DFSI_LDU2_VOICE18: case P25_DFSI_LDU2_VOICE18:
frameLength = P25_DFSI_LDU2_VOICE18_FRAME_LENGTH_BYTES; frameLength = P25_DFSI_LDU2_VOICE18_FRAME_LENGTH_BYTES;
break; break;
case P25_DFSI_LDU2_VOICE10:
default: default:
frameLength = P25_DFSI_LDU2_VOICE10_FRAME_LENGTH_BYTES; {
LogError(LOG_P25, "LC::encodeLDU1(), invalid frametype, frameType = $%02X", m_frameType);
return;
}
break; break;
} }
uint8_t dfsiFrame[frameLength];
::memset(dfsiFrame, 0x00U, frameLength);
uint8_t rawFrame[frameLength]; dfsiFrame[0U] = m_frameType; // Frame Type
::memset(rawFrame, 0x00U, frameLength);
rawFrame[0U] = m_frameType; // Frame Type
// different frame types mean different things // different frame types mean different things
switch (m_frameType) switch (m_frameType)
{ {
case P25_DFSI_LDU2_VOICE11: case P25_DFSI_LDU2_VOICE11:
// TODO TODO TODO {
::memcpy(dfsiFrame + 1U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
dfsiFrame[12U] = P25_DFSI_STATUS; // Status
}
break; break;
case P25_DFSI_LDU2_VOICE12: case P25_DFSI_LDU2_VOICE12:
// TODO TODO TODO {
dfsiFrame[1U] = mi[0U]; // Message Indicator
dfsiFrame[2U] = mi[1U];
dfsiFrame[3U] = mi[2U];
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
dfsiFrame[16U] = P25_DFSI_STATUS; // Status
}
break; break;
case P25_DFSI_LDU2_VOICE13: case P25_DFSI_LDU2_VOICE13:
// TODO TODO TODO {
dfsiFrame[1U] = mi[3U]; // Message Indicator
dfsiFrame[2U] = mi[4U];
dfsiFrame[3U] = mi[5U];
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
dfsiFrame[16U] = P25_DFSI_STATUS; // Status
}
break; break;
case P25_DFSI_LDU2_VOICE14: case P25_DFSI_LDU2_VOICE14:
// TODO TODO TODO {
dfsiFrame[1U] = mi[6U]; // Message Indicator
dfsiFrame[2U] = mi[7U];
dfsiFrame[3U] = mi[8U];
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
dfsiFrame[16U] = P25_DFSI_STATUS; // Status
}
break; break;
case P25_DFSI_LDU2_VOICE15: case P25_DFSI_LDU2_VOICE15:
// TODO TODO TODO {
dfsiFrame[1U] = m_control.getAlgId(); // Algorithm ID
uint32_t kid = m_control.getKId();
dfsiFrame[2U] = (kid >> 8) & 0xFFU; // Key ID
dfsiFrame[3U] = (kid >> 0) & 0xFFU;
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
dfsiFrame[16U] = P25_DFSI_STATUS; // Status
}
break; break;
case P25_DFSI_LDU2_VOICE16: case P25_DFSI_LDU2_VOICE16:
// TODO TODO TODO {
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
dfsiFrame[16U] = P25_DFSI_STATUS; // Status
}
break; break;
case P25_DFSI_LDU2_VOICE17: case P25_DFSI_LDU2_VOICE17:
// TODO TODO TODO {
::memcpy(dfsiFrame + 5U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
dfsiFrame[16U] = P25_DFSI_STATUS; // Status
}
break; break;
case P25_DFSI_LDU2_VOICE18: case P25_DFSI_LDU2_VOICE18:
// TODO TODO TODO {
dfsiFrame[1U] = m_lsd.getLSD1(); // LSD MSB
dfsiFrame[2U] = m_lsd.getLSD2(); // LSD LSB
::memcpy(dfsiFrame + 4U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
}
break; break;
case P25_DFSI_LDU2_VOICE10: case P25_DFSI_LDU2_VOICE10:
default: default:
// TODO TODO TODO {
encodeStart(dfsiFrame + 1U); // Start Record
dfsiFrame[5U] = m_icwFlag; // ICW Flag
dfsiFrame[6U] = m_rssi; // RSSI
::memcpy(dfsiFrame + 10U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE
dfsiFrame[21U] = m_source; // Source
}
break; break;
} }
::memcpy(data, rawFrame, frameLength); ::memcpy(data, dfsiFrame, frameLength);
} }
/// <summary> /// <summary>
/// Decode a logical link data unit 2. /// Decode a logical link data unit 2.
/// </summary> /// </summary>
/// <param name="data"></param> /// <param name="data"></param>
/// <param name="tsbk"></param>
/// <returns>True, if decoded, otherwise false.</returns> /// <returns>True, if decoded, otherwise false.</returns>
bool LC::decodeTSBK(const uint8_t* data) bool LC::decodeTSBK(const uint8_t* data)
{ {
// TODO TODO TODO assert(data != NULL);
return true; m_tsbk = lc::TSBK();
m_frameType = data[0U]; // Frame Type
if (m_frameType != P25_DFSI_TSBK) {
LogError(LOG_P25, "LC::decodeTSBK(), invalid frametype, frameType = $%02X", m_frameType);
return false;
}
decodeStart(data + 1U); // Start Record
uint8_t tsbk[P25_TSBK_LENGTH_BYTES];
::memcpy(tsbk, data + 9U, P25_TSBK_LENGTH_BYTES); // Raw TSBK + CRC
return m_tsbk.decode(tsbk, true);
} }
/// <summary> /// <summary>
/// Encode a TSBK. /// Encode a TSBK.
/// </summary> /// </summary>
/// <param name="data"></param> /// <param name="data"></param>
/// <param name="tsbk"></param> void LC::encodeTSBK(uint8_t* data)
void LC::encodeTSBK(uint8_t* data, const uint8_t* tsbk)
{ {
// TODO TODO TODO uint8_t tsbk[P25_TSBK_LENGTH_BYTES];
m_tsbk.encode(tsbk, true, true);
uint8_t dfsiFrame[P25_DFSI_TSBK_FRAME_LENGTH_BYTES];
::memset(dfsiFrame, 0x00U, P25_DFSI_TSBK_FRAME_LENGTH_BYTES);
dfsiFrame[0U] = P25_DFSI_TSBK; // Frame Type
encodeStart(dfsiFrame + 1U); // Start Record
::memcpy(dfsiFrame + 9U, tsbk, P25_TSBK_LENGTH_BYTES); // Raw TSBK + CRC
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@ -445,9 +740,9 @@ bool LC::decodeStart(const uint8_t* data)
{ {
assert(data != NULL); assert(data != NULL);
m_rtModeFlag = data[1U]; // RT Mode Flag m_rtModeFlag = data[0U]; // RT Mode Flag
m_startStopFlag = data[2U]; // Start/Stop Flag m_startStopFlag = data[1U]; // Start/Stop Flag
m_typeFlag = data[3U]; // Type Flag m_typeFlag = data[2U]; // Type Flag
return true; return true;
} }

@ -80,7 +80,7 @@ namespace p25
/// <summary>Decode a TSBK.</summary> /// <summary>Decode a TSBK.</summary>
bool decodeTSBK(const uint8_t* data); bool decodeTSBK(const uint8_t* data);
/// <summary>Encode a TSBK.</summary> /// <summary>Encode a TSBK.</summary>
void encodeTSBK(uint8_t* data, const uint8_t* tsbk); void encodeTSBK(uint8_t* data);
public: public:
/** Common Data */ /** Common Data */
@ -109,6 +109,9 @@ namespace p25
__PROPERTY(p25::data::LowSpeedData, lsd, LSD); __PROPERTY(p25::data::LowSpeedData, lsd, LSD);
private: private:
/** Encryption data */
uint8_t* m_mi;
/// <summary>Decode start record data.</summary> /// <summary>Decode start record data.</summary>
bool decodeStart(const uint8_t* data); bool decodeStart(const uint8_t* data);
/// <summary>Encode start record data.</summary> /// <summary>Encode start record data.</summary>

@ -294,7 +294,7 @@ bool TSBK::decodeMBT(const data::DataHeader dataHeader, const uint8_t* block)
m_response = (uint8_t)((tsbkValue >> 48) & 0xFFU); // Reason m_response = (uint8_t)((tsbkValue >> 48) & 0xFFU); // Reason
m_netId = (uint32_t)((tsbkValue >> 20) & 0xFFFFFU); // Network ID m_netId = (uint32_t)((tsbkValue >> 20) & 0xFFFFFU); // Network ID
m_sysId = (uint32_t)((tsbkValue >> 8) & 0xFFFU); // System ID m_sysId = (uint32_t)((tsbkValue >> 8) & 0xFFFU); // System ID
m_dstId = (uint32_t)(((tsbkValue) & 0xFFU) << 16 + // Target Radio Address m_dstId = (uint32_t)((((tsbkValue) & 0xFFU) << 16) + // Target Radio Address
(block[6U] << 8) + (block[7U])); (block[6U] << 8) + (block[7U]));
m_srcId = dataHeader.getLLId(); // Source Radio Address m_srcId = dataHeader.getLLId(); // Source Radio Address
break; break;
@ -316,43 +316,60 @@ bool TSBK::decodeMBT(const data::DataHeader dataHeader, const uint8_t* block)
/// Decode a trunking signalling block. /// Decode a trunking signalling block.
/// </summary> /// </summary>
/// <param name="data"></param> /// <param name="data"></param>
/// <param name="rawTSBK"></param>
/// <returns>True, if TSBK was decoded, otherwise false.</returns> /// <returns>True, if TSBK was decoded, otherwise false.</returns>
bool TSBK::decode(const uint8_t* data) bool TSBK::decode(const uint8_t* data, bool rawTSBK)
{ {
assert(data != NULL); assert(data != NULL);
// deinterleave
uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U]; uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
uint8_t raw[P25_TSBK_FEC_LENGTH_BYTES]; if (rawTSBK) {
P25Utils::decode(data, raw, 114U, 318U); ::memcpy(tsbk, data, P25_TSBK_LENGTH_BYTES);
// decode 1/2 rate Trellis & check CRC-CCITT 16 bool ret = edac::CRC::checkCCITT162(tsbk, P25_TSBK_LENGTH_BYTES);
try {
bool ret = m_trellis.decode12(raw, tsbk);
if (!ret) { if (!ret) {
LogError(LOG_P25, "TSBK::decode(), failed to decode Trellis 1/2 rate coding"); if (m_warnCRC) {
LogWarning(LOG_P25, "TSBK::decode(), failed CRC CCITT-162 check");
ret = true; // ignore CRC error
}
else {
LogError(LOG_P25, "TSBK::decode(), failed CRC CCITT-162 check");
}
} }
}
else {
// deinterleave
uint8_t raw[P25_TSBK_FEC_LENGTH_BYTES];
P25Utils::decode(data, raw, 114U, 318U);
if (ret) { // decode 1/2 rate Trellis & check CRC-CCITT 16
ret = edac::CRC::checkCCITT162(tsbk, P25_TSBK_LENGTH_BYTES); try {
bool ret = m_trellis.decode12(raw, tsbk);
if (!ret) { if (!ret) {
if (m_warnCRC) { LogError(LOG_P25, "TSBK::decode(), failed to decode Trellis 1/2 rate coding");
LogWarning(LOG_P25, "TSBK::decode(), failed CRC CCITT-162 check"); }
ret = true; // ignore CRC error
} if (ret) {
else { ret = edac::CRC::checkCCITT162(tsbk, P25_TSBK_LENGTH_BYTES);
LogError(LOG_P25, "TSBK::decode(), failed CRC CCITT-162 check"); if (!ret) {
if (m_warnCRC) {
LogWarning(LOG_P25, "TSBK::decode(), failed CRC CCITT-162 check");
ret = true; // ignore CRC error
}
else {
LogError(LOG_P25, "TSBK::decode(), failed CRC CCITT-162 check");
}
} }
} }
}
if (!ret) if (!ret)
return false;
}
catch (...) {
Utils::dump(2U, "P25, decoding excepted with input data", tsbk, P25_TSBK_LENGTH_BYTES);
return false; return false;
} }
catch (...) { }
Utils::dump(2U, "P25, decoding excepted with input data", tsbk, P25_TSBK_LENGTH_BYTES);
return false;
}
if (m_verbose) { if (m_verbose) {
Utils::dump(2U, "Decoded TSBK", tsbk, P25_TSBK_LENGTH_BYTES); Utils::dump(2U, "Decoded TSBK", tsbk, P25_TSBK_LENGTH_BYTES);
@ -574,7 +591,9 @@ bool TSBK::decode(const uint8_t* data)
/// Encode a trunking signalling block. /// Encode a trunking signalling block.
/// </summary> /// </summary>
/// <param name="data"></param> /// <param name="data"></param>
void TSBK::encode(uint8_t * data, bool singleBlock) /// <param name="rawTSBK"></param>
/// <param name="noTrellis"></param>
void TSBK::encode(uint8_t * data, bool rawTSBK, bool noTrellis)
{ {
assert(data != NULL); assert(data != NULL);
@ -1040,16 +1059,21 @@ void TSBK::encode(uint8_t * data, bool singleBlock)
// encode 1/2 rate Trellis // encode 1/2 rate Trellis
m_trellis.encode12(tsbk, raw); m_trellis.encode12(tsbk, raw);
// is this a single block TSBK? // are we encoding a raw TSBK?
if (singleBlock) { if (rawTSBK) {
if (noTrellis) {
::memcpy(data, tsbk, P25_TSBK_LENGTH_BYTES);
}
else {
::memcpy(data, raw, P25_TSBK_FEC_LENGTH_BYTES);
}
}
else {
// interleave // interleave
P25Utils::encode(raw, data, 114U, 318U); P25Utils::encode(raw, data, 114U, 318U);
// Utils::dump(2U, "TSBK Interleave", data, P25_TSBK_FEC_LENGTH_BYTES + P25_PREAMBLE_LENGTH_BYTES); // Utils::dump(2U, "TSBK Interleave", data, P25_TSBK_FEC_LENGTH_BYTES + P25_PREAMBLE_LENGTH_BYTES);
} }
else {
::memcpy(data, raw, P25_TSBK_FEC_LENGTH_BYTES);
}
} }
/// <summary> /// <summary>

@ -81,9 +81,9 @@ namespace p25
bool decodeMBT(const data::DataHeader dataHeader, const uint8_t* block); bool decodeMBT(const data::DataHeader dataHeader, const uint8_t* block);
/// <summary>Decode a trunking signalling block.</summary> /// <summary>Decode a trunking signalling block.</summary>
bool decode(const uint8_t* data); bool decode(const uint8_t* data, bool rawTSBK = false);
/// <summary>Encode a trunking signalling block.</summary> /// <summary>Encode a trunking signalling block.</summary>
void encode(uint8_t* data, bool singleBlock); void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false);
/// <summary>Sets the flag to skip vendor opcode processing.</summary> /// <summary>Sets the flag to skip vendor opcode processing.</summary>
void setVendorSkip(bool skip); void setVendorSkip(bool skip);

Loading…
Cancel
Save

Powered by TurnKey Linux.