when decoding a PDU data block ensure class variables are set to reasonable defaults (since the actual DataBlock class tends to be reused); ensure DataHeader is passed to DataBlock decode() and setFormat() by reference; implement supporton DataHeader to retreive the raw byte contents of a decoded PDU header; ensure the PDU Rx process resets the second header data, irregardless of use; if we are using a PDU second header, ensure its data contents are added to pduUserData as the second header contents are CRC-32'ed along side all the data blocks (infact only the initial header is excluded from CRC-32 all other blocks following initial header *must* be CRC-32'ed with the data blocks); refactor PDU last block detection; ensure writeRF_PDU_Buffered and writeNet_PDU_Buffered regenerate the full packet CRC-32;

pull/35/head
Bryan Biedenkapp 3 years ago
parent 20882d5100
commit 9b43411376

@ -71,7 +71,7 @@ DataBlock::~DataBlock()
/// <param name="data"></param> /// <param name="data"></param>
/// <param name="header">Instance of the DataHeader class.</param> /// <param name="header">Instance of the DataHeader class.</param>
/// <returns>True, if data block was decoded, otherwise false.</returns> /// <returns>True, if data block was decoded, otherwise false.</returns>
bool DataBlock::decode(const uint8_t* data, const DataHeader header) bool DataBlock::decode(const uint8_t* data, const DataHeader& header)
{ {
assert(data != nullptr); assert(data != nullptr);
assert(m_data != nullptr); assert(m_data != nullptr);
@ -82,6 +82,11 @@ bool DataBlock::decode(const uint8_t* data, const DataHeader header)
m_fmt = header.getFormat(); m_fmt = header.getFormat();
m_headerSap = header.getSAP(); m_headerSap = header.getSAP();
// set these to reasonable defaults
m_serialNo = 0U;
m_lastBlock = false;
m_llId = 0U;
if (m_fmt == PDU_FMT_CONFIRMED) { if (m_fmt == PDU_FMT_CONFIRMED) {
// decode 3/4 rate Trellis // decode 3/4 rate Trellis
try { try {
@ -91,16 +96,6 @@ bool DataBlock::decode(const uint8_t* data, const DataHeader header)
return false; return false;
} }
// determine if this is the last data block
uint32_t count = P25_PDU_CONFIRMED_DATA_LENGTH_BYTES;
if (m_serialNo == (header.getBlocksToFollow() - 1) && header.getBlocksToFollow() > 1) {
m_lastBlock = true;
} else {
if (header.getBlocksToFollow() <= 1) {
m_lastBlock = true;
}
}
#if DEBUG_P25_PDU_DATA #if DEBUG_P25_PDU_DATA
Utils::dump(1U, "P25, DataBlock::decode(), PDU Confirmed Data Block", buffer, P25_PDU_CONFIRMED_LENGTH_BYTES); Utils::dump(1U, "P25, DataBlock::decode(), PDU Confirmed Data Block", buffer, P25_PDU_CONFIRMED_LENGTH_BYTES);
#endif #endif
@ -111,6 +106,7 @@ bool DataBlock::decode(const uint8_t* data, const DataHeader header)
::memset(m_data, 0x00U, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES); ::memset(m_data, 0x00U, P25_PDU_CONFIRMED_DATA_LENGTH_BYTES);
// if this is extended addressing and the first block decode the SAP and LLId // if this is extended addressing and the first block decode the SAP and LLId
uint32_t count = P25_PDU_CONFIRMED_DATA_LENGTH_BYTES;
if (m_headerSap == PDU_SAP_EXT_ADDR && m_serialNo == 0U) { if (m_headerSap == PDU_SAP_EXT_ADDR && m_serialNo == 0U) {
count = P25_PDU_CONFIRMED_DATA_LENGTH_BYTES - 4U; count = P25_PDU_CONFIRMED_DATA_LENGTH_BYTES - 4U;
@ -225,28 +221,36 @@ void DataBlock::encode(uint8_t* data)
} }
} }
/// <summary>Sets the data format.</summary> /// <summary>
/// Sets the data format.
/// </summary>
/// <param name="fmt"></param> /// <param name="fmt"></param>
void DataBlock::setFormat(const uint8_t fmt) void DataBlock::setFormat(const uint8_t fmt)
{ {
m_fmt = fmt; m_fmt = fmt;
} }
/// <summary>Sets the data format from the data header.</summary> /// <summary>
/// Sets the data format from the data header.
/// </summary>
/// <param name="header"></param> /// <param name="header"></param>
void DataBlock::setFormat(const DataHeader header) void DataBlock::setFormat(const DataHeader& header)
{ {
m_fmt = header.getFormat(); m_fmt = header.getFormat();
} }
/// <summary>Gets the data format.</summary> /// <summary>
/// Gets the data format.
/// </summary>
/// <returns></returns> /// <returns></returns>
uint8_t DataBlock::getFormat() const uint8_t DataBlock::getFormat() const
{ {
return m_fmt; return m_fmt;
} }
/// <summary>Sets the raw data stored in the data block.</summary> /// <summary>
/// Sets the raw data stored in the data block.
/// </summary>
/// <param name="buffer"></param> /// <param name="buffer"></param>
void DataBlock::setData(const uint8_t* buffer) void DataBlock::setData(const uint8_t* buffer)
{ {
@ -264,7 +268,9 @@ void DataBlock::setData(const uint8_t* buffer)
} }
} }
/// <summary>Gets the raw data stored in the data block.</summary> /// <summary>
/// Gets the raw data stored in the data block.
/// </summary>
/// <returns></returns> /// <returns></returns>
uint32_t DataBlock::getData(uint8_t* buffer) const uint32_t DataBlock::getData(uint8_t* buffer) const
{ {

@ -49,14 +49,14 @@ namespace p25
~DataBlock(); ~DataBlock();
/// <summary>Decodes P25 PDU data block.</summary> /// <summary>Decodes P25 PDU data block.</summary>
bool decode(const uint8_t* data, const DataHeader header); bool decode(const uint8_t* data, const DataHeader& header);
/// <summary>Encodes a P25 PDU data block.</summary> /// <summary>Encodes a P25 PDU data block.</summary>
void encode(uint8_t* data); void encode(uint8_t* data);
/// <summary>Sets the data format.</summary> /// <summary>Sets the data format.</summary>
void setFormat(const uint8_t fmt); void setFormat(const uint8_t fmt);
/// <summary>Sets the data format from the data header.</summary> /// <summary>Sets the data format from the data header.</summary>
void setFormat(const DataHeader header); void setFormat(const DataHeader& header);
/// <summary>Gets the data format.</summary> /// <summary>Gets the data format.</summary>
uint8_t getFormat() const; uint8_t getFormat() const;

@ -67,9 +67,11 @@ DataHeader::DataHeader() :
m_trellis(), m_trellis(),
m_blocksToFollow(0U), m_blocksToFollow(0U),
m_padCount(0U), m_padCount(0U),
m_dataOctets(0U) m_dataOctets(0U),
m_data(nullptr)
{ {
/* stub */ m_data = new uint8_t[P25_PDU_HEADER_LENGTH_BYTES];
::memset(m_data, 0x00U, P25_PDU_HEADER_LENGTH_BYTES);
} }
/// <summary> /// <summary>
@ -77,7 +79,7 @@ DataHeader::DataHeader() :
/// </summary> /// </summary>
DataHeader::~DataHeader() DataHeader::~DataHeader()
{ {
/* stub */ delete[] m_data;
} }
/// <summary> /// <summary>
@ -89,35 +91,32 @@ bool DataHeader::decode(const uint8_t* data)
{ {
assert(data != nullptr); assert(data != nullptr);
uint8_t header[P25_PDU_HEADER_LENGTH_BYTES];
::memset(header, 0x00U, P25_PDU_HEADER_LENGTH_BYTES);
// decode 1/2 rate Trellis & check CRC-CCITT 16 // decode 1/2 rate Trellis & check CRC-CCITT 16
bool valid = m_trellis.decode12(data, header); bool valid = m_trellis.decode12(data, m_data);
if (valid) if (valid)
valid = edac::CRC::checkCCITT162(header, P25_PDU_HEADER_LENGTH_BYTES); valid = edac::CRC::checkCCITT162(m_data, P25_PDU_HEADER_LENGTH_BYTES);
if (!valid) { if (!valid) {
return false; return false;
} }
#if DEBUG_P25_PDU_DATA #if DEBUG_P25_PDU_DATA
Utils::dump(1U, "P25, DataHeader::decode(), PDU Header Data", header, P25_PDU_HEADER_LENGTH_BYTES); Utils::dump(1U, "P25, DataHeader::decode(), PDU Header Data", m_data, P25_PDU_HEADER_LENGTH_BYTES);
#endif #endif
m_ackNeeded = (header[0U] & 0x40U) == 0x40U; // Acknowledge Needed m_ackNeeded = (m_data[0U] & 0x40U) == 0x40U; // Acknowledge Needed
m_outbound = (header[0U] & 0x20U) == 0x20U; // Inbound/Outbound m_outbound = (m_data[0U] & 0x20U) == 0x20U; // Inbound/Outbound
m_fmt = header[0U] & 0x1FU; // Packet Format m_fmt = m_data[0U] & 0x1FU; // Packet Format
m_sap = header[1U] & 0x3FU; // Service Access Point m_sap = m_data[1U] & 0x3FU; // Service Access Point
m_mfId = header[2U]; // Mfg Id. m_mfId = m_data[2U]; // Mfg Id.
m_llId = (header[3U] << 16) + (header[4U] << 8) + header[5U]; // Logical Link ID m_llId = (m_data[3U] << 16) + (m_data[4U] << 8) + m_data[5U]; // Logical Link ID
m_F = (header[6U] & 0x80U) == 0x80U; // Full Message Flag m_F = (m_data[6U] & 0x80U) == 0x80U; // Full Message Flag
m_blocksToFollow = header[6U] & 0x7FU; // Block Frames to Follow m_blocksToFollow = m_data[6U] & 0x7FU; // Block Frames to Follow
m_padCount = header[7U] & 0x1FU; // Pad Count m_padCount = m_data[7U] & 0x1FU; // Pad Count
if (m_fmt == PDU_FMT_RSP || m_fmt == PDU_FMT_AMBT) { if (m_fmt == PDU_FMT_RSP || m_fmt == PDU_FMT_AMBT) {
m_padCount = 0; m_padCount = 0;
} }
@ -131,28 +130,28 @@ bool DataHeader::decode(const uint8_t* data)
switch (m_fmt) { switch (m_fmt) {
case PDU_FMT_CONFIRMED: case PDU_FMT_CONFIRMED:
m_S = (header[8U] & 0x80U) == 0x80U; // Re-synchronize Flag m_S = (m_data[8U] & 0x80U) == 0x80U; // Re-synchronize Flag
m_Ns = (header[8U] >> 4) & 0x07U; // Packet Sequence No. m_Ns = (m_data[8U] >> 4) & 0x07U; // Packet Sequence No.
m_fsn = header[8U] & 0x07U; // Fragment Sequence No. m_fsn = m_data[8U] & 0x07U; // Fragment Sequence No.
m_lastFragment = (header[8U] & 0x08U) == 0x08U; // Last Fragment Flag m_lastFragment = (m_data[8U] & 0x08U) == 0x08U; // Last Fragment Flag
m_headerOffset = header[9U] & 0x3FU; // Data Header Offset m_headerOffset = m_data[9U] & 0x3FU; // Data Header Offset
break; break;
case PDU_FMT_RSP: case PDU_FMT_RSP:
m_ackNeeded = false; m_ackNeeded = false;
m_sap = PDU_SAP_USER_DATA; m_sap = PDU_SAP_USER_DATA;
m_rspClass = (header[1U] >> 6) & 0x03U; // Response Class m_rspClass = (m_data[1U] >> 6) & 0x03U; // Response Class
m_rspType = (header[1U] >> 3) & 0x07U; // Response Type m_rspType = (m_data[1U] >> 3) & 0x07U; // Response Type
m_rspStatus = header[1U] & 0x07U; // Response Status m_rspStatus = m_data[1U] & 0x07U; // Response Status
if (!m_F) { if (!m_F) {
m_srcLlId = (header[7U] << 16) + (header[8U] << 8) + header[9U]; // Source Logical Link ID m_srcLlId = (m_data[7U] << 16) + (m_data[8U] << 8) + m_data[9U]; // Source Logical Link ID
} }
break; break;
case PDU_FMT_AMBT: case PDU_FMT_AMBT:
m_ambtOpcode = header[7U] & 0x3FU; // AMBT Opcode m_ambtOpcode = m_data[7U] & 0x3FU; // AMBT Opcode
m_ambtField8 = header[8U]; // AMBT Field 8 m_ambtField8 = m_data[8U]; // AMBT Field 8
m_ambtField9 = header[9U]; // AMBT Field 9 m_ambtField9 = m_data[9U]; // AMBT Field 9
// fall-thru // fall-thru
case PDU_FMT_UNCONFIRMED: case PDU_FMT_UNCONFIRMED:
default: default:
@ -207,9 +206,8 @@ void DataHeader::encode(uint8_t* data)
switch (m_fmt) { switch (m_fmt) {
case PDU_FMT_CONFIRMED: case PDU_FMT_CONFIRMED:
header[7U] = (m_padCount & 0x1FU); // Pad Count header[7U] = (m_padCount & 0x1FU); // Pad Count
header[8U] = (m_S ? 0x80U : 0x00U) + // Re-synchronize Flag header[8U] = (m_S ? 0x80U : 0x00U) + // Re-synchronize Flag
((m_Ns << 4) & 0x07U) + // Packet Sequence No. ((m_Ns & 0x07U) << 4) + // Packet Sequence No.
(m_lastFragment ? 0x08U : 0x00U) + // Last Fragment Flag (m_lastFragment ? 0x08U : 0x00U) + // Last Fragment Flag
(m_fsn & 0x07); // Fragment Sequence No. (m_fsn & 0x07); // Fragment Sequence No.
@ -232,6 +230,7 @@ void DataHeader::encode(uint8_t* data)
break; break;
case PDU_FMT_UNCONFIRMED: case PDU_FMT_UNCONFIRMED:
default: default:
header[7U] = (m_padCount & 0x1FU); // Pad Count
header[8U] = 0x00U; header[8U] = 0x00U;
header[9U] = m_headerOffset & 0x3FU; // Data Header Offset header[9U] = m_headerOffset & 0x3FU; // Data Header Offset
break; break;
@ -284,17 +283,36 @@ void DataHeader::reset()
m_ambtOpcode = 0U; m_ambtOpcode = 0U;
m_ambtField8 = 0U; m_ambtField8 = 0U;
m_ambtField9 = 0U; m_ambtField9 = 0U;
::memset(m_data, 0x00U, P25_PDU_HEADER_LENGTH_BYTES);
} }
/// <summary>Gets the total number of data octets.</summary> /// <summary>
/// Gets the total number of data octets.
/// </summary>
/// <returns></returns> /// <returns></returns>
uint32_t DataHeader::getDataOctets() const uint32_t DataHeader::getDataOctets() const
{ {
return m_dataOctets; return m_dataOctets;
} }
/// <summary>
/// Gets the raw header data.
/// </summary>
/// <returns></returns>
uint32_t DataHeader::getData(uint8_t* buffer) const
{
assert(buffer != nullptr);
assert(m_data != nullptr);
::memcpy(buffer, m_data, P25_PDU_HEADER_LENGTH_BYTES);
return P25_PDU_HEADER_LENGTH_BYTES;
}
/** Common Data */ /** Common Data */
/// <summary>Sets the total number of blocks to follow this header.</summary> /// <summary>
/// Sets the total number of blocks to follow this header.
/// </summary>
/// <param name="blocksToFollow"></param> /// <param name="blocksToFollow"></param>
void DataHeader::setBlocksToFollow(uint8_t blocksToFollow) void DataHeader::setBlocksToFollow(uint8_t blocksToFollow)
{ {
@ -309,14 +327,18 @@ void DataHeader::setBlocksToFollow(uint8_t blocksToFollow)
} }
} }
/// <summary>Gets the total number of blocks to follow this header.</summary> /// <summary>
/// Gets the total number of blocks to follow this header.
/// </summary>
/// <returns></returns> /// <returns></returns>
uint8_t DataHeader::getBlocksToFollow() const uint8_t DataHeader::getBlocksToFollow() const
{ {
return m_blocksToFollow; return m_blocksToFollow;
} }
/// <summary>Sets the count of block padding.</summary> /// <summary>
/// Sets the count of block padding.
/// </summary>
/// <param name="padCount"></param> /// <param name="padCount"></param>
void DataHeader::setPadCount(uint8_t padCount) void DataHeader::setPadCount(uint8_t padCount)
{ {
@ -331,7 +353,9 @@ void DataHeader::setPadCount(uint8_t padCount)
} }
} }
/// <summary>Gets the count of block padding.</summary> /// <summary>
/// Gets the count of block padding.
/// </summary>
/// <returns></returns> /// <returns></returns>
uint8_t DataHeader::getPadCount() const uint8_t DataHeader::getPadCount() const
{ {

@ -58,6 +58,9 @@ namespace p25
/// <summary>Gets the total number of data octets.</summary> /// <summary>Gets the total number of data octets.</summary>
uint32_t getDataOctets() const; uint32_t getDataOctets() const;
/// <summary>Gets the raw header data.</summary>
uint32_t getData(uint8_t* buffer) const;
/** Common Data */ /** Common Data */
/// <summary>Sets the total number of blocks to follow this header.</summary> /// <summary>Sets the total number of blocks to follow this header.</summary>
void setBlocksToFollow(uint8_t blocksToFollow); void setBlocksToFollow(uint8_t blocksToFollow);
@ -119,6 +122,8 @@ namespace p25
uint8_t m_blocksToFollow; uint8_t m_blocksToFollow;
uint8_t m_padCount; uint8_t m_padCount;
uint32_t m_dataOctets; uint32_t m_dataOctets;
uint8_t* m_data;
}; };
} // namespace data } // namespace data
} // namespace p25 } // namespace p25

