From b17e02f384a0f9bfb76b0e79ff38ea4e9f713861 Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Fri, 29 Apr 2022 16:42:53 -0400 Subject: [PATCH] implement OSP_SNDCP_CH_GNT (this commit just adds support to respond to an ISP_SNDCP_CH_REQ, it does not mean data services will work); --- p25/TrunkPacket.cpp | 27 +++++++++++++++++++++++---- p25/TrunkPacket.h | 2 +- p25/lc/TSBK.cpp | 25 +++++++++++++++++++++++++ p25/lc/TSBK.h | 3 +++ 4 files changed, 52 insertions(+), 5 deletions(-) diff --git a/p25/TrunkPacket.cpp b/p25/TrunkPacket.cpp index b0024e00..101ae6cf 100644 --- a/p25/TrunkPacket.cpp +++ b/p25/TrunkPacket.cpp @@ -309,9 +309,7 @@ bool TrunkPacket::process(uint8_t* data, uint32_t len, bool preDecoded) m_rfTSBK.getDataServiceOptions(), m_rfTSBK.getDataAccessControl(), srcId); } - // SNDCP data channel requests are currently unsupported -- maybe in the future? - - writeRF_TSDU_Deny(P25_DENY_RSN_SYS_UNSUPPORTED_SVC, TSBK_ISP_SNDCP_CH_REQ); + writeRF_TSDU_Grant(false, false, false, true); break; case TSBK_IOSP_STS_UPDT: // validate the source RID @@ -2017,8 +2015,9 @@ void TrunkPacket::queueRF_TSBK_Ctrl(uint8_t lco) /// /// /// +/// /// -bool TrunkPacket::writeRF_TSDU_Grant(bool grp, bool skip, bool net) +bool TrunkPacket::writeRF_TSDU_Grant(bool grp, bool skip, bool net, bool sndcpGrant) { uint8_t lco = m_rfTSBK.getLCO(); @@ -2101,6 +2100,7 @@ bool TrunkPacket::writeRF_TSDU_Grant(bool grp, bool skip, bool net) m_grantChTable[m_rfTSBK.getDstId()] = chNo; m_rfTSBK.setGrpVchNo(chNo); + m_rfTSBK.setDataChnNo(chNo); m_grantTimers[m_rfTSBK.getDstId()] = Timer(1000U, GRANT_TIMER_TIMEOUT); m_grantTimers[m_rfTSBK.getDstId()].start(); @@ -2112,11 +2112,30 @@ bool TrunkPacket::writeRF_TSDU_Grant(bool grp, bool skip, bool net) else { uint32_t chNo = m_grantChTable[m_rfTSBK.getDstId()]; m_rfTSBK.setGrpVchNo(chNo); + m_rfTSBK.setDataChnNo(chNo); m_grantTimers[m_rfTSBK.getDstId()].start(); } } + if (sndcpGrant) { + if (!net) { + ::ActivityLog("P25", true, "SNDCP grant request from to %u", m_rfTSBK.getDstId()); + } + + if (m_verbose) { + LogMessage((net) ? LOG_NET : LOG_RF, P25_TSDU_STR ", TSBK_OSP_SNDCP_CH_GNT (SNDCP Data Channel Grant), chNo = %u, dstId = %u", + m_rfTSBK.getDataChnNo(), m_rfTSBK.getDstId()); + } + + // transmit SNDCP grant + m_rfTSBK.setLCO(TSBK_OSP_SNDCP_CH_GNT); + writeRF_TSDU_SBF(false, true, net); + + m_rfTSBK.setLCO(lco); + return true; + } + if (grp) { if (!net) { ::ActivityLog("P25", true, "group grant request from %u to TG %u", m_rfTSBK.getSrcId(), m_rfTSBK.getDstId()); diff --git a/p25/TrunkPacket.h b/p25/TrunkPacket.h index b74c4ea4..70707ba1 100644 --- a/p25/TrunkPacket.h +++ b/p25/TrunkPacket.h @@ -196,7 +196,7 @@ namespace p25 void queueRF_TSBK_Ctrl(uint8_t lco); /// Helper to write a grant packet. - bool writeRF_TSDU_Grant(bool grp, bool skip = false, bool net = false); + bool writeRF_TSDU_Grant(bool grp, bool skip = false, bool net = false, bool sndcpGrant = false); /// Helper to write a unit to unit answer request packet. void writeRF_TSDU_UU_Ans_Req(uint32_t srcId, uint32_t dstId); /// Helper to write a acknowledge packet. diff --git a/p25/lc/TSBK.cpp b/p25/lc/TSBK.cpp index 599687d4..4162aa7c 100644 --- a/p25/lc/TSBK.cpp +++ b/p25/lc/TSBK.cpp @@ -590,6 +590,26 @@ void TSBK::encode(uint8_t* data, bool rawTSBK, bool noTrellis) tsbkValue = (tsbkValue << 32) + m_dstId; // Target Radio Address tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address break; + case TSBK_OSP_SNDCP_CH_GNT: + { + uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125); + float calcTxOffset = m_siteIdenEntry.txOffsetMhz() * 1000000; + + uint32_t txFrequency = (uint32_t)((m_siteIdenEntry.baseFrequency() + ((calcSpace * 125) * m_dataChannelNo))); + uint32_t rxFrequency = (uint32_t)(txFrequency + calcTxOffset); + + uint32_t rootFreq = rxFrequency - m_siteIdenEntry.baseFrequency(); + uint32_t rxChNo = rootFreq / (m_siteIdenEntry.chSpaceKhz() * 1000); + + tsbkValue = 0U; + tsbkValue = (tsbkValue << 8) + m_dataServiceOptions; // Data Service Options + tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel (T) ID + tsbkValue = (tsbkValue << 12) + m_dataChannelNo; // Channel (T) Number + tsbkValue = (tsbkValue << 4) + m_siteData.channelId(); // Channel (R) ID + tsbkValue = (tsbkValue << 12) + (rxChNo & 0xFFFU); // Channel (R) Number + tsbkValue = (tsbkValue << 24) + m_dstId; // Target Radio Address + } + break; case TSBK_IOSP_STS_UPDT: tsbkValue = 0U; tsbkValue = (tsbkValue << 16) + m_statusValue; // Status Value @@ -1111,6 +1131,9 @@ TSBK::TSBK(SiteData siteData) : m_messageValue(0U), m_statusValue(0U), m_extendedFunction(P25_EXT_FNCT_CHECK), + m_dataServiceOptions(0U), + m_dataAccessControl(0U), + m_dataChannelNo(0U), m_adjCFVA(P25_CFVA_FAILURE), m_adjRfssId(0U), m_adjSiteId(0U), @@ -1176,6 +1199,8 @@ void TSBK::copy(const TSBK& data) m_extendedFunction = data.m_extendedFunction; + m_dataChannelNo = data.m_dataChannelNo; + m_adjCFVA = data.m_adjCFVA; m_adjRfssId = data.m_adjRfssId; m_adjSiteId = data.m_adjSiteId; diff --git a/p25/lc/TSBK.h b/p25/lc/TSBK.h index 610ba158..8d4e0c6c 100644 --- a/p25/lc/TSBK.h +++ b/p25/lc/TSBK.h @@ -148,6 +148,9 @@ namespace p25 /// SNDCP Data Access Control __PROPERTY(uint32_t, dataAccessControl, DataAccessControl); + /// SNDCP grant channel number. + __PROPERTY(uint32_t, dataChannelNo, DataChnNo); + /** Adjacent Site Data */ /// Adjacent site CFVA flags. __PROPERTY(uint8_t, adjCFVA, AdjSiteCFVA);