diff --git a/dmr/acl/AccessControl.cpp b/dmr/acl/AccessControl.cpp index 627db247..8c71500c 100644 --- a/dmr/acl/AccessControl.cpp +++ b/dmr/acl/AccessControl.cpp @@ -65,6 +65,11 @@ bool AccessControl::validateSrcId(uint32_t id) { // check if RID ACLs are enabled if (m_ridLookup->getACL() == false) { + RadioId rid = m_ridLookup->find(id); + if (!rid.radioDefault() && !rid.radioEnabled()) { + return false; + } + return true; } diff --git a/p25/P25Defines.h b/p25/P25Defines.h index 4225c6a9..160106ad 100644 --- a/p25/P25Defines.h +++ b/p25/P25Defines.h @@ -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_MI_LENGTH_BYTES = 9U; + const uint32_t P25_RAW_IMBE_LENGTH_BYTES = 11U; const uint32_t P25_SS0_START = 70U; const uint32_t P25_SS1_START = 71U; diff --git a/p25/TrunkPacket.cpp b/p25/TrunkPacket.cpp index cb61041f..1c2fa0b9 100644 --- a/p25/TrunkPacket.cpp +++ b/p25/TrunkPacket.cpp @@ -1530,7 +1530,7 @@ void TrunkPacket::writeRF_TSDU_SBF(bool noNetwork, bool clearBeforeWrite, bool f // Generate TSBK block 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) { 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) { // Generate TSBK block m_rfTSBK.setLastBlock(true); // set last block - m_rfTSBK.encode(tsbk, false); + m_rfTSBK.encode(tsbk, true); if (m_debug) { 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 m_rfTSBK.setLastBlock(false); // clear last block - m_rfTSBK.encode(tsbk, false); + m_rfTSBK.encode(tsbk, true); if (m_debug) { 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 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 m_p25->addBusyBits(data, P25_TSDU_FRAME_LENGTH_BYTES, true, false); @@ -2485,7 +2485,7 @@ void TrunkPacket::writeNet_TSDU() // Regenerate TSDU Data 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 m_p25->addBusyBits(buffer + 2U, P25_TSDU_FRAME_LENGTH_BYTES, true, false); diff --git a/p25/VoicePacket.cpp b/p25/VoicePacket.cpp index 507d5d6c..7851471c 100644 --- a/p25/VoicePacket.cpp +++ b/p25/VoicePacket.cpp @@ -729,6 +729,18 @@ bool VoicePacket::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, d 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); if (m_p25->m_netState != RS_NET_IDLE) { writeNet_LDU1(control, lsd); @@ -779,17 +791,9 @@ bool VoicePacket::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, d count += 16U; 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 + if (!m_p25->m_voiceOnControl) { + m_p25->m_modem->clearP25Data(); } - - m_p25->m_modem->clearP25Data(); m_p25->m_queue.clear(); resetRF(); diff --git a/p25/acl/AccessControl.cpp b/p25/acl/AccessControl.cpp index b598b635..9fc23a75 100644 --- a/p25/acl/AccessControl.cpp +++ b/p25/acl/AccessControl.cpp @@ -65,6 +65,11 @@ bool AccessControl::validateSrcId(uint32_t id) { // check if RID ACLs are enabled if (m_ridLookup->getACL() == false) { + RadioId rid = m_ridLookup->find(id); + if (!rid.radioDefault() && !rid.radioEnabled()) { + return false; + } + return true; } diff --git a/p25/dfsi/DFSIDefines.h b/p25/dfsi/DFSIDefines.h index 4707ab12..baaf0d41 100644 --- a/p25/dfsi/DFSIDefines.h +++ b/p25/dfsi/DFSIDefines.h @@ -73,6 +73,8 @@ namespace p25 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_DISABLED = 0x04U; // diff --git a/p25/dfsi/LC.cpp b/p25/dfsi/LC.cpp index 59ba12ce..e73c6e4d 100644 --- a/p25/dfsi/LC.cpp +++ b/p25/dfsi/LC.cpp @@ -54,9 +54,11 @@ LC::LC() : m_source(P25_DFSI_DEF_SOURCE), m_control(), 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); } /// @@ -64,7 +66,7 @@ LC::LC() : /// LC::~LC() { - /* stub */ + delete[] m_mi; } /// @@ -87,6 +89,13 @@ LC& LC::operator=(const LC& data) m_control = data.m_control; m_tsbk = data.m_tsbk; 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; @@ -135,6 +144,11 @@ bool LC::decodeVHDR1(const uint8_t* data) assert(data != NULL); 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)) { LogError(LOG_P25, "LC::decodeVHDR1(), failed to decode start record"); return false; @@ -157,7 +171,7 @@ void LC::encodeVHDR1(uint8_t* data) uint8_t rawFrame[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 encodeStart(rawFrame + 1U); @@ -179,6 +193,10 @@ bool LC::decodeVHDR2(const uint8_t* data) m_control = lc::LC(); 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); m_control.setDstId(dstId); // Talkgroup Address @@ -194,16 +212,17 @@ void LC::encodeVHDR2(uint8_t* data) { assert(data != NULL); - uint8_t rawFrame[P25_DFSI_VHDR2_FRAME_LENGTH_BYTES]; - ::memset(rawFrame, 0x00U, P25_DFSI_VHDR2_FRAME_LENGTH_BYTES); + uint8_t dfsiFrame[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 - rawFrame[2U] = (m_control.getDstId() >> 8) & 0xFFU; - rawFrame[3U] = (m_control.getDstId() >> 0) & 0xFFU; + uint32_t dstId = m_control.getDstId(); + dfsiFrame[1U] = (dstId >> 16) & 0xFFU; // Talkgroup Address + 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); } /// @@ -214,7 +233,87 @@ void LC::encodeVHDR2(uint8_t* data) /// True, if decoded, otherwise false. 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; } @@ -226,11 +325,20 @@ bool LC::decodeLDU1(const uint8_t* data, uint8_t* imbe) void LC::encodeLDU1(uint8_t* data, const uint8_t* imbe) { 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 uint32_t frameLength = P25_DFSI_LDU1_VOICE1_FRAME_LENGTH_BYTES; switch (m_frameType) { + case P25_DFSI_LDU1_VOICE1: + frameLength = P25_DFSI_LDU1_VOICE1_FRAME_LENGTH_BYTES; + break; case P25_DFSI_LDU1_VOICE2: frameLength = P25_DFSI_LDU1_VOICE2_FRAME_LENGTH_BYTES; break; @@ -255,61 +363,96 @@ void LC::encodeLDU1(uint8_t* data, const uint8_t* imbe) case P25_DFSI_LDU1_VOICE9: frameLength = P25_DFSI_LDU1_VOICE9_FRAME_LENGTH_BYTES; break; - - case P25_DFSI_LDU1_VOICE1: default: - frameLength = P25_DFSI_LDU1_VOICE1_FRAME_LENGTH_BYTES; + { + LogError(LOG_P25, "LC::encodeLDU1(), invalid frametype, frameType = $%02X", m_frameType); + return; + } break; } - uint8_t rawFrame[frameLength]; - ::memset(rawFrame, 0x00U, frameLength); + uint8_t dfsiFrame[frameLength]; + ::memset(dfsiFrame, 0x00U, frameLength); - rawFrame[0U] = m_frameType; // Frame Type + dfsiFrame[0U] = m_frameType; // Frame Type // different frame types mean different things switch (m_frameType) { case P25_DFSI_LDU1_VOICE2: - // TODO TODO TODO + { + ::memcpy(dfsiFrame + 1U, imbe, P25_RAW_IMBE_LENGTH_BYTES); // IMBE + dfsiFrame[12U] = m_source; // Source + } break; 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; 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; 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; 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; 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; 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; 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; case P25_DFSI_LDU1_VOICE1: default: { - // encode start record - encodeStart(rawFrame + 1U); - - rawFrame[5U] = m_icwFlag; // ICW Flag - rawFrame[6U] = m_rssi; // RSSI - - // 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; } - ::memcpy(data, rawFrame, frameLength); + ::memcpy(data, dfsiFrame, frameLength); } /// @@ -320,7 +463,89 @@ void LC::encodeLDU1(uint8_t* data, const uint8_t* imbe) /// True, if decoded, otherwise false. 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; } @@ -332,11 +557,19 @@ bool LC::decodeLDU2(const uint8_t* data, uint8_t* imbe) void LC::encodeLDU2(uint8_t* data, const uint8_t* imbe) { 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 uint32_t frameLength = P25_DFSI_LDU2_VOICE10_FRAME_LENGTH_BYTES; switch (m_frameType) { + case P25_DFSI_LDU2_VOICE10: + frameLength = P25_DFSI_LDU2_VOICE10_FRAME_LENGTH_BYTES; + break; case P25_DFSI_LDU2_VOICE11: frameLength = P25_DFSI_LDU2_VOICE11_FRAME_LENGTH_BYTES; break; @@ -361,76 +594,138 @@ void LC::encodeLDU2(uint8_t* data, const uint8_t* imbe) case P25_DFSI_LDU2_VOICE18: frameLength = P25_DFSI_LDU2_VOICE18_FRAME_LENGTH_BYTES; break; - - case P25_DFSI_LDU2_VOICE10: default: - frameLength = P25_DFSI_LDU2_VOICE10_FRAME_LENGTH_BYTES; + { + LogError(LOG_P25, "LC::encodeLDU1(), invalid frametype, frameType = $%02X", m_frameType); + return; + } break; } + uint8_t dfsiFrame[frameLength]; + ::memset(dfsiFrame, 0x00U, frameLength); - uint8_t rawFrame[frameLength]; - ::memset(rawFrame, 0x00U, frameLength); - - rawFrame[0U] = m_frameType; // Frame Type + dfsiFrame[0U] = m_frameType; // Frame Type // different frame types mean different things switch (m_frameType) { 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; 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; 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; 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; 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; 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; 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; 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; case P25_DFSI_LDU2_VOICE10: 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; } - ::memcpy(data, rawFrame, frameLength); + ::memcpy(data, dfsiFrame, frameLength); } /// /// Decode a logical link data unit 2. /// /// -/// /// True, if decoded, otherwise false. bool LC::decodeTSBK(const uint8_t* data) { - // TODO TODO TODO - return true; + assert(data != NULL); + 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); } /// /// Encode a TSBK. /// /// -/// -void LC::encodeTSBK(uint8_t* data, const uint8_t* tsbk) +void LC::encodeTSBK(uint8_t* data) { - // 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); - m_rtModeFlag = data[1U]; // RT Mode Flag - m_startStopFlag = data[2U]; // Start/Stop Flag - m_typeFlag = data[3U]; // Type Flag + m_rtModeFlag = data[0U]; // RT Mode Flag + m_startStopFlag = data[1U]; // Start/Stop Flag + m_typeFlag = data[2U]; // Type Flag return true; } diff --git a/p25/dfsi/LC.h b/p25/dfsi/LC.h index 2407d6ee..4d3e522c 100644 --- a/p25/dfsi/LC.h +++ b/p25/dfsi/LC.h @@ -80,7 +80,7 @@ namespace p25 /// Decode a TSBK. bool decodeTSBK(const uint8_t* data); /// Encode a TSBK. - void encodeTSBK(uint8_t* data, const uint8_t* tsbk); + void encodeTSBK(uint8_t* data); public: /** Common Data */ @@ -109,6 +109,9 @@ namespace p25 __PROPERTY(p25::data::LowSpeedData, lsd, LSD); private: + /** Encryption data */ + uint8_t* m_mi; + /// Decode start record data. bool decodeStart(const uint8_t* data); /// Encode start record data. diff --git a/p25/lc/TSBK.cpp b/p25/lc/TSBK.cpp index 2fc802be..e6d20936 100644 --- a/p25/lc/TSBK.cpp +++ b/p25/lc/TSBK.cpp @@ -294,7 +294,7 @@ bool TSBK::decodeMBT(const data::DataHeader dataHeader, const uint8_t* block) m_response = (uint8_t)((tsbkValue >> 48) & 0xFFU); // Reason m_netId = (uint32_t)((tsbkValue >> 20) & 0xFFFFFU); // Network 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])); m_srcId = dataHeader.getLLId(); // Source Radio Address break; @@ -316,43 +316,60 @@ bool TSBK::decodeMBT(const data::DataHeader dataHeader, const uint8_t* block) /// Decode a trunking signalling block. /// /// +/// /// True, if TSBK was decoded, otherwise false. -bool TSBK::decode(const uint8_t* data) +bool TSBK::decode(const uint8_t* data, bool rawTSBK) { assert(data != NULL); - // deinterleave uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U]; - uint8_t raw[P25_TSBK_FEC_LENGTH_BYTES]; - P25Utils::decode(data, raw, 114U, 318U); - - // decode 1/2 rate Trellis & check CRC-CCITT 16 - try { - bool ret = m_trellis.decode12(raw, tsbk); + if (rawTSBK) { + ::memcpy(tsbk, data, P25_TSBK_LENGTH_BYTES); + + bool ret = edac::CRC::checkCCITT162(tsbk, P25_TSBK_LENGTH_BYTES); 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) { - ret = edac::CRC::checkCCITT162(tsbk, P25_TSBK_LENGTH_BYTES); + // decode 1/2 rate Trellis & check CRC-CCITT 16 + try { + bool ret = m_trellis.decode12(raw, tsbk); 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"); + LogError(LOG_P25, "TSBK::decode(), failed to decode Trellis 1/2 rate coding"); + } + + if (ret) { + ret = edac::CRC::checkCCITT162(tsbk, P25_TSBK_LENGTH_BYTES); + 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; - } - catch (...) { - Utils::dump(2U, "P25, decoding excepted with input data", tsbk, P25_TSBK_LENGTH_BYTES); - return false; - } + } + } if (m_verbose) { 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. /// /// -void TSBK::encode(uint8_t * data, bool singleBlock) +/// +/// +void TSBK::encode(uint8_t * data, bool rawTSBK, bool noTrellis) { assert(data != NULL); @@ -1040,16 +1059,21 @@ void TSBK::encode(uint8_t * data, bool singleBlock) // encode 1/2 rate Trellis m_trellis.encode12(tsbk, raw); - // is this a single block TSBK? - if (singleBlock) { + // are we encoding a raw TSBK? + if (rawTSBK) { + if (noTrellis) { + ::memcpy(data, tsbk, P25_TSBK_LENGTH_BYTES); + } + else { + ::memcpy(data, raw, P25_TSBK_FEC_LENGTH_BYTES); + } + } + else { // interleave P25Utils::encode(raw, data, 114U, 318U); // Utils::dump(2U, "TSBK Interleave", data, P25_TSBK_FEC_LENGTH_BYTES + P25_PREAMBLE_LENGTH_BYTES); } - else { - ::memcpy(data, raw, P25_TSBK_FEC_LENGTH_BYTES); - } } /// diff --git a/p25/lc/TSBK.h b/p25/lc/TSBK.h index fa6bf474..122fd908 100644 --- a/p25/lc/TSBK.h +++ b/p25/lc/TSBK.h @@ -81,9 +81,9 @@ namespace p25 bool decodeMBT(const data::DataHeader dataHeader, const uint8_t* block); /// Decode a trunking signalling block. - bool decode(const uint8_t* data); + bool decode(const uint8_t* data, bool rawTSBK = false); /// Encode a trunking signalling block. - void encode(uint8_t* data, bool singleBlock); + void encode(uint8_t* data, bool rawTSBK = false, bool noTrellis = false); /// Sets the flag to skip vendor opcode processing. void setVendorSkip(bool skip);