@ -134,6 +134,7 @@ bool Data::process(uint8_t* data, uint32_t len)
Utils::dump(1U, "Unfixable PDU Data", buffer, P25_PDU_FEC_LENGTH_BYTES); Utils::dump(1U, "Unfixable PDU Data", buffer, P25_PDU_FEC_LENGTH_BYTES);
m_rfDataHeader.reset(); m_rfDataHeader.reset();
m_rfSecondHeader.reset();
m_rfDataBlockCnt = 0U; m_rfDataBlockCnt = 0U;
m_rfPDUCount = 0U; m_rfPDUCount = 0U;
m_rfPDUBits = 0U; m_rfPDUBits = 0U;
@ -153,6 +154,7 @@ bool Data::process(uint8_t* data, uint32_t len)
LogError(LOG_RF, P25_PDU_STR ", too many PDU blocks to process, %u > %u", m_rfDataHeader.getBlocksToFollow(), P25_MAX_PDU_COUNT); LogError(LOG_RF, P25_PDU_STR ", too many PDU blocks to process, %u > %u", m_rfDataHeader.getBlocksToFollow(), P25_MAX_PDU_COUNT);
m_rfDataHeader.reset(); m_rfDataHeader.reset();
m_rfSecondHeader.reset();
m_rfDataBlockCnt = 0U; m_rfDataBlockCnt = 0U;
m_rfPDUCount = 0U; m_rfPDUCount = 0U;
m_rfPDUBits = 0U; m_rfPDUBits = 0U;
@ -219,11 +221,29 @@ bool Data::process(uint8_t* data, uint32_t len)
if (m_rfPDUBits >= bitLength) { if (m_rfPDUBits >= bitLength) {
// process all blocks in the data stream // process all blocks in the data stream
uint32_t dataOffset = 0U; uint32_t dataOffset = 0U;
// if we are using a secondary header place it in the PDU user data buffer
if (m_rfUseSecondHeader) {
m_rfSecondHeader.getData(m_pduUserData + dataOffset);
dataOffset += P25_PDU_HEADER_LENGTH_BYTES;
m_pduUserDataLength += P25_PDU_HEADER_LENGTH_BYTES;
}
// decode data blocks
for (uint32_t i = 0U; i < blocksToFollow; i++) { for (uint32_t i = 0U; i < blocksToFollow; i++) {
::memset(buffer, 0x00U, P25_PDU_FEC_LENGTH_BYTES); ::memset(buffer, 0x00U, P25_PDU_FEC_LENGTH_BYTES);
Utils::getBitRange(m_rfPDU, buffer, offset, P25_PDU_FEC_LENGTH_BITS); Utils::getBitRange(m_rfPDU, buffer, offset, P25_PDU_FEC_LENGTH_BITS);
bool ret = m_rfData[i].decode(buffer, (m_rfUseSecondHeader) ? m_rfSecondHeader : m_rfDataHeader); bool ret = m_rfData[i].decode(buffer, (m_rfUseSecondHeader) ? m_rfSecondHeader : m_rfDataHeader);
if (ret) { if (ret) {
// if we are getting unconfirmed or confirmed blocks, and if we've reached the total number of blocks
// set this block as the last block for full packet CRC
if ((m_rfDataHeader.getFormat() == PDU_FMT_CONFIRMED) || (m_rfDataHeader.getFormat() == PDU_FMT_UNCONFIRMED)) {
if ((m_rfDataBlockCnt + 1U) == blocksToFollow) {
m_rfData[i].setLastBlock(true);
}
}
// are we processing extended address data from the first block?
if (m_rfDataHeader.getSAP() == PDU_SAP_EXT_ADDR && m_rfDataHeader.getFormat() == PDU_FMT_CONFIRMED && if (m_rfDataHeader.getSAP() == PDU_SAP_EXT_ADDR && m_rfDataHeader.getFormat() == PDU_FMT_CONFIRMED &&
m_rfData[i].getSerialNo() == 0U) { m_rfData[i].getSerialNo() == 0U) {
LogMessage(LOG_RF, P25_PDU_STR ", block %u, fmt = $%02X, lastBlock = %u, sap = $%02X, llId = %u", LogMessage(LOG_RF, P25_PDU_STR ", block %u, fmt = $%02X, lastBlock = %u, sap = $%02X, llId = %u",
@ -430,6 +450,7 @@ bool Data::processNetwork(uint8_t* data, uint32_t len, uint32_t blockLength)
Utils::dump(1U, "Unfixable PDU Data", buffer, P25_PDU_FEC_LENGTH_BYTES); Utils::dump(1U, "Unfixable PDU Data", buffer, P25_PDU_FEC_LENGTH_BYTES);
m_netDataHeader.reset(); m_netDataHeader.reset();
m_netSecondHeader.reset();
m_netDataBlockCnt = 0U; m_netDataBlockCnt = 0U;
m_netPDUCount = 0U; m_netPDUCount = 0U;
m_p25->m_netState = RS_NET_IDLE; m_p25->m_netState = RS_NET_IDLE;
@ -448,6 +469,7 @@ bool Data::processNetwork(uint8_t* data, uint32_t len, uint32_t blockLength)
LogError(LOG_NET, P25_PDU_STR ", too many PDU blocks to process, %u > %u", m_netDataHeader.getBlocksToFollow(), P25_MAX_PDU_COUNT); LogError(LOG_NET, P25_PDU_STR ", too many PDU blocks to process, %u > %u", m_netDataHeader.getBlocksToFollow(), P25_MAX_PDU_COUNT);
m_netDataHeader.reset(); m_netDataHeader.reset();
m_netSecondHeader.reset();
m_netDataOffset = 0U; m_netDataOffset = 0U;
m_netDataBlockCnt = 0U; m_netDataBlockCnt = 0U;
m_netPDUCount = 0U; m_netPDUCount = 0U;
@ -510,12 +532,30 @@ bool Data::processNetwork(uint8_t* data, uint32_t len, uint32_t blockLength)
// process all blocks in the data stream // process all blocks in the data stream
uint32_t dataOffset = 0U; uint32_t dataOffset = 0U;
// if we are using a secondary header place it in the PDU user data buffer
if (m_netUseSecondHeader) {
m_netSecondHeader.getData(m_pduUserData + dataOffset);
dataOffset += P25_PDU_HEADER_LENGTH_BYTES;
m_pduUserDataLength += P25_PDU_HEADER_LENGTH_BYTES;
}
// decode data blocks
for (uint32_t i = 0U; i < blocksToFollow; i++) { for (uint32_t i = 0U; i < blocksToFollow; i++) {
::memset(buffer, 0x00U, P25_PDU_FEC_LENGTH_BYTES); ::memset(buffer, 0x00U, P25_PDU_FEC_LENGTH_BYTES);
::memcpy(buffer, m_netPDU + offset, P25_PDU_FEC_LENGTH_BYTES); ::memcpy(buffer, m_netPDU + offset, P25_PDU_FEC_LENGTH_BYTES);
bool ret = m_netData[i].decode(buffer, (m_netUseSecondHeader) ? m_netSecondHeader : m_netDataHeader); bool ret = m_netData[i].decode(buffer, (m_netUseSecondHeader) ? m_netSecondHeader : m_netDataHeader);
if (ret) { if (ret) {
// if we are getting unconfirmed or confirmed blocks, and if we've reached the total number of blocks
// set this block as the last block for full packet CRC
if ((m_netDataHeader.getFormat() == PDU_FMT_CONFIRMED) || (m_netDataHeader.getFormat() == PDU_FMT_UNCONFIRMED)) {
if ((m_netDataBlockCnt + 1U) == blocksToFollow) {
m_netData[i].setLastBlock(true);
}
}
// are we processing extended address data from the first block?
if (m_netDataHeader.getSAP() == PDU_SAP_EXT_ADDR && m_netDataHeader.getFormat() == PDU_FMT_CONFIRMED && if (m_netDataHeader.getSAP() == PDU_SAP_EXT_ADDR && m_netDataHeader.getFormat() == PDU_FMT_CONFIRMED &&
m_netData[i].getSerialNo() == 0U) { m_netData[i].getSerialNo() == 0U) {
LogMessage(LOG_NET, P25_PDU_STR ", block %u, fmt = $%02X, lastBlock = %u, sap = $%02X, llId = %u", LogMessage(LOG_NET, P25_PDU_STR ", block %u, fmt = $%02X, lastBlock = %u, sap = $%02X, llId = %u",
@ -867,12 +907,15 @@ void Data::writeNet_PDU_Buffered()
uint32_t blocksToFollow = m_netDataHeader.getBlocksToFollow(); uint32_t blocksToFollow = m_netDataHeader.getBlocksToFollow();
// Generate the PDU header and 1/2 rate Trellis // generate the PDU header and 1/2 rate Trellis
m_netDataHeader.encode(block); m_netDataHeader.encode(block);
Utils::setBitRange(block, data, offset, P25_PDU_FEC_LENGTH_BITS); Utils::setBitRange(block, data, offset, P25_PDU_FEC_LENGTH_BITS);
offset += P25_PDU_FEC_LENGTH_BITS; offset += P25_PDU_FEC_LENGTH_BITS;
// Generate the second PDU header uint32_t dataOffset = 0U;
edac::CRC::addCRC32(m_pduUserData, m_pduUserDataLength);
// generate the second PDU header
if (m_netUseSecondHeader) { if (m_netUseSecondHeader) {
::memset(block, 0x00U, P25_PDU_FEC_LENGTH_BYTES); ::memset(block, 0x00U, P25_PDU_FEC_LENGTH_BYTES);
@ -880,11 +923,11 @@ void Data::writeNet_PDU_Buffered()
Utils::setBitRange(block, data, offset, P25_PDU_FEC_LENGTH_BITS); Utils::setBitRange(block, data, offset, P25_PDU_FEC_LENGTH_BITS);
offset += P25_PDU_FEC_LENGTH_BITS; offset += P25_PDU_FEC_LENGTH_BITS;
dataOffset += P25_PDU_HEADER_LENGTH_BYTES;
blocksToFollow--; blocksToFollow--;
} }
// Generate the PDU data // generate the PDU data
uint32_t dataOffset = 0U;
for (uint32_t i = 0U; i < blocksToFollow; i++) { for (uint32_t i = 0U; i < blocksToFollow; i++) {
m_netData[i].setFormat((m_netUseSecondHeader) ? m_netSecondHeader : m_netDataHeader); m_netData[i].setFormat((m_netUseSecondHeader) ? m_netSecondHeader : m_netDataHeader);
m_netData[i].setSerialNo(i); m_netData[i].setSerialNo(i);
@ -917,12 +960,15 @@ void Data::writeRF_PDU_Buffered()
uint32_t blocksToFollow = m_rfDataHeader.getBlocksToFollow(); uint32_t blocksToFollow = m_rfDataHeader.getBlocksToFollow();
// Generate the PDU header and 1/2 rate Trellis // generate the PDU header and 1/2 rate Trellis
m_rfDataHeader.encode(block); m_rfDataHeader.encode(block);
Utils::setBitRange(block, data, offset, P25_PDU_FEC_LENGTH_BITS); Utils::setBitRange(block, data, offset, P25_PDU_FEC_LENGTH_BITS);
offset += P25_PDU_FEC_LENGTH_BITS; offset += P25_PDU_FEC_LENGTH_BITS;
// Generate the second PDU header uint32_t dataOffset = 0U;
edac::CRC::addCRC32(m_pduUserData, m_pduUserDataLength);
// generate the second PDU header
if (m_rfUseSecondHeader) { if (m_rfUseSecondHeader) {
::memset(block, 0x00U, P25_PDU_FEC_LENGTH_BYTES); ::memset(block, 0x00U, P25_PDU_FEC_LENGTH_BYTES);
@ -930,11 +976,11 @@ void Data::writeRF_PDU_Buffered()
Utils::setBitRange(block, data, offset, P25_PDU_FEC_LENGTH_BITS); Utils::setBitRange(block, data, offset, P25_PDU_FEC_LENGTH_BITS);
offset += P25_PDU_FEC_LENGTH_BITS; offset += P25_PDU_FEC_LENGTH_BITS;
dataOffset += P25_PDU_HEADER_LENGTH_BYTES;
blocksToFollow--; blocksToFollow--;
} }
// Generate the PDU data // generate the PDU data
uint32_t dataOffset = 0U;
for (uint32_t i = 0U; i < blocksToFollow; i++) { for (uint32_t i = 0U; i < blocksToFollow; i++) {
m_rfData[i].setFormat((m_rfUseSecondHeader) ? m_rfSecondHeader : m_rfDataHeader); m_rfData[i].setFormat((m_rfUseSecondHeader) ? m_rfSecondHeader : m_rfDataHeader);
m_rfData[i].setSerialNo(i); m_rfData[i].setSerialNo(i);

Loading…
Cancel
Save

Powered by TurnKey Linux.