diff --git a/config.yml b/config.yml index 36df4917..9fc5e862 100644 --- a/config.yml +++ b/config.yml @@ -62,13 +62,6 @@ protocols: callHang: 5 noStatusAck: false noMessageAck: true - statusCmd: - enable: true - radioCheck: 1 - radioInhibit: 0 - radioUninhibit: 0 - radioForceReg: 0 - radioForceDereg: 0 silenceThreshold: 124 disableNetworkHDU: false queueSize: 5000 diff --git a/dmr/Control.cpp b/dmr/Control.cpp index 6c26ac4b..c29e8a8a 100644 --- a/dmr/Control.cpp +++ b/dmr/Control.cpp @@ -129,8 +129,7 @@ bool Control::processWakeup(const uint8_t* data) return false; // generate a new CSBK and check validity - lc::CSBK csbk = lc::CSBK(); - csbk.setVerbose(m_dumpCSBKData); + lc::CSBK csbk = lc::CSBK(SiteData(), lookups::IdenTable(), m_dumpCSBKData); bool valid = csbk.decode(data + 2U); if (!valid) diff --git a/dmr/ControlPacket.cpp b/dmr/ControlPacket.cpp index 94bab4de..34e6a1f2 100644 --- a/dmr/ControlPacket.cpp +++ b/dmr/ControlPacket.cpp @@ -86,8 +86,7 @@ bool ControlPacket::process(uint8_t* data, uint32_t len) if (dataType == DT_CSBK) { // generate a new CSBK and check validity - lc::CSBK csbk = lc::CSBK(); - csbk.setVerbose(m_dumpCSBKData); + lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); bool valid = csbk.decode(data + 2U); if (!valid) @@ -230,7 +229,7 @@ void ControlPacket::processNetwork(const data::Data & dmrData) dmrData.getData(data + 2U); if (dataType == DT_CSBK) { - lc::CSBK csbk = lc::CSBK(); + lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); csbk.setVerbose(m_dumpCSBKData); bool valid = csbk.decode(data + 2U); @@ -399,7 +398,7 @@ void ControlPacket::writeRF_Ext_Func(uint32_t func, uint32_t arg, uint32_t dstId slotType.setColorCode(m_slot->m_colorCode); slotType.setDataType(DT_CSBK); - lc::CSBK csbk = lc::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); csbk.setFID(FID_DMRA); @@ -448,7 +447,7 @@ void ControlPacket::writeRF_Call_Alrt(uint32_t srcId, uint32_t dstId) slotType.setColorCode(m_slot->m_colorCode); slotType.setDataType(DT_CSBK); - lc::CSBK csbk = lc::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_CALL_ALRT); csbk.setFID(FID_DMRA); @@ -521,13 +520,12 @@ void ControlPacket::writeRF_TSCC_Bcast_Ann_Wd(uint32_t channelNo, bool annWd) slotType.setColorCode(m_slot->m_colorCode); slotType.setDataType(DT_CSBK); - lc::CSBK csbk = lc::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); csbk.setFID(FID_ETSI); csbk.setAnncType(BCAST_ANNC_ANN_WD_TSCC); - csbk.setSiteData(m_slot->m_siteData); csbk.setLogicalCh1(channelNo); csbk.setAnnWdCh1(annWd); @@ -557,7 +555,6 @@ void ControlPacket::writeRF_TSCC_Bcast_Ann_Wd(uint32_t channelNo, bool annWd) // MBC frame 2 csbk.setLastBlock(false); csbk.setCdef(true); - csbk.setIdenTable(m_slot->m_idenEntry); // Regenerate the CSBK data csbk.encode(data + 2U); @@ -591,13 +588,12 @@ void ControlPacket::writeRF_TSCC_Bcast_Sys_Parm() slotType.setColorCode(m_slot->m_colorCode); slotType.setDataType(DT_CSBK); - lc::CSBK csbk = lc::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); csbk.setFID(FID_ETSI); csbk.setAnncType(BCAST_ANNC_SITE_PARMS); - csbk.setSiteData(m_slot->m_siteData); // Regenerate the CSBK data csbk.encode(data + 2U); diff --git a/dmr/SiteData.h b/dmr/SiteData.h index 92499bee..3c637a74 100644 --- a/dmr/SiteData.h +++ b/dmr/SiteData.h @@ -48,7 +48,8 @@ namespace dmr m_netId(1U), m_siteId(1U), m_parId(3U), - m_requireReg(false) + m_requireReg(false), + m_netActive(false) { /* stub */ } @@ -63,7 +64,8 @@ namespace dmr m_netId(netId), m_siteId(siteId), m_parId(parId), - m_requireReg(requireReq) + m_requireReg(requireReq), + m_netActive(false) { // siteModel clamping if (siteModel > SITE_MODEL_HUGE) @@ -143,6 +145,13 @@ namespace dmr parId = 3U; } + /// Helper to set the site network active flag. + /// Network active. + void setNetActive(bool netActive) + { + m_netActive = netActive; + } + /// Returns the DMR system identity value. /// /// @@ -197,6 +206,8 @@ namespace dmr m_siteId = data.m_siteId; m_requireReg = data.m_requireReg; + + m_netActive = data.m_netActive; } return *this; @@ -213,6 +224,8 @@ namespace dmr __READONLY_PROPERTY_PLAIN(uint8_t, parId, parId); /// DMR require registration. __READONLY_PROPERTY_PLAIN(bool, requireReg, requireReg); + /// Flag indicating whether this site is a linked active network member. + __READONLY_PROPERTY_PLAIN(bool, netActive, netActive); }; } // namespace dmr diff --git a/dmr/Slot.cpp b/dmr/Slot.cpp index ba6b4ded..8a6829c4 100644 --- a/dmr/Slot.cpp +++ b/dmr/Slot.cpp @@ -360,6 +360,15 @@ void Slot::clock() uint32_t ms = m_interval.elapsed(); m_interval.start(); + if (m_network != NULL) { + if (m_network->getStatus() == network::NET_STAT_RUNNING) { + m_siteData.setNetActive(true); + } + else { + m_siteData.setNetActive(false); + } + } + // increment the TSCC counter on every slot 1 clock if (m_slotNo == 1U) { m_tsccCnt++; diff --git a/dmr/VoicePacket.cpp b/dmr/VoicePacket.cpp index 7e9bf0ff..f1d076d6 100644 --- a/dmr/VoicePacket.cpp +++ b/dmr/VoicePacket.cpp @@ -588,7 +588,7 @@ void VoicePacket::processNetwork(const data::Data& dmrData) return; lc::FullLC fullLC; - lc::LC * lc = fullLC.decode(data + 2U, DT_VOICE_LC_HEADER); + lc::LC* lc = fullLC.decode(data + 2U, DT_VOICE_LC_HEADER); if (lc == NULL) { LogWarning(LOG_NET, "DMR Slot %u, DT_VOICE_LC_HEADER, bad LC received from the network, replacing", m_slot->m_slotNo); lc = new lc::LC(dmrData.getFLCO(), dmrData.getSrcId(), dmrData.getDstId()); diff --git a/dmr/lc/CSBK.cpp b/dmr/lc/CSBK.cpp index 260e239e..1f18692c 100644 --- a/dmr/lc/CSBK.cpp +++ b/dmr/lc/CSBK.cpp @@ -47,25 +47,23 @@ using namespace dmr; /// /// Initializes a new instance of the CSBK class. /// -CSBK::CSBK() : - m_verbose(false), - m_CSBKO(CSBKO_NONE), - m_FID(0x00U), - m_lastBlock(true), - m_bsId(0U), - m_GI(false), - m_Cdef(false), - m_srcId(0U), - m_dstId(0U), - m_dataContent(false), - m_CBF(0U), - m_data(NULL), - m_siteData(), - m_siteNetActive(false) +/// +/// +CSBK::CSBK(SiteData siteData, lookups::IdenTable entry) : CSBK(siteData) { - m_data = new uint8_t[12U]; + m_siteIdenEntry = entry; +} - reset(); +/// +/// Initializes a new instance of the CSBK class. +/// +/// +/// +/// +CSBK::CSBK(SiteData siteData, lookups::IdenTable entry, bool verbose) : CSBK(siteData) +{ + m_verbose = verbose; + m_siteIdenEntry = entry; } /// @@ -297,7 +295,7 @@ void CSBK::encode(uint8_t* bytes) csbkValue = (csbkValue << 1) + ((m_siteTSSync) ? 1U : 0U); // Site Time Slot Synchronization csbkValue = (csbkValue << 3) + DMR_ALOHA_VER_151; // DMR Spec. Version (1.5.1) csbkValue = (csbkValue << 1) + ((m_siteOffsetTiming) ? 1U : 0U); // Site Timing: Aligned or Offset - csbkValue = (csbkValue << 1) + ((m_siteNetActive) ? 1U : 0U); // Site Networked + csbkValue = (csbkValue << 1) + ((m_siteData.netActive()) ? 1U : 0U); // Site Networked csbkValue = (csbkValue << 5) + (m_alohaMask & 0x1FU); // MS Mask csbkValue = (csbkValue << 2) + 0U; // Service Function csbkValue = (csbkValue << 4) + 0U; // @@ -426,58 +424,43 @@ void CSBK::encode(uint8_t* bytes) bptc.encode(m_data, bytes); } +// --------------------------------------------------------------------------- +// Private Class Members +// --------------------------------------------------------------------------- /// -/// Helper to reset data values to defaults. -/// -void CSBK::reset() -{ - m_colorCode = 0U; - - m_backoffNo = 1U; - m_serviceType = 0U; - m_serviceOptions = 0U; - m_targetAddress = TGT_ADRS_TGID; - - m_response = 0U; - - /* Broadcast */ - m_anncType = BCAST_ANNC_SITE_PARMS; - m_hibernating = false; - - m_annWdCh1 = false; - m_logicalCh1 = DMR_CHNULL; - m_annWdCh2 = false; - m_logicalCh2 = DMR_CHNULL; - - /* Aloha */ - m_siteTSSync = false; - m_siteOffsetTiming = false; -} - -/** Local Site data */ -/// -/// Sets local configured site data. -/// -/// Site data. -void CSBK::setSiteData(SiteData siteData) -{ - m_siteData = siteData; -} - -/// -/// Sets the identity lookup table entry. -/// -/// Identity table entry. -void CSBK::setIdenTable(lookups::IdenTable entry) -{ - m_siteIdenEntry = entry; -} - -/// -/// Sets a flag indicating whether or not networking is active. +/// Initializes a new instance of the CSBK class. /// -/// Network active flag. -void CSBK::setNetActive(bool netActive) +/// +CSBK::CSBK(SiteData siteData) : + m_verbose(false), + m_CSBKO(CSBKO_NONE), + m_FID(0x00U), + m_lastBlock(true), + m_bsId(0U), + m_GI(false), + m_Cdef(false), + m_srcId(0U), + m_dstId(0U), + m_dataContent(false), + m_CBF(0U), + m_colorCode(0U), + m_backoffNo(1U), + m_serviceType(0U), + m_serviceOptions(0U), + m_targetAddress(TGT_ADRS_TGID), + m_response(0U), + m_anncType(BCAST_ANNC_SITE_PARMS), + m_hibernating(false), + m_annWdCh1(false), + m_logicalCh1(DMR_CHNULL), + m_annWdCh2(false), + m_logicalCh2(DMR_CHNULL), + m_siteTSSync(false), + m_siteOffsetTiming(false), + m_alohaMask(0U), + m_siteData(siteData), + m_siteIdenEntry(lookups::IdenTable()), + m_data(NULL) { - m_siteNetActive = netActive; + m_data = new uint8_t[12U]; } diff --git a/dmr/lc/CSBK.h b/dmr/lc/CSBK.h index 904029d1..05dfffe6 100644 --- a/dmr/lc/CSBK.h +++ b/dmr/lc/CSBK.h @@ -48,7 +48,9 @@ namespace dmr class HOST_SW_API CSBK { public: /// Initializes a new instance of the CSBK class. - CSBK(); + CSBK(SiteData siteData, lookups::IdenTable entry); + /// Initializes a new instance of the CSBK class. + CSBK(SiteData siteData, lookups::IdenTable entry, bool verbose); /// Finalizes a instance of the CSBK class. ~CSBK(); @@ -57,17 +59,6 @@ namespace dmr /// Encodes a DMR CSBK. void encode(uint8_t* bytes); - /// Helper to reset data values to defaults. - void reset(); - - /** Local Site data */ - /// Sets local configured site data. - void setSiteData(SiteData siteData); - /// Sets the identity lookup table entry. - void setIdenTable(lookups::IdenTable entry); - /// Sets a flag indicating whether or not networking is active. - void setNetActive(bool netActive); - public: /// Flag indicating verbose log output. __PROPERTY(bool, verbose, Verbose); @@ -141,13 +132,17 @@ namespace dmr /// Aloha MS mask. __PROPERTY(uint8_t, alohaMask, AlohaMask); + /** Local Site data */ + /// Local Site Data. + __PROPERTY_PLAIN(SiteData, siteData, siteData); + /// Local Site Identity Entry. + __PROPERTY_PLAIN(lookups::IdenTable, siteIdenEntry, siteIdenEntry); + private: - uint8_t* m_data; + /// Initializes a new instance of the CSBK class. + CSBK(SiteData siteData); - /** Local Site data */ - SiteData m_siteData; - lookups::IdenTable m_siteIdenEntry; - bool m_siteNetActive; + uint8_t* m_data; }; } // namespace lc } // namespace dmr diff --git a/host/calibrate/HostCal.cpp b/host/calibrate/HostCal.cpp index fb9b2946..5b00c041 100644 --- a/host/calibrate/HostCal.cpp +++ b/host/calibrate/HostCal.cpp @@ -1349,7 +1349,7 @@ void HostCal::processP25BER(const uint8_t* buffer) else if (duid == P25_DUID_TSDU) { timerStop(); - lc::TSBK tsbk = lc::TSBK(); + lc::TSBK tsbk = lc::TSBK(SiteData(), lookups::IdenTable()); bool ret = tsbk.decode(buffer + 1U); if (!ret) { LogWarning(LOG_CAL, "P25_DUID_TSDU (Trunking System Data Unit), undecodable LC"); diff --git a/p25/Control.cpp b/p25/Control.cpp index b4ebba25..c9fa9b25 100644 --- a/p25/Control.cpp +++ b/p25/Control.cpp @@ -101,6 +101,7 @@ Control::Control(uint32_t nac, uint32_t callHang, uint32_t queueSize, modem::Mod m_idenTable(idenTable), m_ridLookup(ridLookup), m_tidLookup(tidLookup), + m_idenEntry(), m_queue(queueSize, "P25 Control"), m_rfState(RS_RF_LISTENING), m_rfLastDstId(0U), @@ -119,6 +120,7 @@ Control::Control(uint32_t nac, uint32_t callHang, uint32_t queueSize, modem::Mod m_ccFrameCnt(0U), m_ccSeq(0U), m_nid(nac), + m_siteData(), m_rssiMapper(rssiMapper), m_rssi(0U), m_maxRSSI(0U), @@ -160,7 +162,6 @@ void Control::reset() m_rfState = RS_RF_LISTENING; m_voice->resetRF(); - m_trunk->resetRF(); m_data->resetRF(); m_queue.clear(); } @@ -186,8 +187,6 @@ void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const s yaml::Node systemConf = conf["system"]; yaml::Node p25Protocol = conf["protocols"]["p25"]; - m_trunk->setCallsign(cwCallsign); - m_tduPreambleCount = p25Protocol["tduPreambleCount"].as(8U); m_trunk->m_patchSuperGroup = pSuperGroup; @@ -202,14 +201,6 @@ void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const s m_trunk->m_noStatusAck = p25Protocol["noStatusAck"].as(false); m_trunk->m_noMessageAck = p25Protocol["noMessageAck"].as(true); - yaml::Node statusCmd = p25Protocol["statusCmd"]; - m_trunk->m_statusCmdEnable = statusCmd["enable"].as(false); - m_trunk->m_statusRadioCheck = (uint8_t)statusCmd["radioCheck"].as(0U); - m_trunk->m_statusRadioInhibit = (uint8_t)statusCmd["radioInhibit"].as(0U); - m_trunk->m_statusRadioUninhibit = (uint8_t)statusCmd["radioUninhibit"].as(0U); - m_trunk->m_statusRadioForceReg = (uint8_t)statusCmd["radioForceReg"].as(0U); - m_trunk->m_statusRadioForceDereg = (uint8_t)statusCmd["radioForceDereg"].as(0U); - yaml::Node control = p25Protocol["control"]; m_control = control["enable"].as(false); if (m_control) { @@ -221,17 +212,35 @@ void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const s m_voiceOnControl = p25Protocol["voiceOnControl"].as(false); m_ackTSBKRequests = control["ackRequests"].as(true); - m_trunk->setServiceClass(m_control, m_voiceOnControl); m_voice->m_silenceThreshold = p25Protocol["silenceThreshold"].as(p25::DEFAULT_SILENCE_THRESHOLD); m_disableNetworkHDU = p25Protocol["disableNetworkHDU"].as(false); - m_trunk->setSiteData(netId, sysId, rfssId, siteId, 0U, channelId, channelNo); + uint8_t serviceClass = P25_SVC_CLS_VOICE | P25_SVC_CLS_DATA; + if (m_control) { + serviceClass |= P25_SVC_CLS_REG; + } + + if (m_voiceOnControl) { + serviceClass |= P25_SVC_CLS_COMPOSITE; + } + + m_siteData = SiteData(netId, sysId, rfssId, siteId, 0U, channelId, channelNo, serviceClass); + m_siteData.setCallsign(cwCallsign); + + std::vector entries = m_idenTable->list(); + for (auto it = entries.begin(); it != entries.end(); ++it) { + lookups::IdenTable entry = *it; + if (entry.channelId() == channelId) { + m_idenEntry = entry; + break; + } + } std::vector availCh = voiceChNo; m_trunk->m_voiceChCnt = (uint8_t)availCh.size(); - m_trunk->setSiteChCnt((uint8_t)availCh.size()); + m_siteData.setChCnt((uint8_t)availCh.size()); for (auto it = availCh.begin(); it != availCh.end(); ++it) { m_trunk->m_voiceChTable.push_back(*it); @@ -255,15 +264,14 @@ void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const s LogInfo(" No Status ACK: %s", m_trunk->m_noStatusAck ? "yes" : "no"); LogInfo(" No Message ACK: %s", m_trunk->m_noMessageAck ? "yes" : "no"); - LogInfo(" Status Command Support: %s", m_trunk->m_statusCmdEnable ? "yes" : "no"); - if (m_trunk->m_statusCmdEnable) { - LogInfo(" Status Radio Check: $%02X", m_trunk->m_statusRadioCheck); - LogInfo(" Status Radio Inhibit: $%02X", m_trunk->m_statusRadioInhibit); - LogInfo(" Status Radio Uninhibit: $%02X", m_trunk->m_statusRadioUninhibit); - LogInfo(" Status Radio Force Register: $%02X", m_trunk->m_statusRadioForceReg); - LogInfo(" Status Radio Force Deregister: $%02X", m_trunk->m_statusRadioForceDereg); - } } + + m_voice->resetRF(); + m_voice->resetNet(); + m_data->resetRF(); + + m_trunk->m_rfTSBK = lc::TSBK(m_siteData, m_idenEntry); + m_trunk->m_netTSBK = lc::TSBK(m_siteData, m_idenEntry); } /// @@ -342,9 +350,10 @@ bool Control::processFrame(uint8_t* data, uint32_t len) m_rfState = RS_RF_LISTENING; m_voice->resetRF(); - m_trunk->resetRF(); m_data->resetRF(); + m_trunk->m_rfTSBK = lc::TSBK(m_siteData, m_idenEntry); + return false; } @@ -561,10 +570,10 @@ void Control::clock(uint32_t ms) processNetwork(); if (m_network->getStatus() == network::NET_STAT_RUNNING) { - m_trunk->setNetActive(true); + m_siteData.setNetActive(true); } else { - m_trunk->setNetActive(false); + m_siteData.setNetActive(false); } } @@ -610,7 +619,8 @@ void Control::clock(uint32_t ms) m_tailOnIdle = true; m_voice->resetNet(); - m_trunk->resetNet(); + + m_trunk->m_netTSBK = lc::TSBK(m_siteData, m_idenEntry); m_netTimeout.stop(); } @@ -620,12 +630,13 @@ void Control::clock(uint32_t ms) m_queue.clear(); m_voice->resetRF(); - m_voice->m_rfLastHDU.reset(); m_voice->resetNet(); - m_trunk->resetRF(); - m_trunk->resetNet(); + m_data->resetRF(); + m_trunk->m_rfTSBK = lc::TSBK(m_siteData, m_idenEntry); + m_trunk->m_netTSBK = lc::TSBK(m_siteData, m_idenEntry); + if (m_network != NULL) m_network->resetP25(); @@ -633,6 +644,17 @@ void Control::clock(uint32_t ms) } m_trunk->clock(ms); + + // if the states are "idle" ensure LC data isn't being held in memory + if (m_rfState == RS_RF_LISTENING && m_netState == RS_NET_IDLE) { + m_voice->resetRF(); + m_voice->resetNet(); + + m_data->resetRF(); + + m_trunk->m_rfTSBK = lc::TSBK(m_siteData, m_idenEntry); + m_trunk->m_netTSBK = lc::TSBK(m_siteData, m_idenEntry); + } } /// diff --git a/p25/Control.h b/p25/Control.h index 92b794d1..6ba27458 100644 --- a/p25/Control.h +++ b/p25/Control.h @@ -36,6 +36,7 @@ #include "p25/DataPacket.h" #include "p25/VoicePacket.h" #include "p25/NID.h" +#include "p25/SiteData.h" #include "network/BaseNetwork.h" #include "network/RemoteControl.h" #include "lookups/RSSIInterpolator.h" @@ -138,6 +139,8 @@ namespace p25 lookups::RadioIdLookup* m_ridLookup; lookups::TalkgroupIdLookup* m_tidLookup; + lookups::IdenTable m_idenEntry; + RingBuffer m_queue; RPT_RF_STATE m_rfState; @@ -163,6 +166,8 @@ namespace p25 NID m_nid; + SiteData m_siteData; + lookups::RSSIInterpolator* m_rssiMapper; uint8_t m_rssi; uint8_t m_maxRSSI; diff --git a/p25/DataPacket.cpp b/p25/DataPacket.cpp index 45b73bf7..cd4166fe 100644 --- a/p25/DataPacket.cpp +++ b/p25/DataPacket.cpp @@ -91,8 +91,6 @@ bool DataPacket::process(uint8_t* data, uint32_t len) // handle individual DUIDs if (duid == P25_DUID_PDU) { - m_p25->m_trunk->resetStatusCommand(); - if (m_p25->m_rfState != RS_RF_DATA) { m_rfDataHeader.reset(); m_rfDataBlockCnt = 0U; diff --git a/p25/SiteData.h b/p25/SiteData.h index 10ad1307..3d9d413b 100644 --- a/p25/SiteData.h +++ b/p25/SiteData.h @@ -52,7 +52,10 @@ namespace p25 m_channelId(1U), m_channelNo(1U), m_serviceClass(P25_SVC_CLS_VOICE | P25_SVC_CLS_DATA), - m_isAdjSite(false) + m_isAdjSite(false), + m_callsign("CHANGEME"), + m_chCnt(0U), + m_netActive(false) { /* stub */ } @@ -74,7 +77,10 @@ namespace p25 m_channelId(1U), m_channelNo(1U), m_serviceClass(P25_SVC_CLS_VOICE | P25_SVC_CLS_DATA), - m_isAdjSite(false) + m_isAdjSite(false), + m_callsign("CHANGEME"), + m_chCnt(0U), + m_netActive(false) { // lra clamping if (lra > 0xFFU) // clamp to $FF @@ -128,6 +134,27 @@ namespace p25 m_serviceClass = serviceClass; } + /// Helper to set the site callsign. + /// Callsign. + void setCallsign(std::string callsign) + { + m_callsign = callsign; + } + + /// Helper to set the site channel count. + /// Channel count. + void setChCnt(uint8_t chCnt) + { + m_chCnt = m_chCnt; + } + + /// Helper to set the site network active flag. + /// Network active. + void setNetActive(bool netActive) + { + m_netActive = netActive; + } + /// Helper to set adjacent site data. /// P25 System ID. /// P25 RFSS ID. @@ -179,6 +206,10 @@ namespace p25 m_serviceClass = serviceClass; m_isAdjSite = true; + + m_callsign = "ADJSITE "; + m_chCnt = -1; // don't store channel count for adjacent sites + m_netActive = true; // adjacent sites are explicitly network active } /// Equals operator. @@ -201,6 +232,11 @@ namespace p25 m_serviceClass = data.m_serviceClass; m_isAdjSite = data.m_isAdjSite; + + m_callsign = data.m_callsign; + m_chCnt = data.m_chCnt; + + m_netActive = data.m_netActive; } return *this; @@ -225,6 +261,12 @@ namespace p25 __READONLY_PROPERTY_PLAIN(uint8_t, serviceClass, serviceClass); /// Flag indicating whether this site data is for an adjacent site. __READONLY_PROPERTY_PLAIN(bool, isAdjSite, isAdjSite); + /// Callsign. + __READONLY_PROPERTY_PLAIN(std::string, callsign, callsign); + /// Count of available channels. + __READONLY_PROPERTY_PLAIN(uint8_t, chCnt, chCnt); + /// Flag indicating whether this site is a linked active network member. + __READONLY_PROPERTY_PLAIN(bool, netActive, netActive); }; } // namespace p25 diff --git a/p25/TrunkPacket.cpp b/p25/TrunkPacket.cpp index a6a58b7f..83c10528 100644 --- a/p25/TrunkPacket.cpp +++ b/p25/TrunkPacket.cpp @@ -138,173 +138,6 @@ const uint32_t GRANT_TIMER_TIMEOUT = 15U; // --------------------------------------------------------------------------- // Public Class Members // --------------------------------------------------------------------------- -/// -/// Sets local configured site data. -/// -/// P25 Network ID. -/// P25 System ID. -/// P25 RFSS ID. -/// P25 Site ID. -/// P25 Location Resource Area. -/// Channel ID. -/// Channel Number. -void TrunkPacket::setSiteData(uint32_t netId, uint32_t sysId, uint8_t rfssId, uint8_t siteId, uint8_t lra, - uint8_t channelId, uint32_t channelNo) -{ - uint8_t serviceClass = m_rfTSBK.getServiceClass(); - m_siteData = SiteData(netId, sysId, rfssId, siteId, lra, channelId, channelNo, serviceClass); - - m_rfTSBK.setSiteData(m_siteData); - m_rfTDULC.setSiteData(m_siteData); - m_p25->m_voice->m_rfLC.setSiteData(m_siteData); - - m_netTSBK.setSiteData(m_siteData); - m_netTDULC.setSiteData(m_siteData); - m_p25->m_voice->m_netLC.setSiteData(m_siteData); -} - -/// -/// Sets local configured site callsign. -/// -/// -void TrunkPacket::setCallsign(std::string callsign) -{ - m_rfTSBK.setCallsign(callsign); - m_netTSBK.setCallsign(callsign); -} - -/// -/// Sets a flag indicating whether or not networking is active. -/// -/// -void TrunkPacket::setNetActive(bool active) -{ - m_rfTSBK.setNetActive(active); - m_rfTDULC.setNetActive(active); - m_netTSBK.setNetActive(active); - m_netTDULC.setNetActive(active); -} - -/// -/// Sets the total number of channels at the site. -/// -/// -void TrunkPacket::setSiteChCnt(uint8_t chCnt) -{ - m_rfTSBK.setSiteChCnt(chCnt); - m_netTSBK.setSiteChCnt(chCnt); -} - -/// -/// Sets the service class for this site. -/// -/// -/// -void TrunkPacket::setServiceClass(bool control, bool voiceOnControl) -{ - uint8_t serviceClass = P25_SVC_CLS_VOICE | P25_SVC_CLS_DATA; - if (control) { - serviceClass |= P25_SVC_CLS_REG; - } - - if (voiceOnControl) { - serviceClass |= P25_SVC_CLS_COMPOSITE; - } - - m_rfTSBK.setServiceClass(serviceClass); - m_netTSBK.setServiceClass(serviceClass); - - m_rfTDULC.setServiceClass(serviceClass); - m_netTDULC.setServiceClass(serviceClass); - - m_p25->m_voice->m_rfLC.setServiceClass(serviceClass); - m_p25->m_voice->m_netLC.setServiceClass(serviceClass); -} - -/// -/// Resets the data states for the RF interface. -/// -void TrunkPacket::resetRF() -{ - m_rfTSBK.reset(); - m_rfTDULC.reset(); -} - -/// -/// Resets the data states for the network. -/// -void TrunkPacket::resetNet() -{ - m_netTSBK.reset(); - m_netTDULC.reset(); -} - -/// -/// Sets the RF TSBK and TDULC data to match the given LC data. -/// -/// -void TrunkPacket::setRFLC(const lc::LC& lc) -{ - m_rfTSBK.reset(); - m_rfTDULC.reset(); - - m_rfTSBK.setProtect(lc.getProtect()); - m_rfTDULC.setProtect(lc.getProtect()); - m_rfTSBK.setMFId(lc.getMFId()); - m_rfTDULC.setMFId(lc.getMFId()); - - m_rfTSBK.setSrcId(lc.getSrcId()); - m_rfTDULC.setSrcId(lc.getSrcId()); - m_rfTSBK.setDstId(lc.getDstId()); - m_rfTDULC.setDstId(lc.getDstId()); - - m_rfTSBK.setGrpVchNo(lc.getGrpVchNo()); - m_rfTDULC.setGrpVchNo(lc.getGrpVchNo()); - - m_rfTSBK.setEmergency(lc.getEmergency()); - m_rfTDULC.setEmergency(lc.getEmergency()); - m_rfTSBK.setEncrypted(lc.getEncrypted()); - m_rfTDULC.setEncrypted(lc.getEmergency()); - m_rfTSBK.setPriority(lc.getPriority()); - m_rfTDULC.setPriority(lc.getPriority()); - - m_rfTSBK.setGroup(lc.getGroup()); - m_rfTDULC.setGroup(lc.getGroup()); -} - -/// -/// Sets the network TSBK and TDULC data to match the given LC data. -/// -/// -void TrunkPacket::setNetLC(const lc::LC& lc) -{ - m_netTSBK.reset(); - m_netTDULC.reset(); - - m_netTSBK.setProtect(lc.getProtect()); - m_netTDULC.setProtect(lc.getProtect()); - m_netTSBK.setMFId(lc.getMFId()); - m_netTDULC.setMFId(lc.getMFId()); - - m_netTSBK.setSrcId(lc.getSrcId()); - m_netTDULC.setSrcId(lc.getSrcId()); - m_netTSBK.setDstId(lc.getDstId()); - m_netTDULC.setDstId(lc.getDstId()); - - m_netTSBK.setGrpVchNo(lc.getGrpVchNo()); - m_netTDULC.setGrpVchNo(lc.getGrpVchNo()); - - m_netTSBK.setEmergency(lc.getEmergency()); - m_netTDULC.setEmergency(lc.getEmergency()); - m_netTSBK.setEncrypted(lc.getEncrypted()); - m_netTDULC.setEncrypted(lc.getEmergency()); - m_netTSBK.setPriority(lc.getPriority()); - m_netTDULC.setPriority(lc.getPriority()); - - m_netTSBK.setGroup(lc.getGroup()); - m_netTDULC.setGroup(lc.getGroup()); -} - /// /// Process a data frame from the RF interface. /// @@ -334,8 +167,9 @@ bool TrunkPacket::process(uint8_t* data, uint32_t len) } m_p25->m_queue.clear(); - m_rfTSBK.reset(); - m_netTSBK.reset(); + + m_rfTSBK = lc::TSBK(m_p25->m_siteData, m_p25->m_idenEntry, m_dumpTSBK); + m_netTSBK = lc::TSBK(m_p25->m_siteData, m_p25->m_idenEntry, m_dumpTSBK); bool ret = m_rfTSBK.decode(data + 2U); if (!ret) { @@ -347,8 +181,6 @@ bool TrunkPacket::process(uint8_t* data, uint32_t len) uint32_t srcId = m_rfTSBK.getSrcId(); uint32_t dstId = m_rfTSBK.getDstId(); - resetStatusCommand(m_rfTSBK); - switch (m_rfTSBK.getLCO()) { case TSBK_IOSP_GRP_VCH: // make sure control data is supported @@ -448,23 +280,17 @@ bool TrunkPacket::process(uint8_t* data, uint32_t len) // validate the source RID VALID_SRCID("TSBK_IOSP_STS_UPDT (Status Update)", TSBK_IOSP_STS_UPDT, srcId); - if ((m_statusSrcId == 0U) && (m_statusValue == 0U)) { - RF_TO_WRITE_NET(); - } + RF_TO_WRITE_NET(); if (m_verbose) { LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_STS_UPDT (Status Update), status = $%02X, srcId = %u", m_rfTSBK.getStatus(), srcId); } - ::ActivityLog("P25", true, "status update from %u", srcId); - if (!m_noStatusAck) { writeRF_TSDU_ACK_FNE(srcId, TSBK_IOSP_STS_UPDT, false, false); } - if (m_statusCmdEnable) { - preprocessStatusCommand(); - } + ::ActivityLog("P25", true, "status update from %u", srcId); break; case TSBK_IOSP_MSG_UPDT: // validate the source RID @@ -487,16 +313,6 @@ bool TrunkPacket::process(uint8_t* data, uint32_t len) // validate the source RID VALID_SRCID("TSBK_IOSP_CALL_ALRT (Call Alert)", TSBK_IOSP_CALL_ALRT, srcId); - // is status command mode enabled with status data? - if (m_statusCmdEnable) { - if (processStatusCommand(srcId, dstId)) { - m_p25->m_rfState = prevRfState; - return true; - } - - resetStatusCommand(); - } - // validate the target RID VALID_DSTID("TSBK_IOSP_CALL_ALRT (Call Alert)", TSBK_IOSP_CALL_ALRT, dstId); @@ -548,18 +364,6 @@ bool TrunkPacket::process(uint8_t* data, uint32_t len) m_rfTSBK.getExtendedFunction(), dstId, srcId); } - // is status control mode enabled with status data? - if (m_statusCmdEnable && (m_statusValue != 0U)) { - m_rfTSBK.setLCO(TSBK_IOSP_ACK_RSP); - m_rfTSBK.setAIV(true); - m_rfTSBK.setService(TSBK_IOSP_CALL_ALRT); - - if (m_verbose) { - LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_ACK_RSP (Acknowledge Response), serviceType = $%02X, srcId = %u", - m_rfTSBK.getService(), m_statusSrcId); - } - } - // generate activity log entry if (m_rfTSBK.getExtendedFunction() == P25_EXT_FNCT_CHECK_ACK) { ::ActivityLog("P25", true, "radio check response from %u to %u", dstId, srcId); @@ -572,7 +376,6 @@ bool TrunkPacket::process(uint8_t* data, uint32_t len) } writeRF_TSDU_SBF(true); - resetStatusCommand(); break; case TSBK_IOSP_GRP_AFF: // make sure control data is supported @@ -677,8 +480,8 @@ bool TrunkPacket::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, d switch (duid) { case P25_DUID_TSDU: if (m_p25->m_netState == RS_NET_IDLE) { - m_rfTSBK.reset(); - m_netTSBK.reset(); + m_rfTSBK = lc::TSBK(m_p25->m_siteData, m_p25->m_idenEntry, m_dumpTSBK); + m_netTSBK = lc::TSBK(m_p25->m_siteData, m_p25->m_idenEntry, m_dumpTSBK); bool ret = m_netTSBK.decode(data); if (!ret) { @@ -691,7 +494,7 @@ bool TrunkPacket::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, d return false; } - if (m_netTSBK.getAdjSiteId() != m_siteData.siteId()) { + if (m_netTSBK.getAdjSiteId() != m_p25->m_siteData.siteId()) { // update site table data SiteData site; try { @@ -741,8 +544,6 @@ bool TrunkPacket::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, d uint32_t srcId = m_netTSBK.getSrcId(); uint32_t dstId = m_netTSBK.getDstId(); - resetStatusCommand(m_netTSBK); - switch (m_netTSBK.getLCO()) { case TSBK_IOSP_UU_ANS: if (m_netTSBK.getResponse() > 0U) { @@ -820,8 +621,6 @@ bool TrunkPacket::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, d LogMessage(LOG_NET, P25_TSDU_STR ", TSBK_IOSP_EXT_FNCT (Extended Function), serviceType = $%02X, arg = %u, tgt = %u", m_netTSBK.getService(), srcId, dstId); } - - resetStatusCommand(); break; case TSBK_IOSP_GRP_AFF: // ignore a network group affiliation command @@ -868,15 +667,13 @@ void TrunkPacket::writeAdjSSNetwork() return; } - m_rfTSBK.reset(); - m_netTSBK.reset(); + m_rfTSBK = lc::TSBK(m_p25->m_siteData, m_p25->m_idenEntry, m_dumpTSBK); + m_netTSBK = lc::TSBK(m_p25->m_siteData, m_p25->m_idenEntry, m_dumpTSBK); if (m_network != NULL) { - uint8_t serviceClass = m_rfTSBK.getServiceClass(); - if (m_verbose) { LogMessage(LOG_NET, P25_TSDU_STR ", TSBK_OSP_ADJ_STS_BCAST (Adjacent Site Status Broadcast), network announce, sysId = $%03X, rfss = $%02X, site = $%02X, chId = %u, chNo = %u, svcClass = $%02X", - m_siteData.sysId(), m_siteData.rfssId(), m_siteData.siteId(), m_siteData.channelId(), m_siteData.channelNo(), serviceClass); + m_p25->m_siteData.sysId(), m_p25->m_siteData.rfssId(), m_p25->m_siteData.siteId(), m_p25->m_siteData.channelId(), m_p25->m_siteData.channelNo(), m_p25->m_siteData.serviceClass()); } uint8_t cfva = P25_CFVA_VALID; @@ -887,12 +684,12 @@ void TrunkPacket::writeAdjSSNetwork() // transmit adjacent site broadcast m_rfTSBK.setLCO(TSBK_OSP_ADJ_STS_BCAST); m_rfTSBK.setAdjSiteCFVA(cfva); - m_rfTSBK.setAdjSiteSysId(m_siteData.sysId()); - m_rfTSBK.setAdjSiteRFSSId(m_siteData.rfssId()); - m_rfTSBK.setAdjSiteId(m_siteData.siteId()); - m_rfTSBK.setAdjSiteChnId(m_siteData.channelId()); - m_rfTSBK.setAdjSiteChnNo(m_siteData.channelNo()); - m_rfTSBK.setAdjSiteSvcClass(serviceClass); + m_rfTSBK.setAdjSiteSysId(m_p25->m_siteData.sysId()); + m_rfTSBK.setAdjSiteRFSSId(m_p25->m_siteData.rfssId()); + m_rfTSBK.setAdjSiteId(m_p25->m_siteData.siteId()); + m_rfTSBK.setAdjSiteChnId(m_p25->m_siteData.channelId()); + m_rfTSBK.setAdjSiteChnNo(m_p25->m_siteData.channelNo()); + m_rfTSBK.setAdjSiteSvcClass(m_p25->m_siteData.serviceClass()); RF_TO_WRITE_NET(); } @@ -1039,11 +836,11 @@ void TrunkPacket::releaseDstIdGrant(uint32_t dstId, bool releaseAll) if (m_voiceGrantChCnt > 0U) { m_voiceGrantChCnt--; - setSiteChCnt(m_voiceChCnt + m_voiceGrantChCnt); + m_p25->m_siteData.setChCnt(m_voiceChCnt + m_voiceGrantChCnt); } else { m_voiceGrantChCnt = 0U; - setSiteChCnt(m_voiceChCnt); + m_p25->m_siteData.setChCnt(m_voiceChCnt); } m_grantTimers[dstId].stop(); @@ -1086,24 +883,6 @@ void TrunkPacket::clearGrpAff(uint32_t dstId, bool releaseAll) } } -/// -/// Resets the state of the status commands. -/// -void TrunkPacket::resetStatusCommand() -{ - // reset status control data - if (m_statusCmdEnable) { - if (m_statusSrcId != 0U && m_statusValue != 0U) { - if (m_verbose) { - LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_STS_UPDT (Status Update), canceled command mode, statusCurrentStatus = $%02X", m_statusValue); - } - } - - m_statusSrcId = 0U; - m_statusValue = 0U; - } -} - /// /// Updates the processor by the passed number of milliseconds. /// @@ -1300,11 +1079,7 @@ void TrunkPacket::writeRF_TSDU_Mot_Patch(uint32_t group1, uint32_t group2, uint3 /// Flag indicating whether TSBK dumping is enabled. void TrunkPacket::setTSBKVerbose(bool verbose) { - m_rfTSBK.setVerbose(verbose); - m_netTSBK.setVerbose(verbose); - - m_rfTDULC.setVerbose(verbose); - m_netTDULC.setVerbose(verbose); + m_dumpTSBK = verbose; } // --------------------------------------------------------------------------- @@ -1324,15 +1099,13 @@ TrunkPacket::TrunkPacket(Control* p25, network::BaseNetwork* network, bool dumpT m_patchSuperGroup(0xFFFFU), m_verifyAff(false), m_verifyReg(false), - m_rfTSBK(), - m_netTSBK(), + m_rfTSBK(SiteData(), lookups::IdenTable()), + m_netTSBK(SiteData(), lookups::IdenTable()), m_rfMBF(NULL), m_mbfCnt(0U), m_mbfIdenCnt(0U), m_mbfAdjSSCnt(0U), m_mbfSCCBCnt(0U), - m_rfTDULC(), - m_netTDULC(), m_voiceChTable(), m_adjSiteTable(), m_adjSiteUpdateCnt(), @@ -1346,36 +1119,15 @@ TrunkPacket::TrunkPacket(Control* p25, network::BaseNetwork* network, bool dumpT m_voiceGrantChCnt(0U), m_noStatusAck(false), m_noMessageAck(true), - m_statusCmdEnable(false), - m_statusRadioCheck(0U), - m_statusRadioInhibit(0U), - m_statusRadioUninhibit(0U), - m_statusRadioForceReg(0U), - m_statusRadioForceDereg(0U), - m_statusSrcId(0U), - m_statusValue(0U), - m_siteData(), m_adjSiteUpdateTimer(1000U), m_adjSiteUpdateInterval(ADJ_SITE_TIMER_TIMEOUT), + m_dumpTSBK(false), m_verbose(verbose), m_debug(debug) { m_rfMBF = new uint8_t[P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U]; ::memset(m_rfMBF, 0x00U, P25_MAX_PDU_COUNT * P25_LDU_FRAME_LENGTH_BYTES + 2U); - // set metadata defaults - m_rfTSBK.setSiteData(m_siteData); - m_netTSBK.setSiteData(m_siteData); - m_rfTSBK.setCallsign("CHANGEME"); - m_netTSBK.setCallsign("CHANGEME"); - m_rfTSBK.setVerbose(dumpTSBKData); - m_netTSBK.setVerbose(dumpTSBKData); - - m_rfTDULC.setSiteData(m_siteData); - m_netTDULC.setSiteData(m_siteData); - m_rfTDULC.setVerbose(dumpTSBKData); - m_netTDULC.setVerbose(dumpTSBKData); - m_voiceChTable.clear(); m_adjSiteTable.clear(); @@ -1443,7 +1195,7 @@ void TrunkPacket::writeRF_ControlData(uint8_t frameCnt, uint8_t n, bool adjSS) do { - m_rfTSBK.reset(); + m_rfTSBK = lc::TSBK(m_p25->m_siteData, m_p25->m_idenEntry, m_dumpTSBK); if (m_debug) { LogDebug(LOG_P25, "writeRF_ControlData, mbfCnt = %u, frameCnt = %u, seq = %u, adjSS = %u", m_mbfCnt, frameCnt, n, adjSS); @@ -1523,9 +1275,9 @@ void TrunkPacket::writeRF_ControlData(uint8_t frameCnt, uint8_t n, bool adjSS) /// /// Helper to write a P25 TDU w/ link control packet. /// -/// +/// /// -void TrunkPacket::writeRF_TDULC(uint8_t duid, bool noNetwork) +void TrunkPacket::writeRF_TDULC(lc::TDULC lc, bool noNetwork) { uint8_t data[P25_TDULC_FRAME_LENGTH_BYTES + 2U]; ::memset(data + 2U, 0x00U, P25_TDULC_FRAME_LENGTH_BYTES); @@ -1537,7 +1289,7 @@ void TrunkPacket::writeRF_TDULC(uint8_t duid, bool noNetwork) m_p25->m_nid.encode(data + 2U, P25_DUID_TDULC); // Generate TDULC Data - m_rfTDULC.encode(data + 2U); + lc.encode(data + 2U); // Add busy bits m_p25->addBusyBits(data + 2U, P25_TDULC_FRAME_LENGTH_BITS, true, true); @@ -1568,39 +1320,38 @@ void TrunkPacket::writeRF_TDULC(uint8_t duid, bool noNetwork) void TrunkPacket::writeRF_TDULC_ChanRelease(bool grp, uint32_t srcId, uint32_t dstId) { uint32_t count = m_p25->m_hangCount / 2; + lc::TDULC lc = lc::TDULC(m_p25->m_siteData, m_p25->m_idenEntry, m_dumpTSBK); if (m_p25->m_control) { for (uint32_t i = 0; i < count; i++) { if ((srcId != 0U) && (dstId != 0U)) { - m_rfTDULC.setSrcId(srcId); - m_rfTDULC.setDstId(dstId); - m_rfTDULC.setEmergency(false); + lc.setSrcId(srcId); + lc.setDstId(dstId); + lc.setEmergency(false); if (grp) { - m_rfTDULC.setLCO(LC_GROUP); - writeRF_TDULC(P25_DUID_TDULC, true); + lc.setLCO(LC_GROUP); + writeRF_TDULC(lc, true); } else { - m_rfTDULC.setLCO(LC_PRIVATE); - writeRF_TDULC(P25_DUID_TDULC, true); + lc.setLCO(LC_PRIVATE); + writeRF_TDULC(lc, true); } } - m_rfTDULC.setLCO(LC_NET_STS_BCAST); - writeRF_TDULC(P25_DUID_TDULC, true); - m_rfTDULC.setLCO(LC_RFSS_STS_BCAST); - writeRF_TDULC(P25_DUID_TDULC, true); + lc.setLCO(LC_NET_STS_BCAST); + writeRF_TDULC(lc, true); + lc.setLCO(LC_RFSS_STS_BCAST); + writeRF_TDULC(lc, true); } } if (m_verbose) { - LogMessage(LOG_RF, P25_TDULC_STR ", LC_CALL_TERM (Call Termination), srcId = %u, dstId = %u", m_rfTDULC.getSrcId(), m_rfTDULC.getDstId()); + LogMessage(LOG_RF, P25_TDULC_STR ", LC_CALL_TERM (Call Termination), srcId = %u, dstId = %u", lc.getSrcId(), lc.getDstId()); } - m_rfTDULC.setLCO(LC_CALL_TERM); - writeRF_TDULC(P25_DUID_TDULC, true); - - m_rfTDULC.reset(); + lc.setLCO(LC_CALL_TERM); + writeRF_TDULC(lc, true); } /// @@ -1777,7 +1528,7 @@ void TrunkPacket::queueRF_TSBK_Ctrl_MBF(uint8_t lco) if (!m_p25->m_control) return; - m_rfTSBK.reset(); + m_rfTSBK = lc::TSBK(m_p25->m_siteData, m_p25->m_idenEntry, m_dumpTSBK); switch (lco) { case TSBK_OSP_IDEN_UP: @@ -1805,14 +1556,14 @@ void TrunkPacket::queueRF_TSBK_Ctrl_MBF(uint8_t lco) // handle 700/800/900 identities if (entry.baseFrequency() >= 762000000U) { - m_rfTSBK.setIdenTable(entry); + m_rfTSBK.siteIdenEntry(entry); // transmit channel ident broadcast m_rfTSBK.setLCO(TSBK_OSP_IDEN_UP); } else { // handle as a VHF/UHF identity - m_rfTSBK.setIdenTable(entry); + m_rfTSBK.siteIdenEntry(entry); // transmit channel ident broadcast m_rfTSBK.setLCO(TSBK_OSP_IDEN_UP_VU); @@ -1867,12 +1618,7 @@ void TrunkPacket::queueRF_TSBK_Ctrl_MBF(uint8_t lco) else { cfva |= P25_CFVA_VALID; } -/* - uint8_t serviceClass = site.serviceClass(); - if ((serviceClass & P25_SVC_CLS_COMPOSITE) == P25_SVC_CLS_COMPOSITE) { - cfva |= P25_CFVA_CONV; - } -*/ + // transmit adjacent site broadcast m_rfTSBK.setLCO(TSBK_OSP_ADJ_STS_BCAST); m_rfTSBK.setAdjSiteCFVA(cfva); @@ -2056,7 +1802,7 @@ bool TrunkPacket::writeRF_TSDU_Grant(bool grp, bool skip, bool net) m_grantTimers[m_rfTSBK.getDstId()].start(); m_voiceGrantChCnt++; - setSiteChCnt(m_voiceChCnt + m_voiceGrantChCnt); + m_p25->m_siteData.setChCnt(m_voiceChCnt + m_voiceGrantChCnt); } } else { @@ -2239,7 +1985,7 @@ void TrunkPacket::writeRF_TSDU_U_Reg_Rsp(uint32_t srcId) m_rfTSBK.setResponse(P25_RSP_ACCEPT); // validate the system ID - if (m_rfTSBK.getSysId() != m_siteData.sysId()) { + if (m_rfTSBK.getSysId() != m_p25->m_siteData.sysId()) { LogWarning(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_U_REG (Unit Registration Response) denial, SYSID rejection, sysId = $%03X", m_rfTSBK.getSysId()); ::ActivityLog("P25", true, "unit registration request from %u denied", srcId); m_rfTSBK.setResponse(P25_RSP_DENY); @@ -2424,7 +2170,8 @@ void TrunkPacket::writeNet_TSDU_From_RF(uint8_t* data) /// /// Helper to write a network P25 TDU w/ link control packet. /// -void TrunkPacket::writeNet_TDULC() +/// +void TrunkPacket::writeNet_TDULC(lc::TDULC lc) { uint8_t buffer[P25_TDULC_FRAME_LENGTH_BYTES + 2U]; ::memset(buffer, 0x00U, P25_TDULC_FRAME_LENGTH_BYTES + 2U); @@ -2439,7 +2186,7 @@ void TrunkPacket::writeNet_TDULC() m_p25->m_nid.encode(buffer + 2U, P25_DUID_TDULC); // Regenerate TDULC Data - m_netTDULC.encode(buffer + 2U); + lc.encode(buffer + 2U); // Add busy bits m_p25->addBusyBits(buffer + 2U, P25_TDULC_FRAME_LENGTH_BITS, true, true); @@ -2447,7 +2194,7 @@ void TrunkPacket::writeNet_TDULC() m_p25->writeQueueNet(buffer, P25_TDULC_FRAME_LENGTH_BYTES + 2U); if (m_verbose) { - LogMessage(LOG_NET, P25_TDULC_STR ", lc = $%02X, srcId = %u", m_netTDULC.getLCO(), m_netTDULC.getSrcId()); + LogMessage(LOG_NET, P25_TDULC_STR ", lc = $%02X, srcId = %u", lc.getLCO(), lc.getSrcId()); } if (m_p25->m_voice->m_netFrames > 0) { @@ -2463,7 +2210,6 @@ void TrunkPacket::writeNet_TDULC() m_p25->m_netTimeout.stop(); m_p25->m_networkWatchdog.stop(); - m_netTDULC.reset(); m_p25->m_netState = RS_NET_IDLE; m_p25->m_tailOnIdle = true; } @@ -2518,93 +2264,6 @@ void TrunkPacket::denialInhibit(uint32_t srcId) } } -/// -/// -/// -/// -void TrunkPacket::resetStatusCommand(const lc::TSBK& tsbk) -{ - // reset status control data if the status current mode is set and the LCO isn't CALL ALERT - if (m_statusCmdEnable && ((m_rfTSBK.getLCO() != TSBK_IOSP_CALL_ALRT) && (m_rfTSBK.getLCO() != TSBK_IOSP_EXT_FNCT))) { - resetStatusCommand(); - } -} - -/// -/// -/// -void TrunkPacket::preprocessStatusCommand() -{ - if (m_statusCmdEnable) { - m_statusSrcId = m_rfTSBK.getSrcId(); - m_statusValue = m_rfTSBK.getStatus(); - - if (m_statusValue != 0U) { - if ((m_statusValue == m_statusRadioCheck) || - (m_statusValue == m_statusRadioInhibit) || (m_statusValue == m_statusRadioUninhibit) || - (m_statusValue == m_statusRadioForceReg) || (m_statusValue == m_statusRadioForceDereg)) { - if (m_verbose) { - LogMessage(LOG_RF, P25_TSDU_STR ", TSBK_IOSP_STS_UPDT (Status Update), command mode, statusCurrentStatus = $%02X", m_statusValue); - } - } - else { - resetStatusCommand(); - } - } - } -} - -/// -/// -/// -/// -/// -/// -bool TrunkPacket::processStatusCommand(uint32_t srcId, uint32_t dstId) -{ - // is status command mode enabled with status data? - if (m_statusCmdEnable && (m_statusValue != 0U)) { - // if the status srcId isn't the CALL ALERT srcId ignore - if (m_statusSrcId == srcId) { - if ((m_statusRadioCheck != 0U) && (m_statusValue == m_statusRadioCheck)) { - writeRF_TSDU_Ext_Func(P25_EXT_FNCT_CHECK, srcId, dstId); - } - else if ((m_statusRadioInhibit != 0U) && (m_statusValue == m_statusRadioInhibit)) { - writeRF_TSDU_Ext_Func(P25_EXT_FNCT_INHIBIT, P25_WUID_SYS, dstId); - } - else if ((m_statusRadioUninhibit != 0U) && (m_statusValue == m_statusRadioUninhibit)) { - writeRF_TSDU_Ext_Func(P25_EXT_FNCT_UNINHIBIT, P25_WUID_SYS, dstId); - } - else if ((m_statusRadioForceReg != 0U) && (m_statusValue == m_statusRadioForceReg)) { - // update dynamic unit registration table - if (!hasSrcIdUnitReg(srcId)) { - m_unitRegTable.push_back(srcId); - } - - writeRF_TSDU_Grp_Aff_Rsp(srcId, dstId); - } - else if ((m_statusRadioForceDereg != 0U) && (m_statusValue == m_statusRadioForceDereg)) { - writeRF_TSDU_U_Dereg_Ack(srcId); - } - else { - LogError(LOG_P25, P25_TSDU_STR ", unhandled command mode, statusCurrentStatus = $%02X, srcId = %u, dstId = %u", m_statusValue, srcId, dstId); - resetStatusCommand(); - } - - writeRF_TSDU_ACK_FNE(srcId, TSBK_IOSP_CALL_ALRT, false, false); - return true; - } - else { - if (m_verbose) { - LogWarning(LOG_P25, P25_TSDU_STR ", TSBK_IOSP_STS_UPDT (Status Update), illegal attempt by srcId = %u to access status command", srcId); - } - } - } - - resetStatusCommand(); - return false; -} - /// /// Helper to add the idle status bits on P25 frame data. /// diff --git a/p25/TrunkPacket.h b/p25/TrunkPacket.h index da904913..3062aef4 100644 --- a/p25/TrunkPacket.h +++ b/p25/TrunkPacket.h @@ -34,7 +34,6 @@ #include "p25/lc/TSBK.h" #include "p25/lc/TDULC.h" #include "p25/Control.h" -#include "p25/SiteData.h" #include "network/BaseNetwork.h" #include "network/RemoteControl.h" #include "Timer.h" @@ -60,27 +59,6 @@ namespace p25 class HOST_SW_API TrunkPacket { public: - /// Sets local configured site data. - void setSiteData(uint32_t netId, uint32_t sysId, uint8_t rfssId, uint8_t siteId, uint8_t lra, - uint8_t channelId, uint32_t channelNo); - /// Sets local configured site callsign. - void setCallsign(std::string callsign); - /// Sets a flag indicating whether or not networking is active. - void setNetActive(bool active); - /// Sets the total number of channels at the site. - void setSiteChCnt(uint8_t chCnt); - /// Sets the service class for this site. - void setServiceClass(bool control, bool voiceOnControl); - - /// Resets the data states for the RF interface. - void resetRF(); - /// Resets the data states for the network. - void resetNet(); - /// Sets the RF TSBK and TDULC data to match the given LC data. - void setRFLC(const lc::LC& lc); - /// Sets the network TSBK and TDULC data to match the given LC data. - void setNetLC(const lc::LC& lc); - /// Process a data frame from the RF interface. bool process(uint8_t* data, uint32_t len); /// Process a data frame from the network. @@ -105,9 +83,6 @@ namespace p25 /// Helper to release group affiliations. void clearGrpAff(uint32_t dstId, bool releaseAll); - /// Resets the state of the status commands. - void resetStatusCommand(); - /// Updates the processor by the passed number of milliseconds. void clock(uint32_t ms); @@ -150,9 +125,6 @@ namespace p25 uint8_t m_mbfAdjSSCnt; uint8_t m_mbfSCCBCnt; - lc::TDULC m_rfTDULC; - lc::TDULC m_netTDULC; - std::vector m_voiceChTable; std::unordered_map m_adjSiteTable; @@ -173,21 +145,11 @@ namespace p25 bool m_noStatusAck; bool m_noMessageAck; - bool m_statusCmdEnable; - uint8_t m_statusRadioCheck; - uint8_t m_statusRadioInhibit; - uint8_t m_statusRadioUninhibit; - uint8_t m_statusRadioForceReg; - uint8_t m_statusRadioForceDereg; - - uint32_t m_statusSrcId; - uint8_t m_statusValue; - - SiteData m_siteData; - Timer m_adjSiteUpdateTimer; uint32_t m_adjSiteUpdateInterval; + bool m_dumpTSBK; + bool m_verbose; bool m_debug; @@ -203,7 +165,7 @@ namespace p25 void writeRF_ControlData(uint8_t frameCnt, uint8_t n, bool adjSS); /// Helper to write a P25 TDU w/ link control packet. - void writeRF_TDULC(uint8_t duid, bool noNetwork); + void writeRF_TDULC(lc::TDULC lc, bool noNetwork); /// Helper to write a P25 TDU w/ link control channel release packet. void writeRF_TDULC_ChanRelease(bool grp, uint32_t srcId, uint32_t dstId); @@ -238,20 +200,13 @@ namespace p25 void writeNet_TSDU_From_RF(uint8_t* data); /// Helper to write a network P25 TDU w/ link control packet. - void writeNet_TDULC(); + void writeNet_TDULC(lc::TDULC lc); /// Helper to write a network single-block P25 TSDU packet. void writeNet_TSDU(); /// Helper to automatically inhibit a source ID on a denial. void denialInhibit(uint32_t srcId); - /// - void resetStatusCommand(const lc::TSBK& tsbk); - /// - void preprocessStatusCommand(); - /// - bool processStatusCommand(uint32_t srcId, uint32_t dstId); - /// Helper to add the idle status bits on P25 frame data. void addIdleBits(uint8_t* data, uint32_t length, bool b1, bool b2); }; diff --git a/p25/VoicePacket.cpp b/p25/VoicePacket.cpp index 86421b40..d6d96942 100644 --- a/p25/VoicePacket.cpp +++ b/p25/VoicePacket.cpp @@ -60,9 +60,10 @@ const uint32_t VOC_LDU1_COUNT = 3U; /// void VoicePacket::resetRF() { - m_rfLC.reset(); - m_rfLastLDU1.reset(); - m_rfLastLDU2.reset(); + m_rfLC = lc::LC(m_p25->m_siteData); + //m_rfLastHDU = lc::LC(m_p25->m_siteData); + m_rfLastLDU1 = lc::LC(m_p25->m_siteData); + m_rfLastLDU2 = lc::LC(m_p25->m_siteData);; m_rfFrames = 0U; m_rfErrs = 0U; @@ -76,8 +77,9 @@ void VoicePacket::resetRF() /// void VoicePacket::resetNet() { - m_netLC.reset(); - m_netLastLDU1.reset(); + m_netLC = lc::LC(m_p25->m_siteData); + m_netLastLDU1 = lc::LC(m_p25->m_siteData); + m_netFrames = 0U; m_netLost = 0U; m_vocLDU1Count = 0U; @@ -129,8 +131,6 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) // handle individual DUIDs if (duid == P25_DUID_HDU) { - m_p25->m_trunk->resetStatusCommand(); - m_lastDUID = P25_DUID_HDU; if (m_p25->m_rfState == RS_RF_LISTENING && m_p25->m_ccRunning) { @@ -144,7 +144,8 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) resetRF(); resetNet(); - bool ret = m_rfLC.decodeHDU(data + 2U); + lc::LC lc = lc::LC(m_p25->m_siteData); + bool ret = lc.decodeHDU(data + 2U); if (!ret) { LogWarning(LOG_RF, P25_HDU_STR ", undecodable LC"); m_rfUndecodableLC++; @@ -152,11 +153,11 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) } if (m_verbose) { - LogMessage(LOG_RF, P25_HDU_STR ", HDU_BSDWNACT, dstId = %u, algo = $%02X, kid = $%04X", m_rfLC.getDstId(), m_rfLC.getAlgId(), m_rfLC.getKId()); + LogMessage(LOG_RF, P25_HDU_STR ", HDU_BSDWNACT, dstId = %u, algo = $%02X, kid = $%04X", lc.getDstId(), lc.getAlgId(), lc.getKId()); } // don't process RF frames if the network isn't in a idle state and the RF destination is the network destination - if (m_p25->m_netState != RS_NET_IDLE && m_rfLC.getDstId() == m_p25->m_netLastDstId) { + if (m_p25->m_netState != RS_NET_IDLE && lc.getDstId() == m_p25->m_netLastDstId) { LogWarning(LOG_RF, "Traffic collision detect, preempting new RF traffic to existing network traffic!"); resetRF(); return false; @@ -164,7 +165,7 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) // stop network frames from processing -- RF wants to transmit on a different talkgroup if (m_p25->m_netState != RS_NET_IDLE) { - LogWarning(LOG_RF, "Traffic collision detect, preempting existing network traffic to new RF traffic, rfDstId = %u, netDstId = %u", m_rfLC.getDstId(), + LogWarning(LOG_RF, "Traffic collision detect, preempting existing network traffic to new RF traffic, rfDstId = %u, netDstId = %u", lc.getDstId(), m_p25->m_netLastDstId); resetNet(); @@ -178,17 +179,14 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) } m_p25->m_rfTGHang.start(); - m_p25->m_rfLastDstId = m_rfLC.getDstId(); + m_p25->m_rfLastDstId = lc.getDstId(); - m_rfLastHDU.reset(); - m_rfLastHDU = m_rfLC; + m_rfLastHDU = lc; } return true; } else if (duid == P25_DUID_LDU1) { - m_p25->m_trunk->resetStatusCommand(); - bool alreadyDecoded = false; m_lastDUID = P25_DUID_LDU1; @@ -199,16 +197,18 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) } } - bool ret = m_rfLC.decodeLDU1(data + 2U); + lc::LC lc = lc::LC(m_p25->m_siteData); + bool ret = lc.decodeLDU1(data + 2U); if (!ret) { return false; } - m_rfLastLDU1 = m_rfLC; - alreadyDecoded = true; + uint32_t srcId = lc.getSrcId(); + uint32_t dstId = lc.getDstId(); + bool group = lc.getGroup(); + bool encrypted = lc.getEncrypted(); - uint32_t srcId = m_rfLC.getSrcId(); - uint32_t dstId = m_rfLC.getDstId(); + alreadyDecoded = true; // don't process RF frames if the network isn't in a idle state and the RF destination is the network destination if (m_p25->m_netState != RS_NET_IDLE && dstId == m_p25->m_netLastDstId) { @@ -219,34 +219,32 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) // stop network frames from processing -- RF wants to transmit on a different talkgroup if (m_p25->m_netState != RS_NET_IDLE) { - if (m_netLC.getSrcId() == srcId && m_netLC.getDstId() == dstId) { - LogWarning(LOG_RF, "Traffic collision detect, preempting new RF traffic to existing RF traffic (Are we in a voting condition?), rfSrcId = %u, rfDstId = %u, netSrcId = %u, netDstId = %u", m_rfLC.getSrcId(), m_rfLC.getDstId(), - srcId, dstId); + if (m_netLC.getSrcId() == srcId && m_p25->m_netLastDstId == dstId) { + LogWarning(LOG_RF, "Traffic collision detect, preempting new RF traffic to existing RF traffic (Are we in a voting condition?), rfSrcId = %u, rfDstId = %u, netSrcId = %u, netDstId = %u", srcId, dstId, + m_netLC.getSrcId(), m_p25->m_netLastDstId); resetRF(); return false; } else { - LogWarning(LOG_RF, "Traffic collision detect, preempting existing network traffic to new RF traffic, rfDstId = %u, netDstId = %u", m_rfLC.getDstId(), + LogWarning(LOG_RF, "Traffic collision detect, preempting existing network traffic to new RF traffic, rfDstId = %u, netDstId = %u", dstId, m_p25->m_netLastDstId); resetNet(); -/* - m_p25->writeRF_TDU(true); -*/ } } - m_p25->m_trunk->setRFLC(m_rfLC); + m_p25->m_trunk->m_rfTSBK = lc::TSBK(&lc); + m_p25->m_trunk->m_rfTSBK.setVerbose(m_p25->m_trunk->m_dumpTSBK); // validate the source RID if (!acl::AccessControl::validateSrcId(srcId)) { if (m_lastRejectId == 0U || m_lastRejectId != srcId) { LogWarning(LOG_RF, P25_HDU_STR " denial, RID rejection, srcId = %u", srcId); if (m_p25->m_control) { - m_p25->m_trunk->writeRF_TSDU_Deny(P25_DENY_RSN_REQ_UNIT_NOT_VALID, (m_rfLC.getGroup() ? TSBK_IOSP_GRP_VCH : TSBK_IOSP_UU_VCH)); + m_p25->m_trunk->writeRF_TSDU_Deny(P25_DENY_RSN_REQ_UNIT_NOT_VALID, (group ? TSBK_IOSP_GRP_VCH : TSBK_IOSP_UU_VCH)); m_p25->m_trunk->denialInhibit(srcId); } - ::ActivityLog("P25", true, "RF voice rejection from %u to %s%u ", srcId, m_rfLC.getGroup() ? "TG " : "", dstId); + ::ActivityLog("P25", true, "RF voice rejection from %u to %s%u ", srcId, group ? "TG " : "", dstId); m_lastRejectId = srcId; } @@ -257,7 +255,7 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) } // is this a group or individual operation? - if (!m_rfLC.getGroup()) { + if (!group) { // validate the target RID if (!acl::AccessControl::validateSrcId(dstId)) { if (m_lastRejectId == 0 || m_lastRejectId != dstId) { @@ -266,7 +264,7 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) m_p25->m_trunk->writeRF_TSDU_Deny(P25_DENY_RSN_TGT_UNIT_NOT_VALID, TSBK_IOSP_UU_VCH); } - ::ActivityLog("P25", true, "RF voice rejection from %u to %s%u ", srcId, m_rfLC.getGroup() ? "TG " : "", dstId); + ::ActivityLog("P25", true, "RF voice rejection from %u to %s%u ", srcId, group ? "TG " : "", dstId); m_lastRejectId = dstId; } @@ -285,7 +283,7 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) m_p25->m_trunk->writeRF_TSDU_Deny(P25_DENY_RSN_TGT_GROUP_NOT_VALID, TSBK_IOSP_GRP_VCH); } - ::ActivityLog("P25", true, "RF voice rejection from %u to %s%u ", srcId, m_rfLC.getGroup() ? "TG " : "", dstId); + ::ActivityLog("P25", true, "RF voice rejection from %u to %s%u ", srcId, group ? "TG " : "", dstId); m_lastRejectId = dstId; } @@ -298,15 +296,14 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) // verify the source RID is affiliated to the group TGID; only if control data // is supported - if (m_rfLC.getGroup() && m_p25->m_control) { - if (!m_p25->m_trunk->hasSrcIdGrpAff(srcId, dstId) && - m_p25->m_trunk->m_verifyAff) { + if (group && m_p25->m_control) { + if (!m_p25->m_trunk->hasSrcIdGrpAff(srcId, dstId) && m_p25->m_trunk->m_verifyAff) { if (m_lastRejectId == 0 || m_lastRejectId != srcId) { LogWarning(LOG_RF, P25_HDU_STR " denial, RID not affiliated to TGID, srcId = %u, dstId = %u", srcId, dstId); m_p25->m_trunk->writeRF_TSDU_Deny(P25_DENY_RSN_REQ_UNIT_NOT_AUTH, TSBK_IOSP_GRP_VCH); m_p25->m_trunk->writeRF_TSDU_U_Reg_Cmd(srcId); - ::ActivityLog("P25", true, "RF voice rejection from %u to %s%u ", srcId, m_rfLC.getGroup() ? "TG " : "", dstId); + ::ActivityLog("P25", true, "RF voice rejection from %u to %s%u ", srcId, group ? "TG " : "", dstId); m_lastRejectId = srcId; } @@ -317,11 +314,14 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) } } + m_rfLC = lc; + m_rfLastLDU1 = m_rfLC; + m_lastRejectId = 0U; - ::ActivityLog("P25", true, "RF %svoice transmission from %u to %s%u", m_rfLC.getEncrypted() ? "encrypted ": "", srcId, m_rfLC.getGroup() ? "TG " : "", dstId); + ::ActivityLog("P25", true, "RF %svoice transmission from %u to %s%u", encrypted ? "encrypted ": "", srcId, group ? "TG " : "", dstId); if (m_p25->m_control) { - if (m_rfLC.getGroup() && (m_lastPatchGroup != dstId) && + if (group && (m_lastPatchGroup != dstId) && (dstId != m_p25->m_trunk->m_patchSuperGroup)) { m_p25->m_trunk->writeRF_TSDU_Mot_Patch(dstId, 0U, 0U); m_lastPatchGroup = dstId; @@ -331,7 +331,7 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) if (!m_p25->m_trunk->hasDstIdGranted(dstId)) { if (m_p25->m_legacyGroupGrnt) { // are we auto-registering legacy radios to groups? - if (m_p25->m_legacyGroupReg && m_rfLC.getGroup()) { + if (m_p25->m_legacyGroupReg && group) { if (!m_p25->m_trunk->hasSrcIdGrpAff(srcId, dstId)) { if (!m_p25->m_trunk->writeRF_TSDU_Grp_Aff_Rsp(srcId, dstId)) { return false; @@ -339,7 +339,7 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) } } - if (!m_p25->m_trunk->writeRF_TSDU_Grant(m_rfLC.getGroup(), false, false)) { + if (!m_p25->m_trunk->writeRF_TSDU_Grant(group, false, false)) { return false; } } @@ -352,22 +352,9 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) // single-channel trunking or voice on control support? if (m_p25->m_control && m_p25->m_voiceOnControl) { m_p25->m_ccRunning = false; // otherwise the grant will be bundled with other packets - m_p25->m_trunk->writeRF_TSDU_Grant(m_rfLC.getGroup(), true, false); - } - - if (m_rfLC.getDstId() != m_rfLastHDU.getDstId()) { - m_rfLC.setDstId(m_rfLastHDU.getDstId()); + m_p25->m_trunk->writeRF_TSDU_Grant(group, true, false); } - m_rfLC.setAlgId(m_rfLastHDU.getAlgId()); - m_rfLC.setKId(m_rfLastHDU.getKId()); - - uint8_t mi[P25_MI_LENGTH_BYTES]; - m_rfLastHDU.getMI(mi); - m_rfLC.setMI(mi); - - m_rfLastHDU.reset(); - m_hadVoice = true; m_p25->m_rfState = RS_RF_AUDIO; @@ -375,20 +362,50 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) m_p25->m_rfTGHang.start(); m_p25->m_rfLastDstId = dstId; - uint8_t buffer[P25_HDU_FRAME_LENGTH_BYTES + 2U]; - ::memset(buffer, 0x00U, P25_HDU_FRAME_LENGTH_BYTES + 2U); + // make sure we actually got a HDU -- otherwise treat the call as a late entry + if (m_rfLastHDU.getDstId() != 0U) { + // copy destination and encryption parameters from the last HDU received (if possible) + if (m_rfLC.getDstId() != m_rfLastHDU.getDstId()) { + m_rfLC.setDstId(m_rfLastHDU.getDstId()); + } - // Generate Sync - Sync::addP25Sync(buffer + 2U); + m_rfLC.setAlgId(m_rfLastHDU.getAlgId()); + m_rfLC.setKId(m_rfLastHDU.getKId()); - // Generate NID - m_p25->m_nid.encode(buffer + 2U, P25_DUID_HDU); + uint8_t mi[P25_MI_LENGTH_BYTES]; + m_rfLastHDU.getMI(mi); + m_rfLC.setMI(mi); - // Generate HDU - m_rfLC.encodeHDU(buffer + 2U); + uint8_t buffer[P25_HDU_FRAME_LENGTH_BYTES + 2U]; + ::memset(buffer, 0x00U, P25_HDU_FRAME_LENGTH_BYTES + 2U); - // Add busy bits - m_p25->addBusyBits(buffer + 2U, P25_HDU_FRAME_LENGTH_BITS, false, true); + // Generate Sync + Sync::addP25Sync(buffer + 2U); + + // Generate NID + m_p25->m_nid.encode(buffer + 2U, P25_DUID_HDU); + + // Generate HDU + m_rfLC.encodeHDU(buffer + 2U); + + // Add busy bits + m_p25->addBusyBits(buffer + 2U, P25_HDU_FRAME_LENGTH_BITS, false, true); + + writeNetworkRF(buffer, P25_DUID_HDU); + + if (m_p25->m_duplex) { + buffer[0U] = TAG_DATA; + buffer[1U] = 0x00U; + m_p25->writeQueueRF(buffer, P25_HDU_FRAME_LENGTH_BYTES + 2U); + } + + if (m_verbose) { + LogMessage(LOG_RF, P25_HDU_STR ", dstId = %u, algo = $%02X, kid = $%04X", m_rfLC.getDstId(), m_rfLC.getAlgId(), m_rfLC.getKId()); + } + } + else { + LogWarning(LOG_RF, P25_HDU_STR ", not transmitted; possible late entry, dstId = %u, algo = $%02X, kid = $%04X", m_rfLastHDU.getDstId(), m_rfLastHDU.getAlgId(), m_rfLastHDU.getKId()); + } m_rfFrames = 0U; m_rfErrs = 0U; @@ -398,17 +415,7 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) m_p25->m_rfTimeout.start(); m_lastDUID = P25_DUID_HDU; - writeNetworkRF(buffer, P25_DUID_HDU); - - if (m_p25->m_duplex) { - buffer[0U] = TAG_DATA; - buffer[1U] = 0x00U; - m_p25->writeQueueRF(buffer, P25_HDU_FRAME_LENGTH_BYTES + 2U); - } - - if (m_verbose) { - LogMessage(LOG_RF, P25_HDU_STR ", dstId = %u, algo = $%02X, kid = $%04X", m_rfLC.getDstId(), m_rfLC.getAlgId(), m_rfLC.getKId()); - } + m_rfLastHDU = lc::LC(m_p25->m_siteData); } if (m_p25->m_rfState == RS_RF_AUDIO) { @@ -526,8 +533,6 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) } } else if (duid == P25_DUID_LDU2) { - m_p25->m_trunk->resetStatusCommand(); - m_lastDUID = P25_DUID_LDU2; if (m_p25->m_rfState == RS_RF_LISTENING) { @@ -606,8 +611,6 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) } } else if (duid == P25_DUID_TDU || duid == P25_DUID_TDULC) { - m_p25->m_trunk->resetStatusCommand(); - if (m_p25->m_control) { m_p25->m_trunk->releaseDstIdGrant(m_rfLC.getDstId(), false); } @@ -619,8 +622,16 @@ bool VoicePacket::process(uint8_t* data, uint32_t len) m_p25->m_rfTimeout.stop(); } - else - m_p25->m_trunk->writeRF_TDULC(duid, false); + else { + lc::TDULC tdulc = lc::TDULC(m_p25->m_siteData, m_p25->m_idenEntry, m_p25->m_trunk->m_dumpTSBK); + bool ret = tdulc.decode(data + 2U); + if (!ret) { + LogWarning(LOG_RF, P25_LDU2_STR ", undecodable TDULC"); + } + else { + m_p25->m_trunk->writeRF_TDULC(tdulc, false); + } + } if (m_p25->m_rfState == RS_RF_AUDIO) { if (m_p25->m_rssi != 0U) { @@ -712,8 +723,6 @@ bool VoicePacket::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, d ::memcpy(m_netLDU1 + 200U, data + count, 16U); count += 16U; - m_p25->m_trunk->resetStatusCommand(); - m_netLastLDU1 = control; checkNet_LDU2(control, lsd); @@ -765,21 +774,15 @@ bool VoicePacket::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, d ::memcpy(m_netLDU2 + 200U, data + count, 16U); count += 16U; - m_p25->m_trunk->resetStatusCommand(); - if (m_p25->m_netState == RS_NET_IDLE) { m_p25->m_modem->clearP25Data(); m_p25->m_queue.clear(); resetRF(); - m_rfLastHDU.reset(); - - m_netLC.reset(); - m_netFrames = 0U; - m_netLost = 0U; + resetNet(); - m_p25->m_trunk->resetRF(); - m_p25->m_trunk->resetNet(); + m_p25->m_trunk->m_rfTSBK = lc::TSBK(m_p25->m_siteData, m_p25->m_idenEntry, m_p25->m_trunk->m_dumpTSBK); + m_p25->m_trunk->m_netTSBK = lc::TSBK(m_p25->m_siteData, m_p25->m_idenEntry, m_p25->m_trunk->m_dumpTSBK); writeNet_LDU1(control, lsd); } @@ -805,12 +808,10 @@ bool VoicePacket::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, d } if (m_p25->m_netState != RS_NET_IDLE) { - m_p25->m_trunk->resetStatusCommand(); - if (duid == P25_DUID_TDU) writeNet_TDU(); - else - m_p25->m_trunk->writeNet_TDULC(); + + resetNet(); } break; } @@ -869,12 +870,12 @@ VoicePacket::VoicePacket(Control* p25, network::BaseNetwork* network, bool debug m_netFrames(0U), m_netLost(0U), m_audio(), - m_rfLC(), - m_rfLastHDU(), - m_rfLastLDU1(), - m_rfLastLDU2(), - m_netLC(), - m_netLastLDU1(), + m_rfLC(SiteData()), + m_rfLastHDU(SiteData()), + m_rfLastLDU1(SiteData()), + m_rfLastLDU2(SiteData()), + m_netLC(SiteData()), + m_netLastLDU1(SiteData()), m_rfLSD(), m_netLSD(), m_netLDU1(NULL), @@ -959,17 +960,10 @@ void VoicePacket::writeRF_EndOfVoice() uint32_t dstId = m_rfLC.getDstId(); resetRF(); - m_rfLastHDU.reset(); - resetNet(); // transmit channelNo release burst m_p25->m_trunk->writeRF_TDULC_ChanRelease(grp, srcId, dstId); -/* - if (grp && (m_lastPatchGroup != 0U)) { - m_p25->m_trunk->writeRF_TSDU_Mot_Patch(m_p25->m_trunk->m_patchSuperGroup, 0U, 0U); - } -*/ } /// @@ -1018,8 +1012,7 @@ void VoicePacket::writeNet_TDU() m_p25->m_netTimeout.stop(); m_p25->m_networkWatchdog.stop(); - m_netLC.reset(); - m_netLastLDU1.reset(); + resetNet(); m_p25->m_netState = RS_NET_IDLE; m_p25->m_netLastDstId = 0U; m_p25->m_tailOnIdle = true; @@ -1112,7 +1105,7 @@ void VoicePacket::writeNet_LDU1(const lc::LC& control, const data::LowSpeedData& m_p25->m_trunk->touchDstIdGrant(m_rfLC.getDstId()); } - m_netLC.reset(); + m_netLC = lc::LC(m_p25->m_siteData); m_netLC.setLCO(lco); m_netLC.setMFId(mfId); m_netLC.setSrcId(srcId); @@ -1122,7 +1115,7 @@ void VoicePacket::writeNet_LDU1(const lc::LC& control, const data::LowSpeedData& m_netLC.setEncrypted((serviceOptions & 0x40U) == 0x40U); m_netLC.setPriority((serviceOptions & 0x07U)); - m_rfLC.reset(); + m_rfLC = lc::LC(m_p25->m_siteData); m_rfLC.setMFId(mfId); m_rfLC.setSrcId(srcId); m_rfLC.setDstId(dstId); @@ -1152,8 +1145,10 @@ void VoicePacket::writeNet_LDU1(const lc::LC& control, const data::LowSpeedData& m_netLC.setKId(kId); m_rfLC.setKId(kId); - m_p25->m_trunk->setNetLC(m_netLC); - m_p25->m_trunk->setRFLC(m_rfLC); + m_p25->m_trunk->m_rfTSBK = lc::TSBK(&m_rfLC); + m_p25->m_trunk->m_rfTSBK.setVerbose(m_p25->m_trunk->m_dumpTSBK); + m_p25->m_trunk->m_netTSBK = lc::TSBK(&m_netLC); + m_p25->m_trunk->m_netTSBK.setVerbose(m_p25->m_trunk->m_dumpTSBK); // validate source RID if (!acl::AccessControl::validateSrcId(srcId)) { @@ -1197,8 +1192,10 @@ void VoicePacket::writeNet_LDU1(const lc::LC& control, const data::LowSpeedData& m_p25->m_netTimeout.stop(); m_p25->m_networkWatchdog.stop(); - m_netLC.reset(); - m_netLastLDU1.reset(); + + m_netLC = lc::LC(m_p25->m_siteData); + m_netLastLDU1 = lc::LC(m_p25->m_siteData); + m_p25->m_netState = RS_NET_IDLE; m_p25->m_netLastDstId = 0U; if (m_p25->m_rfState == RS_RF_REJECTED) { @@ -1248,7 +1245,7 @@ void VoicePacket::writeNet_LDU1(const lc::LC& control, const data::LowSpeedData& } else { if (m_verbose) { - LogMessage(LOG_NET, P25_HDU_STR ", network does not transmit, dstId = %u, algo = $%02X, kid = $%04X", m_netLC.getDstId(), m_netLC.getAlgId(), m_netLC.getKId()); + LogMessage(LOG_NET, P25_HDU_STR ", not transmitted; network HDU disabled, dstId = %u, algo = $%02X, kid = $%04X", m_netLC.getDstId(), m_netLC.getAlgId(), m_netLC.getKId()); } } } diff --git a/p25/lc/LC.cpp b/p25/lc/LC.cpp index 74ae8ddb..d5795cd6 100644 --- a/p25/lc/LC.cpp +++ b/p25/lc/LC.cpp @@ -51,29 +51,39 @@ using namespace p25; /// /// Initializes a new instance of the LC class. /// +/// LC::LC() : m_protect(false), m_lco(LC_GROUP), m_mfId(P25_MFG_STANDARD), m_srcId(0U), m_dstId(0U), - m_serviceClass(P25_SVC_CLS_VOICE | P25_SVC_CLS_DATA), + m_grpVchNo(0U), m_emergency(false), m_encrypted(false), m_priority(4U), m_group(true), m_algId(P25_ALGO_UNENCRYPT), m_kId(0U), + m_siteData(SiteData()), m_rs(), m_encryptOverride(false), m_tsbkVendorSkip(false), m_callTimer(0U), - m_mi(NULL), - m_siteData() + m_mi(NULL) { m_mi = new uint8_t[P25_MI_LENGTH_BYTES]; + ::memset(m_mi, 0x00U, P25_MI_LENGTH_BYTES); +} - reset(); +/// +/// Initializes a new instance of the LC class. +/// +/// +LC::LC(SiteData siteData) : LC() +{ + m_siteData = siteData; + m_grpVchNo = m_siteData.channelNo(); } /// @@ -98,8 +108,6 @@ LC& LC::operator=(const LC& data) m_srcId = data.m_srcId; m_dstId = data.m_dstId; - m_serviceClass = data.m_serviceClass; - m_grpVchNo = data.m_grpVchNo; m_emergency = data.m_emergency; @@ -130,6 +138,8 @@ LC& LC::operator=(const LC& data) m_encrypted = false; } } + + m_siteData = data.m_siteData; } return *this; @@ -457,46 +467,6 @@ void LC::encodeLDU2(uint8_t * data) // Utils::dump(2U, "LDU2 Interleave", data, P25_LDU_FRAME_LENGTH_BYTES + P25_PREAMBLE_LENGTH_BYTES); } -/// -/// Helper to reset data values to defaults. -/// -void LC::reset() -{ - m_encryptOverride = false; - m_tsbkVendorSkip = false; - - m_protect = false; - m_lco = LC_GROUP; - m_mfId = P25_MFG_STANDARD; - - m_srcId = 0U; - m_dstId = 0U; - - m_callTimer = 0U; - - m_grpVchNo = m_siteData.channelNo(); - - /* Service Options */ - m_emergency = false; - m_encrypted = false; - m_priority = 4U; - m_group = true; - - /* HDU/LDU2 data */ - m_algId = P25_ALGO_UNENCRYPT; - m_kId = 0x0000U; - - ::memset(m_mi, 0x00U, P25_MI_LENGTH_BYTES); -} - -/** Local Site data */ -/// Sets local configured site data. -/// -void LC::setSiteData(SiteData siteData) -{ - m_siteData = siteData; -} - /** Encryption data */ /// Sets the encryption message indicator. /// @@ -644,7 +614,7 @@ void LC::encodeLC(uint8_t * rs) rsValue = (rsValue << 8) + m_siteData.siteId(); // Site ID rsValue = (rsValue << 4) + m_siteData.channelId(); // Channel ID rsValue = (rsValue << 12) + m_siteData.channelNo(); // Channel Number - rsValue = (rsValue << 8) + m_serviceClass; // System Service Class + rsValue = (rsValue << 8) + m_siteData.serviceClass(); // System Service Class break; default: LogError(LOG_P25, "unknown LC value, mfId = $%02X, lco = $%02X", m_mfId, m_lco); diff --git a/p25/lc/LC.h b/p25/lc/LC.h index 7be2078f..e6c50d60 100644 --- a/p25/lc/LC.h +++ b/p25/lc/LC.h @@ -59,6 +59,8 @@ namespace p25 public: /// Initializes a new instance of the LC class. LC(); + /// Initializes a new instance of the LC class. + LC(SiteData siteData); /// Finalizes a instance of the LC class. ~LC(); @@ -80,13 +82,6 @@ namespace p25 /// Encode a logical link data unit 2. void encodeLDU2(uint8_t* data); - /// Helper to reset data values to defaults. - void reset(); - - /** Local Site data */ - /// Sets local configured site data. - void setSiteData(SiteData siteData); - /** Encryption data */ /// Sets the encryption message indicator. void setMI(const uint8_t* mi); @@ -107,9 +102,6 @@ namespace p25 /// Destination ID. __PROPERTY(uint32_t, dstId, DstId); - /// Service class. - __PROPERTY(uint8_t, serviceClass, ServiceClass); - /// Voice channel number. __PROPERTY(uint32_t, grpVchNo, GrpVchNo); @@ -129,6 +121,10 @@ namespace p25 /// Encryption key ID. __PROPERTY(uint32_t, kId, KId); + /** Local Site data */ + /// Local Site Data. + __PROPERTY_PLAIN(SiteData, siteData, siteData); + private: friend class TSBK; friend class TDULC; @@ -141,9 +137,6 @@ namespace p25 /** Encryption data */ uint8_t* m_mi; - /** Local Site data */ - SiteData m_siteData; - /// Decode link control. bool decodeLC(const uint8_t* rs); /// Encode link control. diff --git a/p25/lc/TDULC.cpp b/p25/lc/TDULC.cpp index dd1a80de..ab236e47 100644 --- a/p25/lc/TDULC.cpp +++ b/p25/lc/TDULC.cpp @@ -49,26 +49,49 @@ using namespace p25; /// /// Initializes a new instance of the TDULC class. /// -TDULC::TDULC() : - m_verbose(false), - m_protect(false), - m_lco(LC_GROUP), - m_mfId(P25_MFG_STANDARD), - m_srcId(0U), - m_dstId(0U), - m_serviceClass(P25_SVC_CLS_VOICE | P25_SVC_CLS_DATA), - m_emergency(false), - m_encrypted(false), - m_priority(4U), - m_group(true), - m_rs(), - m_callTimer(0U), - m_siteData(), - m_siteNetActive(false) +/// +/// +TDULC::TDULC(SiteData siteData, lookups::IdenTable entry) : TDULC(siteData) { - m_siteIdenEntry = lookups::IdenTable(); + m_siteIdenEntry = entry; + m_grpVchNo = m_siteData.channelNo(); +} - reset(); +/// +/// Initializes a new instance of the TDULC class. +/// +/// +/// +/// +TDULC::TDULC(SiteData siteData, lookups::IdenTable entry, bool verbose) : TDULC(siteData) +{ + m_verbose = verbose; + m_siteIdenEntry = entry; + m_grpVchNo = m_siteData.channelNo(); +} + +/// +/// Initializes a new instance of the TDULC class. +/// +/// +TDULC::TDULC(LC* lc) : TDULC(lc->siteData()) +{ + m_protect = lc->m_protect; + m_lco = lc->m_lco; + m_mfId = lc->m_mfId; + + m_srcId = lc->m_srcId; + m_dstId = lc->m_dstId; + + m_grpVchNo = lc->m_grpVchNo; + + m_emergency = lc->m_emergency; + m_encrypted = lc->m_encrypted; + m_priority = lc->m_priority; + + m_group = lc->m_group; + + m_callTimer = lc->m_callTimer; } /// @@ -79,6 +102,46 @@ TDULC::~TDULC() /* stub */ } +/// +/// Equals operator. +/// +/// +/// +TDULC& TDULC::operator=(const TDULC& data) +{ + if (this != &data) { + m_verbose = data.m_verbose; + m_protect = data.m_protect; + m_lco = data.m_lco; + m_mfId = data.m_mfId; + + m_srcId = data.m_srcId; + m_dstId = data.m_dstId; + + m_grpVchNo = data.m_grpVchNo; + + m_adjCFVA = data.m_adjCFVA; + m_adjRfssId = data.m_adjRfssId; + m_adjSiteId = data.m_adjSiteId; + m_adjChannelId = data.m_adjChannelId; + m_adjChannelNo = data.m_adjChannelNo; + m_adjServiceClass = data.m_adjServiceClass; + + m_emergency = data.m_emergency; + m_encrypted = data.m_encrypted; + m_priority = data.m_priority; + + m_group = data.m_group; + + m_callTimer = data.m_callTimer; + + m_siteData = data.m_siteData; + m_siteIdenEntry = data.m_siteIdenEntry; + } + + return *this; +} + /// /// Decode a terminator data unit w/ link control. /// @@ -151,66 +214,39 @@ void TDULC::encode(uint8_t * data) // Utils::dump(2U, "TDULC Interleave", data, P25_TDULC_FRAME_LENGTH_BYTES + P25_PREAMBLE_LENGTH_BYTES); } +// --------------------------------------------------------------------------- +// Private Class Members +// --------------------------------------------------------------------------- /// -/// Helper to reset data values to defaults. +/// Initializes a new instance of the TDULC class. /// -void TDULC::reset() +/// +TDULC::TDULC(SiteData siteData) : + m_verbose(false), + m_protect(false), + m_lco(LC_GROUP), + m_mfId(P25_MFG_STANDARD), + m_srcId(0U), + m_dstId(0U), + m_grpVchNo(0U), + m_adjCFVA(P25_CFVA_FAILURE), + m_adjRfssId(0U), + m_adjSiteId(0U), + m_adjChannelId(0U), + m_adjChannelNo(0U), + m_adjServiceClass(P25_SVC_CLS_INVALID), + m_emergency(false), + m_encrypted(false), + m_priority(4U), + m_group(true), + m_siteData(siteData), + m_siteIdenEntry(), + m_rs(), + m_callTimer(0U) { - m_protect = false; - m_lco = LC_GROUP; - m_mfId = P25_MFG_STANDARD; - - m_srcId = 0U; - m_dstId = 0U; - - m_callTimer = 0U; - m_grpVchNo = m_siteData.channelNo(); - - m_adjCFVA = P25_CFVA_CONV | P25_CFVA_FAILURE; - m_adjRfssId = 0U; - m_adjSiteId = 0U; - m_adjChannelId = 0U; - m_adjChannelNo = 0U; - - /* Service Options */ - m_emergency = false; - m_encrypted = false; - m_priority = 4U; - m_group = true; } -/** Local Site data */ -/// -/// Sets local configured site data. -/// -/// Site data. -void TDULC::setSiteData(SiteData siteData) -{ - m_siteData = siteData; -} - -/// -/// Sets the identity lookup table entry. -/// -/// Identity table entry. -void TDULC::setIdenTable(lookups::IdenTable entry) -{ - m_siteIdenEntry = entry; -} - -/// -/// Sets a flag indicating whether or not networking is active. -/// -/// Network active flag. -void TDULC::setNetActive(bool netActive) -{ - m_siteNetActive = netActive; -} - -// --------------------------------------------------------------------------- -// Private Class Members -// --------------------------------------------------------------------------- /// /// Decode link control. /// @@ -281,7 +317,7 @@ bool TDULC::decodeLC(const uint8_t* rs) /// void TDULC::encodeLC(uint8_t* rs) { - const uint32_t services = (m_siteNetActive) ? P25_SYS_SRV_NET_ACTIVE : 0U | P25_SYS_SRV_DEFAULT; + const uint32_t services = (m_siteData.netActive()) ? P25_SYS_SRV_NET_ACTIVE : 0U | P25_SYS_SRV_DEFAULT; ulong64_t rsValue = 0U; rs[0U] = m_lco; // LCO @@ -376,7 +412,7 @@ void TDULC::encodeLC(uint8_t* rs) rsValue = (rsValue << 8) + m_adjSiteId; // Site ID rsValue = (rsValue << 4) + m_adjChannelId; // Channel ID rsValue = (rsValue << 12) + m_adjChannelNo; // Channel Number - rsValue = (rsValue << 8) + m_serviceClass; // System Service Class + rsValue = (rsValue << 8) + m_adjServiceClass; // System Service Class } else { LogError(LOG_P25, "invalid values for LC_ADJ_STS_BCAST, tsbkAdjSiteRFSSId = $%02X, tsbkAdjSiteId = $%02X, tsbkAdjSiteChannel = $%02X", @@ -393,7 +429,7 @@ void TDULC::encodeLC(uint8_t* rs) rsValue = (rsValue << 8) + m_siteData.siteId(); // Site ID rsValue = (rsValue << 4) + m_siteData.channelId(); // Channel ID rsValue = (rsValue << 12) + m_siteData.channelNo(); // Channel Number - rsValue = (rsValue << 8) + m_serviceClass; // System Service Class + rsValue = (rsValue << 8) + m_siteData.serviceClass(); // System Service Class break; case LC_NET_STS_BCAST: rs[0U] |= 0x40U; // Implicit Operation @@ -402,7 +438,7 @@ void TDULC::encodeLC(uint8_t* rs) rsValue = (rsValue << 12) + m_siteData.sysId(); // System ID rsValue = (rsValue << 4) + m_siteData.channelId(); // Channel ID rsValue = (rsValue << 12) + m_siteData.channelNo(); // Channel Number - rsValue = (rsValue << 8) + m_serviceClass; // System Service Class + rsValue = (rsValue << 8) + m_siteData.serviceClass(); // System Service Class break; default: LogError(LOG_P25, "unknown LC value, mfId = $%02X, lco = $%02X", m_mfId, m_lco); diff --git a/p25/lc/TDULC.h b/p25/lc/TDULC.h index 04dcaffa..ada8e94c 100644 --- a/p25/lc/TDULC.h +++ b/p25/lc/TDULC.h @@ -59,26 +59,22 @@ namespace p25 class HOST_SW_API TDULC { public: /// Initializes a new instance of the TDULC class. - TDULC(); + TDULC(SiteData siteData, lookups::IdenTable entry); + /// Initializes a new instance of the TDULC class. + TDULC(SiteData siteData, lookups::IdenTable entry, bool verbose); + /// Initializes a new instance of the TDULC class. + TDULC(LC* lc); /// Finalizes a instance of the TDULC class. ~TDULC(); + /// Equals operator. + TDULC& operator=(const TDULC& data); + /// Decode a trunking signalling block. bool decode(const uint8_t* data); /// Encode a trunking signalling block. void encode(uint8_t* data); - /// Helper to reset data values to defaults. - void reset(); - - /** Local Site data */ - /// Sets local configured site data. - void setSiteData(SiteData siteData); - /// Sets the identity lookup table entry. - void setIdenTable(lookups::IdenTable entry); - /// Sets a flag indicating whether or not networking is active. - void setNetActive(bool netActive); - public: /// Flag indicating verbose log output. __PROPERTY(bool, verbose, Verbose); @@ -96,9 +92,6 @@ namespace p25 /// Destination ID. __PROPERTY(uint32_t, dstId, DstId); - /// Service class. - __PROPERTY(uint8_t, serviceClass, ServiceClass); - /// Voice channel number. __PROPERTY(uint32_t, grpVchNo, GrpVchNo); @@ -115,6 +108,8 @@ namespace p25 __PROPERTY(uint8_t, adjChannelId, AdjSiteChnId); /// Adjacent site channel number. __PROPERTY(uint32_t, adjChannelNo, AdjSiteChnNo); + /// Adjacent site service class. + __PROPERTY(uint8_t, adjServiceClass, AdjSiteSvcClass); /** Service Options */ /// Flag indicating the emergency bits are set. @@ -126,18 +121,22 @@ namespace p25 /// Flag indicating a group/talkgroup operation. __PROPERTY(bool, group, Group); + /** Local Site data */ + /// Local Site Data. + __PROPERTY_PLAIN(SiteData, siteData, siteData); + /// Local Site Identity Entry. + __PROPERTY_PLAIN(lookups::IdenTable, siteIdenEntry, siteIdenEntry); + private: + /// Initializes a new instance of the TDULC class. + TDULC(SiteData siteData); + friend class LC; friend class TSBK; edac::RS634717 m_rs; uint32_t m_callTimer; - /** Local Site data */ - SiteData m_siteData; - lookups::IdenTable m_siteIdenEntry; - bool m_siteNetActive; - /// Decode link control. bool decodeLC(const uint8_t* rs); /// Encode link control. diff --git a/p25/lc/TSBK.cpp b/p25/lc/TSBK.cpp index 97f1ef95..3c8b92ab 100644 --- a/p25/lc/TSBK.cpp +++ b/p25/lc/TSBK.cpp @@ -48,46 +48,45 @@ using namespace p25; /// /// Initializes a new instance of the TSBK class. /// -TSBK::TSBK() : - m_verbose(false), - m_protect(false), - m_lco(LC_GROUP), - m_mfId(P25_MFG_STANDARD), - m_srcId(0U), - m_dstId(0U), - m_lastBlock(false), - m_aivFlag(true), - m_extendedAddrFlag(false), - m_serviceClass(P25_SVC_CLS_VOICE | P25_SVC_CLS_DATA), - m_emergency(false), - m_encrypted(false), - m_priority(4U), - m_group(true), - m_rs(), - m_trellis(), - m_vendorSkip(false), - m_sndcpAutoAccess(true), - m_sndcpReqAccess(false), - m_sndcpDAC(1U), - m_siteData(), - m_siteNetActive(false), - m_siteChCnt(1U) +/// +/// +TSBK::TSBK(SiteData siteData, lookups::IdenTable entry) : TSBK(siteData) { - m_siteCallsign = new uint8_t[P25_MOT_CALLSIGN_LENGTH_BYTES]; - ::memset(m_siteCallsign, 0x00U, P25_MOT_CALLSIGN_LENGTH_BYTES); + m_siteIdenEntry = entry; +} + +/// +/// Initializes a new instance of the TSBK class. +/// +/// +/// +/// +TSBK::TSBK(SiteData siteData, lookups::IdenTable entry, bool verbose) : TSBK(siteData) +{ + m_verbose = verbose; + m_siteIdenEntry = entry; +} + +/// +/// Initializes a new instance of the TSBK class. +/// +/// +TSBK::TSBK(LC* lc) : TSBK(lc->siteData()) +{ + m_protect = lc->m_protect; + m_lco = lc->m_lco; + m_mfId = lc->m_mfId; - m_siteCallsign[0] = 'C'; - m_siteCallsign[1] = 'H'; - m_siteCallsign[2] = 'A'; - m_siteCallsign[3] = 'N'; - m_siteCallsign[4] = 'G'; - m_siteCallsign[5] = 'E'; - m_siteCallsign[6] = 'M'; - m_siteCallsign[7] = 'E'; + m_srcId = lc->m_srcId; + m_dstId = lc->m_dstId; - m_siteIdenEntry = lookups::IdenTable(); + m_grpVchNo = lc->m_grpVchNo; - reset(); + m_emergency = lc->m_emergency; + m_encrypted = lc->m_encrypted; + m_priority = lc->m_priority; + + m_group = lc->m_group; } /// @@ -98,6 +97,73 @@ TSBK::~TSBK() delete[] m_siteCallsign; } +/// +/// Equals operator. +/// +/// +/// +TSBK& TSBK::operator=(const TSBK& data) +{ + if (this != &data) { + m_verbose = data.m_verbose; + m_protect = data.m_protect; + m_lco = data.m_lco; + m_mfId = data.m_mfId; + + m_srcId = data.m_srcId; + m_dstId = data.m_dstId; + + m_lastBlock = data.m_lastBlock; + m_aivFlag = data.m_aivFlag; + m_extendedAddrFlag = data.m_extendedAddrFlag; + + m_service = data.m_service; + m_response = data.m_response; + + m_netId = data.m_netId; + m_sysId = data.m_sysId; + + m_grpVchNo = data.m_grpVchNo; + + m_messageValue = data.m_messageValue; + m_statusValue = data.m_statusValue; + + m_extendedFunction = data.m_extendedFunction; + + m_adjCFVA = data.m_adjCFVA; + m_adjRfssId = data.m_adjRfssId; + m_adjSiteId = data.m_adjSiteId; + m_adjChannelId = data.m_adjChannelId; + m_adjChannelNo = data.m_adjChannelNo; + m_adjServiceClass = data.m_adjServiceClass; + + m_sccbChannelId1 = data.m_sccbChannelId1; + m_sccbChannelId2 = data.m_sccbChannelId2; + m_sccbChannelNo = data.m_sccbChannelNo; + + m_lra = data.m_lra; + + m_patchSuperGroupId = data.m_patchSuperGroupId; + m_patchGroup1Id = data.m_patchGroup1Id; + m_patchGroup2Id = data.m_patchGroup2Id; + m_patchGroup3Id = data.m_patchGroup3Id; + + m_emergency = data.m_emergency; + m_encrypted = data.m_encrypted; + m_priority = data.m_priority; + + m_group = data.m_group; + + m_siteData = data.m_siteData; + m_siteIdenEntry = data.m_siteIdenEntry; + + m_siteCallsign = new uint8_t[P25_MOT_CALLSIGN_LENGTH_BYTES]; + ::memcpy(m_siteCallsign, data.m_siteCallsign, P25_MOT_CALLSIGN_LENGTH_BYTES); + } + + return *this; +} + /// /// Decode a trunking signalling block. /// @@ -302,7 +368,7 @@ void TSBK::encode(uint8_t * data, bool singleBlock) { assert(data != NULL); - const uint32_t services = (m_siteNetActive) ? P25_SYS_SRV_NET_ACTIVE : 0U | P25_SYS_SRV_DEFAULT; + const uint32_t services = (m_siteData.netActive()) ? P25_SYS_SRV_NET_ACTIVE : 0U | P25_SYS_SRV_DEFAULT; uint8_t tsbk[P25_TSBK_LENGTH_BYTES]; ::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES); @@ -446,7 +512,7 @@ void TSBK::encode(uint8_t * data, bool singleBlock) tsbkValue = (tsbkValue << 12) + m_sccbChannelNo; // Channel (R) Number if (m_sccbChannelId1 > 0) { - tsbkValue = (tsbkValue << 8) + m_serviceClass; // System Service Class + tsbkValue = (tsbkValue << 8) + m_siteData.serviceClass(); // System Service Class } else { tsbkValue = (tsbkValue << 8) + (P25_SVC_CLS_INVALID); // System Service Class @@ -512,14 +578,14 @@ void TSBK::encode(uint8_t * data, bool singleBlock) tsbkValue = (tsbkValue << 8) + m_siteData.siteId(); // Site ID tsbkValue = (tsbkValue << 16) + m_sccbChannelId1; // SCCB Channel ID 1 if (m_sccbChannelId1 > 0) { - tsbkValue = (tsbkValue << 8) + m_serviceClass; // System Service Class + tsbkValue = (tsbkValue << 8) + m_siteData.serviceClass(); // System Service Class } else { tsbkValue = (tsbkValue << 8) + (P25_SVC_CLS_INVALID); // System Service Class } tsbkValue = (tsbkValue << 16) + m_sccbChannelId2; // SCCB Channel ID 2 if (m_sccbChannelId2 > 0) { - tsbkValue = (tsbkValue << 8) + m_serviceClass; // System Service Class + tsbkValue = (tsbkValue << 8) + m_siteData.serviceClass(); // System Service Class } else { tsbkValue = (tsbkValue << 8) + (P25_SVC_CLS_INVALID); // System Service Class @@ -528,13 +594,13 @@ void TSBK::encode(uint8_t * data, bool singleBlock) case TSBK_OSP_RFSS_STS_BCAST: tsbkValue = m_siteData.lra(); // Location Registration Area tsbkValue = (tsbkValue << 4) + - (m_siteNetActive) ? P25_CFVA_NETWORK : 0U; // CFVA + (m_siteData.netActive()) ? P25_CFVA_NETWORK : 0U; // CFVA tsbkValue = (tsbkValue << 12) + m_siteData.sysId(); // System ID tsbkValue = (tsbkValue << 8) + m_siteData.rfssId(); // RF Sub-System ID tsbkValue = (tsbkValue << 8) + m_siteData.siteId(); // Site ID tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel ID tsbkValue = (tsbkValue << 12) + m_siteData.channelNo(); // Channel Number - tsbkValue = (tsbkValue << 8) + m_serviceClass; // System Service Class + tsbkValue = (tsbkValue << 8) + m_siteData.serviceClass(); // System Service Class break; case TSBK_OSP_NET_STS_BCAST: tsbkValue = m_siteData.lra(); // Location Registration Area @@ -542,7 +608,7 @@ void TSBK::encode(uint8_t * data, bool singleBlock) tsbkValue = (tsbkValue << 12) + m_siteData.sysId(); // System ID tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel ID tsbkValue = (tsbkValue << 12) + m_siteData.channelNo(); // Channel Number - tsbkValue = (tsbkValue << 8) + m_serviceClass; // System Service Class + tsbkValue = (tsbkValue << 8) + m_siteData.serviceClass(); // System Service Class break; case TSBK_OSP_ADJ_STS_BCAST: { @@ -754,57 +820,6 @@ void TSBK::encode(uint8_t * data, bool singleBlock) } } -/// -/// Helper to reset data values to defaults. -/// -void TSBK::reset() -{ - m_vendorSkip = false; - - m_protect = false; - m_lco = LC_GROUP; - m_mfId = P25_MFG_STANDARD; - - m_srcId = 0U; - m_dstId = 0U; - - m_lastBlock = true; - m_aivFlag = true; - m_extendedAddrFlag = false; - - m_service = 0U; - m_response = P25_RSP_ACCEPT; - - m_netId = P25_WACN_STD_DEFAULT; - m_sysId = P25_SID_STD_DEFAULT; - - m_grpVchNo = m_siteData.channelNo(); - - m_messageValue = 0U; - m_statusValue = 0U; - - m_extendedFunction = P25_EXT_FNCT_CHECK; - - m_adjCFVA = P25_CFVA_FAILURE; - m_adjRfssId = 0U; - m_adjSiteId = 0U; - m_adjChannelId = 0U; - m_adjChannelNo = 0U; - m_adjServiceClass = P25_SVC_CLS_INVALID; - - /* TSBK Patch Group data */ - m_patchSuperGroupId = 0U; - m_patchGroup1Id = 0U; - m_patchGroup2Id = 0U; - m_patchGroup3Id = 0U; - - /* Service Options */ - m_emergency = false; - m_encrypted = false; - m_priority = 4U; - m_group = true; -} - /// /// Sets the flag to skip vendor opcode processing. /// @@ -814,18 +829,8 @@ void TSBK::setVendorSkip(bool skip) m_vendorSkip = skip; } -/** Local Site data */ -/// -/// Sets local configured site data. -/// -/// Site data. -void TSBK::setSiteData(SiteData siteData) -{ - m_siteData = siteData; -} - /// -/// Sets local configured site callsign. +/// Sets the callsign. /// /// Callsign. void TSBK::setCallsign(std::string callsign) @@ -841,29 +846,60 @@ void TSBK::setCallsign(std::string callsign) } } +// --------------------------------------------------------------------------- +// Private Class Members +// --------------------------------------------------------------------------- /// -/// Sets the identity lookup table entry. -/// -/// Identity table entry. -void TSBK::setIdenTable(lookups::IdenTable entry) -{ - m_siteIdenEntry = entry; -} - -/// -/// Sets a flag indicating whether or not networking is active. -/// -/// Network active flag. -void TSBK::setNetActive(bool netActive) -{ - m_siteNetActive = netActive; -} - -/// -/// Sets the total number of channels at the site. +/// Initializes a new instance of the TSBK class. /// -/// Channel count. -void TSBK::setSiteChCnt(uint8_t chCnt) +/// +TSBK::TSBK(SiteData siteData) : + m_verbose(false), + m_protect(false), + m_lco(LC_GROUP), + m_mfId(P25_MFG_STANDARD), + m_srcId(0U), + m_dstId(0U), + m_lastBlock(false), + m_aivFlag(true), + m_extendedAddrFlag(false), + m_service(0U), + m_response(P25_RSP_ACCEPT), + m_netId(P25_WACN_STD_DEFAULT), + m_sysId(P25_SID_STD_DEFAULT), + m_grpVchNo(0U), + m_messageValue(0U), + m_statusValue(0U), + m_extendedFunction(P25_EXT_FNCT_CHECK), + m_adjCFVA(P25_CFVA_FAILURE), + m_adjRfssId(0U), + m_adjSiteId(0U), + m_adjChannelId(0U), + m_adjChannelNo(0U), + m_adjServiceClass(P25_SVC_CLS_INVALID), + m_sccbChannelId1(0U), + m_sccbChannelId2(0U), + m_sccbChannelNo(0U), + m_lra(0U), + m_patchSuperGroupId(0U), + m_patchGroup1Id(0U), + m_patchGroup2Id(0U), + m_patchGroup3Id(0U), + m_emergency(false), + m_encrypted(false), + m_priority(4U), + m_group(true), + m_siteData(siteData), + m_siteIdenEntry(), + m_rs(), + m_trellis(), + m_vendorSkip(false), + m_sndcpAutoAccess(true), + m_sndcpReqAccess(false), + m_sndcpDAC(1U), + m_siteCallsign(NULL) { - m_siteChCnt = chCnt; + m_siteCallsign = new uint8_t[P25_MOT_CALLSIGN_LENGTH_BYTES]; + ::memset(m_siteCallsign, 0x00U, P25_MOT_CALLSIGN_LENGTH_BYTES); + setCallsign(siteData.callsign()); } diff --git a/p25/lc/TSBK.h b/p25/lc/TSBK.h index 785efd27..68d95fdc 100644 --- a/p25/lc/TSBK.h +++ b/p25/lc/TSBK.h @@ -59,32 +59,27 @@ namespace p25 class HOST_SW_API TSBK { public: /// Initializes a new instance of the TSBK class. - TSBK(); + TSBK(SiteData siteData, lookups::IdenTable entry); + /// Initializes a new instance of the TSBK class. + TSBK(SiteData siteData, lookups::IdenTable entry, bool verbose); + /// Initializes a new instance of the TSBK class. + TSBK(LC* lc); /// Finalizes a instance of the TSBK class. ~TSBK(); + /// Equals operator. + TSBK& operator=(const TSBK& data); + /// Decode a trunking signalling block. bool decode(const uint8_t* data); /// Encode a trunking signalling block. void encode(uint8_t* data, bool singleBlock); - /// Helper to reset data values to defaults. - void reset(); - /// Sets the flag to skip vendor opcode processing. void setVendorSkip(bool skip); - /** Local Site data */ - /// Sets local configured site data. - void setSiteData(SiteData siteData); - /// Sets local configured site callsign. + /// Sets the callsign. void setCallsign(std::string callsign); - /// Sets the identity lookup table entry. - void setIdenTable(lookups::IdenTable entry); - /// Sets a flag indicating whether or not networking is active. - void setNetActive(bool netActive); - /// Sets the total number of channels at the site. - void setSiteChCnt(uint8_t chCnt); public: /// Flag indicating verbose log output. @@ -112,10 +107,6 @@ namespace p25 /// Service type. __PROPERTY(uint8_t, service, Service); - - /// Service class. - __PROPERTY(uint8_t, serviceClass, ServiceClass); - /// Response type. __PROPERTY(uint8_t, response, Response); @@ -148,7 +139,7 @@ namespace p25 __PROPERTY(uint8_t, adjChannelId, AdjSiteChnId); /// Adjacent site channel number. __PROPERTY(uint32_t, adjChannelNo, AdjSiteChnNo); - /// Adjacent site channel number. + /// Adjacent site service class. __PROPERTY(uint8_t, adjServiceClass, AdjSiteSvcClass); /** SCCB Data */ @@ -183,7 +174,16 @@ namespace p25 /// Flag indicating a group/talkgroup operation. __PROPERTY(bool, group, Group); + /** Local Site data */ + /// Local Site Data. + __PROPERTY_PLAIN(SiteData, siteData, siteData); + /// Local Site Identity Entry. + __PROPERTY_PLAIN(lookups::IdenTable, siteIdenEntry, siteIdenEntry); + private: + /// Initializes a new instance of the TSBK class. + TSBK(SiteData siteData); + friend class LC; friend class TDULC; edac::RS634717 m_rs; @@ -195,11 +195,7 @@ namespace p25 uint16_t m_sndcpDAC; /** Local Site data */ - SiteData m_siteData; uint8_t* m_siteCallsign; - lookups::IdenTable m_siteIdenEntry; - bool m_siteNetActive; - uint8_t m_siteChCnt; }; } // namespace lc } // namespace p25