From 025194443853f6483142d3d725e79e586a989b1e Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Fri, 7 Jun 2024 13:05:45 -0400 Subject: [PATCH] fix ability to set MFID via REST before issuing P25 commands; implement MBT for GRP_AFF_Q_RSP; --- src/common/p25/lc/AMBT.cpp | 13 ++- src/common/p25/lc/tsbk/TSBKFactory.cpp | 3 +- src/common/p25/lc/tsbk/TSBKFactory.h | 1 + .../p25/lc/tsbk/mbt/MBT_ISP_GRP_AFF_Q_RSP.cpp | 83 +++++++++++++++++++ .../p25/lc/tsbk/mbt/MBT_ISP_GRP_AFF_Q_RSP.h | 47 +++++++++++ src/host/p25/packet/ControlSignaling.cpp | 24 ++++++ 6 files changed, 166 insertions(+), 5 deletions(-) create mode 100644 src/common/p25/lc/tsbk/mbt/MBT_ISP_GRP_AFF_Q_RSP.cpp create mode 100644 src/common/p25/lc/tsbk/mbt/MBT_ISP_GRP_AFF_Q_RSP.h diff --git a/src/common/p25/lc/AMBT.cpp b/src/common/p25/lc/AMBT.cpp index 034b1f9d..cdf37ec3 100644 --- a/src/common/p25/lc/AMBT.cpp +++ b/src/common/p25/lc/AMBT.cpp @@ -102,12 +102,12 @@ bool AMBT::decode(const data::DataHeader& dataHeader, const data::DataBlock* blo assert(pduUserData != nullptr); if (dataHeader.getFormat() != PDU_FMT_AMBT) { - LogError(LOG_P25, "TSBK::decodeMBT(), PDU is not a AMBT PDU"); + LogError(LOG_P25, "AMBT::decode(), PDU is not a AMBT PDU"); return false; } if (dataHeader.getBlocksToFollow() == 0U) { - LogError(LOG_P25, "TSBK::decodeMBT(), PDU contains no data blocks"); + LogError(LOG_P25, "AMBT::decode(), PDU contains no data blocks"); return false; } @@ -116,7 +116,7 @@ bool AMBT::decode(const data::DataHeader& dataHeader, const data::DataBlock* blo m_mfId = dataHeader.getMFId(); // Mfg Id. if (dataHeader.getOutbound()) { - LogWarning(LOG_P25, "TSBK::decodeMBT(), MBT is an outbound MBT?, mfId = $%02X, lco = $%02X", m_mfId, m_lco); + LogWarning(LOG_P25, "AMBT::decode(), MBT is an outbound MBT?, mfId = $%02X, lco = $%02X", m_mfId, m_lco); } // get PDU block data @@ -126,13 +126,18 @@ bool AMBT::decode(const data::DataHeader& dataHeader, const data::DataBlock* blo for (uint8_t i = 0; i < dataHeader.getBlocksToFollow(); i++) { uint32_t len = blocks[i].getData(pduUserData + dataOffset); if (len != P25_PDU_UNCONFIRMED_LENGTH_BYTES) { - LogError(LOG_P25, "TSBK::decodeMBT(), failed to read PDU data block"); + LogError(LOG_P25, "AMBT::decode(), failed to read PDU data block"); return false; } dataOffset += P25_PDU_UNCONFIRMED_LENGTH_BYTES; } + if (m_verbose) { + LogDebug(LOG_P25, "AMBT::decode(), mfId = $%02X, lco = $%02X, ambt8 = $%02X, ambt9 = $%02X", m_mfId, m_lco, dataHeader.getAMBTField8(), dataHeader.getAMBTField9()); + Utils::dump(2U, "AMBT::decode(), pduUserData", pduUserData, P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow()); + } + return true; } diff --git a/src/common/p25/lc/tsbk/TSBKFactory.cpp b/src/common/p25/lc/tsbk/TSBKFactory.cpp index 718579b5..7623ff03 100644 --- a/src/common/p25/lc/tsbk/TSBKFactory.cpp +++ b/src/common/p25/lc/tsbk/TSBKFactory.cpp @@ -269,7 +269,6 @@ std::unique_ptr TSBKFactory::createAMBT(const data::DataHeader& dataHeader case TSBK_IOSP_GRP_AFF: case TSBK_IOSP_U_REG: case TSBK_ISP_CAN_SRV_REQ: - case TSBK_ISP_GRP_AFF_Q_RSP: case TSBK_OSP_DENY_RSP: case TSBK_OSP_QUE_RSP: case TSBK_ISP_U_DEREG_REQ: @@ -277,6 +276,8 @@ std::unique_ptr TSBKFactory::createAMBT(const data::DataHeader& dataHeader case TSBK_ISP_LOC_REG_REQ: mfId = P25_MFG_STANDARD; break; + case TSBK_ISP_GRP_AFF_Q_RSP: + return decode(new MBT_ISP_GRP_AFF_Q_RSP(), dataHeader, blocks); default: LogError(LOG_P25, "TSBKFactory::createAMBT(), unknown TSBK LCO value, mfId = $%02X, lco = $%02X", mfId, lco); break; diff --git a/src/common/p25/lc/tsbk/TSBKFactory.h b/src/common/p25/lc/tsbk/TSBKFactory.h index 2009e8ba..54ea39f7 100644 --- a/src/common/p25/lc/tsbk/TSBKFactory.h +++ b/src/common/p25/lc/tsbk/TSBKFactory.h @@ -78,6 +78,7 @@ #include "common/p25/lc/tsbk/mbt/MBT_ISP_AUTH_RESP_M.h" #include "common/p25/lc/tsbk/mbt/MBT_ISP_AUTH_SU_DMD.h" #include "common/p25/lc/tsbk/mbt/MBT_ISP_CAN_SRV_REQ.h" +#include "common/p25/lc/tsbk/mbt/MBT_ISP_GRP_AFF_Q_RSP.h" #include "common/p25/lc/tsbk/mbt/MBT_OSP_ADJ_STS_BCAST.h" #include "common/p25/lc/tsbk/mbt/MBT_OSP_AUTH_DMD.h" #include "common/p25/lc/tsbk/mbt/MBT_OSP_NET_STS_BCAST.h" diff --git a/src/common/p25/lc/tsbk/mbt/MBT_ISP_GRP_AFF_Q_RSP.cpp b/src/common/p25/lc/tsbk/mbt/MBT_ISP_GRP_AFF_Q_RSP.cpp new file mode 100644 index 00000000..728d22d9 --- /dev/null +++ b/src/common/p25/lc/tsbk/mbt/MBT_ISP_GRP_AFF_Q_RSP.cpp @@ -0,0 +1,83 @@ +// SPDX-License-Identifier: GPL-2.0-only +/** +* Digital Voice Modem - Common Library +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Common Library +* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) +* +* Copyright (C) 2024 Bryan Biedenkapp, N2PLL +* +*/ +#include "Defines.h" +#include "p25/lc/tsbk/mbt/MBT_ISP_GRP_AFF_Q_RSP.h" + +using namespace p25::lc::tsbk; +using namespace p25::lc; +using namespace p25; + +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the MBT_ISP_GRP_AFF_Q_RSP class. +/// +MBT_ISP_GRP_AFF_Q_RSP::MBT_ISP_GRP_AFF_Q_RSP() : AMBT() +{ + m_lco = TSBK_ISP_GRP_AFF_Q_RSP; +} + +/// +/// Decode a alternate trunking signalling block. +/// +/// +/// +/// True, if TSBK was decoded, otherwise false. +bool MBT_ISP_GRP_AFF_Q_RSP::decodeMBT(const data::DataHeader& dataHeader, const data::DataBlock* blocks) +{ + assert(blocks != nullptr); + + uint8_t pduUserData[P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow()]; + ::memset(pduUserData, 0x00U, P25_PDU_UNCONFIRMED_LENGTH_BYTES * dataHeader.getBlocksToFollow()); + + bool ret = AMBT::decode(dataHeader, blocks, pduUserData); + if (!ret) + return false; + + ulong64_t tsbkValue = AMBT::toValue(dataHeader, pduUserData); + + m_netId = (uint32_t)((tsbkValue >> 44) & 0xFFFFFU); // Network ID + m_sysId = (uint32_t)((tsbkValue >> 32) & 0xFFFU); // System ID + m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFU); // Talkgroup Address + m_srcId = dataHeader.getLLId(); // Source Radio Address + + return true; +} + +/// +/// Encode a alternate trunking signalling block. +/// +/// +/// +void MBT_ISP_GRP_AFF_Q_RSP::encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData) +{ + assert(pduUserData != nullptr); + + /* stub */ + + return; +} + +/// +/// Returns a string that represents the current TSBK. +/// +/// +/// +std::string MBT_ISP_GRP_AFF_Q_RSP::toString(bool isp) +{ + return std::string("TSBK_ISP_GRP_AFF_Q_RSP (Group Affiliation Query Response)"); +} diff --git a/src/common/p25/lc/tsbk/mbt/MBT_ISP_GRP_AFF_Q_RSP.h b/src/common/p25/lc/tsbk/mbt/MBT_ISP_GRP_AFF_Q_RSP.h new file mode 100644 index 00000000..4c7d9431 --- /dev/null +++ b/src/common/p25/lc/tsbk/mbt/MBT_ISP_GRP_AFF_Q_RSP.h @@ -0,0 +1,47 @@ +// SPDX-License-Identifier: GPL-2.0-only +/** +* Digital Voice Modem - Common Library +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Common Library +* @license GPLv2 License (https://opensource.org/licenses/GPL-2.0) +* +* Copyright (C) 2024 Bryan Biedenkapp, N2PLL +* +*/ +#if !defined(__P25_LC_TSBK__MBT_ISP_GRP_AFF_Q_RSP_H__) +#define __P25_LC_TSBK__MBT_ISP_GRP_AFF_Q_RSP_H__ + +#include "common/Defines.h" +#include "common/p25/lc/AMBT.h" + +namespace p25 +{ + namespace lc + { + namespace tsbk + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements GRP AFF Q RSP - Group Affiliation Query Response + // --------------------------------------------------------------------------- + + class HOST_SW_API MBT_ISP_GRP_AFF_Q_RSP : public AMBT { + public: + /// Initializes a new instance of the MBT_ISP_GRP_AFF_Q_RSP class. + MBT_ISP_GRP_AFF_Q_RSP(); + + /// Decode a alternate trunking signalling block. + bool decodeMBT(const data::DataHeader& dataHeader, const data::DataBlock* blocks) override; + /// Encode a alternate trunking signalling block. + void encodeMBT(data::DataHeader& dataHeader, uint8_t* pduUserData) override; + + /// Returns a string that represents the current TSBK. + std::string toString(bool isp = true) override; + }; + } // namespace tsbk + } // namespace lc +} // namespace p25 + +#endif // __P25_LC_TSBK__MBT_ISP_GRP_AFF_Q_RSP_H__ diff --git a/src/host/p25/packet/ControlSignaling.cpp b/src/host/p25/packet/ControlSignaling.cpp index ea589d80..d2053ddc 100644 --- a/src/host/p25/packet/ControlSignaling.cpp +++ b/src/host/p25/packet/ControlSignaling.cpp @@ -514,6 +514,10 @@ bool ControlSignaling::process(uint8_t* data, uint32_t len, std::unique_ptrtoString(true), TSBK_ISP_GRP_AFF_Q_RSP, srcId); + if (m_p25->m_ackTSBKRequests) { + writeRF_TSDU_ACK_FNE(srcId, TSBK_ISP_GRP_AFF_Q_RSP, true, true); + } + ISP_GRP_AFF_Q_RSP* isp = static_cast(tsbk.get()); if (m_verbose) { LogMessage(LOG_RF, P25_TSDU_STR ", %s, srcId = %u, dstId = %u, anncId = %u", @@ -1006,6 +1010,11 @@ void ControlSignaling::writeRF_TSDU_Call_Alrt(uint32_t srcId, uint32_t dstId) iosp->setSrcId(srcId); iosp->setDstId(dstId); + if (m_lastMFID != P25_MFG_STANDARD) { + iosp->setMFId(m_lastMFID); + m_lastMFID = P25_MFG_STANDARD; + } + VERBOSE_LOG_TSBK(iosp->toString(), srcId, dstId); ::ActivityLog("P25", true, "call alert request from %u to %u", srcId, dstId); @@ -1047,6 +1056,11 @@ void ControlSignaling::writeRF_TSDU_Ext_Func(uint32_t func, uint32_t arg, uint32 iosp->setSrcId(arg); iosp->setDstId(dstId); + if (m_lastMFID != P25_MFG_STANDARD) { + iosp->setMFId(m_lastMFID); + m_lastMFID = P25_MFG_STANDARD; + } + if (m_verbose) { LogMessage(LOG_RF, P25_TSDU_STR ", %s, op = $%02X, arg = %u, tgt = %u", iosp->toString().c_str(), iosp->getExtendedFunction(), iosp->getSrcId(), iosp->getDstId()); @@ -1076,6 +1090,11 @@ void ControlSignaling::writeRF_TSDU_Grp_Aff_Q(uint32_t dstId) osp->setSrcId(P25_WUID_FNE); osp->setDstId(dstId); + if (m_lastMFID != P25_MFG_STANDARD) { + osp->setMFId(m_lastMFID); + m_lastMFID = P25_MFG_STANDARD; + } + VERBOSE_LOG_TSBK_DST(osp->toString(), dstId); ::ActivityLog("P25", true, "group affiliation query command from %u to %u", P25_WUID_FNE, dstId); @@ -1092,6 +1111,11 @@ void ControlSignaling::writeRF_TSDU_U_Reg_Cmd(uint32_t dstId) osp->setSrcId(P25_WUID_FNE); osp->setDstId(dstId); + if (m_lastMFID != P25_MFG_STANDARD) { + osp->setMFId(m_lastMFID); + m_lastMFID = P25_MFG_STANDARD; + } + VERBOSE_LOG_TSBK_DST(osp->toString(), dstId); ::ActivityLog("P25", true, "unit registration command from %u to %u", P25_WUID_FNE, dstId);