diff --git a/config.example.yml b/config.example.yml index a903345a..590a6f68 100644 --- a/config.example.yml +++ b/config.example.yml @@ -40,6 +40,9 @@ protocols: dumpDataPacket: false repeatDataPacket: true dumpCsbkData: false + verifyReg: false + nRandWait: 8 + backOff: 1 callHang: 5 txHang: 8 silenceThreshold: 21 diff --git a/dmr/Control.cpp b/dmr/Control.cpp index fde2933e..70b57832 100644 --- a/dmr/Control.cpp +++ b/dmr/Control.cpp @@ -88,7 +88,7 @@ Control::Control(uint32_t colorCode, uint32_t callHang, uint32_t queueSize, bool assert(rssiMapper != NULL); acl::AccessControl::init(m_ridLookup, m_tidLookup); - Slot::init(colorCode, SiteData(), embeddedLCOnly, dumpTAData, callHang, modem, network, duplex, m_ridLookup, m_tidLookup, m_idenTable, rssiMapper, jitter); + Slot::init(this, colorCode, SiteData(), embeddedLCOnly, dumpTAData, callHang, modem, network, duplex, m_ridLookup, m_tidLookup, m_idenTable, rssiMapper, jitter, verbose); m_slot1 = new Slot(1U, timeout, tgHang, queueSize, dumpDataPacket, repeatDataPacket, dumpCSBKData, debug, verbose); m_slot2 = new Slot(2U, timeout, tgHang, queueSize, dumpDataPacket, repeatDataPacket, dumpCSBKData, debug, verbose); @@ -117,6 +117,8 @@ void Control::setOptions(yaml::Node& conf, uint32_t netId, uint8_t siteId, uint8 yaml::Node systemConf = conf["system"]; yaml::Node dmrProtocol = conf["protocols"]["dmr"]; + Slot::m_verifyReg = dmrProtocol["verifyReg"].as(false); + uint8_t nRandWait = (uint8_t)dmrProtocol["nRandWait"].as(dmr::DEFAULT_NRAND_WAIT); if (nRandWait > 15U) nRandWait = 15U; @@ -165,7 +167,10 @@ void Control::setOptions(yaml::Node& conf, uint32_t netId, uint8_t siteId, uint8 LogInfo(" TSCC Aloha Random Access Wait: %u", nRandWait); LogInfo(" TSCC Aloha Backoff: %u", backOff); } + LogInfo(" Silence Threshold: %u (%.1f%%)", silenceThreshold, float(silenceThreshold) / 1.41F); + + LogInfo(" Verify Registration: %s", Slot::m_verifyReg ? "yes" : "no"); } } @@ -383,3 +388,26 @@ void Control::setDebugVerbose(bool debug, bool verbose) m_slot1->setDebugVerbose(debug, verbose); m_slot2->setDebugVerbose(debug, verbose); } + +// --------------------------------------------------------------------------- +// Private Class Members +// --------------------------------------------------------------------------- + +/// +/// Helper to return the slot carrying the TSCC. +/// +/// Pointer to the TSCC slot instance. +Slot* Control::getTSCCSlot() const +{ + switch (m_tsccSlotNo) { + case 1U: + return m_slot1; + break; + case 2U: + return m_slot2; + break; + default: + LogError(LOG_NET, "DMR, invalid slot, TSCC disabled, slotNo = %u", m_tsccSlotNo); + return NULL; + } +} diff --git a/dmr/Control.h b/dmr/Control.h index e09a1ca7..e11c44a9 100644 --- a/dmr/Control.h +++ b/dmr/Control.h @@ -50,6 +50,7 @@ namespace dmr // --------------------------------------------------------------------------- class HOST_SW_API Slot; + namespace packet { class HOST_SW_API ControlSignaling; } // --------------------------------------------------------------------------- // Class Declaration @@ -101,6 +102,9 @@ namespace dmr void setDebugVerbose(bool debug, bool verbose); private: + friend class Slot; + friend class packet::ControlSignaling; + uint32_t m_colorCode; modem::Modem* m_modem; @@ -120,6 +124,9 @@ namespace dmr bool m_dumpCSBKData; bool m_verbose; bool m_debug; + + /// Helper to return the slot carrying the TSCC. + Slot* getTSCCSlot() const; }; } // namespace dmr diff --git a/dmr/DMRDefines.h b/dmr/DMRDefines.h index d53c7c95..c398b614 100644 --- a/dmr/DMRDefines.h +++ b/dmr/DMRDefines.h @@ -278,6 +278,7 @@ namespace dmr const uint8_t CSBKO_UU_ANS_RSP = 0x05U; // UU ANS RSP - Unit to Unit Answer Response const uint8_t CSBKO_CTCSBK = 0x07U; // CT CSBK - Channel Timing CSBK const uint8_t CSBKO_ALOHA = 0x19U; // ALOHA - Aloha PDUs for the random access protocol + const uint8_t CSBKO_AHOY = 0x1CU; // AHOY - Enquiry from TSCC const uint8_t CSBKO_RAND = 0x1FU; // (ETSI) RAND - Random Access / (DMRA) CALL ALRT - Call Alert const uint8_t CSBKO_ACK_RSP = 0x20U; // ACK RSP - Acknowledge Response const uint8_t CSBKO_EXT_FNCT = 0x24U; // (DMRA) EXT FNCT - Extended Function diff --git a/dmr/Slot.cpp b/dmr/Slot.cpp index 07c0b786..b3a172c2 100644 --- a/dmr/Slot.cpp +++ b/dmr/Slot.cpp @@ -54,6 +54,8 @@ const uint16_t TSCC_MAX_CNT = 511U; // Static Class Members // --------------------------------------------------------------------------- +Control* Slot::m_dmr = NULL; + uint32_t Slot::m_colorCode = 0U; SiteData Slot::m_siteData = SiteData(); @@ -70,6 +72,7 @@ bool Slot::m_duplex = true; lookups::IdenTableLookup* Slot::m_idenTable = NULL; lookups::RadioIdLookup* Slot::m_ridLookup = NULL; lookups::TalkgroupIdLookup* Slot::m_tidLookup = NULL; +lookups::AffiliationLookup *Slot::m_affiliations = NULL; lookups::IdenTable Slot::m_idenEntry = lookups::IdenTable(); @@ -89,6 +92,8 @@ uint8_t Slot::m_flco2; uint8_t Slot::m_id2 = 0U; bool Slot::m_voice2 = true; +bool Slot::m_verifyReg = false; + uint16_t Slot::m_tsccCnt = 0U; uint8_t Slot::m_alohaNRandWait = DEFAULT_NRAND_WAIT; @@ -561,6 +566,7 @@ void Slot::setSilenceThreshold(uint32_t threshold) /// /// Helper to initialize the DMR slot processor. /// +/// Instance of the Control class. /// DMR access color code. /// DMR site data. /// @@ -574,16 +580,20 @@ void Slot::setSilenceThreshold(uint32_t threshold) /// Instance of the IdenTableLookup class. /// Instance of the RSSIInterpolator class. /// -void Slot::init(uint32_t colorCode, SiteData siteData, bool embeddedLCOnly, bool dumpTAData, uint32_t callHang, modem::Modem* modem, +/// +void Slot::init(Control* dmr, uint32_t colorCode, SiteData siteData, bool embeddedLCOnly, bool dumpTAData, uint32_t callHang, modem::Modem* modem, network::BaseNetwork* network, bool duplex, lookups::RadioIdLookup* ridLookup, lookups::TalkgroupIdLookup* tidLookup, - lookups::IdenTableLookup* idenTable, lookups::RSSIInterpolator* rssiMapper, uint32_t jitter) + lookups::IdenTableLookup* idenTable, lookups::RSSIInterpolator* rssiMapper, uint32_t jitter, bool verbose) { + assert(dmr != NULL); assert(modem != NULL); assert(ridLookup != NULL); assert(tidLookup != NULL); assert(idenTable != NULL); assert(rssiMapper != NULL); + m_dmr = dmr; + m_colorCode = colorCode; m_siteData = siteData; @@ -599,6 +609,7 @@ void Slot::init(uint32_t colorCode, SiteData siteData, bool embeddedLCOnly, bool m_idenTable = idenTable; m_ridLookup = ridLookup; m_tidLookup = tidLookup; + m_affiliations = new lookups::AffiliationLookup("DMR Affiliations", verbose); m_hangCount = callHang * 17U; diff --git a/dmr/Slot.h b/dmr/Slot.h index 5b2f9176..d61a276a 100644 --- a/dmr/Slot.h +++ b/dmr/Slot.h @@ -43,6 +43,7 @@ #include "lookups/IdenTableLookup.h" #include "lookups/RadioIdLookup.h" #include "lookups/TalkgroupIdLookup.h" +#include "lookups/AffiliationLookup.h" #include "RingBuffer.h" #include "StopWatch.h" #include "Timer.h" @@ -55,6 +56,7 @@ namespace dmr // Class Prototypes // --------------------------------------------------------------------------- + class HOST_SW_API Control; namespace packet { class HOST_SW_API Voice; } namespace packet { class HOST_SW_API Data; } namespace packet { class HOST_SW_API ControlSignaling; } @@ -104,9 +106,9 @@ namespace dmr void setSilenceThreshold(uint32_t threshold); /// Helper to initialize the slot processor. - static void init(uint32_t colorCode, SiteData siteData, bool embeddedLCOnly, bool dumpTAData, uint32_t callHang, modem::Modem* modem, + static void init(Control* dmr, uint32_t colorCode, SiteData siteData, bool embeddedLCOnly, bool dumpTAData, uint32_t callHang, modem::Modem* modem, network::BaseNetwork* network, bool duplex, lookups::RadioIdLookup* ridLookup, lookups::TalkgroupIdLookup* tidLookup, - lookups::IdenTableLookup* idenTable, lookups::RSSIInterpolator* rssiMapper, uint32_t jitter); + lookups::IdenTableLookup* idenTable, lookups::RSSIInterpolator* rssiMapper, uint32_t jitter, bool verbose); /// Sets local configured site data. static void setSiteData(uint32_t netId, uint8_t siteId, uint8_t channelId, uint32_t channelNo); /// Sets TSCC Aloha configuration. @@ -184,6 +186,8 @@ namespace dmr bool m_verbose; bool m_debug; + static Control* m_dmr; + static uint32_t m_colorCode; static SiteData m_siteData; @@ -200,6 +204,7 @@ namespace dmr static lookups::IdenTableLookup* m_idenTable; static lookups::RadioIdLookup* m_ridLookup; static lookups::TalkgroupIdLookup* m_tidLookup; + static lookups::AffiliationLookup* m_affiliations; static lookups::IdenTable m_idenEntry; @@ -220,6 +225,8 @@ namespace dmr static uint8_t m_id2; static bool m_voice2; + static bool m_verifyReg; + static uint16_t m_tsccCnt; static uint8_t m_alohaNRandWait; diff --git a/dmr/lc/CSBK.h b/dmr/lc/CSBK.h index 8a6ac1c2..20a0f953 100644 --- a/dmr/lc/CSBK.h +++ b/dmr/lc/CSBK.h @@ -122,7 +122,7 @@ namespace dmr /// Response information. __PROPERTY(uint8_t, response, Response); /// Reason type. - __PROPERTY(uint8_t, reason, reason); + __PROPERTY(uint8_t, reason, Reason); /// Broadcast Announcment Type. __PROPERTY(uint8_t, anncType, AnncType); diff --git a/dmr/packet/ControlSignaling.cpp b/dmr/packet/ControlSignaling.cpp index 3d3b8265..92063d66 100644 --- a/dmr/packet/ControlSignaling.cpp +++ b/dmr/packet/ControlSignaling.cpp @@ -66,6 +66,46 @@ using namespace dmr::packet; } \ } +// Make sure control data is supported. +#define IS_SUPPORT_CONTROL_CHECK(_PCKT_STR, _PCKT, _SRCID) \ + if (!m_slot->m_dmr->getTSCCSlot()->m_enableTSCC) { \ + LogWarning(LOG_RF, "DMR Slot %u, " _PCKT_STR " denial, unsupported service, srcId = %u", m_slot->m_slotNo, _SRCID); \ + writeRF_CSBK_ACK_RSP(TS_DENY_RSN_SYS_UNSUPPORTED_SVC, _PCKT); \ + return false; \ + } + +// Validate the source RID. +#define VALID_SRCID(_PCKT_STR, _PCKT, _SRCID, _RSN) \ + if (!acl::AccessControl::validateSrcId(_SRCID)) { \ + LogWarning(LOG_RF, "DMR Slot %u, " _PCKT_STR " denial, RID rejection, srcId = %u", m_slot->m_slotNo, _SRCID); \ + writeRF_CSBK_ACK_RSP(_RSN, _PCKT); \ + return false; \ + } + +// Validate the target RID. +#define VALID_DSTID(_PCKT_STR, _PCKT, _DSTID, _RSN) \ + if (!acl::AccessControl::validateSrcId(_DSTID)) { \ + LogWarning(LOG_RF, "DMR Slot %u, " _PCKT_STR " denial, RID rejection, dstId = %u", m_slot->m_slotNo, _DSTID); \ + writeRF_CSBK_ACK_RSP(_RSN, _PCKT); \ + return false; \ + } + +// Validate the talkgroup ID. +#define VALID_TGID(_PCKT_STR, _PCKT, _DSTID, _RSN) \ + if (!acl::AccessControl::validateTGId(_DSTID)) { \ + LogWarning(LOG_RF, "DMR Slot %u, " _PCKT_STR " denial, TGID rejection, dstId = %u", m_slot->m_slotNo, _DSTID); \ + writeRF_CSBK_ACK_RSP(_RSN, _PCKT); \ + return false; \ + } + +// Verify the source RID is registered. +#define VERIFY_SRCID_REG(_PCKT_STR, _PCKT, _SRCID, _RSN) \ + if (!m_slot->m_affiliations->isUnitReg(_SRCID) && m_slot->m_verifyReg) { \ + LogWarning(LOG_RF, "DMR Slot %u, " _PCKT_STR " denial, RID not registered, srcId = %u", m_slot->m_slotNo, _SRCID); \ + writeRF_CSBK_ACK_RSP(_RSN, _PCKT); \ + return false; \ + } + // --------------------------------------------------------------------------- // Public Class Members // --------------------------------------------------------------------------- @@ -147,11 +187,38 @@ bool ControlSignaling::process(uint8_t* data, uint32_t len) ::ActivityLog("DMR", true, "Slot %u call alert request from %u to %u", m_slot->m_slotNo, srcId, dstId); } else { handled = true; - + if (m_verbose) { LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), emerg = %u, prio = %u, serviceType = %02X, serviceData = %02X, srcId = %u, dstId = %u", m_slot->m_slotNo, csbk.getEmergency(), csbk.getPriority(), csbk.getServiceType(), csbk.getServiceData(), csbk.getSrcId(), csbk.getDstId()); } + + switch (csbk.getServiceType()) { + case SVC_KIND_IND_VOICE_CALL: + // TODO TODO TODO + break; + case SVC_KIND_GRP_VOICE_CALL: + // TODO TODO TODO + break; + case SVC_KIND_IND_DATA_CALL: + case SVC_KIND_IND_UDT_DATA_CALL: + // TODO TODO TODO + break; + case SVC_KIND_GRP_DATA_CALL: + case SVC_KIND_GRP_UDT_DATA_CALL: + // TODO TODO TODO + break; + case SVC_KIND_REG_SVC: + // make sure control data is supported + IS_SUPPORT_CONTROL_CHECK("DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_REG_SVC (Registration Service)", SVC_KIND_REG_SVC, srcId); + + writeRF_CSBK_U_Reg_Rsp(srcId); + break; + default: + LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), unhandled service, serviceType = %02X", m_slot->m_slotNo, csbk.getServiceType()); + // should we drop the CSBK and not repeat it? + break; + } } break; case CSBKO_ACK_RSP: @@ -212,13 +279,13 @@ bool ControlSignaling::process(uint8_t* data, uint32_t len) } if (!handled) { - // Regenerate the CSBK data + // regenerate the CSBK data csbk.encode(data + 2U); - // Regenerate the Slot Type + // regenerate the Slot Type slotType.encode(data + 2U); - // Convert the Data Sync to be from the BS or MS as needed + // convert the Data Sync to be from the BS or MS as needed Sync::addDMRDataSync(data + 2U, m_slot->m_duplex); m_slot->m_rfSeqNo = 0U; @@ -356,16 +423,16 @@ void ControlSignaling::processNetwork(const data::Data & dmrData) } if (!handled) { - // Regenerate the CSBK data + // regenerate the CSBK data csbk.encode(data + 2U); - // Regenerate the Slot Type + // regenerate the Slot Type SlotType slotType; slotType.decode(data + 2U); slotType.setColorCode(m_slot->m_colorCode); slotType.encode(data + 2U); - // Convert the Data Sync to be from the BS or MS as needed + // convert the Data Sync to be from the BS or MS as needed Sync::addDMRDataSync(data + 2U, m_slot->m_duplex); data[0U] = modem::TAG_DATA; @@ -374,19 +441,19 @@ void ControlSignaling::processNetwork(const data::Data & dmrData) if (csbko == CSBKO_PRECCSBK && csbk.getDataContent()) { uint32_t cbf = NO_PREAMBLE_CSBK + csbk.getCBF() - 1U; for (uint32_t i = 0U; i < NO_PREAMBLE_CSBK; i++, cbf--) { - // Change blocks to follow + // change blocks to follow csbk.setCBF(cbf); - // Regenerate the CSBK data + // regenerate the CSBK data csbk.encode(data + 2U); - // Regenerate the Slot Type + // regenerate the Slot Type SlotType slotType; slotType.decode(data + 2U); slotType.setColorCode(m_slot->m_colorCode); slotType.encode(data + 2U); - // Convert the Data Sync to be from the BS or MS as needed + // convert the Data Sync to be from the BS or MS as needed Sync::addDMRDataSync(data + 2U, m_slot->m_duplex); m_slot->addFrame(data, true); @@ -397,7 +464,7 @@ void ControlSignaling::processNetwork(const data::Data & dmrData) } } else { - // Unhandled data type + // unhandled data type LogWarning(LOG_NET, "DMR Slot %u, unhandled network data, type = $%02X", m_slot->m_slotNo, dataType); } } @@ -426,13 +493,6 @@ void ControlSignaling::writeRF_Ext_Func(uint32_t func, uint32_t arg, uint32_t ds ::ActivityLog("DMR", true, "Slot %u radio uninhibit request from %u to %u", m_slot->m_slotNo, arg, dstId); } - uint8_t data[DMR_FRAME_LENGTH_BYTES + 2U]; - ::memset(data + 2U, 0x00U, DMR_FRAME_LENGTH_BYTES); - - SlotType slotType; - slotType.setColorCode(m_slot->m_colorCode); - slotType.setDataType(DT_CSBK); - lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); csbk.setVerbose(m_dumpCSBKData); csbk.setCSBKO(CSBKO_EXT_FNCT); @@ -443,22 +503,7 @@ void ControlSignaling::writeRF_Ext_Func(uint32_t func, uint32_t arg, uint32_t ds csbk.setSrcId(arg); csbk.setDstId(dstId); - // Regenerate the CSBK data - csbk.encode(data + 2U); - - // Regenerate the Slot Type - slotType.encode(data + 2U); - - // Convert the Data Sync to be from the BS or MS as needed - Sync::addDMRDataSync(data + 2U, m_slot->m_duplex); - - m_slot->m_rfSeqNo = 0U; - - data[0U] = modem::TAG_DATA; - data[1U] = 0x00U; - - if (m_slot->m_duplex) - m_slot->addFrame(data); + writeRF_CSBK(csbk); } /// @@ -475,13 +520,6 @@ void ControlSignaling::writeRF_Call_Alrt(uint32_t srcId, uint32_t dstId) ::ActivityLog("DMR", true, "Slot %u call alert request from %u to %u", m_slot->m_slotNo, srcId, dstId); - uint8_t data[DMR_FRAME_LENGTH_BYTES + 2U]; - ::memset(data + 2U, 0x00U, DMR_FRAME_LENGTH_BYTES); - - SlotType slotType; - slotType.setColorCode(m_slot->m_colorCode); - slotType.setDataType(DT_CSBK); - lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); csbk.setVerbose(m_dumpCSBKData); csbk.setCSBKO(CSBKO_RAND); @@ -491,22 +529,7 @@ void ControlSignaling::writeRF_Call_Alrt(uint32_t srcId, uint32_t dstId) csbk.setSrcId(srcId); csbk.setDstId(dstId); - // Regenerate the CSBK data - csbk.encode(data + 2U); - - // Regenerate the Slot Type - slotType.encode(data + 2U); - - // Convert the Data Sync to be from the BS or MS as needed - Sync::addDMRDataSync(data + 2U, m_slot->m_duplex); - - m_slot->m_rfSeqNo = 0U; - - data[0U] = modem::TAG_DATA; - data[1U] = 0x00U; - - if (m_slot->m_duplex) - m_slot->addFrame(data); + writeRF_CSBK(csbk); } // --------------------------------------------------------------------------- @@ -539,14 +562,12 @@ ControlSignaling::~ControlSignaling() } /// -/// Helper to write a TSCC Aloha broadcast packet on the RF interface. +/// Helper to write a CSBK packet. /// -void ControlSignaling::writeRF_TSCC_Aloha() +/// +/// +void ControlSignaling::writeRF_CSBK(lc::CSBK csbk, bool clearBeforeWrite) { - if (m_debug) { - LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_ALOHA (Aloha)", m_slot->m_slotNo); - } - uint8_t data[DMR_FRAME_LENGTH_BYTES + 2U]; ::memset(data + 2U, 0x00U, DMR_FRAME_LENGTH_BYTES); @@ -554,14 +575,6 @@ void ControlSignaling::writeRF_TSCC_Aloha() slotType.setColorCode(m_slot->m_colorCode); slotType.setDataType(DT_CSBK); - lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); - csbk.setVerbose(m_dumpCSBKData); - csbk.setCSBKO(CSBKO_ALOHA); - csbk.setFID(FID_ETSI); - - csbk.setNRandWait(m_slot->m_alohaNRandWait); - csbk.setBackoffNo(m_slot->m_alohaBackOff); - // Regenerate the CSBK data csbk.encode(data + 2U); @@ -576,10 +589,94 @@ void ControlSignaling::writeRF_TSCC_Aloha() data[0U] = modem::TAG_DATA; data[1U] = 0x00U; + if (clearBeforeWrite) { + if (m_slot->m_slotNo == 1U) + m_slot->m_modem->clearDMRData1(); + if (m_slot->m_slotNo == 2U) + m_slot->m_modem->clearDMRData2(); + m_slot->m_queue.clear(); + } + if (m_slot->m_duplex) m_slot->addFrame(data); } +/// +/// Helper to write a deny packet. +/// +/// +/// +void ControlSignaling::writeRF_CSBK_ACK_RSP(uint8_t reason, uint8_t service) +{ + lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); + csbk.setVerbose(m_dumpCSBKData); + csbk.setCSBKO(CSBKO_ACK_RSP); + csbk.setFID(FID_ETSI); + + csbk.setReason(reason); + + writeRF_CSBK(csbk); +} + +/// +/// Helper to write a unit registration response packet. +/// +/// +void ControlSignaling::writeRF_CSBK_U_Reg_Rsp(uint32_t srcId) +{ + lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); + csbk.setVerbose(m_dumpCSBKData); + csbk.setCSBKO(CSBKO_ACK_RSP); + csbk.setFID(FID_ETSI); + + csbk.setReason(TS_ACK_RSN_REG); + + // validate the source RID + if (!acl::AccessControl::validateSrcId(srcId)) { + LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_REG_SVC (Registration Service), denial, RID rejection, srcId = %u", m_slot->m_slotNo, srcId); + ::ActivityLog("DMR", true, "unit registration request from %u denied", srcId); + csbk.setReason(TS_DENY_RSN_REG_DENIED); + } + + if (csbk.getReason() == TS_ACK_RSN_REG) { + if (m_verbose) { + LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_REG_SVC (Registration Service), srcId = %u", m_slot->m_slotNo, srcId); + } + + ::ActivityLog("DMR", true, "unit registration request from %u", srcId); + + // update dynamic unit registration table + if (!m_slot->m_affiliations->isUnitReg(srcId)) { + m_slot->m_affiliations->unitReg(srcId); + } + } + + csbk.setSrcId(srcId); + csbk.setDstId(srcId); + + writeRF_CSBK(csbk); +} + +/// +/// Helper to write a TSCC Aloha broadcast packet on the RF interface. +/// +void ControlSignaling::writeRF_TSCC_Aloha() +{ + if (m_debug) { + LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_ALOHA (Aloha)", m_slot->m_slotNo); + } + + lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); + csbk.setVerbose(m_dumpCSBKData); + csbk.setCSBKO(CSBKO_ALOHA); + csbk.setFID(FID_ETSI); + + csbk.setNRandWait(m_slot->m_alohaNRandWait); + csbk.setBackoffNo(m_slot->m_alohaBackOff); + + writeRF_CSBK(csbk); +} + /// /// Helper to write a TSCC Ann-Wd broadcast packet on the RF interface. /// @@ -594,10 +691,6 @@ void ControlSignaling::writeRF_TSCC_Bcast_Ann_Wd(uint32_t channelNo, bool annWd) m_slot->m_rfSeqNo = 0U; - SlotType slotType; - slotType.setColorCode(m_slot->m_colorCode); - slotType.setDataType(DT_CSBK); - lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); csbk.setCdef(false); csbk.setVerbose(m_dumpCSBKData); @@ -608,23 +701,7 @@ void ControlSignaling::writeRF_TSCC_Bcast_Ann_Wd(uint32_t channelNo, bool annWd) csbk.setLogicalCh1(channelNo); csbk.setAnnWdCh1(annWd); - uint8_t data[DMR_FRAME_LENGTH_BYTES + 2U]; - ::memset(data + 2U, 0x00U, DMR_FRAME_LENGTH_BYTES); - - // Regenerate the CSBK data - csbk.encode(data + 2U); - - // Regenerate the Slot Type - slotType.encode(data + 2U); - - // Convert the Data Sync to be from the BS or MS as needed - Sync::addDMRDataSync(data + 2U, m_slot->m_duplex); - - data[0U] = modem::TAG_DATA; - data[1U] = 0x00U; - - if (m_slot->m_duplex) - m_slot->addFrame(data); + writeRF_CSBK(csbk); } /// @@ -636,13 +713,6 @@ void ControlSignaling::writeRF_TSCC_Bcast_Sys_Parm() LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_BROADCAST (Broadcast), BCAST_ANNC_SITE_PARMS (Announce Site Parms)", m_slot->m_slotNo); } - uint8_t data[DMR_FRAME_LENGTH_BYTES + 2U]; - ::memset(data + 2U, 0x00U, DMR_FRAME_LENGTH_BYTES); - - SlotType slotType; - slotType.setColorCode(m_slot->m_colorCode); - slotType.setDataType(DT_CSBK); - lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); csbk.setVerbose(m_dumpCSBKData); csbk.setCSBKO(CSBKO_BROADCAST); @@ -650,22 +720,7 @@ void ControlSignaling::writeRF_TSCC_Bcast_Sys_Parm() csbk.setAnncType(BCAST_ANNC_SITE_PARMS); - // Regenerate the CSBK data - csbk.encode(data + 2U); - - // Regenerate the Slot Type - slotType.encode(data + 2U); - - // Convert the Data Sync to be from the BS or MS as needed - Sync::addDMRDataSync(data + 2U, m_slot->m_duplex); - - m_slot->m_rfSeqNo = 0U; - - data[0U] = modem::TAG_DATA; - data[1U] = 0x00U; - - if (m_slot->m_duplex) - m_slot->addFrame(data); + writeRF_CSBK(csbk); } /// @@ -677,32 +732,10 @@ void ControlSignaling::writeRF_TSCC_Git_Hash() LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_DVM_GIT_HASH (DVM Git Hash)", m_slot->m_slotNo); } - uint8_t data[DMR_FRAME_LENGTH_BYTES + 2U]; - ::memset(data + 2U, 0x00U, DMR_FRAME_LENGTH_BYTES); - - SlotType slotType; - slotType.setColorCode(m_slot->m_colorCode); - slotType.setDataType(DT_CSBK); - lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); csbk.setVerbose(m_dumpCSBKData); csbk.setCSBKO(CSBKO_DVM_GIT_HASH); csbk.setFID(FID_DVM); - // Regenerate the CSBK data - csbk.encode(data + 2U); - - // Regenerate the Slot Type - slotType.encode(data + 2U); - - // Convert the Data Sync to be from the BS or MS as needed - Sync::addDMRDataSync(data + 2U, m_slot->m_duplex); - - m_slot->m_rfSeqNo = 0U; - - data[0U] = modem::TAG_DATA; - data[1U] = 0x00U; - - if (m_slot->m_duplex) - m_slot->addFrame(data); + writeRF_CSBK(csbk); } diff --git a/dmr/packet/ControlSignaling.h b/dmr/packet/ControlSignaling.h index 3b2f7a0b..44c35d6c 100644 --- a/dmr/packet/ControlSignaling.h +++ b/dmr/packet/ControlSignaling.h @@ -35,6 +35,7 @@ #include "dmr/data/Data.h" #include "dmr/data/EmbeddedData.h" #include "dmr/lc/LC.h" +#include "dmr/lc/CSBK.h" #include "modem/Modem.h" #include "network/BaseNetwork.h" #include "RingBuffer.h" @@ -86,6 +87,14 @@ namespace dmr /// Finalizes a instance of the ControlSignaling class. ~ControlSignaling(); + /// Helper to write a CSBK packet. + void writeRF_CSBK(lc::CSBK csbk, bool clearBeforeWrite = false); + + /// Helper to write a ACK RSP packet. + void writeRF_CSBK_ACK_RSP(uint8_t reason, uint8_t service); + /// Helper to write a unit registration response packet. + void writeRF_CSBK_U_Reg_Rsp(uint32_t srcId); + /// Helper to write a TSCC Aloha broadcast packet on the RF interface. void writeRF_TSCC_Aloha(); /// Helper to write a TSCC Ann-Wd broadcast packet on the RF interface. diff --git a/nxdn/packet/Trunk.cpp b/nxdn/packet/Trunk.cpp index 5487f2fe..498a772d 100644 --- a/nxdn/packet/Trunk.cpp +++ b/nxdn/packet/Trunk.cpp @@ -415,7 +415,7 @@ void Trunk::writeRF_Message(bool noNetwork, bool clearBeforeWrite) writeNetwork(data, NXDN_FRAME_LENGTH_BYTES + 2U); if (clearBeforeWrite) { - m_nxdn->m_modem->clearP25Data(); + m_nxdn->m_modem->clearNXDNData(); m_nxdn->m_queue.clear(); }