diff --git a/src/dmr/Control.cpp b/src/dmr/Control.cpp
index 8cafdba8..1ac1d5a2 100644
--- a/src/dmr/Control.cpp
+++ b/src/dmr/Control.cpp
@@ -650,6 +650,26 @@ uint32_t Control::getLastDstId(uint32_t slotNo) const
return 0U;
}
+///
+/// Helper to get the last transmitted source ID.
+///
+/// DMR slot number.
+///
+uint32_t Control::getLastSrcId(uint32_t slotNo) const
+{
+ switch (slotNo) {
+ case 1U:
+ return m_slot1->getLastSrcId();
+ case 2U:
+ return m_slot2->getLastSrcId();
+ default:
+ LogError(LOG_DMR, "DMR, invalid slot, slotNo = %u", slotNo);
+ break;
+ }
+
+ return 0U;
+}
+
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
diff --git a/src/dmr/Control.h b/src/dmr/Control.h
index 7dca0794..063d5ff3 100644
--- a/src/dmr/Control.h
+++ b/src/dmr/Control.h
@@ -132,6 +132,8 @@ namespace dmr
/// Helper to get the last transmitted destination ID.
uint32_t getLastDstId(uint32_t slotNo) const;
+ /// Helper to get the last transmitted source ID.
+ uint32_t getLastSrcId(uint32_t slotNo) const;
private:
friend class Slot;
diff --git a/src/dmr/Slot.cpp b/src/dmr/Slot.cpp
index 1ec500dc..66a72a31 100644
--- a/src/dmr/Slot.cpp
+++ b/src/dmr/Slot.cpp
@@ -124,8 +124,10 @@ Slot::Slot(uint32_t slotNo, uint32_t timeout, uint32_t tgHang, uint32_t queueSiz
m_txQueue(queueSize, "DMR Slot Frame"),
m_rfState(RS_RF_LISTENING),
m_rfLastDstId(0U),
+ m_rfLastSrcId(0U),
m_netState(RS_NET_IDLE),
m_netLastDstId(0U),
+ m_netLastSrcId(0U),
m_permittedDstId(0U),
m_rfLC(nullptr),
m_rfPrivacyLC(nullptr),
@@ -222,6 +224,7 @@ bool Slot::processFrame(uint8_t *data, uint32_t len)
m_rfState = RS_RF_LISTENING;
m_rfLastDstId = 0U;
+ m_rfLastSrcId = 0U;
m_rfTGHang.stop();
return false;
@@ -502,6 +505,7 @@ void Slot::clock()
LogMessage(LOG_RF, "Slot %u, talkgroup hang has expired, lastDstId = %u", m_slotNo, m_rfLastDstId);
}
m_rfLastDstId = 0U;
+ m_rfLastSrcId = 0U;
// reset permitted ID and clear permission state
if (!m_authoritative && m_permittedDstId != 0U) {
@@ -693,6 +697,23 @@ uint32_t Slot::getLastDstId() const
return 0U;
}
+///
+/// Helper to get the last transmitted source ID.
+///
+///
+uint32_t Slot::getLastSrcId() const
+{
+ if (m_rfLastSrcId != 0U) {
+ return m_rfLastSrcId;
+ }
+
+ if (m_netLastSrcId != 0U) {
+ return m_netLastSrcId;
+ }
+
+ return 0U;
+}
+
///
/// Helper to initialize the DMR slot processor.
///
diff --git a/src/dmr/Slot.h b/src/dmr/Slot.h
index b1fff954..0e8aa127 100644
--- a/src/dmr/Slot.h
+++ b/src/dmr/Slot.h
@@ -123,6 +123,8 @@ namespace dmr
/// Helper to get the last transmitted destination ID.
uint32_t getLastDstId() const;
+ /// Helper to get the last transmitted source ID.
+ uint32_t getLastSrcId() const;
/// Helper to initialize the slot processor.
static void init(Control* dmr, bool authoritative, uint32_t colorCode, SiteData siteData, bool embeddedLCOnly, bool dumpTAData, uint32_t callHang, modem::Modem* modem,
@@ -150,8 +152,10 @@ namespace dmr
RPT_RF_STATE m_rfState;
uint32_t m_rfLastDstId;
+ uint32_t m_rfLastSrcId;
RPT_NET_STATE m_netState;
uint32_t m_netLastDstId;
+ uint32_t m_netLastSrcId;
uint32_t m_permittedDstId;
diff --git a/src/dmr/packet/Data.cpp b/src/dmr/packet/Data.cpp
index 98edcfbd..90fbce60 100644
--- a/src/dmr/packet/Data.cpp
+++ b/src/dmr/packet/Data.cpp
@@ -216,6 +216,7 @@ bool Data::process(uint8_t* data, uint32_t len)
m_slot->m_rfState = RS_RF_DATA;
m_slot->m_rfLastDstId = dstId;
+ m_slot->m_rfLastSrcId = srcId;
if (m_slot->m_netState == RS_NET_IDLE) {
m_slot->setShortLC(m_slot->m_slotNo, dstId, gi ? FLCO_GROUP : FLCO_PRIVATE, false);
@@ -423,6 +424,7 @@ void Data::processNetwork(const data::Data& dmrData)
m_slot->m_netState = RS_NET_DATA;
m_slot->m_netLastDstId = dstId;
+ m_slot->m_netLastSrcId = srcId;
m_slot->setShortLC(m_slot->m_slotNo, dstId, gi ? FLCO_GROUP : FLCO_PRIVATE, false);
diff --git a/src/dmr/packet/Voice.cpp b/src/dmr/packet/Voice.cpp
index c1436dbd..02066031 100644
--- a/src/dmr/packet/Voice.cpp
+++ b/src/dmr/packet/Voice.cpp
@@ -125,6 +125,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
}
m_slot->m_rfLastDstId = 0U;
+ m_slot->m_rfLastSrcId = 0U;
m_slot->m_rfTGHang.stop();
m_slot->m_rfState = RS_RF_REJECTED;
@@ -140,6 +141,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
}
m_slot->m_rfLastDstId = 0U;
+ m_slot->m_rfLastSrcId = 0U;
m_slot->m_rfTGHang.stop();
m_slot->m_rfState = RS_RF_REJECTED;
@@ -203,6 +205,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
m_slot->m_rfState = RS_RF_AUDIO;
m_slot->m_rfLastDstId = dstId;
+ m_slot->m_rfLastSrcId = srcId;
if (m_slot->m_netState == RS_NET_IDLE) {
m_slot->setShortLC(m_slot->m_slotNo, dstId, flco, true);
@@ -289,6 +292,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
m_slot->m_rfTGHang.start();
m_slot->m_rfLastDstId = m_slot->m_rfLC->getDstId();
+ m_slot->m_rfLastSrcId = m_slot->m_rfLC->getSrcId();
m_rfEmbeddedReadN = (m_rfEmbeddedReadN + 1U) % 2U;
m_rfEmbeddedWriteN = (m_rfEmbeddedWriteN + 1U) % 2U;
@@ -356,6 +360,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
m_slot->m_rfTGHang.start();
m_slot->m_rfLastDstId = m_slot->m_rfLC->getDstId();
+ m_slot->m_rfLastSrcId = m_slot->m_rfLC->getSrcId();
// get the LCSS from the EMB
data::EMB emb;
@@ -611,6 +616,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
m_slot->m_rfTGHang.start();
m_slot->m_rfLastDstId = dstId;
+ m_slot->m_rfLastSrcId = srcId;
if (m_slot->m_netState == RS_NET_IDLE) {
m_slot->setShortLC(m_slot->m_slotNo, dstId, flco, true);
@@ -718,6 +724,7 @@ void Voice::processNetwork(const data::Data& dmrData)
m_slot->m_netState = RS_NET_AUDIO;
m_slot->m_netLastDstId = dstId;
+ m_slot->m_netLastSrcId = srcId;
m_slot->setShortLC(m_slot->m_slotNo, dstId, flco, true);
@@ -785,6 +792,7 @@ void Voice::processNetwork(const data::Data& dmrData)
m_slot->m_netState = RS_NET_AUDIO;
m_slot->m_netLastDstId = dstId;
+ m_slot->m_netLastSrcId = srcId;
m_slot->setShortLC(m_slot->m_slotNo, dstId, m_slot->m_netLC->getFLCO(), true);
@@ -889,6 +897,7 @@ void Voice::processNetwork(const data::Data& dmrData)
m_slot->m_netState = RS_NET_AUDIO;
m_slot->m_netLastDstId = dstId;
+ m_slot->m_netLastSrcId = srcId;
m_slot->setShortLC(m_slot->m_slotNo, dstId, m_slot->m_netLC->getFLCO(), true);
diff --git a/src/host/Host.cpp b/src/host/Host.cpp
index 559c2340..1269636e 100644
--- a/src/host/Host.cpp
+++ b/src/host/Host.cpp
@@ -100,6 +100,7 @@ Host::Host(const std::string& confFile) :
m_rfTalkgroupHang(10U),
m_netModeHang(3U),
m_lastDstId(0U),
+ m_lastSrcId(0U),
m_identity(),
m_cwCallsign(),
m_cwIdTime(0U),
@@ -892,6 +893,7 @@ int Host::run()
}
m_lastDstId = dmr->getLastDstId(1U);
+ m_lastSrcId = dmr->getLastSrcId(1U);
}
}
@@ -939,6 +941,7 @@ int Host::run()
}
m_lastDstId = dmr->getLastDstId(2U);
+ m_lastSrcId = dmr->getLastSrcId(2U);
}
}
}
@@ -979,6 +982,7 @@ int Host::run()
}
m_lastDstId = p25->getLastDstId();
+ m_lastSrcId = p25->getLastSrcId();
}
else {
nextLen = 0U;
@@ -1059,6 +1063,7 @@ int Host::run()
}
m_lastDstId = nxdn->getLastDstId();
+ m_lastSrcId = nxdn->getLastSrcId();
}
}
}
diff --git a/src/host/Host.h b/src/host/Host.h
index 813f9925..7bb73e7e 100644
--- a/src/host/Host.h
+++ b/src/host/Host.h
@@ -100,6 +100,7 @@ private:
uint32_t m_netModeHang;
uint32_t m_lastDstId;
+ uint32_t m_lastSrcId;
std::string m_identity;
std::string m_cwCallsign;
diff --git a/src/network/RESTAPI.cpp b/src/network/RESTAPI.cpp
index d509882f..4e0bf93b 100644
--- a/src/network/RESTAPI.cpp
+++ b/src/network/RESTAPI.cpp
@@ -531,6 +531,7 @@ void RESTAPI::restAPI_GetStatus(const HTTPPayload& request, HTTPPayload& reply,
response["channelNo"].set(m_host->m_channelNo);
response["lastDstId"].set(m_host->m_lastDstId);
+ response["lastSrcId"].set(m_host->m_lastSrcId);
}
{
diff --git a/src/nxdn/Control.cpp b/src/nxdn/Control.cpp
index 8129d55d..6f1fabe0 100644
--- a/src/nxdn/Control.cpp
+++ b/src/nxdn/Control.cpp
@@ -122,8 +122,10 @@ Control::Control(bool authoritative, uint32_t ran, uint32_t callHang, uint32_t q
m_txQueue(queueSize, "NXDN Frame"),
m_rfState(RS_RF_LISTENING),
m_rfLastDstId(0U),
+ m_rfLastSrcId(0U),
m_netState(RS_NET_IDLE),
m_netLastDstId(0U),
+ m_netLastSrcId(0U),
m_ccRunning(false),
m_ccPrevRunning(false),
m_ccHalted(false),
@@ -592,6 +594,7 @@ void Control::clock(uint32_t ms)
LogMessage(LOG_RF, "talkgroup hang has expired, lastDstId = %u", m_rfLastDstId);
}
m_rfLastDstId = 0U;
+ m_rfLastSrcId = 0U;
// reset permitted ID and clear permission state
if (!m_authoritative && m_permittedDstId != 0U) {
@@ -765,6 +768,23 @@ uint32_t Control::getLastDstId() const
return 0U;
}
+///
+/// Helper to get the last transmitted source ID.
+///
+///
+uint32_t Control::getLastSrcId() const
+{
+ if (m_rfLastSrcId != 0U) {
+ return m_rfLastSrcId;
+ }
+
+ if (m_netLastSrcId != 0U) {
+ return m_netLastSrcId;
+ }
+
+ return 0U;
+}
+
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
diff --git a/src/nxdn/Control.h b/src/nxdn/Control.h
index 8a28be80..d1536b04 100644
--- a/src/nxdn/Control.h
+++ b/src/nxdn/Control.h
@@ -132,6 +132,8 @@ namespace nxdn
/// Helper to get the last transmitted destination ID.
uint32_t getLastDstId() const;
+ /// Helper to get the last transmitted source ID.
+ uint32_t getLastSrcId() const;
private:
friend class packet::Voice;
@@ -177,8 +179,10 @@ namespace nxdn
RPT_RF_STATE m_rfState;
uint32_t m_rfLastDstId;
+ uint32_t m_rfLastSrcId;
RPT_NET_STATE m_netState;
uint32_t m_netLastDstId;
+ uint32_t m_netLastSrcId;
bool m_ccRunning;
bool m_ccPrevRunning;
diff --git a/src/nxdn/packet/Data.cpp b/src/nxdn/packet/Data.cpp
index 23b20289..74f1f067 100644
--- a/src/nxdn/packet/Data.cpp
+++ b/src/nxdn/packet/Data.cpp
@@ -115,6 +115,7 @@ using namespace nxdn::packet;
} \
\
m_nxdn->m_rfLastDstId = 0U; \
+ m_nxdn->m_rfLastSrcId = 0U; \
m_nxdn->m_rfTGHang.stop(); \
m_nxdn->m_rfState = RS_RF_REJECTED; \
return false; \
@@ -131,6 +132,7 @@ using namespace nxdn::packet;
} \
\
m_nxdn->m_rfLastDstId = 0U; \
+ m_nxdn->m_rfLastSrcId = 0U; \
m_nxdn->m_rfTGHang.stop(); \
m_nxdn->m_rfState = RS_RF_REJECTED; \
return false; \
@@ -145,6 +147,7 @@ using namespace nxdn::packet;
} \
\
m_nxdn->m_rfLastDstId = 0U; \
+ m_nxdn->m_rfLastSrcId = 0U; \
m_nxdn->m_rfTGHang.stop(); \
m_nxdn->m_rfState = RS_RF_REJECTED; \
return false; \
diff --git a/src/nxdn/packet/Voice.cpp b/src/nxdn/packet/Voice.cpp
index 81222a3b..5d976211 100644
--- a/src/nxdn/packet/Voice.cpp
+++ b/src/nxdn/packet/Voice.cpp
@@ -117,6 +117,7 @@ using namespace nxdn::packet;
} \
\
m_nxdn->m_rfLastDstId = 0U; \
+ m_nxdn->m_rfLastSrcId = 0U; \
m_nxdn->m_rfTGHang.stop(); \
m_nxdn->m_rfState = RS_RF_REJECTED; \
return false; \
@@ -133,6 +134,7 @@ using namespace nxdn::packet;
} \
\
m_nxdn->m_rfLastDstId = 0U; \
+ m_nxdn->m_rfLastSrcId = 0U; \
m_nxdn->m_rfTGHang.stop(); \
m_nxdn->m_rfState = RS_RF_REJECTED; \
return false; \
@@ -147,6 +149,7 @@ using namespace nxdn::packet;
} \
\
m_nxdn->m_rfLastDstId = 0U; \
+ m_nxdn->m_rfLastSrcId = 0U; \
m_nxdn->m_rfTGHang.stop(); \
m_nxdn->m_rfState = RS_RF_REJECTED; \
return false; \
@@ -251,6 +254,7 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len)
}
m_nxdn->m_rfLastDstId = lc.getDstId();
+ m_nxdn->m_rfLastSrcId = lc.getSrcId();
m_nxdn->m_rfLC = lc;
Sync::addNXDNSync(data + 2U);
@@ -411,6 +415,7 @@ bool Voice::process(uint8_t fct, uint8_t option, uint8_t* data, uint32_t len)
VALID_DSTID(srcId, dstId, group);
m_nxdn->m_rfLastDstId = m_nxdn->m_rfLC.getDstId();
+ m_nxdn->m_rfLastSrcId = m_nxdn->m_rfLC.getSrcId();
m_rfFrames = 0U;
m_rfErrs = 0U;
m_rfBits = 1U;
@@ -695,6 +700,7 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t
}
m_nxdn->m_netLastDstId = lc.getDstId();
+ m_nxdn->m_netLastSrcId = lc.getSrcId();
m_nxdn->m_netLC = lc;
Sync::addNXDNSync(data + 2U);
@@ -834,6 +840,7 @@ bool Voice::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t
VALID_DSTID(srcId, dstId, group);
m_nxdn->m_netLastDstId = m_nxdn->m_netLC.getDstId();
+ m_nxdn->m_netLastSrcId = m_nxdn->m_netLC.getSrcId();
m_rfFrames = 0U;
m_rfErrs = 0U;
m_rfBits = 1U;
diff --git a/src/p25/Control.cpp b/src/p25/Control.cpp
index 9e1d3bff..3e6e5096 100644
--- a/src/p25/Control.cpp
+++ b/src/p25/Control.cpp
@@ -116,8 +116,10 @@ Control::Control(bool authoritative, uint32_t nac, uint32_t callHang, uint32_t q
m_txQueue(queueSize, "P25 Frame"),
m_rfState(RS_RF_LISTENING),
m_rfLastDstId(0U),
+ m_rfLastSrcId(0U),
m_netState(RS_NET_IDLE),
m_netLastDstId(0U),
+ m_netLastSrcId(0U),
m_permittedDstId(0U),
m_tailOnIdle(false),
m_ccRunning(false),
@@ -715,6 +717,7 @@ void Control::clock(uint32_t ms)
LogMessage(LOG_RF, "talkgroup hang has expired, lastDstId = %u", m_rfLastDstId);
}
m_rfLastDstId = 0U;
+ m_rfLastSrcId = 0U;
// reset permitted ID and clear permission state
if (!m_authoritative && m_permittedDstId != 0U) {
@@ -878,6 +881,23 @@ uint32_t Control::getLastDstId() const
return 0U;
}
+///
+/// Helper to get the last transmitted source ID.
+///
+///
+uint32_t Control::getLastSrcId() const
+{
+ if (m_rfLastSrcId != 0U) {
+ return m_rfLastSrcId;
+ }
+
+ if (m_rfLastSrcId != 0U) {
+ return m_rfLastSrcId;
+ }
+
+ return 0U;
+}
+
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
@@ -1115,6 +1135,7 @@ void Control::processFrameLoss()
m_rfState = RS_RF_LISTENING;
m_rfLastDstId = 0U;
+ m_rfLastSrcId = 0U;
m_rfTGHang.stop();
m_tailOnIdle = true;
@@ -1129,6 +1150,7 @@ void Control::processFrameLoss()
if (m_rfState == RS_RF_DATA) {
m_rfState = RS_RF_LISTENING;
m_rfLastDstId = 0U;
+ m_rfLastSrcId = 0U;
m_rfTGHang.stop();
m_tailOnIdle = true;
diff --git a/src/p25/Control.h b/src/p25/Control.h
index ce9fb32b..44b73936 100644
--- a/src/p25/Control.h
+++ b/src/p25/Control.h
@@ -141,6 +141,8 @@ namespace p25
/// Helper to get the last transmitted destination ID.
uint32_t getLastDstId() const;
+ /// Helper to get the last transmitted source ID.
+ uint32_t getLastSrcId() const;
private:
friend class packet::Voice;
@@ -185,8 +187,10 @@ namespace p25
RPT_RF_STATE m_rfState;
uint32_t m_rfLastDstId;
+ uint32_t m_rfLastSrcId;
RPT_NET_STATE m_netState;
uint32_t m_netLastDstId;
+ uint32_t m_netLastSrcId;
uint32_t m_permittedDstId;
diff --git a/src/p25/packet/Voice.cpp b/src/p25/packet/Voice.cpp
index ae173e7e..2fc1eba2 100644
--- a/src/p25/packet/Voice.cpp
+++ b/src/p25/packet/Voice.cpp
@@ -193,6 +193,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
m_p25->m_rfTGHang.start();
m_p25->m_rfLastDstId = lc.getDstId();
+ m_p25->m_rfLastSrcId = lc.getSrcId();
m_rfLastHDU = lc;
}
@@ -282,6 +283,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
}
m_p25->m_rfLastDstId = 0U;
+ m_p25->m_rfLastSrcId = 0U;
m_p25->m_rfTGHang.stop();
m_p25->m_rfState = RS_RF_REJECTED;
return false;
@@ -302,6 +304,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
}
m_p25->m_rfLastDstId = 0U;
+ m_p25->m_rfLastSrcId = 0U;
m_p25->m_rfTGHang.stop();
m_p25->m_rfState = RS_RF_REJECTED;
return false;
@@ -321,6 +324,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
}
m_p25->m_rfLastDstId = 0U;
+ m_p25->m_rfLastSrcId = 0U;
m_p25->m_rfTGHang.stop();
m_p25->m_rfState = RS_RF_REJECTED;
return false;
@@ -341,6 +345,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
}
m_p25->m_rfLastDstId = 0U;
+ m_p25->m_rfLastSrcId = 0U;
m_p25->m_rfTGHang.stop();
m_p25->m_rfState = RS_RF_REJECTED;
return false;
@@ -397,6 +402,7 @@ bool Voice::process(uint8_t* data, uint32_t len)
}
m_p25->m_rfLastDstId = dstId;
+ m_p25->m_rfLastSrcId = srcId;
// make sure we actually got a HDU -- otherwise treat the call as a late entry
if (m_rfLastHDU.getDstId() != 0U) {
@@ -1106,6 +1112,7 @@ void Voice::writeNet_TDU()
resetNet();
m_p25->m_netState = RS_NET_IDLE;
m_p25->m_netLastDstId = 0U;
+ m_p25->m_netLastSrcId = 0U;
m_p25->m_tailOnIdle = true;
}
@@ -1304,6 +1311,7 @@ void Voice::writeNet_LDU1()
m_p25->m_netState = RS_NET_IDLE;
m_p25->m_netLastDstId = 0U;
+ m_p25->m_netLastSrcId = 0U;
if (m_p25->m_rfState == RS_RF_REJECTED) {
m_p25->m_rfState = RS_RF_LISTENING;
@@ -1318,6 +1326,7 @@ void Voice::writeNet_LDU1()
m_hadVoice = true;
m_p25->m_netState = RS_NET_AUDIO;
m_p25->m_netLastDstId = dstId;
+ m_p25->m_netLastSrcId = srcId;
m_p25->m_netTimeout.start();
m_netFrames = 0U;
m_netLost = 0U;