From 64529052ff47cede86bf9b31b5834a41a7a81e1d Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Thu, 14 May 2026 09:01:59 -0400 Subject: [PATCH] refactor how the P25 voice handler gets the currently active TGs, this is in effort to hopefully remove the crash condition by the use of the old at() code in the m_activeTG vector; --- src/host/p25/packet/Voice.cpp | 76 +++++++++++++++++++++-------------- src/host/p25/packet/Voice.h | 12 ++++++ 2 files changed, 58 insertions(+), 30 deletions(-) diff --git a/src/host/p25/packet/Voice.cpp b/src/host/p25/packet/Voice.cpp index e0f22aa0..389152fe 100644 --- a/src/host/p25/packet/Voice.cpp +++ b/src/host/p25/packet/Voice.cpp @@ -674,24 +674,16 @@ bool Voice::process(uint8_t* data, uint32_t len) else { std::lock_guard lock(m_p25->s_activeTGLock); if (m_p25->m_activeTG.size() > 0) { - if (m_grpUpdtCount > m_p25->m_activeTG.size()) - m_grpUpdtCount = 0U; - - if (m_p25->m_activeTG.size() < 2) { - uint32_t dstId = m_p25->m_activeTG.at(0); - m_rfLC.setMFId(MFG_STANDARD); - m_rfLC.setLCO(LCO::GROUP_UPDT); - m_rfLC.setDstId(dstId); - } - else { - uint32_t dstId = m_p25->m_activeTG.at(m_grpUpdtCount); - uint32_t dstIdB = m_p25->m_activeTG.at(m_grpUpdtCount + 1U); + uint32_t dstId = 0U; + uint32_t dstIdB = 0U; + bool hasDstIdB = false; + if (nextActiveTalkgroups(m_p25->m_activeTG, m_grpUpdtCount, dstId, dstIdB, hasDstIdB)) { m_rfLC.setMFId(MFG_STANDARD); m_rfLC.setLCO(LCO::GROUP_UPDT); m_rfLC.setDstId(dstId); - m_rfLC.setDstIdB(dstIdB); - - m_grpUpdtCount++; + if (hasDstIdB) { + m_rfLC.setDstIdB(dstIdB); + } } } } @@ -2063,24 +2055,16 @@ void Voice::writeNet_LDU1() else { std::lock_guard lock(m_p25->s_activeTGLock); if (m_p25->m_activeTG.size() > 0) { - if (m_grpUpdtCount > m_p25->m_activeTG.size()) - m_grpUpdtCount = 0U; - - if (m_p25->m_activeTG.size() < 2) { - uint32_t dstId = m_p25->m_activeTG.at(0); + uint32_t dstId = 0U; + uint32_t dstIdB = 0U; + bool hasDstIdB = false; + if (nextActiveTalkgroups(m_p25->m_activeTG, m_grpUpdtCount, dstId, dstIdB, hasDstIdB)) { m_netLC.setMFId(MFG_STANDARD); m_netLC.setLCO(LCO::GROUP_UPDT); m_netLC.setDstId(dstId); - } - else { - uint32_t dstId = m_p25->m_activeTG.at(m_grpUpdtCount); - uint32_t dstIdB = m_p25->m_activeTG.at(m_grpUpdtCount + 1U); - m_netLC.setMFId(MFG_STANDARD); - m_netLC.setLCO(LCO::GROUP_UPDT); - m_netLC.setDstId(dstId); - m_netLC.setDstIdB(dstIdB); - - m_grpUpdtCount++; + if (hasDstIdB) { + m_netLC.setDstIdB(dstIdB); + } } } } @@ -2352,6 +2336,38 @@ void Voice::resetWithNullAudio(uint8_t* data, bool encrypted) } } +/* Helper to determine the next active talkgroup in a active multi-group scenario. */ + +bool Voice::nextActiveTalkgroups(const std::vector& activeTG, uint8_t& groupUpdtIndex, uint32_t& dstId, uint32_t& dstIdB, bool& hasDstIdB) +{ + const size_t count = activeTG.size(); + if (count == 0U) { + groupUpdtIndex = 0U; + hasDstIdB = false; + return false; + } + + size_t index = static_cast(groupUpdtIndex); + if (index >= count) { + index = 0U; + } + + dstId = activeTG[index]; + if (count < 2U) { + groupUpdtIndex = static_cast(index); + hasDstIdB = false; + return true; + } + + const size_t nextIndex = (index + 1U) % count; + dstIdB = activeTG[nextIndex]; + hasDstIdB = true; + + // move the rolling index forward for the next report cycle + groupUpdtIndex = static_cast(nextIndex); + return true; +} + /* Given the last MI, generate the next MI using LFSR. */ void Voice::getNextMI(uint8_t lastMI[9U], uint8_t nextMI[9U]) diff --git a/src/host/p25/packet/Voice.h b/src/host/p25/packet/Voice.h index a5bb238f..c515e111 100644 --- a/src/host/p25/packet/Voice.h +++ b/src/host/p25/packet/Voice.h @@ -210,6 +210,18 @@ namespace p25 */ void resetWithNullAudio(uint8_t* data, bool encrypted); + /** + * @brief Helper to determine the next active talkgroup in a active multi-group scenario, + * this is intended to update the GROUP_UPDT LC field for the next transmission. + * @param activeTG Vector of active talkgroups. + * @param groupUpdtIndex Index of the current group update. + * @param dstId Destination ID of the current talkgroup. + * @param dstIdB Destination ID of the secondary talkgroup. + * @param hasDstIdB Flag indicating whether a secondary talkgroup exists. + * @return bool True if there is a next active talkgroup, otherwise false. + */ + bool nextActiveTalkgroups(const std::vector& activeTG, uint8_t& groupUpdtIndex, uint32_t& dstId, uint32_t& dstIdB, bool& hasDstIdB); + /** * @brief Given the last MI, generate the next MI using LFSR. * @param lastMI Last MI received.