From 8acd86785458e351fa0f4c32c0485609392023d2 Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Sat, 17 Jan 2026 19:16:47 -0500 Subject: [PATCH] BUGFIX: handle edge case where a opcode $27 is not an ISP_EMERG_ALARM_REQ but rather its a network sourced OSP_DENY_RSP; BUGFIX: handle incorrect decoding of OSP_DENY_RSP by SysView; BUGFIX: for DVRS operation properly set MFG_MOT for DENY and QUEUE outbounds; --- src/common/p25/lc/tsbk/ISP_EMERG_ALRM_REQ.cpp | 25 +++++++++++++------ src/host/p25/packet/ControlSignaling.cpp | 4 ++- src/sysview/SysViewMain.cpp | 15 +++++++---- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/common/p25/lc/tsbk/ISP_EMERG_ALRM_REQ.cpp b/src/common/p25/lc/tsbk/ISP_EMERG_ALRM_REQ.cpp index 3cc80f99..62d5f2da 100644 --- a/src/common/p25/lc/tsbk/ISP_EMERG_ALRM_REQ.cpp +++ b/src/common/p25/lc/tsbk/ISP_EMERG_ALRM_REQ.cpp @@ -4,7 +4,7 @@ * GPLv2 Open Source. Use is subject to license terms. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * Copyright (C) 2022,2024 Bryan Biedenkapp, N2PLL + * Copyright (C) 2022,2024,2026 Bryan Biedenkapp, N2PLL * */ #include "Defines.h" @@ -47,16 +47,27 @@ bool ISP_EMERG_ALRM_REQ::decode(const uint8_t* data, bool rawTSBK) ** bryanb: this is a bit of a hack -- because the EMERG ALRM and DENY have the same ** opcode; the following are used by TSBK_OSP_DENY_RSP; best way to check is for m_response > 0 */ - m_aivFlag = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Additional Info. Flag - m_service = (uint8_t)((tsbkValue >> 56) & 0x3FU); // Service Type - m_response = (uint8_t)((tsbkValue >> 48) & 0xFFU); // Reason + uint8_t si1 = (uint8_t)((tsbkValue >> 56) & 0xFFU); // Emerg. Special Info 1 + bool manDown = si1 & 0x01U; // Man Down Flag + uint8_t si2 = (uint8_t)((tsbkValue >> 48) & 0xFFU); // Emerg. Special Info 2 + + // if we have no special info, this is a defacto emergency button press + if (si1 == 0U && si2 == 0U) { + m_emergency = true; + } - if (m_response == 0U) { + // if we have a man down flag set and no special info 2, this is a man-down emergency + if (manDown && si2 == 0U) { m_emergency = true; - } else { - m_emergency = false; } + // all other emergency alarms aren't supported and are ignored (and infact most code will treat that as + // OSP_DENY_RSP) + + m_aivFlag = (((tsbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // Additional Info. Flag + m_service = (uint8_t)((tsbkValue >> 56) & 0x3FU); // Service Type + m_response = (uint8_t)((tsbkValue >> 48) & 0xFFU); // Reason + m_dstId = (uint32_t)((tsbkValue >> 24) & 0xFFFFU); // Target Radio Address m_srcId = (uint32_t)(tsbkValue & 0xFFFFFFU); // Source Radio Address diff --git a/src/host/p25/packet/ControlSignaling.cpp b/src/host/p25/packet/ControlSignaling.cpp index 39ea922b..8a730d5f 100644 --- a/src/host/p25/packet/ControlSignaling.cpp +++ b/src/host/p25/packet/ControlSignaling.cpp @@ -4,7 +4,7 @@ * GPLv2 Open Source. Use is subject to license terms. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * Copyright (C) 2017-2025 Bryan Biedenkapp, N2PLL + * Copyright (C) 2017-2026 Bryan Biedenkapp, N2PLL * Copyright (C) 2022 Jason-UWU * */ @@ -2762,6 +2762,7 @@ void ControlSignaling::writeRF_TSDU_ACK_FNE(uint32_t srcId, uint32_t service, bo void ControlSignaling::writeRF_TSDU_Deny(uint32_t srcId, uint32_t dstId, uint8_t reason, uint8_t service, bool grp, bool aiv) { std::unique_ptr osp = std::make_unique(); + osp->setMFId(m_lastMFID); osp->setAIV(aiv); osp->setSrcId(srcId); osp->setDstId(dstId); @@ -2962,6 +2963,7 @@ void ControlSignaling::writeRF_TSDU_U_Dereg_Ack(uint32_t srcId) void ControlSignaling::writeRF_TSDU_Queue(uint32_t srcId, uint32_t dstId, uint8_t reason, uint8_t service, bool grp, bool aiv) { std::unique_ptr osp = std::make_unique(); + osp->setMFId(m_lastMFID); osp->setAIV(aiv); osp->setSrcId(srcId); osp->setDstId(dstId); diff --git a/src/sysview/SysViewMain.cpp b/src/sysview/SysViewMain.cpp index 02194985..8deeb53c 100644 --- a/src/sysview/SysViewMain.cpp +++ b/src/sysview/SysViewMain.cpp @@ -4,7 +4,7 @@ * GPLv2 Open Source. Use is subject to license terms. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * - * Copyright (C) 2024,2025 Bryan Biedenkapp, N2PLL + * Copyright (C) 2024-2026 Bryan Biedenkapp, N2PLL * */ #include "Defines.h" @@ -764,13 +764,16 @@ void* threadNetworkPump(void* arg) } } break; - case P25DEF::TSBKO::ISP_EMERG_ALRM_REQ: + case P25DEF::TSBKO::OSP_DENY_RSP: { // non-emergency mode is a TSBKO::OSP_DENY_RSP if (!tsbk->getEmergency()) { - lc::tsbk::OSP_DENY_RSP* osp = static_cast(tsbk.get()); - LogInfoEx(LOG_NET, P25_TSDU_STR ", %s, AIV = %u, reason = $%02X, srcId = %u (%s), dstId = %u (%s)", - osp->toString().c_str(), osp->getAIV(), osp->getResponse(), + // bryanb: because our TSBKFactory will emit ISP_EMERG_ALRM_REQ for emergency alarm requests, we decoding OSP_DENY_RSP here + lc::tsbk::OSP_DENY_RSP* osp = new lc::tsbk::OSP_DENY_RSP(); + osp->decode(data.get()); + + LogInfoEx(LOG_NET, P25_TSDU_STR ", %s, AIV = %u, reason = $%02X (%s), srcId = %u (%s), dstId = %u (%s)", + osp->toString().c_str(), osp->getAIV(), osp->getResponse(), P25Utils::denyRsnToString(osp->getResponse()).c_str(), osp->getSrcId(), resolveRID(osp->getSrcId()).c_str(), osp->getDstId(), resolveTGID(osp->getDstId()).c_str()); // generate a net event for this @@ -787,6 +790,8 @@ void* threadNetworkPump(void* arg) g_netDataEvent(netEvent); } + + delete osp; } else { LogInfoEx(LOG_NET, P25_TSDU_STR ", %s, srcId = %u (%s), dstId = %u (%s)", tsbk->toString().c_str(), srcId, resolveRID(srcId).c_str(), dstId, resolveTGID(dstId).c_str());