From 562fb3cc67de3c1476b8077500ecb1762844f20b Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Wed, 15 Jul 2026 17:08:27 -0400 Subject: [PATCH] internally generate a GRP_VCH grant demand message for a net event when encountering a grant demand TDU; --- src/sysview/SysViewMain.cpp | 104 ++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/src/sysview/SysViewMain.cpp b/src/sysview/SysViewMain.cpp index 39192f5e..9c3afc02 100644 --- a/src/sysview/SysViewMain.cpp +++ b/src/sysview/SysViewMain.cpp @@ -419,6 +419,8 @@ void* threadNetworkPump(void* arg) dmrData.setN(n); } + uint8_t controlByte = dmrData.getControl(); + // is this the end of the call stream? if (dataSync && (dataType == DMRDEF::DataType::TERMINATOR_WITH_LC)) { if (srcId == 0U && dstId == 0U) { @@ -582,6 +584,8 @@ void* threadNetworkPump(void* arg) uint32_t sysId = (p25Buffer[11U] << 8) | (p25Buffer[12U] << 0); uint32_t netId = GET_UINT24(p25Buffer, 16U); + uint8_t controlByte = p25Buffer[14U]; + // log call status if (duid != P25DEF::DUID::TSDU && duid != P25DEF::DUID::PDU) { // is this the end of the call stream? @@ -633,6 +637,106 @@ void* threadNetworkPump(void* arg) if (duid == P25DEF::DUID::TDU) { LogInfoEx(LOG_NET, P25_TDU_STR ", srcId = %u (%s), dstId = %u (%s)", srcId, resolveRID(srcId).c_str(), dstId, resolveTGID(dstId).c_str()); + + // if this is a grant demand TDU, generate a GRP_VCH TSDU event to indicate that the call + // is trying to start + if (((controlByte & network::NET_CTRL_GRANT_DEMAND) == network::NET_CTRL_GRANT_DEMAND) && + g_netDataEvent != nullptr) { + bool unitToUnit = (controlByte & network::NET_CTRL_U2U) == network::NET_CTRL_U2U; + + json::object netEvent = json::object(); + std::string type = "tsbk"; + netEvent["type"].set(type); + + if (!unitToUnit) { + std::unique_ptr tsbk = std::make_unique(); + + uint8_t lco = tsbk->getLCO(); + netEvent["opcode"].set(lco); + std::string desc = tsbk->toString(); + desc.append(" Demand"); + netEvent["desc"].set(desc); + + tsbk->setSrcId(srcId); + tsbk->setDstId(dstId); + tsbk->setGrpVchId(0U); + tsbk->setGrpVchNo(0U); + tsbk->setPriority(4U); + + bool emerg = tsbk->getEmergency(); + netEvent["emerg"].set(emerg); + bool encry = tsbk->getEncrypted(); + netEvent["encry"].set(encry); + uint8_t prio = tsbk->getPriority(); + netEvent["prio"].set(prio); + uint32_t chId = tsbk->getGrpVchId(); + netEvent["chId"].set(chId); + uint32_t chNo = tsbk->getGrpVchNo(); + netEvent["chNo"].set(chNo); + + std::string resolvedSrc = resolveRID(srcId); + std::string resolvedDst = resolveTGID(dstId); + netEvent["srcId"].set(srcId); + netEvent["srcStr"].set(resolvedSrc); + netEvent["dstId"].set(dstId); + netEvent["dstStr"].set(resolvedDst); + + // report raw TSBK bytes in hex format + DECLARE_UINT8_ARRAY(tsbkRaw, P25DEF::P25_TSBK_LENGTH_BYTES); + tsbk->encode(tsbkRaw, true, true); + std::stringstream ss; + ss << std::hex << std::setfill('0'); + for (uint8_t i = 0; i < P25DEF::P25_TSBK_LENGTH_BYTES; i++) { + ss << std::setw(2) << (int)tsbkRaw[i]; + } + netEvent["data"].set(ss.str()); + } + else { + std::unique_ptr tsbk = std::make_unique(); + + uint8_t lco = tsbk->getLCO(); + netEvent["opcode"].set(lco); + std::string desc = tsbk->toString(); + desc.append(" Demand"); + netEvent["desc"].set(desc); + + tsbk->setSrcId(srcId); + tsbk->setDstId(dstId); + tsbk->setGrpVchId(0U); + tsbk->setGrpVchNo(0U); + tsbk->setPriority(4U); + + bool emerg = tsbk->getEmergency(); + netEvent["emerg"].set(emerg); + bool encry = tsbk->getEncrypted(); + netEvent["encry"].set(encry); + uint8_t prio = tsbk->getPriority(); + netEvent["prio"].set(prio); + uint32_t chId = tsbk->getGrpVchId(); + netEvent["chId"].set(chId); + uint32_t chNo = tsbk->getGrpVchNo(); + netEvent["chNo"].set(chNo); + + std::string resolvedSrc = resolveRID(srcId); + std::string resolvedDst = resolveTGID(dstId); + netEvent["srcId"].set(srcId); + netEvent["srcStr"].set(resolvedSrc); + netEvent["dstId"].set(dstId); + netEvent["dstStr"].set(resolvedDst); + + // report raw TSBK bytes in hex format + DECLARE_UINT8_ARRAY(tsbkRaw, P25DEF::P25_TSBK_LENGTH_BYTES); + tsbk->encode(tsbkRaw, true, true); + std::stringstream ss; + ss << std::hex << std::setfill('0'); + for (uint8_t i = 0; i < P25DEF::P25_TSBK_LENGTH_BYTES; i++) { + ss << std::setw(2) << (int)tsbkRaw[i]; + } + netEvent["data"].set(ss.str()); + } + + g_netDataEvent(netEvent); + } } else { std::unique_ptr tdulc = lc::tdulc::TDULCFactory::createTDULC(data.get());