diff --git a/p25/DataPacket.cpp b/p25/DataPacket.cpp index cd4166fe..0ef94454 100644 --- a/p25/DataPacket.cpp +++ b/p25/DataPacket.cpp @@ -302,6 +302,17 @@ bool DataPacket::process(uint8_t* data, uint32_t len) } } break; + case PDU_SAP_TRUNK_CTRL: + { + for (uint32_t i = 0; i < blocksToFollow; i++) { + uint8_t data[P25_TSBK_FEC_LENGTH_BYTES + 2U]; + ::memset(data, 0x00U, P25_TSBK_FEC_LENGTH_BYTES + 2U); + + uint32_t len = m_rfData[i].getData(data + 2U); + m_p25->m_trunk->process(data, len, true); + } + } + break; default: ::ActivityLog("P25", true, "RF data transmission from %u to %u, %u blocks", m_rfDataHeader.getLLId(), m_rfDataHeader.getLLId(), m_rfDataHeader.getBlocksToFollow()); diff --git a/p25/P25Defines.h b/p25/P25Defines.h index 766353ce..4225c6a9 100644 --- a/p25/P25Defines.h +++ b/p25/P25Defines.h @@ -210,6 +210,7 @@ namespace p25 const uint8_t PDU_FMT_RSP = 0x03U; const uint8_t PDU_FMT_UNCONFIRMED = 0x15U; const uint8_t PDU_FMT_CONFIRMED = 0x16U; + const uint8_t PDU_FMT_AMBT = 0x17U; // PDU SAP const uint8_t PDU_SAP_USER_DATA = 0x00U; @@ -221,6 +222,7 @@ namespace p25 const uint8_t PDU_SAP_REG = 0x20U; const uint8_t PDU_SAP_UNENC_KMM = 0x28U; const uint8_t PDU_SAP_ENC_KMM = 0x29U; + const uint8_t PDU_SAP_TRUNK_CTRL = 0x3DU; // PDU ACK Class const uint8_t PDU_ACK_CLASS_ACK = 0x00U; diff --git a/p25/TrunkPacket.cpp b/p25/TrunkPacket.cpp index f76d5179..36af0dab 100644 --- a/p25/TrunkPacket.cpp +++ b/p25/TrunkPacket.cpp @@ -157,23 +157,30 @@ void TrunkPacket::resetNet() /// /// Buffer containing data frame. /// Length of data frame. +/// Flag indicating the data parameter contains MBT data. /// -bool TrunkPacket::process(uint8_t* data, uint32_t len) +bool TrunkPacket::process(uint8_t* data, uint32_t len, bool mbtData) { assert(data != NULL); if (!m_p25->m_control) return false; - // Decode the NID - bool valid = m_p25->m_nid.decode(data + 2U); + uint8_t duid = 0U; + if (!mbtData) { + // Decode the NID + bool valid = m_p25->m_nid.decode(data + 2U); - if (m_p25->m_rfState == RS_RF_LISTENING && !valid) - return false; + if (m_p25->m_rfState == RS_RF_LISTENING && !valid) + return false; - RPT_RF_STATE prevRfState = m_p25->m_rfState; - uint8_t duid = m_p25->m_nid.getDUID(); + duid = m_p25->m_nid.getDUID(); + } else { + duid = P25_DUID_TSDU; + } + RPT_RF_STATE prevRfState = m_p25->m_rfState; + // handle individual DUIDs if (duid == P25_DUID_TSDU) { if (m_p25->m_rfState != RS_RF_DATA) { diff --git a/p25/TrunkPacket.h b/p25/TrunkPacket.h index aa8ac381..7bbb31e7 100644 --- a/p25/TrunkPacket.h +++ b/p25/TrunkPacket.h @@ -61,7 +61,7 @@ namespace p25 void resetNet(); /// Process a data frame from the RF interface. - bool process(uint8_t* data, uint32_t len); + bool process(uint8_t* data, uint32_t len, bool mbtData = false); /// Process a data frame from the network. bool processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::LowSpeedData& lsd, uint8_t& duid); diff --git a/p25/data/DataHeader.cpp b/p25/data/DataHeader.cpp index e111210d..30e13d4a 100644 --- a/p25/data/DataHeader.cpp +++ b/p25/data/DataHeader.cpp @@ -54,6 +54,7 @@ DataHeader::DataHeader() : m_n(0U), m_seqNo(0U), m_headerOffset(0U), + m_ambtOpcode(0U), m_trellis(), m_blocksToFollow(0U), m_padCount(0U), @@ -103,8 +104,15 @@ bool DataHeader::decode(const uint8_t* data) m_llId = (header[3U] << 16) + (header[4U] << 8) + header[5U]; // Logical Link ID m_fullMessage = (header[6U] & 0x80U) == 0x80U; // Full Message Flag + m_blocksToFollow = header[6U] & 0x7FU; // Block Frames to Follow - m_padCount = header[7U] & 0x1FU; // Pad Count + if (m_fmt == PDU_FMT_AMBT) { + m_padCount = 0; + m_ambtOpcode = header[7U] & 0x3FU; // AMBT Opcode + } + else { + m_padCount = header[7U] & 0x1FU; // Pad Count + } if (m_fmt == PDU_FMT_CONFIRMED) { m_dataOctets = 16 * m_blocksToFollow - 4 - m_padCount; @@ -150,7 +158,12 @@ void DataHeader::encode(uint8_t* data) header[6U] = (m_fullMessage ? 0x80U : 0x00U) + // Full Message Flag (m_blocksToFollow & 0x7FU); // Blocks Frames to Follow - header[7U] = (m_padCount & 0x1FU); // Pad Count + if (m_fmt == PDU_FMT_AMBT) { + header[7U] = (m_ambtOpcode & 0x3FU); // AMBT Opcode + } + else { + header[7U] = (m_padCount & 0x1FU); // Pad Count + } header[8U] = (m_sync ? 0x80U : 0x00U) + // Re-synchronize Flag ((m_n << 4) && 0x07U) + // Packet Sequence No. @@ -191,6 +204,7 @@ void DataHeader::reset() m_seqNo = 0U; m_headerOffset = 0U; + m_ambtOpcode = 0U; } /// Gets the total number of data octets. diff --git a/p25/data/DataHeader.h b/p25/data/DataHeader.h index 57f5a231..084e94bf 100644 --- a/p25/data/DataHeader.h +++ b/p25/data/DataHeader.h @@ -91,6 +91,8 @@ namespace p25 __PROPERTY(uint8_t, seqNo, SeqNo); /// Offset of the header. __PROPERTY(uint8_t, headerOffset, HeaderOffset); + /// Alternate Trunking Block Opcode + __PROPERTY(uint8_t, ambtOpcode, AMBTOpcode); private: edac::Trellis m_trellis;