diff --git a/src/dmr/packet/ControlSignaling.cpp b/src/dmr/packet/ControlSignaling.cpp index 64b64ab7..56cfcbe8 100644 --- a/src/dmr/packet/ControlSignaling.cpp +++ b/src/dmr/packet/ControlSignaling.cpp @@ -443,6 +443,43 @@ void ControlSignaling::processNetwork(const data::Data & dmrData) LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), serviceKind = $%02X, serviceOptions = $%02X, serviceExtra = $%02X, srcId = %u, dstId = %u", m_slot->m_slotNo, isp->getServiceKind(), isp->getServiceOptions(), isp->getServiceExtra(), isp->getSrcId(), isp->getDstId()); } + + switch (isp->getServiceKind()) { + case SVC_KIND_IND_VOICE_CALL: + writeRF_CSBK_ACK_RSP(srcId, TS_WAIT_RSN, 1U); + + if (m_slot->m_authoritative) { + writeRF_CSBK_Grant(srcId, dstId, isp->getServiceOptions(), false); + } + break; + case SVC_KIND_GRP_VOICE_CALL: + writeRF_CSBK_ACK_RSP(srcId, TS_WAIT_RSN, 1U); + + if (m_slot->m_authoritative) { + writeRF_CSBK_Grant(srcId, dstId, isp->getServiceOptions(), true); + } + break; + case SVC_KIND_IND_DATA_CALL: + case SVC_KIND_IND_UDT_DATA_CALL: + writeRF_CSBK_ACK_RSP(srcId, TS_WAIT_RSN, 0U); + + writeRF_CSBK_Data_Grant(srcId, dstId, isp->getServiceOptions(), false); + break; + case SVC_KIND_GRP_DATA_CALL: + case SVC_KIND_GRP_UDT_DATA_CALL: + writeRF_CSBK_ACK_RSP(srcId, TS_WAIT_RSN, 0U); + + writeRF_CSBK_Data_Grant(srcId, dstId, isp->getServiceOptions(), true); + break; + case SVC_KIND_REG_SVC: + break; + default: + LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), unhandled service, serviceKind = %02X", m_slot->m_slotNo, isp->getServiceKind()); + // should we drop the CSBK and not repeat it? + break; + } + + handled = true; } } break; diff --git a/src/nxdn/packet/Trunk.cpp b/src/nxdn/packet/Trunk.cpp index 46573347..bce765b3 100644 --- a/src/nxdn/packet/Trunk.cpp +++ b/src/nxdn/packet/Trunk.cpp @@ -43,6 +43,7 @@ using namespace nxdn; using namespace nxdn::lc; +using namespace nxdn::lc::rcch; using namespace nxdn::packet; #include @@ -235,10 +236,50 @@ bool Trunk::processNetwork(uint8_t fct, uint8_t option, lc::RTCH& netLC, uint8_t { assert(data != nullptr); + if (!m_nxdn->m_control) + return false; + if (m_nxdn->m_rfState != RS_RF_LISTENING && m_nxdn->m_netState == RS_NET_IDLE) + return false; + if (m_nxdn->m_netState == RS_NET_IDLE) { m_nxdn->m_queue.clear(); } + if (m_nxdn->m_netState == RS_NET_IDLE) { + std::unique_ptr rcch = RCCHFactory::createRCCH(data, len); + if (rcch == nullptr) { + return false; + } + + uint16_t srcId = rcch->getSrcId(); + uint16_t dstId = rcch->getDstId(); + + // handle standard P25 reference opcodes + switch (rcch->getMessageType()) { + case RTCH_MESSAGE_TYPE_VCALL: + { + if (m_verbose) { + LogMessage(LOG_NET, NXDN_RCCH_MSG_TYPE_VCALL_CONN_REQ ", emerg = %u, encrypt = %u, prio = %u, chNo = %u, srcId = %u, dstId = %u", + rcch->getEmergency(), rcch->getEncrypted(), rcch->getPriority(), rcch->getGrpVchNo(), srcId, dstId); + } + + uint8_t serviceOptions = (rcch->getEmergency() ? 0x80U : 0x00U) + // Emergency Flag + (rcch->getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag + (rcch->getPriority() & 0x07U); // Priority + + if (m_nxdn->m_dedicatedControl && !m_nxdn->m_voiceOnControl) { + writeRF_Message_Grant(srcId, dstId, serviceOptions, true); + } + } + return true; // don't allow this to write to the air + default: + LogError(LOG_NET, "NXDN, unhandled message type, messageType = $%02X", rcch->getMessageType()); + return false; + } // switch (rcch->getMessageType()) + + writeRF_Message(rcch.get(), true); + } + return true; } diff --git a/src/p25/packet/Trunk.cpp b/src/p25/packet/Trunk.cpp index 7cbabf10..a62890e0 100644 --- a/src/p25/packet/Trunk.cpp +++ b/src/p25/packet/Trunk.cpp @@ -710,8 +710,7 @@ bool Trunk::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::L (tsbk->getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag (tsbk->getPriority() & 0x07U); // Priority - // workaround for single channel dedicated sites to pass network traffic on a lone VC - if (m_p25->m_dedicatedControl && !m_p25->m_voiceOnControl && m_p25->m_affiliations.getRFChCnt() == 1U) { + if (m_p25->m_dedicatedControl && !m_p25->m_voiceOnControl) { writeRF_TSDU_Grant(srcId, dstId, serviceOptions, true); } } @@ -727,8 +726,7 @@ bool Trunk::processNetwork(uint8_t* data, uint32_t len, lc::LC& control, data::L (tsbk->getEncrypted() ? 0x40U : 0x00U) + // Encrypted Flag (tsbk->getPriority() & 0x07U); // Priority - // workaround for single channel dedicated sites to pass network traffic on a lone VC - if (m_p25->m_dedicatedControl && !m_p25->m_voiceOnControl && m_p25->m_affiliations.getRFChCnt() == 1U) { + if (m_p25->m_dedicatedControl && !m_p25->m_voiceOnControl) { writeRF_TSDU_Grant(srcId, dstId, serviceOptions, false); } }