From 471a00fa04c957acd18a779d5b427f87a6070905 Mon Sep 17 00:00:00 2001 From: Bryan Biedenkapp Date: Sun, 16 Oct 2022 12:15:31 -0400 Subject: [PATCH] refactor TDULC into factory code pattern; --- CMakeLists.txt | 11 + p25/Control.cpp | 2 - p25/dfsi/packet/DFSITrunk.cpp | 2 +- p25/dfsi/packet/DFSITrunk.h | 2 +- p25/lc/TDULC.cpp | 340 +++++---------------------- p25/lc/TDULC.h | 71 +++--- p25/lc/tdulc/LC_ADJ_STS_BCAST.cpp | 123 ++++++++++ p25/lc/tdulc/LC_ADJ_STS_BCAST.h | 75 ++++++ p25/lc/tdulc/LC_CALL_TERM.cpp | 81 +++++++ p25/lc/tdulc/LC_CALL_TERM.h | 57 +++++ p25/lc/tdulc/LC_CONV_FALLBACK.cpp | 83 +++++++ p25/lc/tdulc/LC_CONV_FALLBACK.h | 57 +++++ p25/lc/tdulc/LC_GROUP.cpp | 99 ++++++++ p25/lc/tdulc/LC_GROUP.h | 57 +++++ p25/lc/tdulc/LC_GROUP_UPDT.cpp | 85 +++++++ p25/lc/tdulc/LC_GROUP_UPDT.h | 57 +++++ p25/lc/tdulc/LC_IDEN_UP.cpp | 121 ++++++++++ p25/lc/tdulc/LC_IDEN_UP.h | 57 +++++ p25/lc/tdulc/LC_NET_STS_BCAST.cpp | 84 +++++++ p25/lc/tdulc/LC_NET_STS_BCAST.h | 57 +++++ p25/lc/tdulc/LC_PRIVATE.cpp | 99 ++++++++ p25/lc/tdulc/LC_PRIVATE.h | 57 +++++ p25/lc/tdulc/LC_RFSS_STS_BCAST.cpp | 86 +++++++ p25/lc/tdulc/LC_RFSS_STS_BCAST.h | 57 +++++ p25/lc/tdulc/LC_SYS_SRV_BCAST.cpp | 84 +++++++ p25/lc/tdulc/LC_SYS_SRV_BCAST.h | 57 +++++ p25/lc/tdulc/LC_TEL_INT_VCH_USER.cpp | 101 ++++++++ p25/lc/tdulc/LC_TEL_INT_VCH_USER.h | 57 +++++ p25/lc/tdulc/TDULCFactory.cpp | 136 +++++++++++ p25/lc/tdulc/TDULCFactory.h | 76 ++++++ p25/packet/Trunk.cpp | 61 +++-- p25/packet/Trunk.h | 6 +- p25/packet/Voice.cpp | 8 +- 33 files changed, 2043 insertions(+), 363 deletions(-) create mode 100644 p25/lc/tdulc/LC_ADJ_STS_BCAST.cpp create mode 100644 p25/lc/tdulc/LC_ADJ_STS_BCAST.h create mode 100644 p25/lc/tdulc/LC_CALL_TERM.cpp create mode 100644 p25/lc/tdulc/LC_CALL_TERM.h create mode 100644 p25/lc/tdulc/LC_CONV_FALLBACK.cpp create mode 100644 p25/lc/tdulc/LC_CONV_FALLBACK.h create mode 100644 p25/lc/tdulc/LC_GROUP.cpp create mode 100644 p25/lc/tdulc/LC_GROUP.h create mode 100644 p25/lc/tdulc/LC_GROUP_UPDT.cpp create mode 100644 p25/lc/tdulc/LC_GROUP_UPDT.h create mode 100644 p25/lc/tdulc/LC_IDEN_UP.cpp create mode 100644 p25/lc/tdulc/LC_IDEN_UP.h create mode 100644 p25/lc/tdulc/LC_NET_STS_BCAST.cpp create mode 100644 p25/lc/tdulc/LC_NET_STS_BCAST.h create mode 100644 p25/lc/tdulc/LC_PRIVATE.cpp create mode 100644 p25/lc/tdulc/LC_PRIVATE.h create mode 100644 p25/lc/tdulc/LC_RFSS_STS_BCAST.cpp create mode 100644 p25/lc/tdulc/LC_RFSS_STS_BCAST.h create mode 100644 p25/lc/tdulc/LC_SYS_SRV_BCAST.cpp create mode 100644 p25/lc/tdulc/LC_SYS_SRV_BCAST.h create mode 100644 p25/lc/tdulc/LC_TEL_INT_VCH_USER.cpp create mode 100644 p25/lc/tdulc/LC_TEL_INT_VCH_USER.h create mode 100644 p25/lc/tdulc/TDULCFactory.cpp create mode 100644 p25/lc/tdulc/TDULCFactory.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2266788c..56525117 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -33,6 +33,8 @@ file(GLOB dvmhost_SRC "p25/edac/*.cpp" "p25/lc/*.h" "p25/lc/*.cpp" + "p25/lc/tdulc/*.h" + "p25/lc/tdulc/*.cpp" "p25/lc/tsbk/*.h" "p25/lc/tsbk/*.cpp" "p25/lookups/*.h" @@ -105,6 +107,7 @@ option(ENABLE_DMR "Enable DMR Digtial Mode" on) option(ENABLE_P25 "Enable P25 Digital Mode" on) option(ENABLE_NXDN "Enable NXDN Digital Mode" off) option(ENABLE_DFSI_SUPPORT "Enable P25 DFSI Transport Support" off) +option(ENABLE_TESTS "Enable compilation of test suite" off) message(CHECK_START "DMR Digital Mode") if (ENABLE_DMR) @@ -134,6 +137,12 @@ if (ENABLE_DFSI_SUPPORT) else () message(CHECK_PASS "disabled") endif (ENABLE_DFSI_SUPPORT) +message(CHECK_START "Enable test suite compilation") +if (ENABLE_TESTS) + message(CHECK_PASS "enabled") +else () + message(CHECK_PASS "disabled") +endif (ENABLE_TESTS) # debug options option(DEBUG_DMR_PDU_DATA "" off) @@ -267,6 +276,7 @@ add_executable(dvmcmd ${dvmcmd_SRC}) target_link_libraries(dvmcmd PRIVATE Threads::Threads) target_include_directories(dvmcmd PRIVATE .) +if (ENABLE_TESTS) project(dvmtest) Include(FetchContent) @@ -281,3 +291,4 @@ find_package(Threads REQUIRED) add_executable(dvmtests ${dvmtests_SRC}) target_link_libraries(dvmtests PRIVATE Catch2::Catch2WithMain Threads::Threads util) target_include_directories(dvmtests PRIVATE .) +endif (ENABLE_TESTS) diff --git a/p25/Control.cpp b/p25/Control.cpp index 7b60bcba..13e28926 100644 --- a/p25/Control.cpp +++ b/p25/Control.cpp @@ -300,8 +300,6 @@ void Control::setOptions(yaml::Node& conf, const std::string cwCallsign, const s } } - lc::TDULC::setIdenEntry(m_idenEntry); - std::vector availCh = voiceChNo; m_siteData.setChCnt((uint8_t)availCh.size()); diff --git a/p25/dfsi/packet/DFSITrunk.cpp b/p25/dfsi/packet/DFSITrunk.cpp index 96c5554f..ddc5c12e 100644 --- a/p25/dfsi/packet/DFSITrunk.cpp +++ b/p25/dfsi/packet/DFSITrunk.cpp @@ -101,7 +101,7 @@ DFSITrunk::~DFSITrunk() /// /// /// -void DFSITrunk::writeRF_TDULC(lc::TDULC lc, bool noNetwork) +void DFSITrunk::writeRF_TDULC(lc::TDULC* lc, bool noNetwork) { // for now this is ignored... } diff --git a/p25/dfsi/packet/DFSITrunk.h b/p25/dfsi/packet/DFSITrunk.h index cac6fc4e..075ecb34 100644 --- a/p25/dfsi/packet/DFSITrunk.h +++ b/p25/dfsi/packet/DFSITrunk.h @@ -65,7 +65,7 @@ namespace p25 virtual ~DFSITrunk(); /// Helper to write a P25 TDU w/ link control packet. - virtual void writeRF_TDULC(lc::TDULC lc, bool noNetwork); + virtual void writeRF_TDULC(lc::TDULC* lc, bool noNetwork); /// Helper to write a single-block P25 TSDU packet. virtual void writeRF_TSDU_SBF(lc::TSBK* tsbk, bool noNetwork, bool clearBeforeWrite = false, bool force = false); diff --git a/p25/lc/TDULC.cpp b/p25/lc/TDULC.cpp index dd558dd4..5d917b08 100644 --- a/p25/lc/TDULC.cpp +++ b/p25/lc/TDULC.cpp @@ -47,7 +47,6 @@ using namespace p25; bool TDULC::m_verbose = false; SiteData TDULC::m_siteData = SiteData(); -::lookups::IdenTable TDULC::m_siteIdenEntry = ::lookups::IdenTable(); // --------------------------------------------------------------------------- // Public Class Members @@ -96,17 +95,13 @@ TDULC::TDULC() : 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_siteIdenEntry(lookups::IdenTable()), m_rs(), + m_implicit(false), m_callTimer(0U) { m_grpVchNo = m_siteData.channelNo(); @@ -120,31 +115,66 @@ TDULC::~TDULC() /* stub */ } +// --------------------------------------------------------------------------- +// Private Class Members +// --------------------------------------------------------------------------- + /// -/// Equals operator. +/// Internal helper to convert RS bytes to a 64-bit long value. /// -/// +/// /// -TDULC& TDULC::operator=(const TDULC& data) +ulong64_t TDULC::toValue(const uint8_t* rs) { - if (this != &data) { - copy(data); - } + ulong64_t rsValue = 0U; + + // combine bytes into ulong64_t (8 byte) value + rsValue = rs[1U]; + rsValue = (rsValue << 8) + rs[2U]; + rsValue = (rsValue << 8) + rs[3U]; + rsValue = (rsValue << 8) + rs[4U]; + rsValue = (rsValue << 8) + rs[5U]; + rsValue = (rsValue << 8) + rs[6U]; + rsValue = (rsValue << 8) + rs[7U]; + rsValue = (rsValue << 8) + rs[8U]; - return *this; + return rsValue; } /// -/// Decode a terminator data unit w/ link control. +/// Internal helper to convert a 64-bit long value to RS bytes. +/// +/// +/// +std::unique_ptr TDULC::fromValue(const ulong64_t rsValue) +{ + __UNIQUE_BUFFER(rs, uint8_t, P25_TDULC_LENGTH_BYTES); + + // split ulong64_t (8 byte) value into bytes + rs[1U] = (uint8_t)((rsValue >> 56) & 0xFFU); + rs[2U] = (uint8_t)((rsValue >> 48) & 0xFFU); + rs[3U] = (uint8_t)((rsValue >> 40) & 0xFFU); + rs[4U] = (uint8_t)((rsValue >> 32) & 0xFFU); + rs[5U] = (uint8_t)((rsValue >> 24) & 0xFFU); + rs[6U] = (uint8_t)((rsValue >> 16) & 0xFFU); + rs[7U] = (uint8_t)((rsValue >> 8) & 0xFFU); + rs[8U] = (uint8_t)((rsValue >> 0) & 0xFFU); + + return rs; +} + +/// +/// Internal helper to decode a terminator data unit w/ link control. /// /// +/// /// True, if TDULC was decoded, otherwise false. -bool TDULC::decode(const uint8_t* data) +bool TDULC::decode(const uint8_t* data, uint8_t* rs) { assert(data != nullptr); + assert(rs != nullptr); // deinterleave - uint8_t rs[P25_TDULC_LENGTH_BYTES + 1U]; uint8_t raw[P25_TDULC_FEC_LENGTH_BYTES + 1U]; P25Utils::decode(data, raw, 114U, 410U); @@ -172,39 +202,42 @@ bool TDULC::decode(const uint8_t* data) Utils::dump(2U, "Decoded TDULC", rs, P25_TDULC_LENGTH_BYTES); } - return decodeLC(rs); + return true; } /// -/// Encode a terminator data unit w/ link control. +/// Internal helper to encode a terminator data unit w/ link control. /// /// -/// True, if TDULC was decoded, otherwise false. -void TDULC::encode(uint8_t * data) +/// +void TDULC::encode(uint8_t* data, const uint8_t* rs) { assert(data != nullptr); - - uint8_t rs[P25_TDULC_LENGTH_BYTES]; - ::memset(rs, 0x00U, P25_TDULC_LENGTH_BYTES); - - encodeLC(rs); + assert(rs != nullptr); if (m_verbose) { Utils::dump(2U, "Encoded TDULC", rs, P25_TDULC_LENGTH_BYTES); } + uint8_t outRs[P25_TDULC_LENGTH_BYTES]; + ::memset(outRs, 0x00U, P25_TDULC_LENGTH_BYTES); + ::memcpy(outRs, rs, P25_TDULC_LENGTH_BYTES); + + if (m_implicit) + outRs[0U] |= 0x40U; // Implicit Operation + // encode RS (24,12,13) FEC - m_rs.encode241213(rs); + m_rs.encode241213(outRs); #if DEBUG_P25_TDULC - Utils::dump(2U, "TDULC::encode(), TDULC RS", rs, P25_TDULC_LENGTH_BYTES); + Utils::dump(2U, "TDULC::encode(), TDULC RS", outRs, P25_TDULC_LENGTH_BYTES); #endif uint8_t raw[P25_TDULC_FEC_LENGTH_BYTES + 1U]; ::memset(raw, 0x00U, P25_TDULC_FEC_LENGTH_BYTES + 1U); // encode Golay (24,12,8) FEC - edac::Golay24128::encode24128(raw, rs, P25_TDULC_LENGTH_BYTES); + edac::Golay24128::encode24128(raw, outRs, P25_TDULC_LENGTH_BYTES); // interleave P25Utils::encode(raw, data, 114U, 410U); @@ -214,10 +247,6 @@ void TDULC::encode(uint8_t * data) #endif } -// --------------------------------------------------------------------------- -// Private Class Members -// --------------------------------------------------------------------------- - /// /// Internal helper to copy the the class. /// @@ -234,13 +263,6 @@ void TDULC::copy(const TDULC& data) 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; @@ -252,241 +274,3 @@ void TDULC::copy(const TDULC& data) m_siteData = data.m_siteData; m_siteIdenEntry = data.m_siteIdenEntry; } - -/// -/// Decode link control. -/// -/// -/// -bool TDULC::decodeLC(const uint8_t* rs) -{ - ulong64_t rsValue = 0U; - - // combine bytes into ulong64_t (8 byte) value - rsValue = rs[1U]; - rsValue = (rsValue << 8) + rs[2U]; - rsValue = (rsValue << 8) + rs[3U]; - rsValue = (rsValue << 8) + rs[4U]; - rsValue = (rsValue << 8) + rs[5U]; - rsValue = (rsValue << 8) + rs[6U]; - rsValue = (rsValue << 8) + rs[7U]; - rsValue = (rsValue << 8) + rs[8U]; - - m_protect = (rs[0U] & 0x80U) == 0x80U; // Protect Flag - m_lco = rs[0U] & 0x3FU; // LCO - - // standard P25 reference opcodes - switch (m_lco) { - case LC_GROUP: - m_mfId = rs[1U]; // Mfg Id. - m_group = true; - m_emergency = (rs[2U] & 0x80U) == 0x80U; // Emergency Flag - m_encrypted = (rs[2U] & 0x40U) == 0x40U; // Encryption Flag - m_priority = (rs[2U] & 0x07U); // Priority - m_dstId = (uint32_t)((rsValue >> 24) & 0xFFFFU); // Talkgroup Address - m_srcId = (uint32_t)(rsValue & 0xFFFFFFU); // Source Radio Address - break; - case LC_PRIVATE: - m_mfId = rs[1U]; // Mfg Id. - m_group = false; - m_emergency = (rs[2U] & 0x80U) == 0x80U; // Emergency Flag - m_encrypted = (rs[2U] & 0x40U) == 0x40U; // Encryption Flag - m_priority = (rs[2U] & 0x07U); // Priority - m_dstId = (uint32_t)((rsValue >> 24) & 0xFFFFFFU); // Target Radio Address - m_srcId = (uint32_t)(rsValue & 0xFFFFFFU); // Source Radio Address - break; - case LC_TEL_INT_VCH_USER: - m_emergency = (rs[2U] & 0x80U) == 0x80U; // Emergency Flag - m_encrypted = (rs[2U] & 0x40U) == 0x40U; // Encryption Flag - m_priority = (rs[2U] & 0x07U); // Priority - m_callTimer = (uint32_t)((rsValue >> 24) & 0xFFFFU); // Call Timer - if (m_srcId == 0U) { - m_srcId = (uint32_t)(rsValue & 0xFFFFFFU); // Source/Target Address - } - break; - default: - LogError(LOG_P25, "TDULC::decodeLC(), unknown LC value, mfId = $%02X, lco = $%02X", m_mfId, m_lco); - return false; - } - - // sanity check priority (per TIA-102.AABC-B) it should never be 0, if its 0, default to 4 - if (m_priority == 0) { - m_priority = 4U; - } - - return true; -} - -/// -/// Encode link control. -/// -/// -void TDULC::encodeLC(uint8_t* rs) -{ - 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 - - // standard P25 reference opcodes - switch (m_lco) { - case LC_GROUP: - rsValue = m_mfId; - rsValue = (rsValue << 8) + - (m_emergency ? 0x80U : 0x00U) + // Emergency Flag - (m_encrypted ? 0x40U : 0x00U) + // Encrypted Flag - (m_priority & 0x07U); // Priority - rsValue = (rsValue << 24) + m_dstId; // Talkgroup Address - rsValue = (rsValue << 24) + m_srcId; // Source Radio Address - break; - case LC_GROUP_UPDT: - rs[0U] |= 0x40U; // Implicit Operation - rsValue = m_siteData.channelId(); // Group A - Channel ID - rsValue = (rsValue << 12) + m_grpVchNo; // Group A - Channel Number - rsValue = (rsValue << 16) + m_dstId; // Group A - Talkgroup Address - rsValue = (rsValue << 4) + m_siteData.channelId(); // Group B - Channel ID - rsValue = (rsValue << 12) + m_grpVchNo; // Group B - Channel Number - rsValue = (rsValue << 16) + m_dstId; // Group B - Talkgroup Address - break; - case LC_PRIVATE: - rsValue = m_mfId; - rsValue = (rsValue << 8) + - (m_emergency ? 0x80U : 0x00U) + // Emergency Flag - (m_encrypted ? 0x40U : 0x00U) + // Encrypted Flag - (m_priority & 0x07U); // Priority - rsValue = (rsValue << 24) + m_dstId; // Target Radio Address - rsValue = (rsValue << 24) + m_srcId; // Source Radio Address - break; - case LC_TEL_INT_VCH_USER: - rs[0U] |= 0x40U; // Implicit Operation - rsValue = (rsValue << 8) + - (m_emergency ? 0x80U : 0x00U) + // Emergency Flag - (m_encrypted ? 0x40U : 0x00U) + // Encrypted Flag - (m_priority & 0x07U); // Priority - rsValue = (rsValue << 16) + m_callTimer; // Call Timer - rsValue = (rsValue << 24) + m_srcId; // Source/Target Radio Address - break; - case LC_CALL_TERM: - rs[0U] |= 0x40U; // Implicit Operation - rsValue = 0U; - rsValue = (rsValue << 24) + P25_WUID_FNE; // System Radio Address - break; - case LC_IDEN_UP: - rs[0U] |= 0x40U; // Implicit Operation - { - if ((m_siteIdenEntry.chBandwidthKhz() != 0.0F) && (m_siteIdenEntry.chSpaceKhz() != 0.0F) && - (m_siteIdenEntry.txOffsetMhz() != 0U) && (m_siteIdenEntry.baseFrequency() != 0U)) { - if (m_siteIdenEntry.baseFrequency() < 762000000U) { - uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125); - - float fCalcTxOffset = (fabs(m_siteIdenEntry.txOffsetMhz()) / m_siteIdenEntry.chSpaceKhz()) * 1000.0F; - uint32_t uCalcTxOffset = (uint32_t)fCalcTxOffset; - if (m_siteIdenEntry.txOffsetMhz() > 0.0F) - uCalcTxOffset |= 0x2000U; // this sets a positive offset ... - - uint32_t calcBaseFreq = (uint32_t)(m_siteIdenEntry.baseFrequency() / 5); - uint8_t chanBw = (m_siteIdenEntry.chBandwidthKhz() >= 12.5F) ? P25_IDEN_UP_VU_BW_125K : P25_IDEN_UP_VU_BW_625K; - - rsValue = m_siteIdenEntry.channelId(); // Channel ID - rsValue = (rsValue << 4) + chanBw; // Channel Bandwidth - rsValue = (rsValue << 14) + uCalcTxOffset; // Transmit Offset - rsValue = (rsValue << 10) + calcSpace; // Channel Spacing - rsValue = (rsValue << 32) + calcBaseFreq; // Base Frequency - } else { - uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125); - - float fCalcTxOffset = (fabs(m_siteIdenEntry.txOffsetMhz()) * 1000000.0F) / 250000.0F; - uint32_t uCalcTxOffset = (uint32_t)fCalcTxOffset; - if (m_siteIdenEntry.txOffsetMhz() > 0.0F) - uCalcTxOffset |= 0x2000U; // this sets a positive offset ... - - uint32_t calcBaseFreq = (uint32_t)(m_siteIdenEntry.baseFrequency() / 5); - uint16_t chanBw = (uint16_t)((m_siteIdenEntry.chBandwidthKhz() * 1000) / 125); - - rsValue = m_siteIdenEntry.channelId(); // Channel ID - rsValue = (rsValue << 4) + chanBw; // Channel Bandwidth - rsValue = (rsValue << 14) + uCalcTxOffset; // Transmit Offset - rsValue = (rsValue << 10) + calcSpace; // Channel Spacing - rsValue = (rsValue << 32) + calcBaseFreq; // Base Frequency - } - } - else { - LogError(LOG_P25, "TDULC::encodeLC(), invalid values for LC_IDEN_UP, baseFrequency = %uHz, txOffsetMhz = %fMHz, chBandwidthKhz = %fKHz, chSpaceKhz = %fKHz", - m_siteIdenEntry.baseFrequency(), m_siteIdenEntry.txOffsetMhz(), m_siteIdenEntry.chBandwidthKhz(), - m_siteIdenEntry.chSpaceKhz()); - return; // blatently ignore creating this TSBK - } - } - break; - case LC_SYS_SRV_BCAST: - rs[0U] |= 0x40U; // Implicit Operation - rsValue = 0U; - rsValue = (rsValue << 16) + services; // System Services Available - rsValue = (rsValue << 24) + services; // System Services Supported - break; - case LC_ADJ_STS_BCAST: - rs[0U] |= 0x40U; // Implicit Operation - { - if ((m_adjRfssId != 0U) && (m_adjSiteId != 0U) && (m_adjChannelNo != 0U)) { - if (m_adjSysId == 0U) { - m_adjSysId = m_siteData.sysId(); - } - - rsValue = m_siteData.lra(); // Location Registration Area - rsValue = (rsValue << 12) + m_adjSysId; // System ID - rsValue = (rsValue << 8) + m_adjRfssId; // RF Sub-System ID - 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_adjServiceClass; // System Service Class - } - else { - LogError(LOG_P25, "TDULC::encodeLC(), invalid values for LC_ADJ_STS_BCAST, tsbkAdjSiteRFSSId = $%02X, tsbkAdjSiteId = $%02X, tsbkAdjSiteChannel = $%02X", - m_adjRfssId, m_adjSiteId, m_adjChannelNo); - return; // blatently ignore creating this TSBK - } - } - break; - case LC_RFSS_STS_BCAST: - rs[0U] |= 0x40U; // Implicit Operation - rsValue = m_siteData.lra(); // Location Registration Area - rsValue = (rsValue << 12) + m_siteData.sysId(); // System ID - rsValue = (rsValue << 8) + m_siteData.rfssId(); // RF Sub-System ID - 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_siteData.serviceClass(); // System Service Class - break; - case LC_NET_STS_BCAST: - rs[0U] |= 0x40U; // Implicit Operation - rsValue = 0U; - rsValue = (rsValue << 20) + m_siteData.netId(); // Network ID - 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_siteData.serviceClass(); // System Service Class - break; - case LC_CONV_FALLBACK: - rsValue = 0U; - rsValue = (rsValue << 48) + m_siteData.channelId(); // Channel ID 6 - rsValue = (rsValue << 40) + m_siteData.channelId(); // Channel ID 5 - rsValue = (rsValue << 32) + m_siteData.channelId(); // Channel ID 4 - rsValue = (rsValue << 24) + m_siteData.channelId(); // Channel ID 3 - rsValue = (rsValue << 16) + m_siteData.channelId(); // Channel ID 2 - rsValue = (rsValue << 8) + m_siteData.channelId(); // Channel ID 1 - break; - default: - LogError(LOG_P25, "TDULC::encodeLC(), unknown LC value, mfId = $%02X, lco = $%02X", m_mfId, m_lco); - break; - } - - // split ulong64_t (8 byte) value into bytes - rs[1U] = (uint8_t)((rsValue >> 56) & 0xFFU); - rs[2U] = (uint8_t)((rsValue >> 48) & 0xFFU); - rs[3U] = (uint8_t)((rsValue >> 40) & 0xFFU); - rs[4U] = (uint8_t)((rsValue >> 32) & 0xFFU); - rs[5U] = (uint8_t)((rsValue >> 24) & 0xFFU); - rs[6U] = (uint8_t)((rsValue >> 16) & 0xFFU); - rs[7U] = (uint8_t)((rsValue >> 8) & 0xFFU); - rs[8U] = (uint8_t)((rsValue >> 0) & 0xFFU); -} diff --git a/p25/lc/TDULC.h b/p25/lc/TDULC.h index 6d9750b9..be0594fc 100644 --- a/p25/lc/TDULC.h +++ b/p25/lc/TDULC.h @@ -61,15 +61,12 @@ namespace p25 /// Initializes a new instance of the TDULC class. TDULC(); /// Finalizes a instance of the TDULC class. - ~TDULC(); - - /// Equals operator. - TDULC& operator=(const TDULC& data); + virtual ~TDULC(); /// Decode a terminator data unit w/ link control. - bool decode(const uint8_t* data); + virtual bool decode(const uint8_t* data) = 0; /// Encode a terminator data unit w/ link control. - void encode(uint8_t* data); + virtual void encode(uint8_t* data) = 0; /// Sets the flag indicating verbose log output. static void setVerbose(bool verbose) { m_verbose = verbose; } @@ -79,74 +76,62 @@ namespace p25 static SiteData getSiteData() { return m_siteData; } /// Sets the local site data. static void setSiteData(SiteData siteData) { m_siteData = siteData; } - /// Gets the local site identity entry. - static ::lookups::IdenTable getIdenEntry() { return m_siteIdenEntry; } - /// Sets the local site identity entry. - static void setIdenEntry(::lookups::IdenTable entry) { m_siteIdenEntry = entry; } public: /** Common Data */ /// Flag indicating the link control data is protected. - __PROPERTY(bool, protect, Protect); + __PROTECTED_PROPERTY(bool, protect, Protect); /// Link control opcode. - __PROPERTY(uint8_t, lco, LCO); + __PROTECTED_PROPERTY(uint8_t, lco, LCO); /// Manufacturer ID. - __PROPERTY(uint8_t, mfId, MFId); + __PROTECTED_PROPERTY(uint8_t, mfId, MFId); /// Source ID. - __PROPERTY(uint32_t, srcId, SrcId); + __PROTECTED_PROPERTY(uint32_t, srcId, SrcId); /// Destination ID. - __PROPERTY(uint32_t, dstId, DstId); + __PROTECTED_PROPERTY(uint32_t, dstId, DstId); /// Voice channel number. - __PROPERTY(uint32_t, grpVchNo, GrpVchNo); - - /** Adjacent Site Data */ - /// Adjacent site CFVA flags. - __PROPERTY(uint8_t, adjCFVA, AdjSiteCFVA); - /// Adjacent site system ID. - __PROPERTY(uint32_t, adjSysId, AdjSiteSysId); - /// Adjacent site RFSS ID. - __PROPERTY(uint8_t, adjRfssId, AdjSiteRFSSId); - /// Adjacent site ID. - __PROPERTY(uint8_t, adjSiteId, AdjSiteId); - /// Adjacent site channel ID. - __PROPERTY(uint8_t, adjChannelId, AdjSiteChnId); - /// Adjacent site channel number. - __PROPERTY(uint32_t, adjChannelNo, AdjSiteChnNo); - /// Adjacent site service class. - __PROPERTY(uint8_t, adjServiceClass, AdjSiteSvcClass); + __PROTECTED_PROPERTY(uint32_t, grpVchNo, GrpVchNo); /** Service Options */ /// Flag indicating the emergency bits are set. - __PROPERTY(bool, emergency, Emergency); + __PROTECTED_PROPERTY(bool, emergency, Emergency); /// Flag indicating that encryption is enabled. - __PROPERTY(bool, encrypted, Encrypted); + __PROTECTED_PROPERTY(bool, encrypted, Encrypted); /// Priority level for the traffic. - __PROPERTY(uint8_t, priority, Priority); + __PROTECTED_PROPERTY(uint8_t, priority, Priority); /// Flag indicating a group/talkgroup operation. - __PROPERTY(bool, group, Group); + __PROTECTED_PROPERTY(bool, group, Group); + + /** Local Site data */ + /// Local Site Identity Entry. + __PROTECTED_PROPERTY_PLAIN(::lookups::IdenTable, siteIdenEntry, siteIdenEntry); protected: friend class LC; friend class TSBK; edac::RS634717 m_rs; + bool m_implicit; uint32_t m_callTimer; static bool m_verbose; /** Local Site data */ static SiteData m_siteData; - static ::lookups::IdenTable m_siteIdenEntry; - /// Internal helper to copy the class. - void copy(const TDULC& data); + /// Internal helper to convert RS bytes to a 64-bit long value. + static ulong64_t toValue(const uint8_t* rs); + /// Internal helper to convert a 64-bit long value to RS bytes. + static std::unique_ptr fromValue(const ulong64_t rsValue); + + /// Internal helper to decode terminator data unit w/ link control. + bool decode(const uint8_t* data, uint8_t* rs); + /// Internal helper to encode terminator data unit w/ link control. + void encode(uint8_t* data, const uint8_t* rs); - /// Decode link control. - bool decodeLC(const uint8_t* rs); - /// Encode link control. - void encodeLC(uint8_t* rs); + __PROTECTED_COPY(TDULC); }; } // namespace lc } // namespace p25 diff --git a/p25/lc/tdulc/LC_ADJ_STS_BCAST.cpp b/p25/lc/tdulc/LC_ADJ_STS_BCAST.cpp new file mode 100644 index 00000000..92d0821f --- /dev/null +++ b/p25/lc/tdulc/LC_ADJ_STS_BCAST.cpp @@ -0,0 +1,123 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "Defines.h" +#include "p25/lc/tdulc/LC_ADJ_STS_BCAST.h" +#include "Log.h" +#include "Utils.h" + +using namespace p25::lc::tdulc; +using namespace p25::lc; +using namespace p25; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the LC_ADJ_STS_BCAST class. +/// +LC_ADJ_STS_BCAST::LC_ADJ_STS_BCAST() : TDULC(), + m_adjCFVA(P25_CFVA_FAILURE), + m_adjRfssId(0U), + m_adjSiteId(0U), + m_adjChannelId(0U), + m_adjChannelNo(0U), + m_adjServiceClass(P25_SVC_CLS_INVALID) +{ + m_lco = p25::LC_ADJ_STS_BCAST; +} + +/// +/// Decode a terminator data unit w/ link control. +/// +/// +/// True, if TDULC was decoded, otherwise false. +bool LC_ADJ_STS_BCAST::decode(const uint8_t* data) +{ + assert(data != NULL); + + /* stub */ + + return true; +} + +/// +/// Encode a terminator data unit w/ link control. +/// +/// +void LC_ADJ_STS_BCAST::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t rsValue = 0U; + + m_implicit = true; + + if ((m_adjRfssId != 0U) && (m_adjSiteId != 0U) && (m_adjChannelNo != 0U)) { + if (m_adjSysId == 0U) { + m_adjSysId = m_siteData.sysId(); + } + + rsValue = m_siteData.lra(); // Location Registration Area + rsValue = (rsValue << 12) + m_adjSysId; // System ID + rsValue = (rsValue << 8) + m_adjRfssId; // RF Sub-System ID + 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_adjServiceClass; // System Service Class + } + else { + LogError(LOG_P25, "TDULC::encodeLC(), invalid values for LC_ADJ_STS_BCAST, tsbkAdjSiteRFSSId = $%02X, tsbkAdjSiteId = $%02X, tsbkAdjSiteChannel = $%02X", + m_adjRfssId, m_adjSiteId, m_adjChannelNo); + return; // blatently ignore creating this TSBK + } + + std::unique_ptr rs = TDULC::fromValue(rsValue); + TDULC::encode(data, rs.get()); +} + +// --------------------------------------------------------------------------- +// Private Class Members +// --------------------------------------------------------------------------- + +/// +/// Internal helper to copy the the class. +/// +/// +void LC_ADJ_STS_BCAST::copy(const LC_ADJ_STS_BCAST& data) +{ + TDULC::copy(data); + + 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; +} diff --git a/p25/lc/tdulc/LC_ADJ_STS_BCAST.h b/p25/lc/tdulc/LC_ADJ_STS_BCAST.h new file mode 100644 index 00000000..b92f5ee7 --- /dev/null +++ b/p25/lc/tdulc/LC_ADJ_STS_BCAST.h @@ -0,0 +1,75 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#if !defined(__P25_LC_TSBK__LC_ADJ_STS_BCAST_H__) +#define __P25_LC_TSBK__LC_ADJ_STS_BCAST_H__ + +#include "Defines.h" +#include "p25/lc/TDULC.h" + +namespace p25 +{ + namespace lc + { + namespace tdulc + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements ADJ STS BCAST - Adjacent Site Status Broadcast + // --------------------------------------------------------------------------- + + class HOST_SW_API LC_ADJ_STS_BCAST : public TDULC { + public: + /// Initializes a new instance of the LC_ADJ_STS_BCAST class. + LC_ADJ_STS_BCAST(); + + /// Decode a terminator data unit w/ link control. + virtual bool decode(const uint8_t* data); + /// Encode a terminator data unit w/ link control. + virtual void encode(uint8_t* data); + + public: + /// Adjacent site CFVA flags. + __PROPERTY(uint8_t, adjCFVA, AdjSiteCFVA); + /// Adjacent site system ID. + __PROPERTY(uint32_t, adjSysId, AdjSiteSysId); + /// Adjacent site RFSS ID. + __PROPERTY(uint8_t, adjRfssId, AdjSiteRFSSId); + /// Adjacent site ID. + __PROPERTY(uint8_t, adjSiteId, AdjSiteId); + /// Adjacent site channel ID. + __PROPERTY(uint8_t, adjChannelId, AdjSiteChnId); + /// Adjacent site channel number. + __PROPERTY(uint32_t, adjChannelNo, AdjSiteChnNo); + /// Adjacent site service class. + __PROPERTY(uint8_t, adjServiceClass, AdjSiteSvcClass); + + __COPY(LC_ADJ_STS_BCAST); + }; + } // namespace tdulc + } // namespace lc +} // namespace p25 + +#endif // __P25_LC_TSBK__LC_ADJ_STS_BCAST_H__ diff --git a/p25/lc/tdulc/LC_CALL_TERM.cpp b/p25/lc/tdulc/LC_CALL_TERM.cpp new file mode 100644 index 00000000..1afaeb51 --- /dev/null +++ b/p25/lc/tdulc/LC_CALL_TERM.cpp @@ -0,0 +1,81 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "Defines.h" +#include "p25/lc/tdulc/LC_CALL_TERM.h" +#include "Log.h" +#include "Utils.h" + +using namespace p25::lc::tdulc; +using namespace p25::lc; +using namespace p25; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the LC_CALL_TERM class. +/// +LC_CALL_TERM::LC_CALL_TERM() : TDULC() +{ + m_lco = p25::LC_CALL_TERM; +} + +/// +/// Decode a terminator data unit w/ link control. +/// +/// +/// True, if TDULC was decoded, otherwise false. +bool LC_CALL_TERM::decode(const uint8_t* data) +{ + assert(data != NULL); + + /* stub */ + + return true; +} + +/// +/// Encode a terminator data unit w/ link control. +/// +/// +void LC_CALL_TERM::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t rsValue = 0U; + + m_implicit = true; + + rsValue = 0U; + rsValue = (rsValue << 24) + P25_WUID_FNE; // System Radio Address + + std::unique_ptr rs = TDULC::fromValue(rsValue); + TDULC::encode(data, rs.get()); +} diff --git a/p25/lc/tdulc/LC_CALL_TERM.h b/p25/lc/tdulc/LC_CALL_TERM.h new file mode 100644 index 00000000..2ad0ef5a --- /dev/null +++ b/p25/lc/tdulc/LC_CALL_TERM.h @@ -0,0 +1,57 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#if !defined(__P25_LC_TSBK__LC_CALL_TERM_H__) +#define __P25_LC_TSBK__LC_CALL_TERM_H__ + +#include "Defines.h" +#include "p25/lc/TDULC.h" + +namespace p25 +{ + namespace lc + { + namespace tdulc + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements CALL TERM - Call Termination or Cancellation + // --------------------------------------------------------------------------- + + class HOST_SW_API LC_CALL_TERM : public TDULC { + public: + /// Initializes a new instance of the LC_CALL_TERM class. + LC_CALL_TERM(); + + /// Decode a terminator data unit w/ link control. + virtual bool decode(const uint8_t* data); + /// Encode a terminator data unit w/ link control. + virtual void encode(uint8_t* data); + }; + } // namespace tdulc + } // namespace lc +} // namespace p25 + +#endif // __P25_LC_TSBK__LC_CALL_TERM_H__ diff --git a/p25/lc/tdulc/LC_CONV_FALLBACK.cpp b/p25/lc/tdulc/LC_CONV_FALLBACK.cpp new file mode 100644 index 00000000..48705197 --- /dev/null +++ b/p25/lc/tdulc/LC_CONV_FALLBACK.cpp @@ -0,0 +1,83 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "Defines.h" +#include "p25/lc/tdulc/LC_CONV_FALLBACK.h" +#include "Log.h" +#include "Utils.h" + +using namespace p25::lc::tdulc; +using namespace p25::lc; +using namespace p25; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the LC_CONV_FALLBACK class. +/// +LC_CONV_FALLBACK::LC_CONV_FALLBACK() : TDULC() +{ + m_lco = p25::LC_CONV_FALLBACK; +} + +/// +/// Decode a terminator data unit w/ link control. +/// +/// +/// True, if TDULC was decoded, otherwise false. +bool LC_CONV_FALLBACK::decode(const uint8_t* data) +{ + assert(data != NULL); + + /* stub */ + + return true; +} + +/// +/// Encode a terminator data unit w/ link control. +/// +/// +void LC_CONV_FALLBACK::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t rsValue = 0U; + + rsValue = (rsValue << 48) + m_siteData.channelId(); // Channel ID 6 + rsValue = (rsValue << 40) + m_siteData.channelId(); // Channel ID 5 + rsValue = (rsValue << 32) + m_siteData.channelId(); // Channel ID 4 + rsValue = (rsValue << 24) + m_siteData.channelId(); // Channel ID 3 + rsValue = (rsValue << 16) + m_siteData.channelId(); // Channel ID 2 + rsValue = (rsValue << 8) + m_siteData.channelId(); // Channel ID 1 + + std::unique_ptr rs = TDULC::fromValue(rsValue); + TDULC::encode(data, rs.get()); +} diff --git a/p25/lc/tdulc/LC_CONV_FALLBACK.h b/p25/lc/tdulc/LC_CONV_FALLBACK.h new file mode 100644 index 00000000..6b08f9bc --- /dev/null +++ b/p25/lc/tdulc/LC_CONV_FALLBACK.h @@ -0,0 +1,57 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#if !defined(__P25_LC_TSBK__LC_CONV_FALLBACK_H__) +#define __P25_LC_TSBK__LC_CONV_FALLBACK_H__ + +#include "Defines.h" +#include "p25/lc/TDULC.h" + +namespace p25 +{ + namespace lc + { + namespace tdulc + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements CONV FALLBACK - Conventional Fallback + // --------------------------------------------------------------------------- + + class HOST_SW_API LC_CONV_FALLBACK : public TDULC { + public: + /// Initializes a new instance of the LC_CONV_FALLBACK class. + LC_CONV_FALLBACK(); + + /// Decode a terminator data unit w/ link control. + virtual bool decode(const uint8_t* data); + /// Encode a terminator data unit w/ link control. + virtual void encode(uint8_t* data); + }; + } // namespace tdulc + } // namespace lc +} // namespace p25 + +#endif // __P25_LC_TSBK__LC_CONV_FALLBACK_H__ diff --git a/p25/lc/tdulc/LC_GROUP.cpp b/p25/lc/tdulc/LC_GROUP.cpp new file mode 100644 index 00000000..5f2e8269 --- /dev/null +++ b/p25/lc/tdulc/LC_GROUP.cpp @@ -0,0 +1,99 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "Defines.h" +#include "p25/lc/tdulc/LC_GROUP.h" +#include "Log.h" +#include "Utils.h" + +using namespace p25::lc::tdulc; +using namespace p25::lc; +using namespace p25; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the LC_GROUP class. +/// +LC_GROUP::LC_GROUP() : TDULC() +{ + m_lco = p25::LC_GROUP; +} + +/// +/// Decode a terminator data unit w/ link control. +/// +/// +/// True, if TDULC was decoded, otherwise false. +bool LC_GROUP::decode(const uint8_t* data) +{ + assert(data != NULL); + + uint8_t rs[P25_TDULC_LENGTH_BYTES + 1U]; + ::memset(rs, 0x00U, P25_TDULC_LENGTH_BYTES); + + bool ret = TDULC::decode(data, rs); + if (!ret) + return false; + + ulong64_t rsValue = TDULC::toValue(rs); + + m_mfId = rs[1U]; // Mfg Id. + m_group = true; + m_emergency = (rs[2U] & 0x80U) == 0x80U; // Emergency Flag + m_encrypted = (rs[2U] & 0x40U) == 0x40U; // Encryption Flag + m_priority = (rs[2U] & 0x07U); // Priority + m_dstId = (uint32_t)((rsValue >> 24) & 0xFFFFU); // Talkgroup Address + m_srcId = (uint32_t)(rsValue & 0xFFFFFFU); // Source Radio Address + + return true; +} + +/// +/// Encode a terminator data unit w/ link control. +/// +/// +void LC_GROUP::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t rsValue = 0U; + + rsValue = m_mfId; + rsValue = (rsValue << 8) + + (m_emergency ? 0x80U : 0x00U) + // Emergency Flag + (m_encrypted ? 0x40U : 0x00U) + // Encrypted Flag + (m_priority & 0x07U); // Priority + rsValue = (rsValue << 24) + m_dstId; // Talkgroup Address + rsValue = (rsValue << 24) + m_srcId; // Source Radio Address + + std::unique_ptr rs = TDULC::fromValue(rsValue); + TDULC::encode(data, rs.get()); +} diff --git a/p25/lc/tdulc/LC_GROUP.h b/p25/lc/tdulc/LC_GROUP.h new file mode 100644 index 00000000..cf542e93 --- /dev/null +++ b/p25/lc/tdulc/LC_GROUP.h @@ -0,0 +1,57 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#if !defined(__P25_LC_TSBK__LC_GROUP_H__) +#define __P25_LC_TSBK__LC_GROUP_H__ + +#include "Defines.h" +#include "p25/lc/TDULC.h" + +namespace p25 +{ + namespace lc + { + namespace tdulc + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements GRP VCH USER - Group Voice Channel User + // --------------------------------------------------------------------------- + + class HOST_SW_API LC_GROUP : public TDULC { + public: + /// Initializes a new instance of the LC_GROUP class. + LC_GROUP(); + + /// Decode a terminator data unit w/ link control. + virtual bool decode(const uint8_t* data); + /// Encode a terminator data unit w/ link control. + virtual void encode(uint8_t* data); + }; + } // namespace tdulc + } // namespace lc +} // namespace p25 + +#endif // __P25_LC_TSBK__LC_GROUP_H__ diff --git a/p25/lc/tdulc/LC_GROUP_UPDT.cpp b/p25/lc/tdulc/LC_GROUP_UPDT.cpp new file mode 100644 index 00000000..806581e6 --- /dev/null +++ b/p25/lc/tdulc/LC_GROUP_UPDT.cpp @@ -0,0 +1,85 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "Defines.h" +#include "p25/lc/tdulc/LC_GROUP_UPDT.h" +#include "Log.h" +#include "Utils.h" + +using namespace p25::lc::tdulc; +using namespace p25::lc; +using namespace p25; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the LC_GROUP_UPDT class. +/// +LC_GROUP_UPDT::LC_GROUP_UPDT() : TDULC() +{ + m_lco = p25::LC_GROUP_UPDT; +} + +/// +/// Decode a terminator data unit w/ link control. +/// +/// +/// True, if TDULC was decoded, otherwise false. +bool LC_GROUP_UPDT::decode(const uint8_t* data) +{ + assert(data != NULL); + + /* stub */ + + return true; +} + +/// +/// Encode a terminator data unit w/ link control. +/// +/// +void LC_GROUP_UPDT::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t rsValue = 0U; + + m_implicit = true; + + rsValue = m_siteData.channelId(); // Group A - Channel ID + rsValue = (rsValue << 12) + m_grpVchNo; // Group A - Channel Number + rsValue = (rsValue << 16) + m_dstId; // Group A - Talkgroup Address + rsValue = (rsValue << 4) + m_siteData.channelId(); // Group B - Channel ID + rsValue = (rsValue << 12) + m_grpVchNo; // Group B - Channel Number + rsValue = (rsValue << 16) + m_dstId; // Group B - Talkgroup Address + + std::unique_ptr rs = TDULC::fromValue(rsValue); + TDULC::encode(data, rs.get()); +} diff --git a/p25/lc/tdulc/LC_GROUP_UPDT.h b/p25/lc/tdulc/LC_GROUP_UPDT.h new file mode 100644 index 00000000..42a7b0ef --- /dev/null +++ b/p25/lc/tdulc/LC_GROUP_UPDT.h @@ -0,0 +1,57 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#if !defined(__P25_LC_TSBK__LC_GROUP_UPDT_H__) +#define __P25_LC_TSBK__LC_GROUP_UPDT_H__ + +#include "Defines.h" +#include "p25/lc/TDULC.h" + +namespace p25 +{ + namespace lc + { + namespace tdulc + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements GRP VCH UPDT - Group Voice Channel Update + // --------------------------------------------------------------------------- + + class HOST_SW_API LC_GROUP_UPDT : public TDULC { + public: + /// Initializes a new instance of the LC_GROUP_UPDT class. + LC_GROUP_UPDT(); + + /// Decode a terminator data unit w/ link control. + virtual bool decode(const uint8_t* data); + /// Encode a terminator data unit w/ link control. + virtual void encode(uint8_t* data); + }; + } // namespace tdulc + } // namespace lc +} // namespace p25 + +#endif // __P25_LC_TSBK__LC_GROUP_UPDT_H__ diff --git a/p25/lc/tdulc/LC_IDEN_UP.cpp b/p25/lc/tdulc/LC_IDEN_UP.cpp new file mode 100644 index 00000000..11e11d74 --- /dev/null +++ b/p25/lc/tdulc/LC_IDEN_UP.cpp @@ -0,0 +1,121 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "Defines.h" +#include "p25/lc/tdulc/LC_IDEN_UP.h" +#include "Log.h" +#include "Utils.h" + +using namespace p25::lc::tdulc; +using namespace p25::lc; +using namespace p25; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the LC_IDEN_UP class. +/// +LC_IDEN_UP::LC_IDEN_UP() : TDULC() +{ + m_lco = p25::LC_IDEN_UP; +} + +/// +/// Decode a terminator data unit w/ link control. +/// +/// +/// True, if TDULC was decoded, otherwise false. +bool LC_IDEN_UP::decode(const uint8_t* data) +{ + assert(data != NULL); + + /* stub */ + + return true; +} + +/// +/// Encode a terminator data unit w/ link control. +/// +/// +void LC_IDEN_UP::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t rsValue = 0U; + + m_implicit = true; + + if ((m_siteIdenEntry.chBandwidthKhz() != 0.0F) && (m_siteIdenEntry.chSpaceKhz() != 0.0F) && + (m_siteIdenEntry.txOffsetMhz() != 0U) && (m_siteIdenEntry.baseFrequency() != 0U)) { + if (m_siteIdenEntry.baseFrequency() < 762000000U) { + uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125); + + float fCalcTxOffset = (fabs(m_siteIdenEntry.txOffsetMhz()) / m_siteIdenEntry.chSpaceKhz()) * 1000.0F; + uint32_t uCalcTxOffset = (uint32_t)fCalcTxOffset; + if (m_siteIdenEntry.txOffsetMhz() > 0.0F) + uCalcTxOffset |= 0x2000U; // this sets a positive offset ... + + uint32_t calcBaseFreq = (uint32_t)(m_siteIdenEntry.baseFrequency() / 5); + uint8_t chanBw = (m_siteIdenEntry.chBandwidthKhz() >= 12.5F) ? P25_IDEN_UP_VU_BW_125K : P25_IDEN_UP_VU_BW_625K; + + rsValue = m_siteIdenEntry.channelId(); // Channel ID + rsValue = (rsValue << 4) + chanBw; // Channel Bandwidth + rsValue = (rsValue << 14) + uCalcTxOffset; // Transmit Offset + rsValue = (rsValue << 10) + calcSpace; // Channel Spacing + rsValue = (rsValue << 32) + calcBaseFreq; // Base Frequency + } else { + uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125); + + float fCalcTxOffset = (fabs(m_siteIdenEntry.txOffsetMhz()) * 1000000.0F) / 250000.0F; + uint32_t uCalcTxOffset = (uint32_t)fCalcTxOffset; + if (m_siteIdenEntry.txOffsetMhz() > 0.0F) + uCalcTxOffset |= 0x2000U; // this sets a positive offset ... + + uint32_t calcBaseFreq = (uint32_t)(m_siteIdenEntry.baseFrequency() / 5); + uint16_t chanBw = (uint16_t)((m_siteIdenEntry.chBandwidthKhz() * 1000) / 125); + + rsValue = m_siteIdenEntry.channelId(); // Channel ID + rsValue = (rsValue << 4) + chanBw; // Channel Bandwidth + rsValue = (rsValue << 14) + uCalcTxOffset; // Transmit Offset + rsValue = (rsValue << 10) + calcSpace; // Channel Spacing + rsValue = (rsValue << 32) + calcBaseFreq; // Base Frequency + } + } + else { + LogError(LOG_P25, "TDULC::encodeLC(), invalid values for LC_IDEN_UP, baseFrequency = %uHz, txOffsetMhz = %fMHz, chBandwidthKhz = %fKHz, chSpaceKhz = %fKHz", + m_siteIdenEntry.baseFrequency(), m_siteIdenEntry.txOffsetMhz(), m_siteIdenEntry.chBandwidthKhz(), + m_siteIdenEntry.chSpaceKhz()); + return; // blatently ignore creating this TSBK + } + + std::unique_ptr rs = TDULC::fromValue(rsValue); + TDULC::encode(data, rs.get()); +} diff --git a/p25/lc/tdulc/LC_IDEN_UP.h b/p25/lc/tdulc/LC_IDEN_UP.h new file mode 100644 index 00000000..80f4fd26 --- /dev/null +++ b/p25/lc/tdulc/LC_IDEN_UP.h @@ -0,0 +1,57 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#if !defined(__P25_LC_TSBK__LC_IDEN_UP_H__) +#define __P25_LC_TSBK__LC_IDEN_UP_H__ + +#include "Defines.h" +#include "p25/lc/TDULC.h" + +namespace p25 +{ + namespace lc + { + namespace tdulc + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements IDEN UP - Channel Identifier Update + // --------------------------------------------------------------------------- + + class HOST_SW_API LC_IDEN_UP : public TDULC { + public: + /// Initializes a new instance of the LC_IDEN_UP class. + LC_IDEN_UP(); + + /// Decode a terminator data unit w/ link control. + virtual bool decode(const uint8_t* data); + /// Encode a terminator data unit w/ link control. + virtual void encode(uint8_t* data); + }; + } // namespace tdulc + } // namespace lc +} // namespace p25 + +#endif // __P25_LC_TSBK__LC_IDEN_UP_H__ diff --git a/p25/lc/tdulc/LC_NET_STS_BCAST.cpp b/p25/lc/tdulc/LC_NET_STS_BCAST.cpp new file mode 100644 index 00000000..5764364a --- /dev/null +++ b/p25/lc/tdulc/LC_NET_STS_BCAST.cpp @@ -0,0 +1,84 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "Defines.h" +#include "p25/lc/tdulc/LC_NET_STS_BCAST.h" +#include "Log.h" +#include "Utils.h" + +using namespace p25::lc::tdulc; +using namespace p25::lc; +using namespace p25; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the LC_NET_STS_BCAST class. +/// +LC_NET_STS_BCAST::LC_NET_STS_BCAST() : TDULC() +{ + m_lco = p25::LC_NET_STS_BCAST; +} + +/// +/// Decode a terminator data unit w/ link control. +/// +/// +/// True, if TDULC was decoded, otherwise false. +bool LC_NET_STS_BCAST::decode(const uint8_t* data) +{ + assert(data != NULL); + + /* stub */ + + return true; +} + +/// +/// Encode a terminator data unit w/ link control. +/// +/// +void LC_NET_STS_BCAST::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t rsValue = 0U; + + m_implicit = true; + + rsValue = (rsValue << 20) + m_siteData.netId(); // Network ID + 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_siteData.serviceClass(); // System Service Class + + std::unique_ptr rs = TDULC::fromValue(rsValue); + TDULC::encode(data, rs.get()); +} diff --git a/p25/lc/tdulc/LC_NET_STS_BCAST.h b/p25/lc/tdulc/LC_NET_STS_BCAST.h new file mode 100644 index 00000000..55b16989 --- /dev/null +++ b/p25/lc/tdulc/LC_NET_STS_BCAST.h @@ -0,0 +1,57 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#if !defined(__P25_LC_TSBK__LC_NET_STS_BCAST_H__) +#define __P25_LC_TSBK__LC_NET_STS_BCAST_H__ + +#include "Defines.h" +#include "p25/lc/TDULC.h" + +namespace p25 +{ + namespace lc + { + namespace tdulc + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements NET STS BCAST - Network Status Broadcast + // --------------------------------------------------------------------------- + + class HOST_SW_API LC_NET_STS_BCAST : public TDULC { + public: + /// Initializes a new instance of the LC_NET_STS_BCAST class. + LC_NET_STS_BCAST(); + + /// Decode a terminator data unit w/ link control. + virtual bool decode(const uint8_t* data); + /// Encode a terminator data unit w/ link control. + virtual void encode(uint8_t* data); + }; + } // namespace tdulc + } // namespace lc +} // namespace p25 + +#endif // __P25_LC_TSBK__LC_NET_STS_BCAST_H__ diff --git a/p25/lc/tdulc/LC_PRIVATE.cpp b/p25/lc/tdulc/LC_PRIVATE.cpp new file mode 100644 index 00000000..8be79281 --- /dev/null +++ b/p25/lc/tdulc/LC_PRIVATE.cpp @@ -0,0 +1,99 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "Defines.h" +#include "p25/lc/tdulc/LC_PRIVATE.h" +#include "Log.h" +#include "Utils.h" + +using namespace p25::lc::tdulc; +using namespace p25::lc; +using namespace p25; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the LC_PRIVATE class. +/// +LC_PRIVATE::LC_PRIVATE() : TDULC() +{ + m_lco = p25::LC_PRIVATE; +} + +/// +/// Decode a terminator data unit w/ link control. +/// +/// +/// True, if TDULC was decoded, otherwise false. +bool LC_PRIVATE::decode(const uint8_t* data) +{ + assert(data != NULL); + + uint8_t rs[P25_TDULC_LENGTH_BYTES + 1U]; + ::memset(rs, 0x00U, P25_TDULC_LENGTH_BYTES); + + bool ret = TDULC::decode(data, rs); + if (!ret) + return false; + + ulong64_t rsValue = TDULC::toValue(rs); + + m_mfId = rs[1U]; // Mfg Id. + m_group = false; + m_emergency = (rs[2U] & 0x80U) == 0x80U; // Emergency Flag + m_encrypted = (rs[2U] & 0x40U) == 0x40U; // Encryption Flag + m_priority = (rs[2U] & 0x07U); // Priority + m_dstId = (uint32_t)((rsValue >> 24) & 0xFFFFFFU); // Target Radio Address + m_srcId = (uint32_t)(rsValue & 0xFFFFFFU); // Source Radio Address + + return true; +} + +/// +/// Encode a terminator data unit w/ link control. +/// +/// +void LC_PRIVATE::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t rsValue = 0U; + + rsValue = m_mfId; + rsValue = (rsValue << 8) + + (m_emergency ? 0x80U : 0x00U) + // Emergency Flag + (m_encrypted ? 0x40U : 0x00U) + // Encrypted Flag + (m_priority & 0x07U); // Priority + rsValue = (rsValue << 24) + m_dstId; // Target Radio Address + rsValue = (rsValue << 24) + m_srcId; // Source Radio Address + + std::unique_ptr rs = TDULC::fromValue(rsValue); + TDULC::encode(data, rs.get()); +} diff --git a/p25/lc/tdulc/LC_PRIVATE.h b/p25/lc/tdulc/LC_PRIVATE.h new file mode 100644 index 00000000..59182db8 --- /dev/null +++ b/p25/lc/tdulc/LC_PRIVATE.h @@ -0,0 +1,57 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#if !defined(__P25_LC_TSBK__LC_PRIVATE_H__) +#define __P25_LC_TSBK__LC_PRIVATE_H__ + +#include "Defines.h" +#include "p25/lc/TDULC.h" + +namespace p25 +{ + namespace lc + { + namespace tdulc + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements UU VCH USER - Unit-to-Unit Voice Channel User + // --------------------------------------------------------------------------- + + class HOST_SW_API LC_PRIVATE : public TDULC { + public: + /// Initializes a new instance of the LC_PRIVATE class. + LC_PRIVATE(); + + /// Decode a terminator data unit w/ link control. + virtual bool decode(const uint8_t* data); + /// Encode a terminator data unit w/ link control. + virtual void encode(uint8_t* data); + }; + } // namespace tdulc + } // namespace lc +} // namespace p25 + +#endif // __P25_LC_TSBK__LC_PRIVATE_H__ diff --git a/p25/lc/tdulc/LC_RFSS_STS_BCAST.cpp b/p25/lc/tdulc/LC_RFSS_STS_BCAST.cpp new file mode 100644 index 00000000..3c56a0b3 --- /dev/null +++ b/p25/lc/tdulc/LC_RFSS_STS_BCAST.cpp @@ -0,0 +1,86 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "Defines.h" +#include "p25/lc/tdulc/LC_RFSS_STS_BCAST.h" +#include "Log.h" +#include "Utils.h" + +using namespace p25::lc::tdulc; +using namespace p25::lc; +using namespace p25; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the LC_RFSS_STS_BCAST class. +/// +LC_RFSS_STS_BCAST::LC_RFSS_STS_BCAST() : TDULC() +{ + m_lco = p25::LC_RFSS_STS_BCAST; +} + +/// +/// Decode a terminator data unit w/ link control. +/// +/// +/// True, if TDULC was decoded, otherwise false. +bool LC_RFSS_STS_BCAST::decode(const uint8_t* data) +{ + assert(data != NULL); + + /* stub */ + + return true; +} + +/// +/// Encode a terminator data unit w/ link control. +/// +/// +void LC_RFSS_STS_BCAST::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t rsValue = 0U; + + m_implicit = true; + + rsValue = m_siteData.lra(); // Location Registration Area + rsValue = (rsValue << 12) + m_siteData.sysId(); // System ID + rsValue = (rsValue << 8) + m_siteData.rfssId(); // RF Sub-System ID + 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_siteData.serviceClass(); // System Service Class + + std::unique_ptr rs = TDULC::fromValue(rsValue); + TDULC::encode(data, rs.get()); +} diff --git a/p25/lc/tdulc/LC_RFSS_STS_BCAST.h b/p25/lc/tdulc/LC_RFSS_STS_BCAST.h new file mode 100644 index 00000000..df563b9a --- /dev/null +++ b/p25/lc/tdulc/LC_RFSS_STS_BCAST.h @@ -0,0 +1,57 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#if !defined(__P25_LC_TSBK__LC_RFSS_STS_BCAST_H__) +#define __P25_LC_TSBK__LC_RFSS_STS_BCAST_H__ + +#include "Defines.h" +#include "p25/lc/TDULC.h" + +namespace p25 +{ + namespace lc + { + namespace tdulc + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements RFSS STS BCAST - RFSS Status Broadcast + // --------------------------------------------------------------------------- + + class HOST_SW_API LC_RFSS_STS_BCAST : public TDULC { + public: + /// Initializes a new instance of the LC_RFSS_STS_BCAST class. + LC_RFSS_STS_BCAST(); + + /// Decode a terminator data unit w/ link control. + virtual bool decode(const uint8_t* data); + /// Encode a terminator data unit w/ link control. + virtual void encode(uint8_t* data); + }; + } // namespace tdulc + } // namespace lc +} // namespace p25 + +#endif // __P25_LC_TSBK__LC_RFSS_STS_BCAST_H__ diff --git a/p25/lc/tdulc/LC_SYS_SRV_BCAST.cpp b/p25/lc/tdulc/LC_SYS_SRV_BCAST.cpp new file mode 100644 index 00000000..e1e11f27 --- /dev/null +++ b/p25/lc/tdulc/LC_SYS_SRV_BCAST.cpp @@ -0,0 +1,84 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "Defines.h" +#include "p25/lc/tdulc/LC_SYS_SRV_BCAST.h" +#include "Log.h" +#include "Utils.h" + +using namespace p25::lc::tdulc; +using namespace p25::lc; +using namespace p25; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the LC_SYS_SRV_BCAST class. +/// +LC_SYS_SRV_BCAST::LC_SYS_SRV_BCAST() : TDULC() +{ + m_lco = p25::LC_SYS_SRV_BCAST; +} + +/// +/// Decode a terminator data unit w/ link control. +/// +/// +/// True, if TDULC was decoded, otherwise false. +bool LC_SYS_SRV_BCAST::decode(const uint8_t* data) +{ + assert(data != NULL); + + /* stub */ + + return true; +} + +/// +/// Encode a terminator data unit w/ link control. +/// +/// +void LC_SYS_SRV_BCAST::encode(uint8_t* data) +{ + assert(data != NULL); + + const uint32_t services = (m_siteData.netActive()) ? P25_SYS_SRV_NET_ACTIVE : 0U | P25_SYS_SRV_DEFAULT; + + ulong64_t rsValue = 0U; + + m_implicit = true; + + rsValue = 0U; + rsValue = (rsValue << 16) + services; // System Services Available + rsValue = (rsValue << 24) + services; // System Services Supported + + std::unique_ptr rs = TDULC::fromValue(rsValue); + TDULC::encode(data, rs.get()); +} diff --git a/p25/lc/tdulc/LC_SYS_SRV_BCAST.h b/p25/lc/tdulc/LC_SYS_SRV_BCAST.h new file mode 100644 index 00000000..2f3b3df8 --- /dev/null +++ b/p25/lc/tdulc/LC_SYS_SRV_BCAST.h @@ -0,0 +1,57 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#if !defined(__P25_LC_TSBK__LC_SYS_SRV_BCAST_H__) +#define __P25_LC_TSBK__LC_SYS_SRV_BCAST_H__ + +#include "Defines.h" +#include "p25/lc/TDULC.h" + +namespace p25 +{ + namespace lc + { + namespace tdulc + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements SYS SRV BCAST - System Service Broadcast + // --------------------------------------------------------------------------- + + class HOST_SW_API LC_SYS_SRV_BCAST : public TDULC { + public: + /// Initializes a new instance of the LC_SYS_SRV_BCAST class. + LC_SYS_SRV_BCAST(); + + /// Decode a terminator data unit w/ link control. + virtual bool decode(const uint8_t* data); + /// Encode a terminator data unit w/ link control. + virtual void encode(uint8_t* data); + }; + } // namespace tdulc + } // namespace lc +} // namespace p25 + +#endif // __P25_LC_TSBK__LC_SYS_SRV_BCAST_H__ diff --git a/p25/lc/tdulc/LC_TEL_INT_VCH_USER.cpp b/p25/lc/tdulc/LC_TEL_INT_VCH_USER.cpp new file mode 100644 index 00000000..7e4c6d83 --- /dev/null +++ b/p25/lc/tdulc/LC_TEL_INT_VCH_USER.cpp @@ -0,0 +1,101 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "Defines.h" +#include "p25/lc/tdulc/LC_TEL_INT_VCH_USER.h" +#include "Log.h" +#include "Utils.h" + +using namespace p25::lc::tdulc; +using namespace p25::lc; +using namespace p25; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the LC_TEL_INT_VCH_USER class. +/// +LC_TEL_INT_VCH_USER::LC_TEL_INT_VCH_USER() : TDULC() +{ + m_lco = p25::LC_TEL_INT_VCH_USER; +} + +/// +/// Decode a terminator data unit w/ link control. +/// +/// +/// True, if TDULC was decoded, otherwise false. +bool LC_TEL_INT_VCH_USER::decode(const uint8_t* data) +{ + assert(data != NULL); + + uint8_t rs[P25_TDULC_LENGTH_BYTES + 1U]; + ::memset(rs, 0x00U, P25_TDULC_LENGTH_BYTES); + + bool ret = TDULC::decode(data, rs); + if (!ret) + return false; + + ulong64_t rsValue = TDULC::toValue(rs); + + m_emergency = (rs[2U] & 0x80U) == 0x80U; // Emergency Flag + m_encrypted = (rs[2U] & 0x40U) == 0x40U; // Encryption Flag + m_priority = (rs[2U] & 0x07U); // Priority + m_callTimer = (uint32_t)((rsValue >> 24) & 0xFFFFU); // Call Timer + if (m_srcId == 0U) { + m_srcId = (uint32_t)(rsValue & 0xFFFFFFU); // Source/Target Address + } + + return true; +} + +/// +/// Encode a terminator data unit w/ link control. +/// +/// +void LC_TEL_INT_VCH_USER::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t rsValue = 0U; + + m_implicit = true; + + rsValue = m_mfId; + rsValue = (rsValue << 8) + + (m_emergency ? 0x80U : 0x00U) + // Emergency Flag + (m_encrypted ? 0x40U : 0x00U) + // Encrypted Flag + (m_priority & 0x07U); // Priority + rsValue = (rsValue << 24) + m_dstId; // Target Radio Address + rsValue = (rsValue << 24) + m_srcId; // Source Radio Address + + std::unique_ptr rs = TDULC::fromValue(rsValue); + TDULC::encode(data, rs.get()); +} diff --git a/p25/lc/tdulc/LC_TEL_INT_VCH_USER.h b/p25/lc/tdulc/LC_TEL_INT_VCH_USER.h new file mode 100644 index 00000000..192acc5a --- /dev/null +++ b/p25/lc/tdulc/LC_TEL_INT_VCH_USER.h @@ -0,0 +1,57 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#if !defined(__P25_LC_TSBK__LC_TEL_INT_VCH_USER_H__) +#define __P25_LC_TSBK__LC_TEL_INT_VCH_USER_H__ + +#include "Defines.h" +#include "p25/lc/TDULC.h" + +namespace p25 +{ + namespace lc + { + namespace tdulc + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements TEL INT VCH USER - Telephone Interconnect Voice Channel User + // --------------------------------------------------------------------------- + + class HOST_SW_API LC_TEL_INT_VCH_USER : public TDULC { + public: + /// Initializes a new instance of the LC_TEL_INT_VCH_USER class. + LC_TEL_INT_VCH_USER(); + + /// Decode a terminator data unit w/ link control. + virtual bool decode(const uint8_t* data); + /// Encode a terminator data unit w/ link control. + virtual void encode(uint8_t* data); + }; + } // namespace tdulc + } // namespace lc +} // namespace p25 + +#endif // __P25_LC_TSBK__LC_TEL_INT_VCH_USER_H__ diff --git a/p25/lc/tdulc/TDULCFactory.cpp b/p25/lc/tdulc/TDULCFactory.cpp new file mode 100644 index 00000000..d31b525a --- /dev/null +++ b/p25/lc/tdulc/TDULCFactory.cpp @@ -0,0 +1,136 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#include "Defines.h" +#include "p25/lc/tdulc/TDULCFactory.h" +#include "edac/Golay24128.h" +#include "Log.h" +#include "Utils.h" + +using namespace p25::lc::tdulc; +using namespace p25::lc; +using namespace p25; + +#include + +// --------------------------------------------------------------------------- +// Static Class Members +// --------------------------------------------------------------------------- + +::edac::RS634717 TDULCFactory::m_rs = ::edac::RS634717(); + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the TDULCFactory class. +/// +TDULCFactory::TDULCFactory() +{ + /* stub */ +} + +/// +/// Finalizes a instance of TDULCFactory class. +/// +TDULCFactory::~TDULCFactory() +{ + /* stub */ +} + +/// +/// Create an instance of a TDULC. +/// +/// +/// True, if TDULC was decoded, otherwise false. +std::unique_ptr TDULCFactory::createTDULC(const uint8_t* data) +{ + assert(data != nullptr); + + // deinterleave + uint8_t rs[P25_TDULC_LENGTH_BYTES + 1U]; + uint8_t raw[P25_TDULC_FEC_LENGTH_BYTES + 1U]; + P25Utils::decode(data, raw, 114U, 410U); + + // decode Golay (24,12,8) FEC + edac::Golay24128::decode24128(rs, raw, P25_TDULC_LENGTH_BYTES); + +#if DEBUG_P25_TDULC + Utils::dump(2U, "TDULCFactory::decode(), TDULC RS", rs, P25_TDULC_LENGTH_BYTES); +#endif + + // decode RS (24,12,13) FEC + try { + bool ret = m_rs.decode241213(rs); + if (!ret) { + LogError(LOG_P25, "TDULCFactory::decode(), failed to decode RS (24,12,13) FEC"); + return nullptr; + } + } + catch (...) { + Utils::dump(2U, "P25, RS excepted with input data", rs, P25_TDULC_LENGTH_BYTES); + return nullptr; + } + + uint8_t lco = rs[0U] & 0x3FU; // LCO + + // standard P25 reference opcodes + switch (lco) { + case p25::LC_GROUP: + return decode(new LC_GROUP(), data); + case p25::LC_PRIVATE: + return decode(new LC_PRIVATE(), data); + case p25::LC_TEL_INT_VCH_USER: + return decode(new LC_TEL_INT_VCH_USER(), data); + default: + LogError(LOG_P25, "TDULCFactory::create(), unknown TDULC LCO value, lco = $%02X", lco); + break; + } + + return nullptr; +} + +// --------------------------------------------------------------------------- +// Private Class Members +// --------------------------------------------------------------------------- + +/// +/// +/// +/// +/// +/// +std::unique_ptr TDULCFactory::decode(TDULC* tdulc, const uint8_t* data) +{ + assert(tdulc != nullptr); + assert(data != nullptr); + + if (!tdulc->decode(data)) { + return nullptr; + } + + return std::unique_ptr(tdulc); +} diff --git a/p25/lc/tdulc/TDULCFactory.h b/p25/lc/tdulc/TDULCFactory.h new file mode 100644 index 00000000..0dfc4f4e --- /dev/null +++ b/p25/lc/tdulc/TDULCFactory.h @@ -0,0 +1,76 @@ +/** +* Digital Voice Modem - Host Software +* GPLv2 Open Source. Use is subject to license terms. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* @package DVM / Host Software +* +*/ +/* +* Copyright (C) 2022 by Bryan Biedenkapp N2PLL +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +#if !defined(__P25_LC__TDULC_FACTORY_H__) +#define __P25_LC__TDULC_FACTORY_H__ + +#include "Defines.h" +#include "edac/RS634717.h" + +#include "p25/lc/TDULC.h" +#include "p25/lc/tdulc/LC_ADJ_STS_BCAST.h" +#include "p25/lc/tdulc/LC_CALL_TERM.h" +#include "p25/lc/tdulc/LC_CONV_FALLBACK.h" +#include "p25/lc/tdulc/LC_GROUP_UPDT.h" +#include "p25/lc/tdulc/LC_GROUP.h" +#include "p25/lc/tdulc/LC_IDEN_UP.h" +#include "p25/lc/tdulc/LC_NET_STS_BCAST.h" +#include "p25/lc/tdulc/LC_PRIVATE.h" +#include "p25/lc/tdulc/LC_RFSS_STS_BCAST.h" +#include "p25/lc/tdulc/LC_SYS_SRV_BCAST.h" +#include "p25/lc/tdulc/LC_TEL_INT_VCH_USER.h" + +namespace p25 +{ + namespace lc + { + namespace tdulc + { + // --------------------------------------------------------------------------- + // Class Declaration + // Helper class to instantiate an instance of a TDULC. + // --------------------------------------------------------------------------- + + class HOST_SW_API TDULCFactory { + public: + /// Initializes a new instance of the TDULCFactory class. + TDULCFactory(); + /// Finalizes a instance of the TDULCFactory class. + ~TDULCFactory(); + + /// Create an instance of a TDULC. + static std::unique_ptr createTDULC(const uint8_t* data); + + private: + static edac::RS634717 m_rs; + + /// + static std::unique_ptr decode(TDULC* tdulc, const uint8_t* data); + }; + } // namespace tdulc + } // namespace lc +} // namespace p25 + +#endif // __P25_LC__TDULC_FACTORY_H__ diff --git a/p25/packet/Trunk.cpp b/p25/packet/Trunk.cpp index b6b93f45..42812d63 100644 --- a/p25/packet/Trunk.cpp +++ b/p25/packet/Trunk.cpp @@ -30,6 +30,7 @@ #include "p25/packet/Trunk.h" #include "p25/acl/AccessControl.h" #include "p25/lc/tsbk/TSBKFactory.h" +#include "p25/lc/tdulc/TDULCFactory.h" #include "p25/lookups/P25AffiliationLookup.h" #include "p25/P25Utils.h" #include "p25/Sync.h" @@ -1265,7 +1266,7 @@ void Trunk::writeNetworkRF(lc::TSBK* tsbk, const uint8_t* data, bool autoReset) /// /// /// -void Trunk::writeNetworkRF(lc::TDULC& tduLc, const uint8_t* data, bool autoReset) +void Trunk::writeNetworkRF(lc::TDULC* tduLc, const uint8_t* data, bool autoReset) { assert(data != nullptr); @@ -1276,10 +1277,10 @@ void Trunk::writeNetworkRF(lc::TDULC& tduLc, const uint8_t* data, bool autoReset return; lc::LC lc = lc::LC(); - lc.setLCO(tduLc.getLCO()); - lc.setMFId(tduLc.getMFId()); - lc.setSrcId(tduLc.getSrcId()); - lc.setDstId(tduLc.getDstId()); + lc.setLCO(tduLc->getLCO()); + lc.setMFId(tduLc->getMFId()); + lc.setSrcId(tduLc->getSrcId()); + lc.setDstId(tduLc->getDstId()); m_network->writeP25TSDU(lc, data); if (autoReset) @@ -1301,11 +1302,10 @@ void Trunk::writeRF_ControlData(uint8_t frameCnt, uint8_t n, bool adjSS) bool fallbackTx = (frameCnt % 253U) == 0U; if (fallbackTx && n == 7U) { if (m_convFallbackPacketDelay >= CONV_FALLBACK_PACKET_DELAY) { - lc::TDULC lc = lc::TDULC(); - lc.setLCO(LC_CONV_FALLBACK); + std::unique_ptr lc = new_unique(lc::tdulc::LC_CONV_FALLBACK); for (uint8_t i = 0U; i < 3U; i++) { - writeRF_TDULC(lc, true); + writeRF_TDULC(lc.get(), true); } m_convFallbackPacketDelay = 0U; @@ -1434,7 +1434,7 @@ void Trunk::writeRF_ControlData(uint8_t frameCnt, uint8_t n, bool adjSS) /// /// /// -void Trunk::writeRF_TDULC(lc::TDULC lc, bool noNetwork) +void Trunk::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); @@ -1446,7 +1446,7 @@ void Trunk::writeRF_TDULC(lc::TDULC lc, bool noNetwork) m_p25->m_nid.encode(data + 2U, P25_DUID_TDULC); // Generate TDULC Data - lc.encode(data + 2U); + lc->encode(data + 2U); // Add busy bits m_p25->addBusyBits(data + 2U, P25_TDULC_FRAME_LENGTH_BITS, true, true); @@ -1472,7 +1472,7 @@ void Trunk::writeRF_TDULC(lc::TDULC lc, bool noNetwork) /// Helper to write a network P25 TDU w/ link control packet. /// /// -void Trunk::writeNet_TDULC(lc::TDULC lc) +void Trunk::writeNet_TDULC(lc::TDULC* lc) { uint8_t buffer[P25_TDULC_FRAME_LENGTH_BYTES + 2U]; ::memset(buffer, 0x00U, P25_TDULC_FRAME_LENGTH_BYTES + 2U); @@ -1487,7 +1487,7 @@ void Trunk::writeNet_TDULC(lc::TDULC lc) m_p25->m_nid.encode(buffer + 2U, P25_DUID_TDULC); // Regenerate TDULC Data - lc.encode(buffer + 2U); + lc->encode(buffer + 2U); // Add busy bits m_p25->addBusyBits(buffer + 2U, P25_TDULC_FRAME_LENGTH_BITS, true, true); @@ -1495,7 +1495,7 @@ void Trunk::writeNet_TDULC(lc::TDULC lc) m_p25->addFrame(buffer, P25_TDULC_FRAME_LENGTH_BYTES + 2U, true); if (m_verbose) { - LogMessage(LOG_NET, P25_TDULC_STR ", lc = $%02X, srcId = %u", lc.getLCO(), lc.getSrcId()); + LogMessage(LOG_NET, P25_TDULC_STR ", lc = $%02X, srcId = %u", lc->getLCO(), lc->getSrcId()); } if (m_p25->m_voice->m_netFrames > 0) { @@ -1528,38 +1528,37 @@ void Trunk::writeRF_TDULC_ChanRelease(bool grp, uint32_t srcId, uint32_t dstId) } uint32_t count = m_p25->m_hangCount / 2; - lc::TDULC lc = lc::TDULC(); + std::unique_ptr lc = nullptr; if (m_p25->m_control) { for (uint32_t i = 0; i < count; i++) { if ((srcId != 0U) && (dstId != 0U)) { - lc.setSrcId(srcId); - lc.setDstId(dstId); - lc.setEmergency(false); - if (grp) { - lc.setLCO(LC_GROUP); - writeRF_TDULC(lc, true); - } - else { - lc.setLCO(LC_PRIVATE); - writeRF_TDULC(lc, true); + lc = new_unique(lc::tdulc::LC_GROUP); + } else { + lc = new_unique(lc::tdulc::LC_PRIVATE); } + + lc->setSrcId(srcId); + lc->setDstId(dstId); + lc->setEmergency(false); + + writeRF_TDULC(lc.get(), true); } - lc.setLCO(LC_NET_STS_BCAST); - writeRF_TDULC(lc, true); - lc.setLCO(LC_RFSS_STS_BCAST); - writeRF_TDULC(lc, true); + lc = new_unique(lc::tdulc::LC_NET_STS_BCAST); + writeRF_TDULC(lc.get(), true); + lc = new_unique(lc::tdulc::LC_RFSS_STS_BCAST); + writeRF_TDULC(lc.get(), true); } } if (m_verbose) { - LogMessage(LOG_RF, P25_TDULC_STR ", LC_CALL_TERM (Call Termination), srcId = %u, dstId = %u", lc.getSrcId(), lc.getDstId()); + LogMessage(LOG_RF, P25_TDULC_STR ", LC_CALL_TERM (Call Termination), srcId = %u, dstId = %u", srcId, dstId); } - lc.setLCO(LC_CALL_TERM); - writeRF_TDULC(lc, true); + lc = new_unique(lc::tdulc::LC_CALL_TERM); + writeRF_TDULC(lc.get(), true); if (m_p25->m_control) { writeNet_TSDU_Call_Term(srcId, dstId); diff --git a/p25/packet/Trunk.h b/p25/packet/Trunk.h index 6984ff8e..c4c8a152 100644 --- a/p25/packet/Trunk.h +++ b/p25/packet/Trunk.h @@ -157,15 +157,15 @@ namespace p25 /// Write data processed from RF to the network. void writeNetworkRF(lc::TSBK* tsbk, const uint8_t* data, bool autoReset); /// Write data processed from RF to the network. - void writeNetworkRF(lc::TDULC& tduLc, const uint8_t* data, bool autoReset); + void writeNetworkRF(lc::TDULC* tduLc, const uint8_t* data, bool autoReset); /// Helper to write control channel packet data. void writeRF_ControlData(uint8_t frameCnt, uint8_t n, bool adjSS); /// Helper to write a P25 TDU w/ link control packet. - void writeRF_TDULC(lc::TDULC lc, bool noNetwork); + void writeRF_TDULC(lc::TDULC* lc, bool noNetwork); /// Helper to write a network P25 TDU w/ link control packet. - virtual void writeNet_TDULC(lc::TDULC lc); + virtual void writeNet_TDULC(lc::TDULC* lc); /// Helper to write a P25 TDU w/ link control channel release packet. void writeRF_TDULC_ChanRelease(bool grp, uint32_t srcId, uint32_t dstId); diff --git a/p25/packet/Voice.cpp b/p25/packet/Voice.cpp index 2ee2f4f8..4d1c5f73 100644 --- a/p25/packet/Voice.cpp +++ b/p25/packet/Voice.cpp @@ -34,6 +34,7 @@ #include "p25/packet/Trunk.h" #include "p25/acl/AccessControl.h" #include "p25/dfsi/DFSIDefines.h" +#include "p25/lc/tdulc/TDULCFactory.h" #include "p25/P25Utils.h" #include "p25/Sync.h" #include "edac/CRC.h" @@ -640,13 +641,12 @@ bool Voice::process(uint8_t* data, uint32_t len) m_p25->m_rfTimeout.stop(); } else { - lc::TDULC tdulc = lc::TDULC(); - bool ret = tdulc.decode(data + 2U); - if (!ret) { + std::unique_ptr tdulc = lc::tdulc::TDULCFactory::createTDULC(data + 2U); + if (tdulc == nullptr) { LogWarning(LOG_RF, P25_LDU2_STR ", undecodable TDULC"); } else { - m_p25->m_trunk->writeRF_TDULC(tdulc, false); + m_p25->m_trunk->writeRF_TDULC(tdulc.get(), false); } }