diff --git a/configs/config.example.yml b/configs/config.example.yml index be6f6f2f..2a0f6111 100644 --- a/configs/config.example.yml +++ b/configs/config.example.yml @@ -185,6 +185,12 @@ protocols: # Flag indicating whether or not the composite flag in the CC service options is set. # (This is useful to disable for some radios when running in VOC mode.) disableCompositeFlag: false + # Flag indicating whether or not a voice HDU will transmitted at the start of a call from the network. + disableNetworkHDU: false + # Flag indicating whether or not network calls will generate a channel grant. + # (This applies only in conventional operations where channel granting is utilized and RF-only talkgroup + # steering is required.) + disableNetworkGrant: false # Flag indicating that the host will attempt to automatically inhibit unauthorized RIDs (those not in the # RID ACL list). inhibitUnauthorized: false @@ -220,8 +226,6 @@ protocols: silenceThreshold: 124 # Maximum number of lost frames before terminating a call. frameLossThreshold: 6 - # Flag indicating whether or not a voice HDU will transmitted at the start of a call from the network. - disableNetworkHDU: false # Internal data queue size (in P25 packets). queueSize: 12 # Flag indicating whether or not verbose logging is enabled. diff --git a/src/dmr/Control.cpp b/src/dmr/Control.cpp index f3927c97..d263a436 100644 --- a/src/dmr/Control.cpp +++ b/src/dmr/Control.cpp @@ -185,6 +185,9 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::vectorsetNotifyCC(notifyCC); m_slot2->setNotifyCC(notifyCC); + /* + ** Voice Silence and Frame Loss Thresholds + */ uint32_t silenceThreshold = dmrProtocol["silenceThreshold"].as(dmr::DEFAULT_SILENCE_THRESHOLD); if (silenceThreshold > MAX_DMR_VOICE_ERRORS) { LogWarning(LOG_DMR, "Silence threshold > %u, defaulting to %u", dmr::MAX_DMR_VOICE_ERRORS, dmr::DEFAULT_SILENCE_THRESHOLD); diff --git a/src/nxdn/Control.cpp b/src/nxdn/Control.cpp index 25339275..ff651ef6 100644 --- a/src/nxdn/Control.cpp +++ b/src/nxdn/Control.cpp @@ -246,6 +246,15 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::string cw m_voiceOnControl = nxdnProtocol["voiceOnControl"].as(false); + m_trunk->m_disableGrantSrcIdCheck = control["disableGrantSourceIdCheck"].as(false); + + yaml::Node rfssConfig = systemConf["config"]; + yaml::Node controlCh = rfssConfig["controlCh"]; + m_notifyCC = controlCh["notifyEnable"].as(false); + + /* + ** Voice Silence and Frame Loss Thresholds + */ m_voice->m_silenceThreshold = nxdnProtocol["silenceThreshold"].as(nxdn::DEFAULT_SILENCE_THRESHOLD); if (m_voice->m_silenceThreshold > MAX_NXDN_VOICE_ERRORS) { LogWarning(LOG_NXDN, "Silence threshold > %u, defaulting to %u", nxdn::MAX_NXDN_VOICE_ERRORS, nxdn::DEFAULT_SILENCE_THRESHOLD); @@ -266,6 +275,9 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::string cw LogWarning(LOG_NXDN, "Frame loss threshold may be excessive, default is %u, configured is %u", nxdn::DEFAULT_FRAME_LOSS_THRESHOLD, m_frameLossThreshold); } + /* + ** CC Service Class + */ bool disableCompositeFlag = nxdnProtocol["disableCompositeFlag"].as(false); uint8_t serviceClass = NXDN_SIF1_VOICE_CALL_SVC | NXDN_SIF1_DATA_CALL_SVC; if (m_control) { @@ -278,6 +290,9 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::string cw } } + /* + ** Site Data + */ // calculate the NXDN location ID uint32_t locId = NXDN_LOC_CAT_LOCAL; // DVM is currently fixed to "local" category locId = (locId << 17) + sysId; @@ -328,12 +343,6 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::string cw } } - m_trunk->m_disableGrantSrcIdCheck = control["disableGrantSourceIdCheck"].as(false); - - yaml::Node rfssConfig = systemConf["config"]; - yaml::Node controlCh = rfssConfig["controlCh"]; - m_notifyCC = controlCh["notifyEnable"].as(false); - if (printOptions) { LogInfo(" Silence Threshold: %u (%.1f%%)", m_voice->m_silenceThreshold, float(m_voice->m_silenceThreshold) / 12.33F); LogInfo(" Frame Loss Threshold: %u", m_frameLossThreshold); diff --git a/src/p25/Control.cpp b/src/p25/Control.cpp index 3d9f3ff7..52bda0cc 100644 --- a/src/p25/Control.cpp +++ b/src/p25/Control.cpp @@ -103,6 +103,7 @@ Control::Control(bool authoritative, uint32_t nac, uint32_t callHang, uint32_t q m_dedicatedControl(false), m_voiceOnControl(false), m_ackTSBKRequests(true), + m_disableNetworkGrant(false), m_disableNetworkHDU(false), m_idenTable(idenTable), m_ridLookup(ridLookup), @@ -273,6 +274,24 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::string cw m_trunk->m_ctrlTimeDateAnn = control["enableTimeDateAnn"].as(false); m_trunk->m_redundantGrant = control["redundantGrantTransmit"].as(false); + m_allowExplicitSourceId = p25Protocol["allowExplicitSourceId"].as(true); + + uint32_t ccBcstInterval = p25Protocol["control"]["interval"].as(300U); + m_trunk->m_adjSiteUpdateInterval += ccBcstInterval; + + m_trunk->m_disableGrantSrcIdCheck = p25Protocol["control"]["disableGrantSourceIdCheck"].as(false); + + yaml::Node controlCh = rfssConfig["controlCh"]; + m_notifyCC = controlCh["notifyEnable"].as(false); + + // voice on control forcibly disables CC notification + if (m_voiceOnControl) { + m_notifyCC = false; + } + + /* + ** Voice Silence and Frame Loss Thresholds + */ m_voice->m_silenceThreshold = p25Protocol["silenceThreshold"].as(p25::DEFAULT_SILENCE_THRESHOLD); if (m_voice->m_silenceThreshold > MAX_P25_VOICE_ERRORS) { LogWarning(LOG_P25, "Silence threshold > %u, defaulting to %u", p25::MAX_P25_VOICE_ERRORS, p25::DEFAULT_SILENCE_THRESHOLD); @@ -293,8 +312,25 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::string cw LogWarning(LOG_P25, "Frame loss threshold may be excessive, default is %u, configured is %u", p25::DEFAULT_FRAME_LOSS_THRESHOLD, m_frameLossThreshold); } + /* + ** Network HDU and Grant Disables + */ + m_disableNetworkGrant = p25Protocol["disableNetworkGrant"].as(false); m_disableNetworkHDU = p25Protocol["disableNetworkHDU"].as(false); + if (m_disableNetworkGrant && m_control && m_dedicatedControl) { + LogWarning(LOG_P25, "Cannot disable network traffic grants for dedicated control configuration."); + m_disableNetworkGrant = false; + } + + if (m_disableNetworkGrant && m_controlOnly) { + LogWarning(LOG_P25, "Cannot disable network traffic grants for control-only configuration."); + m_disableNetworkGrant = false; + } + + /* + ** CC Service Class + */ bool disableCompositeFlag = p25Protocol["disableCompositeFlag"].as(false); uint8_t serviceClass = P25_SVC_CLS_VOICE | P25_SVC_CLS_DATA; if (m_control) { @@ -307,8 +343,10 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::string cw } } + /* + ** Site Data + */ int8_t lto = (int8_t)systemConf["localTimeOffset"].as(0); - m_siteData = SiteData(netId, sysId, rfssId, siteId, 0U, channelId, channelNo, serviceClass, lto); uint32_t valueTest = (netId >> 8); const uint32_t constValue = 0x17DC0U; @@ -363,21 +401,6 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::string cw } }); - uint32_t ccBcstInterval = p25Protocol["control"]["interval"].as(300U); - m_trunk->m_adjSiteUpdateInterval += ccBcstInterval; - - m_trunk->m_disableGrantSrcIdCheck = p25Protocol["control"]["disableGrantSourceIdCheck"].as(false); - - yaml::Node controlCh = rfssConfig["controlCh"]; - m_notifyCC = controlCh["notifyEnable"].as(false); - - // voice on control forcibly disables CC notification - if (m_voiceOnControl) { - m_notifyCC = false; - } - - m_allowExplicitSourceId = p25Protocol["allowExplicitSourceId"].as(true); - if (printOptions) { LogInfo(" Silence Threshold: %u (%.1f%%)", m_voice->m_silenceThreshold, float(m_voice->m_silenceThreshold) / 12.33F); LogInfo(" Frame Loss Threshold: %u", m_frameLossThreshold); @@ -398,7 +421,12 @@ void Control::setOptions(yaml::Node& conf, bool supervisor, const std::string cw LogInfo(" Announcement Group: $%04X", m_trunk->m_announcementGroup); LogInfo(" Notify Control: %s", m_notifyCC ? "yes" : "no"); - LogInfo(" Disable Network HDUs: %s", m_disableNetworkHDU ? "yes" : "no"); + if (!m_disableNetworkHDU) { + LogInfo(" Disable Network HDUs: yes"); + } + if (!m_disableNetworkGrant) { + LogInfo(" Disable Network Grants: yes"); + } if (!m_trunk->m_ctrlTSDUMBF) { LogInfo(" Disable Multi-Block TSDUs: yes"); } @@ -1229,6 +1257,10 @@ void Control::processNetwork() case P25_DUID_TDULC: // is this an TDU with a grant demand? if (duid == P25_DUID_TDU && m_control && grantDemand) { + if (m_disableNetworkGrant) { + return; + } + // validate source RID if (!acl::AccessControl::validateSrcId(srcId)) { return; diff --git a/src/p25/Control.h b/src/p25/Control.h index 4417f759..2dea9e9a 100644 --- a/src/p25/Control.h +++ b/src/p25/Control.h @@ -173,6 +173,7 @@ namespace p25 bool m_voiceOnControl; bool m_controlOnly; bool m_ackTSBKRequests; + bool m_disableNetworkGrant; bool m_disableNetworkHDU; bool m_allowExplicitSourceId; diff --git a/src/p25/packet/Voice.cpp b/src/p25/packet/Voice.cpp index d3508d4c..b65f0db0 100644 --- a/src/p25/packet/Voice.cpp +++ b/src/p25/packet/Voice.cpp @@ -1344,7 +1344,7 @@ void Voice::writeNet_LDU1() ::ActivityLog("P25", false, "network %svoice transmission from %u to %s%u", m_netLC.getEncrypted() ? "encrypted " : "", srcId, group ? "TG " : "", dstId); // single-channel trunking or voice on control support? - if (m_p25->m_control && m_p25->m_voiceOnControl) { + if (m_p25->m_control && m_p25->m_voiceOnControl && !m_p25->m_disableNetworkGrant) { uint8_t serviceOptions = (m_netLC.getEmergency() ? 0x80U : 0x00U) + // Emergency Flag (m_netLC.getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag (m_netLC.getPriority() & 0x07U); // Priority