diff --git a/CMakeLists.txt b/CMakeLists.txt index cf7ba747..317796ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -13,6 +13,8 @@ file(GLOB dvmhost_SRC "dmr/edac/*.cpp" "dmr/lc/*.h" "dmr/lc/*.cpp" + "dmr/lc/csbk/*.h" + "dmr/lc/csbk/*.cpp" "dmr/packet*.h" "dmr/packet/*.cpp" diff --git a/Defines.h b/Defines.h index 27a8ea96..a4ef8adb 100644 --- a/Defines.h +++ b/Defines.h @@ -241,7 +241,7 @@ inline std::string __IP_FROM_ULONG(const ulong64_t& value) { /// Creates a private copy implementation. /// This requires the copy(const type& data) to be declared in the class definition. #define __COPY(type) \ - private: void copy(const type& data); \ + private: virtual void copy(const type& data); \ public: __forceinline type& operator=(const type& data) { \ if (this != &data) { \ copy(data); \ @@ -251,7 +251,7 @@ inline std::string __IP_FROM_ULONG(const ulong64_t& value) { /// Creates a protected copy implementation. /// This requires the copy(const type& data) to be declared in the class definition. #define __PROTECTED_COPY(type) \ - protected: void copy(const type& data); \ + protected: virtual void copy(const type& data); \ public: __forceinline type& operator=(const type& data) { \ if (this != &data) { \ copy(data); \ diff --git a/dmr/Control.cpp b/dmr/Control.cpp index 2197ac6b..e80cc90e 100644 --- a/dmr/Control.cpp +++ b/dmr/Control.cpp @@ -27,6 +27,7 @@ #include "dmr/Control.h" #include "dmr/acl/AccessControl.h" #include "dmr/lc/CSBK.h" +#include "dmr/lc/csbk/CSBKFactory.h" #include "Log.h" using namespace dmr; @@ -228,17 +229,15 @@ bool Control::processWakeup(const uint8_t* data) return false; // generate a new CSBK and check validity - lc::CSBK csbk = lc::CSBK(SiteData(), lookups::IdenTable(), m_dumpCSBKData); - - bool valid = csbk.decode(data + 2U); - if (!valid) + std::unique_ptr csbk = lc::csbk::CSBKFactory::createCSBK(data + 2U); + if (csbk == nullptr) return false; - uint8_t csbko = csbk.getCSBKO(); + uint8_t csbko = csbk->getCSBKO(); if (csbko != CSBKO_BSDWNACT) return false; - uint32_t srcId = csbk.getSrcId(); + uint32_t srcId = csbk->getSrcId(); // check the srcId against the ACL control bool ret = acl::AccessControl::validateSrcId(srcId); @@ -415,6 +414,5 @@ void Control::setDebugVerbose(bool debug, bool verbose) void Control::setCSBKVerbose(bool verbose) { m_dumpCSBKData = verbose; - m_slot1->setCSBKVerbose(verbose); - m_slot2->setCSBKVerbose(verbose); + lc::CSBK::setVerbose(verbose); } diff --git a/dmr/Slot.cpp b/dmr/Slot.cpp index ce87e4c1..8cc28f96 100644 --- a/dmr/Slot.cpp +++ b/dmr/Slot.cpp @@ -159,7 +159,6 @@ Slot::Slot(uint32_t slotNo, uint32_t timeout, uint32_t tgHang, uint32_t queueSiz m_ccPrevRunning(false), m_ccHalted(false), m_enableTSCC(false), - m_dumpCSBKData(dumpCSBKData), m_verbose(verbose), m_debug(debug) { @@ -548,15 +547,6 @@ void Slot::setDebugVerbose(bool debug, bool verbose) m_verbose = m_voice->m_verbose = m_data->m_verbose = verbose = m_control->m_verbose; } -/// -/// Helper to change the CSBK verbose state. -/// -/// Flag indicating whether CSBK dumping is enabled. -void Slot::setCSBKVerbose(bool verbose) -{ - m_dumpCSBKData = verbose; -} - /// /// Helper to enable and configure TSCC support for this slot. /// diff --git a/dmr/Slot.h b/dmr/Slot.h index b2845e38..5e3a65b4 100644 --- a/dmr/Slot.h +++ b/dmr/Slot.h @@ -99,8 +99,6 @@ namespace dmr /// Helper to change the debug and verbose state. void setDebugVerbose(bool debug, bool verbose); - /// Helper to change the CSBK verbose state. - void setCSBKVerbose(bool verbose); /// Helper to enable and configure TSCC support for this slot. void setTSCC(bool enable, bool dedicated); @@ -184,7 +182,6 @@ namespace dmr bool m_enableTSCC; bool m_dedicatedTSCC; - bool m_dumpCSBKData; bool m_verbose; bool m_debug; diff --git a/dmr/lc/CSBK.cpp b/dmr/lc/CSBK.cpp index 6eb06c2e..db53593c 100644 --- a/dmr/lc/CSBK.cpp +++ b/dmr/lc/CSBK.cpp @@ -32,7 +32,6 @@ #include "dmr/lc/CSBK.h" #include "edac/BPTC19696.h" #include "edac/CRC.h" -#include "HostMain.h" #include "Log.h" #include "Utils.h" @@ -42,30 +41,56 @@ using namespace dmr; #include #include +// --------------------------------------------------------------------------- +// Static Class Members +// --------------------------------------------------------------------------- + +bool CSBK::m_verbose = false; + +SiteData CSBK::m_siteData = SiteData(); + // --------------------------------------------------------------------------- // Public Class Members // --------------------------------------------------------------------------- /// -/// Initializes a new instance of the CSBK class. +/// Initializes a copy instance of the CSBK class. /// -/// -/// -CSBK::CSBK(SiteData siteData, lookups::IdenTable entry) : CSBK(siteData) +/// +CSBK::CSBK(const CSBK& data) : CSBK() { - m_siteIdenEntry = entry; + copy(data); } /// /// Initializes a new instance of the CSBK class. /// -/// -/// -/// -CSBK::CSBK(SiteData siteData, lookups::IdenTable entry, bool verbose) : CSBK(siteData) +CSBK::CSBK() : + m_colorCode(0U), + m_lastBlock(true), + m_Cdef(false), + m_CSBKO(CSBKO_NONE), + m_FID(0x00U), + m_GI(false), + m_srcId(0U), + m_dstId(0U), + m_dataContent(false), + m_CBF(0U), + m_emergency(false), + m_privacy(false), + m_supplementData(false), + m_priority(0U), + m_broadcast(false), + m_proxy(false), + m_response(0U), + m_reason(0U), + m_siteOffsetTiming(false), + m_logicalCh1(DMR_CHNULL), + m_logicalCh2(DMR_CHNULL), + m_slotNo(0U), + m_siteIdenEntry(lookups::IdenTable()) { - m_verbose = verbose; - m_siteIdenEntry = entry; + /* stub */ } /// @@ -77,15 +102,14 @@ CSBK::~CSBK() } /// -/// Decodes a DMR CSBK. +/// Regenerate a DMR CSBK without decoding. /// /// -/// True, if DMR CSBK was decoded, otherwise false. -bool CSBK::decode(const uint8_t* data) +/// True, if TSBK was decoded, otherwise false. +bool CSBK::regenerate(uint8_t* data) { - assert(data != nullptr); - uint8_t csbk[DMR_CSBK_LENGTH_BYTES]; + ::memset(csbk, 0x00U, DMR_CSBK_LENGTH_BYTES); // decode BPTC (196,96) FEC edac::BPTC19696 bptc; @@ -105,17 +129,32 @@ bool CSBK::decode(const uint8_t* data) csbk[10U] ^= CSBK_CRC_MASK[0U]; csbk[11U] ^= CSBK_CRC_MASK[1U]; - if (m_verbose) { - Utils::dump(2U, "Decoded CSBK", csbk, DMR_CSBK_LENGTH_BYTES); - } + // calculate checksum + csbk[10U] ^= CSBK_CRC_MASK[0U]; + csbk[11U] ^= CSBK_CRC_MASK[1U]; - m_CSBKO = csbk[0U] & 0x3FU; // CSBKO - m_lastBlock = (csbk[0U] & 0x80U) == 0x80U; // Last Block Marker - m_FID = csbk[1U]; // Feature ID + edac::CRC::addCCITT162(csbk, 12U); - m_dataContent = false; - m_CBF = 0U; + csbk[10U] ^= CSBK_CRC_MASK[0U]; + csbk[11U] ^= CSBK_CRC_MASK[1U]; + + // encode BPTC (196,96) FEC + bptc.encode(csbk, data); + + return true; +} +// --------------------------------------------------------------------------- +// Protected Class Members +// --------------------------------------------------------------------------- + +/// +/// Internal helper to convert CSBK bytes to a 64-bit long value. +/// +/// +/// +ulong64_t CSBK::toValue(const uint8_t* csbk) +{ ulong64_t csbkValue = 0U; // combine bytes into ulong64_t (8 byte) value @@ -128,306 +167,17 @@ bool CSBK::decode(const uint8_t* data) csbkValue = (csbkValue << 8) + csbk[8U]; csbkValue = (csbkValue << 8) + csbk[9U]; - switch (m_CSBKO) { - case CSBKO_BSDWNACT: - m_bsId = (uint32_t)((csbkValue >> 24) & 0xFFFFFFU); // Base Station Address - m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address - break; - case CSBKO_UU_V_REQ: - m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFFFU); // Target Radio Address - m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address - break; - case CSBKO_UU_ANS_RSP: - m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFFFU); // Target Radio Address - m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address - break; - case CSBKO_PRECCSBK: - m_GI = (((csbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Group/Individual Flag - m_dataContent = (((csbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // - m_CBF = (uint8_t)((csbkValue >> 48) & 0xFFU); // Blocks to Follow - m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFFFU); // Target Radio Address - m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address - break; - case CSBKO_RAND: // CSBKO_CALL_ALRT when FID == FID_DMRA - switch (m_FID) - { - case FID_DMRA: - m_GI = (((csbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Group/Individual Flag - m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFFFU); // Target Radio Address - m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address - break; - case FID_ETSI: - default: - m_serviceOptions = (uint8_t)((csbkValue >> 57U) & 0x7FU); // Service Options - m_proxy = (((csbkValue >> 56U) & 0xFF) & 0x01U) == 0x01U; // Proxy Flag - m_serviceExtra = (uint8_t)((csbkValue >> 52U) & 0x0FU); // Service Extras (content dependant on service) - m_serviceKind = (uint8_t)((csbkValue >> 48U) & 0x0FU); // Service Kind - m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFFFU); // Target Radio Address - m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address - break; - } - case CSBKO_EXT_FNCT: - m_dataContent = (((csbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // - m_serviceKind = (uint8_t)((csbkValue >> 48) & 0xFFU); // Service Kind - m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFFFU); // Target Radio Address - m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address - break; - case CSBKO_NACK_RSP: - m_GI = (((csbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Group/Individual Flag - m_serviceKind = (((csbkValue >> 56) & 0xFFU) & 0x3FU); // Service Kind - m_reason = (uint8_t)((csbkValue >> 48) & 0xFFU); // Reason Code - m_srcId = (uint32_t)((csbkValue >> 24) & 0xFFFFFFU); // Source Radio Address - m_dstId = (uint32_t)(csbkValue & 0xFFFFFFU); // Target Radio Address - break; - - /** Tier 3 */ - case CSBKO_ACK_RSP: - m_GI = (((csbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Group/Individual Flag - m_reason = (uint8_t)((csbkValue >> 33) & 0xFFU); // Reason Code - m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFU); // Target Radio Address - m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address - break; - - default: - LogError(LOG_DMR, "CSBK::decode(), unknown CSBK type, csbko = $%02X", m_CSBKO); - return true; - } - - return true; + return csbkValue; } /// -/// Encodes a DMR CSBK. +/// Internal helper to convert a 64-bit long value to CSBK bytes. /// -/// -void CSBK::encode(uint8_t* data) +/// +/// +std::unique_ptr CSBK::fromValue(const ulong64_t csbkValue) { - assert(data != nullptr); - - uint8_t csbk[DMR_CSBK_LENGTH_BYTES]; - ::memset(csbk, 0x00U, DMR_CSBK_LENGTH_BYTES); - - ulong64_t csbkValue = 0U; - csbk[0U] = m_CSBKO; // CSBKO - csbk[0U] |= (m_lastBlock) ? 0x80U : 0x00U; // Last Block Marker - if (!m_Cdef) { - csbk[1U] = m_FID; // Feature ID - } - else { - csbk[1U] = m_colorCode & 0x0FU; // Cdef uses Color Code - } - - switch (m_CSBKO) { - case CSBKO_EXT_FNCT: - csbkValue = - (m_GI ? 0x40U : 0x00U) + // Group or Invididual - (m_dataContent ? 0x80U : 0x00U); - csbkValue = (csbkValue << 8) + m_serviceKind; // Service Kind - csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address - csbkValue = (csbkValue << 24) + m_dstId; // Target Radio Address - break; - - case CSBKO_NACK_RSP: - csbkValue = 0x80U + // Additional Information Field (always 1) - (m_GI ? 0x40U : 0x00U) + // Source Type - (m_serviceKind & 0x3FU); // Service Kind - csbkValue = (csbkValue << 8) + m_reason; // Reason Code - csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address - csbkValue = (csbkValue << 24) + m_dstId; // Target Radio Address - break; - - /* Tier III */ - case CSBKO_ACK_RSP: - if (m_reason == TS_ACK_RSN_REG) { - csbkValue = 0U; - } else { - csbkValue = (m_GI ? 0x40U : 0x00U) + // Source Type - (m_siteData.siteId() & 0x3FU); // Net + Site LSB - } - csbkValue = (csbkValue << 7) + (m_response & 0x7FU); // Response Information - csbkValue = (csbkValue << 8) + (m_reason & 0xFFU); // Reason Code - csbkValue = (csbkValue << 25) + m_dstId; // Target Radio Address - csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address - break; - - case CSBKO_ALOHA: - csbkValue = 0U; - csbkValue = (csbkValue << 2) + 0U; // Reserved - csbkValue = (csbkValue << 1) + ((m_siteTSSync) ? 1U : 0U); // Site Time Slot Synchronization - csbkValue = (csbkValue << 3) + DMR_ALOHA_VER_151; // DMR Spec. Version (1.5.1) - csbkValue = (csbkValue << 1) + ((m_siteOffsetTiming) ? 1U : 0U); // Site Timing: Aligned or Offset - csbkValue = (csbkValue << 1) + ((m_siteData.netActive()) ? 1U : 0U); // Site Networked - csbkValue = (csbkValue << 5) + (m_alohaMask & 0x1FU); // MS Mask - csbkValue = (csbkValue << 2) + 0U; // Service Function - csbkValue = (csbkValue << 4) + (m_nRandWait & 0x0FU); // Random Access Wait - csbkValue = (csbkValue << 1) + ((m_siteData.requireReg()) ? 1U : 0U); // Require Registration - csbkValue = (csbkValue << 4) + (m_backoffNo & 0x0FU); // Backoff Number - csbkValue = (csbkValue << 16) + m_siteData.systemIdentity(); // Site Identity - csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address - break; - - case CSBKO_PV_GRANT: - csbkValue = 0U; - csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Physical Channel 1 - csbkValue = (csbkValue << 1) + (m_slotNo & 0x3U); // Logical Slot Number - csbkValue = (csbkValue << 1) + 0U; // Reserved - csbkValue = (csbkValue << 1) + ((m_emergency) ? 1U : 0U); // Emergency - csbkValue = (csbkValue << 1) + ((m_siteOffsetTiming) ? 1U : 0U); // Site Timing: Aligned or Offset - csbkValue = (csbkValue << 24) + m_dstId; // Talkgroup ID - csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address - break; - - case CSBKO_TV_GRANT: - case CSBKO_BTV_GRANT: - csbkValue = 0U; - csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Physical Channel 1 - csbkValue = (csbkValue << 1) + (m_slotNo & 0x3U); // Logical Slot Number - csbkValue = (csbkValue << 1) + 0U; // Late Entry - csbkValue = (csbkValue << 1) + ((m_emergency) ? 1U : 0U); // Emergency - csbkValue = (csbkValue << 1) + ((m_siteOffsetTiming) ? 1U : 0U); // Site Timing: Aligned or Offset - csbkValue = (csbkValue << 24) + m_dstId; // Talkgroup ID - csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address - break; - - case CSBKO_PD_GRANT: - csbkValue = 0U; - csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Physical Channel 1 - csbkValue = (csbkValue << 1) + (m_slotNo & 0x3U); // Logical Slot Number - csbkValue = (csbkValue << 1) + 0U; // High Rate Flag - Always Single Slot Data - csbkValue = (csbkValue << 1) + ((m_emergency) ? 1U : 0U); // Emergency - csbkValue = (csbkValue << 1) + ((m_siteOffsetTiming) ? 1U : 0U); // Site Timing: Aligned or Offset - csbkValue = (csbkValue << 24) + m_dstId; // Talkgroup ID - csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address - break; - - case CSBKO_TD_GRANT: - csbkValue = 0U; - csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Physical Channel 1 - csbkValue = (csbkValue << 1) + (m_slotNo & 0x3U); // Logical Slot Number - csbkValue = (csbkValue << 1) + 0U; // High Rate Flag - Always Single Slot Data - csbkValue = (csbkValue << 1) + ((m_emergency) ? 1U : 0U); // Emergency - csbkValue = (csbkValue << 1) + ((m_siteOffsetTiming) ? 1U : 0U); // Site Timing: Aligned or Offset - csbkValue = (csbkValue << 24) + m_dstId; // Talkgroup ID - csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address - break; - - case CSBKO_BROADCAST: - { - csbkValue = 0U; - if (!m_Cdef) { - csbkValue = m_anncType; // Announcement Type - } - - switch (m_anncType) - { - case BCAST_ANNC_ANN_WD_TSCC: - // Broadcast Parms 1 - csbkValue = (csbkValue << 4) + 0U; // Reserved - csbkValue = (csbkValue << 4) + (m_colorCode & 0x0FU); // Color Code 1 - csbkValue = (csbkValue << 4) + (m_colorCode & 0x0FU); // Color Code 2 - csbkValue = (csbkValue << 1) + ((m_annWdCh1) ? 1U : 0U); // Announce/Withdraw Channel 1 - csbkValue = (csbkValue << 1) + ((m_annWdCh2) ? 1U : 0U); // Announce/Withdraw Channel 2 - - csbkValue = (csbkValue << 1) + ((m_siteData.requireReg()) ? 1U : 0U); // Require Registration - csbkValue = (csbkValue << 4) + (m_backoffNo & 0x0FU); // Backoff Number - csbkValue = (csbkValue << 16) + m_siteData.systemIdentity(); // Site Identity - - // Broadcast Parms 2 - csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Channel 1 - csbkValue = (csbkValue << 12) + (m_logicalCh2 & 0xFFFU); // Logical Channel 2 - break; - case BCAST_ANNC_CHAN_FREQ: - { - uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125); - float calcTxOffset = m_siteIdenEntry.txOffsetMhz() * 1000000; - const uint32_t multiple = 100000; - - // calculate Rx frequency - uint32_t rxFrequency = (uint32_t)((m_siteIdenEntry.baseFrequency() + ((calcSpace * 125) * m_logicalCh1)) + calcTxOffset); - - // generate frequency in mhz - uint32_t rxFreqMhz = rxFrequency + multiple / 2; - rxFreqMhz -= rxFreqMhz % multiple; - rxFreqMhz /= multiple * 10; - - // generate khz offset - uint32_t rxFreqKhz = rxFrequency - (rxFreqMhz * 1000000); - - // calculate Tx Frequency - uint32_t txFrequency = (uint32_t)((m_siteIdenEntry.baseFrequency() + ((calcSpace * 125) * m_logicalCh1))); - - // generate frequency in mhz - uint32_t txFreqMhz = txFrequency + multiple / 2; - txFreqMhz -= txFreqMhz % multiple; - txFreqMhz /= multiple * 10; - - // generate khz offset - uint32_t txFreqKhz = txFrequency - (txFreqMhz * 1000000); - - csbkValue = 0U; // Cdef Type (always 0 for ANN_WD_TSCC) - csbkValue = (csbkValue << 2) + 0U; // Reserved - csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Channel - csbkValue = (csbkValue << 10) + (txFreqMhz & 0x7FFU); // Transmit Freq Mhz - csbkValue = (csbkValue << 13) + (txFreqKhz & 0x3FFFU); // Transmit Freq Offset Khz - csbkValue = (csbkValue << 10) + (rxFreqMhz & 0x7FFU); // Receive Freq Mhz - csbkValue = (csbkValue << 13) + (rxFreqKhz & 0x3FFFU); // Receive Freq Khz - } - break; - case BCAST_ANNC_SITE_PARMS: - // Broadcast Parms 1 - csbkValue = (csbkValue << 14) + m_siteData.systemIdentity(true); // Site Identity (Broadcast Parms 1) - - csbkValue = (csbkValue << 1) + ((m_siteData.requireReg()) ? 1U : 0U); // Require Registration - csbkValue = (csbkValue << 4) + (m_backoffNo & 0x0FU); // Backoff Number - csbkValue = (csbkValue << 16) + m_siteData.systemIdentity(); // Site Identity - - // Broadcast Parms 2 - csbkValue = (csbkValue << 1) + 0U; // Roaming TG Subscription/Attach - csbkValue = (csbkValue << 1) + ((m_hibernating) ? 1U : 0U); // TSCC Hibernating - csbkValue = (csbkValue << 22) + 0U; // Broadcast Parms 2 (Reserved) - break; - } - } - break; - - default: - csbkValue = - (m_GI ? 0x40U : 0x00U) + // Group or Invididual - (m_dataContent ? 0x80U : 0x00U); - csbkValue = (csbkValue << 8) + m_CBF; // Blocks to Follow - csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address - csbkValue = (csbkValue << 24) + m_dstId; // Target Radio Address - - if ((m_FID == FID_ETSI) || (m_FID == FID_DMRA)) { - LogError(LOG_DMR, "CSBK::encode(), unknown CSBK type, csbko = $%02X", m_CSBKO); - } - break; - } - - // internal DMR vendor opcodes - if (m_FID == FID_DVM) { - switch (m_CSBKO) { - case CSBKO_DVM_GIT_HASH: - csbkValue = 0U; - csbkValue = g_gitHashBytes[0]; // ... - csbkValue = (csbkValue << 8) + (g_gitHashBytes[1U]); // ... - csbkValue = (csbkValue << 8) + (g_gitHashBytes[2U]); // ... - csbkValue = (csbkValue << 8) + (g_gitHashBytes[3U]); // ... - csbkValue = (csbkValue << 16) + 0U; - csbkValue = (csbkValue << 4) + m_siteIdenEntry.channelId(); // Channel ID - csbkValue = (csbkValue << 12) + m_logicalCh1; // Channel Number - break; - default: - csbkValue = - (m_GI ? 0x40U : 0x00U) + // Group or Invididual - (m_dataContent ? 0x80U : 0x00U); - csbkValue = (csbkValue << 8) + m_CBF; // Blocks to Follow - csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address - csbkValue = (csbkValue << 24) + m_dstId; // Target Radio Address - LogError(LOG_DMR, "CSBK::encode(), unknown CSBK type, csbko = $%02X", m_CSBKO); - break; - } - } + __UNIQUE_BUFFER(csbk, uint8_t, DMR_CSBK_LENGTH_BYTES); // split ulong64_t (8 byte) value into bytes csbk[2U] = (uint8_t)((csbkValue >> 56) & 0xFFU); @@ -439,70 +189,132 @@ void CSBK::encode(uint8_t* data) csbk[8U] = (uint8_t)((csbkValue >> 8) & 0xFFU); csbk[9U] = (uint8_t)((csbkValue >> 0) & 0xFFU); + return csbk; +} + +/// +/// Internal helper to decode a control signalling block. +/// +/// +/// +/// True, if TSBK was decoded, otherwise false. +bool CSBK::decode(const uint8_t* data, uint8_t* csbk) +{ + assert(data != nullptr); + assert(csbk != nullptr); + + // decode BPTC (196,96) FEC + edac::BPTC19696 bptc; + bptc.decode(data, csbk); + + // validate the CRC-CCITT 16 csbk[10U] ^= CSBK_CRC_MASK[0U]; csbk[11U] ^= CSBK_CRC_MASK[1U]; - edac::CRC::addCCITT162(csbk, 12U); + bool valid = edac::CRC::checkCCITT162(csbk, DMR_CSBK_LENGTH_BYTES); + if (!valid) { + LogError(LOG_DMR, "CSBK::decode(), failed CRC CCITT-162 check"); + return false; + } + // restore the checksum csbk[10U] ^= CSBK_CRC_MASK[0U]; csbk[11U] ^= CSBK_CRC_MASK[1U]; if (m_verbose) { - Utils::dump(2U, "Encoded CSBK", csbk, DMR_CSBK_LENGTH_BYTES); + Utils::dump(2U, "Decoded CSBK", csbk, DMR_CSBK_LENGTH_BYTES); + } + + m_CSBKO = csbk[0U] & 0x3FU; // CSBKO + m_lastBlock = (csbk[0U] & 0x80U) == 0x80U; // Last Block Marker + m_FID = csbk[1U]; // Feature ID + + m_dataContent = false; + m_CBF = 0U; + + return true; +} + +/// +/// Internal helper to encode a control signalling block. +/// +/// +/// +/// +/// +void CSBK::encode(uint8_t* data, const uint8_t* csbk) +{ + assert(data != nullptr); + assert(csbk != nullptr); + + uint8_t outCsbk[DMR_CSBK_LENGTH_BYTES]; + ::memset(outCsbk, 0x00U, DMR_CSBK_LENGTH_BYTES); + ::memcpy(outCsbk, csbk, DMR_CSBK_LENGTH_BYTES); + + outCsbk[0U] = m_CSBKO; // CSBKO + outCsbk[0U] |= (m_lastBlock) ? 0x80U : 0x00U; // Last Block Marker + if (!m_Cdef) { + outCsbk[1U] = m_FID; // Feature ID + } + else { + outCsbk[1U] = m_colorCode & 0x0FU; // Cdef uses Color Code + } + + outCsbk[10U] ^= CSBK_CRC_MASK[0U]; + outCsbk[11U] ^= CSBK_CRC_MASK[1U]; + + edac::CRC::addCCITT162(outCsbk, 12U); + + outCsbk[10U] ^= CSBK_CRC_MASK[0U]; + outCsbk[11U] ^= CSBK_CRC_MASK[1U]; + + if (m_verbose) { + Utils::dump(2U, "Encoded CSBK", outCsbk, DMR_CSBK_LENGTH_BYTES); } // encode BPTC (196,96) FEC edac::BPTC19696 bptc; - bptc.encode(csbk, data); + bptc.encode(outCsbk, data); } -// --------------------------------------------------------------------------- -// Private Class Members -// --------------------------------------------------------------------------- - /// -/// Initializes a new instance of the CSBK class. +/// Internal helper to copy the the class. /// -/// -CSBK::CSBK(SiteData siteData) : - m_verbose(false), - m_colorCode(0U), - m_lastBlock(true), - m_Cdef(false), - m_CSBKO(CSBKO_NONE), - m_FID(0x00U), - m_GI(false), - m_bsId(0U), - m_srcId(0U), - m_dstId(0U), - m_dataContent(false), - m_CBF(0U), - m_emergency(false), - m_privacy(false), - m_supplementData(false), - m_priority(0U), - m_broadcast(false), - m_proxy(false), - m_backoffNo(1U), - m_nRandWait(DEFAULT_NRAND_WAIT), - m_serviceOptions(0U), - m_serviceExtra(0U), - m_serviceKind(0U), - m_targetAddress(TGT_ADRS_TGID), - m_response(0U), - m_reason(0U), - m_anncType(BCAST_ANNC_SITE_PARMS), - m_hibernating(false), - m_annWdCh1(false), - m_logicalCh1(DMR_CHNULL), - m_annWdCh2(false), - m_logicalCh2(DMR_CHNULL), - m_slotNo(0U), - m_siteTSSync(false), - m_siteOffsetTiming(false), - m_alohaMask(0U), - m_siteData(siteData), - m_siteIdenEntry(lookups::IdenTable()) +/// +void CSBK::copy(const CSBK& data) { - /* stub */ + m_colorCode = data.m_colorCode; + + m_lastBlock = data.m_lastBlock; + m_Cdef = data.m_Cdef; + + m_CSBKO = data.m_CSBKO; + m_FID = data.m_FID; + + m_GI = data.m_GI; + + m_srcId = data.m_srcId; + m_dstId = data.m_dstId; + + m_dataContent = data.m_dataContent; + + m_CBF = data.m_CBF; + + m_emergency = data.m_emergency; + m_privacy = data.m_privacy; + m_supplementData = data.m_supplementData; + m_priority = data.m_priority; + m_broadcast = data.m_broadcast; + m_proxy = data.m_proxy; + + m_response = data.m_response; + m_response = data.m_reason; + + m_siteOffsetTiming = data.m_siteOffsetTiming; + + m_logicalCh1 = data.m_logicalCh1; + m_logicalCh2 = data.m_logicalCh2; + m_slotNo = data.m_slotNo; + + m_siteIdenEntry = data.m_siteIdenEntry; } diff --git a/dmr/lc/CSBK.h b/dmr/lc/CSBK.h index 80afbdc4..a8bbb28b 100644 --- a/dmr/lc/CSBK.h +++ b/dmr/lc/CSBK.h @@ -47,120 +47,111 @@ namespace dmr class HOST_SW_API CSBK { public: + /// Initializes a copy instance of the CSBK class. + CSBK(const CSBK& data); /// Initializes a new instance of the CSBK class. - CSBK(SiteData siteData, lookups::IdenTable entry); - /// Initializes a new instance of the CSBK class. - CSBK(SiteData siteData, lookups::IdenTable entry, bool verbose); + CSBK(); /// Finalizes a instance of the CSBK class. - ~CSBK(); + virtual ~CSBK(); /// Decodes a DMR CSBK. - bool decode(const uint8_t* data); + virtual bool decode(const uint8_t* data) = 0; /// Encodes a DMR CSBK. - void encode(uint8_t* data); + virtual void encode(uint8_t* data) = 0; - public: - /// Flag indicating verbose log output. - __PROPERTY(bool, verbose, Verbose); + /// Regenerate a DMR CSBK without decoding. + /// This is because the DMR archeticture allows fall-thru of unsupported CSBKs. + static bool regenerate(uint8_t* data); - /// DMR access color code. - __PROPERTY(uint8_t, colorCode, ColorCode); + /// Sets the flag indicating verbose log output. + static void setVerbose(bool verbose) { m_verbose = verbose; } + + /** Local Site data */ + /// Gets the local site data. + static SiteData getSiteData() { return m_siteData; } + /// Sets the local site data. + static void setSiteData(SiteData siteData) { m_siteData = siteData; } + public: /** Common Data */ + /// DMR access color code. + __PROTECTED_PROPERTY(uint8_t, colorCode, ColorCode); + /// Flag indicating this is the last TSBK in a sequence of TSBKs. - __PROPERTY(bool, lastBlock, LastBlock); + __PROTECTED_PROPERTY(bool, lastBlock, LastBlock); /// Flag indicating whether the CSBK is a Cdef block. - __PROPERTY(bool, Cdef, Cdef); + __PROTECTED_PROPERTY(bool, Cdef, Cdef); /// CSBK opcode. - __PROPERTY(uint8_t, CSBKO, CSBKO); + __PROTECTED_PROPERTY(uint8_t, CSBKO, CSBKO); /// CSBK feature ID. - __PROPERTY(uint8_t, FID, FID); + __PROTECTED_PROPERTY(uint8_t, FID, FID); /// Flag indicating whether the CSBK is group or individual. - __PROPERTY(bool, GI, GI); + __PROTECTED_PROPERTY(bool, GI, GI); - /// Base Station ID. - __READONLY_PROPERTY(uint32_t, bsId, BSId); /// 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); /// - __READONLY_PROPERTY(bool, dataContent, DataContent); + __PROTECTED_READONLY_PROPERTY(bool, dataContent, DataContent); /// Number of blocks to follow. - __PROPERTY(uint8_t, CBF, CBF); + __PROTECTED_PROPERTY(uint8_t, CBF, CBF); - /** Service Options */ + /** Common Service Options */ /// Flag indicating the emergency bits are set. - __PROPERTY(bool, emergency, Emergency); + __PROTECTED_PROPERTY(bool, emergency, Emergency); /// Flag indicating that privacy is enabled. - __PROPERTY(bool, privacy, Privacy); + __PROTECTED_PROPERTY(bool, privacy, Privacy); /// Flag indicating that supplementary data is required. - __PROPERTY(bool, supplementData, SupplementData); + __PROTECTED_PROPERTY(bool, supplementData, SupplementData); /// Priority level for the traffic. - __PROPERTY(uint8_t, priority, Priority); + __PROTECTED_PROPERTY(uint8_t, priority, Priority); /// Flag indicating a broadcast service. - __PROPERTY(bool, broadcast, Broadcast); + __PROTECTED_PROPERTY(bool, broadcast, Broadcast); /// Flag indicating a proxy. - __PROPERTY(bool, proxy, Proxy); - - /** Tier III */ - /// Backoff Number. - __PROPERTY(uint8_t, backoffNo, BackoffNo); - /// Random Access Wait Delay. - __PROPERTY(uint8_t, nRandWait, NRandWait); - - /// Service Options. - __PROPERTY(uint8_t, serviceOptions, ServiceOptions); - /// Service Extra Options. - __PROPERTY(uint8_t, serviceExtra, ServiceExtra); - /// Service Kind. - __PROPERTY(uint8_t, serviceKind, ServiceKind); - - /// Destination/Target address type. - __PROPERTY(uint8_t, targetAddress, TargetAddress); + __PROTECTED_PROPERTY(bool, proxy, Proxy); /// Response information. - __PROPERTY(uint8_t, response, Response); + __PROTECTED_PROPERTY(uint8_t, response, Response); /// Reason type. - __PROPERTY(uint8_t, reason, Reason); + __PROTECTED_PROPERTY(uint8_t, reason, Reason); - /// Broadcast Announcment Type. - __PROPERTY(uint8_t, anncType, AnncType); - /// Broadcast Hibernation Flag. - __PROPERTY(bool, hibernating, Hibernating); + /** Tier 3 */ + /// Site offset timing. + __PROTECTED_PROPERTY(bool, siteOffsetTiming, SiteOffsetTiming); - /// Broadcast Announce/Withdraw Channel 1 Flag. - __PROPERTY(bool, annWdCh1, AnnWdCh1); /// Broadcast Logical Channel ID 1. - __PROPERTY(uint16_t, logicalCh1, LogicalCh1); - /// Broadcast Announce/Withdraw Channel 2 Flag. - __PROPERTY(bool, annWdCh2, AnnWdCh2); + __PROTECTED_PROPERTY(uint16_t, logicalCh1, LogicalCh1); /// Broadcast Logical Channel ID 2. - __PROPERTY(uint16_t, logicalCh2, LogicalCh2); - + __PROTECTED_PROPERTY(uint16_t, logicalCh2, LogicalCh2); /// Logical Channel Slot Number. - __PROPERTY(uint8_t, slotNo, SlotNo); - - /// Aloha Site Time Slot Synchronization. - __PROPERTY(bool, siteTSSync, SiteTSSync); - /// Aloha site users offset timing. - __PROPERTY(bool, siteOffsetTiming, SiteOffsetTiming); - /// Aloha MS mask. - __PROPERTY(uint8_t, alohaMask, AlohaMask); + __PROTECTED_PROPERTY(uint8_t, slotNo, SlotNo); /** Local Site data */ - /// Local Site Data. - __PROPERTY_PLAIN(SiteData, siteData, siteData); /// Local Site Identity Entry. - __PROPERTY_PLAIN(lookups::IdenTable, siteIdenEntry, siteIdenEntry); + __PROTECTED_PROPERTY_PLAIN(lookups::IdenTable, siteIdenEntry, siteIdenEntry); - private: - /// Initializes a new instance of the CSBK class. - CSBK(SiteData siteData); + protected: + static bool m_verbose; + + /** Local Site data */ + static SiteData m_siteData; + + /// Internal helper to convert CSBK bytes to a 64-bit long value. + static ulong64_t toValue(const uint8_t* Csbk); + /// Internal helper to convert a 64-bit long value to CSBK bytes. + static std::unique_ptr fromValue(const ulong64_t csbkValue); + + /// Internal helper to decode a control signalling block. + bool decode(const uint8_t* data, uint8_t* csbk); + /// Internal helper to encode a control signalling block. + void encode(uint8_t* data, const uint8_t* csbk); + + __PROTECTED_COPY(CSBK); }; } // namespace lc } // namespace dmr diff --git a/dmr/lc/csbk/CSBKFactory.cpp b/dmr/lc/csbk/CSBKFactory.cpp new file mode 100644 index 00000000..64c31dc9 --- /dev/null +++ b/dmr/lc/csbk/CSBKFactory.cpp @@ -0,0 +1,146 @@ +/** +* 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 "dmr/lc/csbk/CSBKFactory.h" +#include "edac/BPTC19696.h" +#include "edac/CRC.h" +#include "Log.h" +#include "Utils.h" + +using namespace dmr::lc::csbk; +using namespace dmr::lc; +using namespace dmr; + +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the CSBKFactory class. +/// +CSBKFactory::CSBKFactory() +{ + /* stub */ +} + +/// +/// Finalizes a instance of CSBKFactory class. +/// +CSBKFactory::~CSBKFactory() +{ + /* stub */ +} + +/// +/// Create an instance of a CSBK. +/// +/// +/// True, if CSBK was decoded, otherwise false. +std::unique_ptr CSBKFactory::createCSBK(const uint8_t* data) +{ + assert(data != nullptr); + + uint8_t csbk[DMR_CSBK_LENGTH_BYTES]; + + // decode BPTC (196,96) FEC + edac::BPTC19696 bptc; + bptc.decode(data, csbk); + + // validate the CRC-CCITT 16 + csbk[10U] ^= CSBK_CRC_MASK[0U]; + csbk[11U] ^= CSBK_CRC_MASK[1U]; + + bool valid = edac::CRC::checkCCITT162(csbk, DMR_CSBK_LENGTH_BYTES); + if (!valid) { + LogError(LOG_DMR, "CSBK::decode(), failed CRC CCITT-162 check"); + return nullptr; + } + + // restore the checksum + csbk[10U] ^= CSBK_CRC_MASK[0U]; + csbk[11U] ^= CSBK_CRC_MASK[1U]; + + uint8_t CSBKO = csbk[0U] & 0x3FU; // CSBKO + uint8_t FID = csbk[1U]; // Feature ID + + switch (CSBKO) { + case CSBKO_BSDWNACT: + return decode(new CSBK_BSDWNACT(), data); + case CSBKO_UU_V_REQ: + return decode(new CSBK_UU_V_REQ(), data); + case CSBKO_UU_ANS_RSP: + return decode(new CSBK_UU_ANS_RSP(), data); + case CSBKO_PRECCSBK: + return decode(new CSBK_PRECCSBK(), data); + case CSBKO_RAND: // CSBKO_CALL_ALRT when FID == FID_DMRA + switch (FID) + { + case FID_DMRA: + return decode(new CSBK_CALL_ALRT(), data); + case FID_ETSI: + default: + return decode(new CSBK_RAND(), data); + } + case CSBKO_EXT_FNCT: + return decode(new CSBK_EXT_FNCT(), data); + case CSBKO_NACK_RSP: + return decode(new CSBK_NACK_RSP(), data); + + /** Tier 3 */ + case CSBKO_ACK_RSP: + return decode(new CSBK_ACK_RSP(), data); + + default: + LogError(LOG_DMR, "CSBKFactory::create(), unknown CSBK type, csbko = $%02X", CSBKO); + break; + } + + return nullptr; +} + +// --------------------------------------------------------------------------- +// Private Class Members +// --------------------------------------------------------------------------- + +/// +/// +/// +/// +/// +/// +std::unique_ptr CSBKFactory::decode(CSBK* csbk, const uint8_t* data) +{ + assert(csbk != nullptr); + assert(data != nullptr); + + if (!csbk->decode(data)) { + return nullptr; + } + + return std::unique_ptr(csbk); +} diff --git a/dmr/lc/csbk/CSBKFactory.h b/dmr/lc/csbk/CSBKFactory.h new file mode 100644 index 00000000..e7c78511 --- /dev/null +++ b/dmr/lc/csbk/CSBKFactory.h @@ -0,0 +1,78 @@ +/** +* 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(__DMR_LC__CSBK_FACTORY_H__) +#define __DMR_LC__CSBK_FACTORY_H__ + +#include "Defines.h" + +#include "dmr/lc/CSBK.h" +#include "dmr/lc/csbk/CSBK_ACK_RSP.h" +#include "dmr/lc/csbk/CSBK_ALOHA.h" +#include "dmr/lc/csbk/CSBK_BROADCAST.h" +#include "dmr/lc/csbk/CSBK_BSDWNACT.h" +#include "dmr/lc/csbk/CSBK_CALL_ALRT.h" +#include "dmr/lc/csbk/CSBK_DVM_GIT_HASH.h" +#include "dmr/lc/csbk/CSBK_EXT_FNCT.h" +#include "dmr/lc/csbk/CSBK_NACK_RSP.h" +#include "dmr/lc/csbk/CSBK_PD_GRANT.h" +#include "dmr/lc/csbk/CSBK_PRECCSBK.h" +#include "dmr/lc/csbk/CSBK_PV_GRANT.h" +#include "dmr/lc/csbk/CSBK_RAND.h" +#include "dmr/lc/csbk/CSBK_TD_GRANT.h" +#include "dmr/lc/csbk/CSBK_TV_GRANT.h" +#include "dmr/lc/csbk/CSBK_UU_ANS_RSP.h" +#include "dmr/lc/csbk/CSBK_UU_V_REQ.h" + +namespace dmr +{ + namespace lc + { + namespace csbk + { + // --------------------------------------------------------------------------- + // Class Declaration + // Helper class to instantiate an instance of a CSBK. + // --------------------------------------------------------------------------- + + class HOST_SW_API CSBKFactory { + public: + /// Initializes a new instance of the CSBKFactory class. + CSBKFactory(); + /// Finalizes a instance of the CSBKFactory class. + ~CSBKFactory(); + + /// Create an instance of a CSBK. + static std::unique_ptr createCSBK(const uint8_t* data); + + private: + /// + static std::unique_ptr decode(CSBK* tsbk, const uint8_t* data); + }; + } // namespace csbk + } // namespace lc +} // namespace dmr + +#endif // __DMR_LC__CSBK_FACTORY_H__ diff --git a/dmr/lc/csbk/CSBK_ACK_RSP.cpp b/dmr/lc/csbk/CSBK_ACK_RSP.cpp new file mode 100644 index 00000000..f41832bd --- /dev/null +++ b/dmr/lc/csbk/CSBK_ACK_RSP.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 "dmr/lc/csbk/CSBK_ACK_RSP.h" +#include "Log.h" +#include "Utils.h" + +using namespace dmr::lc::csbk; +using namespace dmr::lc; +using namespace dmr; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the CSBK_ACK_RSP class. +/// +CSBK_ACK_RSP::CSBK_ACK_RSP() : CSBK() +{ + m_CSBKO = CSBKO_ACK_RSP; +} + +/// +/// Decode a control signalling block. +/// +/// +/// True, if CSBK was decoded, otherwise false. +bool CSBK_ACK_RSP::decode(const uint8_t* data) +{ + assert(data != NULL); + + uint8_t csbk[DMR_CSBK_LENGTH_BYTES]; + ::memset(csbk, 0x00U, DMR_CSBK_LENGTH_BYTES); + + bool ret = CSBK::decode(data, csbk); + if (!ret) + return false; + + ulong64_t csbkValue = CSBK::toValue(csbk); + + m_GI = (((csbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Group/Individual Flag + m_reason = (uint8_t)((csbkValue >> 33) & 0xFFU); // Reason Code + m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFU); // Target Radio Address + m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address + + return true; +} + +/// +/// Encode a control signalling block. +/// +/// +void CSBK_ACK_RSP::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t csbkValue = 0U; + + if (m_reason == TS_ACK_RSN_REG) { + csbkValue = 0U; + } else { + csbkValue = (m_GI ? 0x40U : 0x00U) + // Source Type + (m_siteData.siteId() & 0x3FU); // Net + Site LSB + } + csbkValue = (csbkValue << 7) + (m_response & 0x7FU); // Response Information + csbkValue = (csbkValue << 8) + (m_reason & 0xFFU); // Reason Code + csbkValue = (csbkValue << 25) + m_dstId; // Target Radio Address + csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address + + std::unique_ptr csbk = CSBK::fromValue(csbkValue); + CSBK::encode(data, csbk.get()); +} diff --git a/dmr/lc/csbk/CSBK_ACK_RSP.h b/dmr/lc/csbk/CSBK_ACK_RSP.h new file mode 100644 index 00000000..11b283ef --- /dev/null +++ b/dmr/lc/csbk/CSBK_ACK_RSP.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(__DMR_LC_CSBK__CSBK_ACK_RSP_H__) +#define __DMR_LC_CSBK__CSBK_ACK_RSP_H__ + +#include "Defines.h" +#include "dmr/lc/CSBK.h" + +namespace dmr +{ + namespace lc + { + namespace csbk + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements ACK RSP - Acknowledge Response + // --------------------------------------------------------------------------- + + class HOST_SW_API CSBK_ACK_RSP : public CSBK { + public: + /// Initializes a new instance of the CSBK_ACK_RSP class. + CSBK_ACK_RSP(); + + /// Decode a control signalling block. + virtual bool decode(const uint8_t* data); + /// Encode a control signalling block. + virtual void encode(uint8_t* data); + }; + } // namespace csbk + } // namespace lc +} // namespace dmr + +#endif // __DMR_LC_CSBK__CSBK_ACK_RSP_H__ diff --git a/dmr/lc/csbk/CSBK_ALOHA.cpp b/dmr/lc/csbk/CSBK_ALOHA.cpp new file mode 100644 index 00000000..0d5c701b --- /dev/null +++ b/dmr/lc/csbk/CSBK_ALOHA.cpp @@ -0,0 +1,112 @@ +/** +* 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 "dmr/lc/csbk/CSBK_ALOHA.h" +#include "Log.h" +#include "Utils.h" + +using namespace dmr::lc::csbk; +using namespace dmr::lc; +using namespace dmr; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the CSBK_ALOHA class. +/// +CSBK_ALOHA::CSBK_ALOHA() : CSBK(), + m_siteTSSync(false), + m_alohaMask(0U), + m_backoffNo(1U), + m_nRandWait(DEFAULT_NRAND_WAIT) +{ + m_CSBKO = CSBKO_ALOHA; +} + +/// +/// Decode a control signalling block. +/// +/// +/// True, if CSBK was decoded, otherwise false. +bool CSBK_ALOHA::decode(const uint8_t* data) +{ + assert(data != NULL); + + /* stub */ + + return true; +} + +/// +/// Encode a control signalling block. +/// +/// +void CSBK_ALOHA::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t csbkValue = 0U; + + csbkValue = (csbkValue << 2) + 0U; // Reserved + csbkValue = (csbkValue << 1) + ((m_siteTSSync) ? 1U : 0U); // Site Time Slot Synchronization + csbkValue = (csbkValue << 3) + DMR_ALOHA_VER_151; // DMR Spec. Version (1.5.1) + csbkValue = (csbkValue << 1) + ((m_siteOffsetTiming) ? 1U : 0U); // Site Timing: Aligned or Offset + csbkValue = (csbkValue << 1) + ((m_siteData.netActive()) ? 1U : 0U); // Site Networked + csbkValue = (csbkValue << 5) + (m_alohaMask & 0x1FU); // MS Mask + csbkValue = (csbkValue << 2) + 0U; // Service Function + csbkValue = (csbkValue << 4) + (m_nRandWait & 0x0FU); // Random Access Wait + csbkValue = (csbkValue << 1) + ((m_siteData.requireReg()) ? 1U : 0U); // Require Registration + csbkValue = (csbkValue << 4) + (m_backoffNo & 0x0FU); // Backoff Number + csbkValue = (csbkValue << 16) + m_siteData.systemIdentity(); // Site Identity + csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address + + std::unique_ptr csbk = CSBK::fromValue(csbkValue); + CSBK::encode(data, csbk.get()); +} + +// --------------------------------------------------------------------------- +// Private Class Members +// --------------------------------------------------------------------------- + +/// +/// Internal helper to copy the the class. +/// +/// +void CSBK_ALOHA::copy(const CSBK_ALOHA& data) +{ + CSBK::copy(data); + + m_siteTSSync = data.m_siteTSSync; + m_alohaMask = data.m_alohaMask; + + m_backoffNo = data.m_backoffNo; + m_nRandWait = data.m_nRandWait; +} diff --git a/dmr/lc/csbk/CSBK_ALOHA.h b/dmr/lc/csbk/CSBK_ALOHA.h new file mode 100644 index 00000000..01e10502 --- /dev/null +++ b/dmr/lc/csbk/CSBK_ALOHA.h @@ -0,0 +1,70 @@ +/** +* 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(__DMR_LC_CSBK__CSBK_ALOHA_H__) +#define __DMR_LC_CSBK__CSBK_ALOHA_H__ + +#include "Defines.h" +#include "dmr/lc/CSBK.h" + +namespace dmr +{ + namespace lc + { + namespace csbk + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements ALOHA - Aloha PDUs for the random access protocol + // --------------------------------------------------------------------------- + + class HOST_SW_API CSBK_ALOHA : public CSBK { + public: + /// Initializes a new instance of the CSBK_ALOHA class. + CSBK_ALOHA(); + + /// Decode a control signalling block. + virtual bool decode(const uint8_t* data); + /// Encode a control signalling block. + virtual void encode(uint8_t* data); + + public: + /// Aloha Site Time Slot Synchronization. + __PROPERTY(bool, siteTSSync, SiteTSSync); + /// Aloha MS mask. + __PROPERTY(uint8_t, alohaMask, AlohaMask); + + /// Backoff Number. + __PROPERTY(uint8_t, backoffNo, BackoffNo); + /// Random Access Wait Delay. + __PROPERTY(uint8_t, nRandWait, NRandWait); + + __COPY(CSBK_ALOHA); + }; + } // namespace csbk + } // namespace lc +} // namespace dmr + +#endif // __DMR_LC_CSBK__CSBK_ALOHA_H__ diff --git a/dmr/lc/csbk/CSBK_BROADCAST.cpp b/dmr/lc/csbk/CSBK_BROADCAST.cpp new file mode 100644 index 00000000..c9f4ad13 --- /dev/null +++ b/dmr/lc/csbk/CSBK_BROADCAST.cpp @@ -0,0 +1,174 @@ +/** +* 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 "dmr/lc/csbk/CSBK_BROADCAST.h" +#include "Log.h" +#include "Utils.h" + +using namespace dmr::lc::csbk; +using namespace dmr::lc; +using namespace dmr; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the CSBK_BROADCAST class. +/// +CSBK_BROADCAST::CSBK_BROADCAST() : CSBK(), + m_anncType(BCAST_ANNC_SITE_PARMS), + m_hibernating(false), + m_annWdCh1(false), + m_annWdCh2(false), + m_backoffNo(1U) +{ + m_CSBKO = CSBKO_BROADCAST; +} + +/// +/// Decode a control signalling block. +/// +/// +/// True, if CSBK was decoded, otherwise false. +bool CSBK_BROADCAST::decode(const uint8_t* data) +{ + assert(data != NULL); + + /* stub */ + + return true; +} + +/// +/// Encode a control signalling block. +/// +/// +void CSBK_BROADCAST::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t csbkValue = 0U; + + if (!m_Cdef) { + csbkValue = m_anncType; // Announcement Type + } + + switch (m_anncType) + { + case BCAST_ANNC_ANN_WD_TSCC: + // Broadcast Parms 1 + csbkValue = (csbkValue << 4) + 0U; // Reserved + csbkValue = (csbkValue << 4) + (m_colorCode & 0x0FU); // Color Code 1 + csbkValue = (csbkValue << 4) + (m_colorCode & 0x0FU); // Color Code 2 + csbkValue = (csbkValue << 1) + ((m_annWdCh1) ? 1U : 0U); // Announce/Withdraw Channel 1 + csbkValue = (csbkValue << 1) + ((m_annWdCh2) ? 1U : 0U); // Announce/Withdraw Channel 2 + + csbkValue = (csbkValue << 1) + ((m_siteData.requireReg()) ? 1U : 0U); // Require Registration + csbkValue = (csbkValue << 4) + (m_backoffNo & 0x0FU); // Backoff Number + csbkValue = (csbkValue << 16) + m_siteData.systemIdentity(); // Site Identity + + // Broadcast Parms 2 + csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Channel 1 + csbkValue = (csbkValue << 12) + (m_logicalCh2 & 0xFFFU); // Logical Channel 2 + break; + case BCAST_ANNC_CHAN_FREQ: + { + uint32_t calcSpace = (uint32_t)(m_siteIdenEntry.chSpaceKhz() / 0.125); + float calcTxOffset = m_siteIdenEntry.txOffsetMhz() * 1000000; + const uint32_t multiple = 100000; + + // calculate Rx frequency + uint32_t rxFrequency = (uint32_t)((m_siteIdenEntry.baseFrequency() + ((calcSpace * 125) * m_logicalCh1)) + calcTxOffset); + + // generate frequency in mhz + uint32_t rxFreqMhz = rxFrequency + multiple / 2; + rxFreqMhz -= rxFreqMhz % multiple; + rxFreqMhz /= multiple * 10; + + // generate khz offset + uint32_t rxFreqKhz = rxFrequency - (rxFreqMhz * 1000000); + + // calculate Tx Frequency + uint32_t txFrequency = (uint32_t)((m_siteIdenEntry.baseFrequency() + ((calcSpace * 125) * m_logicalCh1))); + + // generate frequency in mhz + uint32_t txFreqMhz = txFrequency + multiple / 2; + txFreqMhz -= txFreqMhz % multiple; + txFreqMhz /= multiple * 10; + + // generate khz offset + uint32_t txFreqKhz = txFrequency - (txFreqMhz * 1000000); + + csbkValue = 0U; // Cdef Type (always 0 for ANN_WD_TSCC) + csbkValue = (csbkValue << 2) + 0U; // Reserved + csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Channel + csbkValue = (csbkValue << 10) + (txFreqMhz & 0x7FFU); // Transmit Freq Mhz + csbkValue = (csbkValue << 13) + (txFreqKhz & 0x3FFFU); // Transmit Freq Offset Khz + csbkValue = (csbkValue << 10) + (rxFreqMhz & 0x7FFU); // Receive Freq Mhz + csbkValue = (csbkValue << 13) + (rxFreqKhz & 0x3FFFU); // Receive Freq Khz + } + break; + case BCAST_ANNC_SITE_PARMS: + // Broadcast Parms 1 + csbkValue = (csbkValue << 14) + m_siteData.systemIdentity(true); // Site Identity (Broadcast Parms 1) + + csbkValue = (csbkValue << 1) + ((m_siteData.requireReg()) ? 1U : 0U); // Require Registration + csbkValue = (csbkValue << 4) + (m_backoffNo & 0x0FU); // Backoff Number + csbkValue = (csbkValue << 16) + m_siteData.systemIdentity(); // Site Identity + + // Broadcast Parms 2 + csbkValue = (csbkValue << 1) + 0U; // Roaming TG Subscription/Attach + csbkValue = (csbkValue << 1) + ((m_hibernating) ? 1U : 0U); // TSCC Hibernating + csbkValue = (csbkValue << 22) + 0U; // Broadcast Parms 2 (Reserved) + break; + } + + std::unique_ptr csbk = CSBK::fromValue(csbkValue); + CSBK::encode(data, csbk.get()); +} + +// --------------------------------------------------------------------------- +// Private Class Members +// --------------------------------------------------------------------------- + +/// +/// Internal helper to copy the the class. +/// +/// +void CSBK_BROADCAST::copy(const CSBK_BROADCAST& data) +{ + CSBK::copy(data); + + m_anncType = data.m_anncType; + m_hibernating = data.m_hibernating; + + m_annWdCh1 = data.m_annWdCh1; + m_annWdCh2 = data.m_annWdCh2; +} diff --git a/dmr/lc/csbk/CSBK_BROADCAST.h b/dmr/lc/csbk/CSBK_BROADCAST.h new file mode 100644 index 00000000..03f106d1 --- /dev/null +++ b/dmr/lc/csbk/CSBK_BROADCAST.h @@ -0,0 +1,73 @@ +/** +* 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(__DMR_LC_CSBK__CSBK_BROADCAST_H__) +#define __DMR_LC_CSBK__CSBK_BROADCAST_H__ + +#include "Defines.h" +#include "dmr/lc/CSBK.h" + +namespace dmr +{ + namespace lc + { + namespace csbk + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements BCAST - Announcement PDUs + // --------------------------------------------------------------------------- + + class HOST_SW_API CSBK_BROADCAST : public CSBK { + public: + /// Initializes a new instance of the CSBK_BROADCAST class. + CSBK_BROADCAST(); + + /// Decode a control signalling block. + virtual bool decode(const uint8_t* data); + /// Encode a control signalling block. + virtual void encode(uint8_t* data); + + public: + /// Broadcast Announcment Type. + __PROPERTY(uint8_t, anncType, AnncType); + /// Broadcast Hibernation Flag. + __PROPERTY(bool, hibernating, Hibernating); + + /// Broadcast Announce/Withdraw Channel 1 Flag. + __PROPERTY(bool, annWdCh1, AnnWdCh1); + /// Broadcast Announce/Withdraw Channel 2 Flag. + __PROPERTY(bool, annWdCh2, AnnWdCh2); + + /// Backoff Number. + __PROPERTY(uint8_t, backoffNo, BackoffNo); + + __COPY(CSBK_BROADCAST); + }; + } // namespace csbk + } // namespace lc +} // namespace dmr + +#endif // __DMR_LC_CSBK__CSBK_BROADCAST_H__ diff --git a/dmr/lc/csbk/CSBK_BSDWNACT.cpp b/dmr/lc/csbk/CSBK_BSDWNACT.cpp new file mode 100644 index 00000000..8235abcc --- /dev/null +++ b/dmr/lc/csbk/CSBK_BSDWNACT.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 "dmr/lc/csbk/CSBK_BSDWNACT.h" +#include "Log.h" +#include "Utils.h" + +using namespace dmr::lc::csbk; +using namespace dmr::lc; +using namespace dmr; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the CSBK_BSDWNACT class. +/// +CSBK_BSDWNACT::CSBK_BSDWNACT() : CSBK(), + m_bsId(0U) +{ + m_CSBKO = CSBKO_BSDWNACT; +} + +/// +/// Decode a control signalling block. +/// +/// +/// True, if CSBK was decoded, otherwise false. +bool CSBK_BSDWNACT::decode(const uint8_t* data) +{ + assert(data != NULL); + + uint8_t csbk[DMR_CSBK_LENGTH_BYTES]; + ::memset(csbk, 0x00U, DMR_CSBK_LENGTH_BYTES); + + bool ret = CSBK::decode(data, csbk); + if (!ret) + return false; + + ulong64_t csbkValue = CSBK::toValue(csbk); + + m_bsId = (uint32_t)((csbkValue >> 24) & 0xFFFFFFU); // Base Station Address + m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address + + return true; +} + +/// +/// Encode a control signalling block. +/// +/// +void CSBK_BSDWNACT::encode(uint8_t* data) +{ + assert(data != NULL); + + /* stub */ +} + +// --------------------------------------------------------------------------- +// Private Class Members +// --------------------------------------------------------------------------- + +/// +/// Internal helper to copy the the class. +/// +/// +void CSBK_BSDWNACT::copy(const CSBK_BSDWNACT& data) +{ + CSBK::copy(data); + + m_bsId = data.m_bsId; +} diff --git a/dmr/lc/csbk/CSBK_BSDWNACT.h b/dmr/lc/csbk/CSBK_BSDWNACT.h new file mode 100644 index 00000000..86ef22c7 --- /dev/null +++ b/dmr/lc/csbk/CSBK_BSDWNACT.h @@ -0,0 +1,63 @@ +/** +* 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(__DMR_LC_CSBK__CSBK_BSDWNACT_H__) +#define __DMR_LC_CSBK__CSBK_BSDWNACT_H__ + +#include "Defines.h" +#include "dmr/lc/CSBK.h" + +namespace dmr +{ + namespace lc + { + namespace csbk + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements BS DWN ACT - BS Outbound Activation + // --------------------------------------------------------------------------- + + class HOST_SW_API CSBK_BSDWNACT : public CSBK { + public: + /// Initializes a new instance of the CSBK_BSDWNACT class. + CSBK_BSDWNACT(); + + /// Decode a control signalling block. + virtual bool decode(const uint8_t* data); + /// Encode a control signalling block. + virtual void encode(uint8_t* data); + + public: + /// Base Station ID. + __READONLY_PROPERTY(uint32_t, bsId, BSId); + + __COPY(CSBK_BSDWNACT); + }; + } // namespace csbk + } // namespace lc +} // namespace dmr + +#endif // __DMR_LC_CSBK__CSBK_BSDWNACT_H__ diff --git a/dmr/lc/csbk/CSBK_CALL_ALRT.cpp b/dmr/lc/csbk/CSBK_CALL_ALRT.cpp new file mode 100644 index 00000000..7ce4546c --- /dev/null +++ b/dmr/lc/csbk/CSBK_CALL_ALRT.cpp @@ -0,0 +1,92 @@ +/** +* 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 "dmr/lc/csbk/CSBK_CALL_ALRT.h" +#include "Log.h" +#include "Utils.h" + +using namespace dmr::lc::csbk; +using namespace dmr::lc; +using namespace dmr; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the CSBK_CALL_ALRT class. +/// +CSBK_CALL_ALRT::CSBK_CALL_ALRT() : CSBK() +{ + m_CSBKO = CSBKO_RAND; + m_FID = FID_DMRA; +} + +/// +/// Decode a control signalling block. +/// +/// +/// True, if CSBK was decoded, otherwise false. +bool CSBK_CALL_ALRT::decode(const uint8_t* data) +{ + assert(data != NULL); + + uint8_t csbk[DMR_CSBK_LENGTH_BYTES]; + ::memset(csbk, 0x00U, DMR_CSBK_LENGTH_BYTES); + + bool ret = CSBK::decode(data, csbk); + if (!ret) + return false; + + ulong64_t csbkValue = CSBK::toValue(csbk); + + m_GI = (((csbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Group/Individual Flag + m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFFFU); // Target Radio Address + m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address + + return true; +} + +/// +/// Encode a control signalling block. +/// +/// +void CSBK_CALL_ALRT::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t csbkValue = 0U; + + csbkValue = (m_GI) ? 0x40U : 0x00U; // Group/Individual Flag + csbkValue = (csbkValue << 32) + m_dstId; // Target Radio Address + csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address + + std::unique_ptr csbk = CSBK::fromValue(csbkValue); + CSBK::encode(data, csbk.get()); +} diff --git a/dmr/lc/csbk/CSBK_CALL_ALRT.h b/dmr/lc/csbk/CSBK_CALL_ALRT.h new file mode 100644 index 00000000..fc24a84d --- /dev/null +++ b/dmr/lc/csbk/CSBK_CALL_ALRT.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(__DMR_LC_CSBK__CSBK_CALL_ALRT_H__) +#define __DMR_LC_CSBK__CSBK_CALL_ALRT_H__ + +#include "Defines.h" +#include "dmr/lc/CSBK.h" + +namespace dmr +{ + namespace lc + { + namespace csbk + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements CALL ALRT - Call Alert + // --------------------------------------------------------------------------- + + class HOST_SW_API CSBK_CALL_ALRT : public CSBK { + public: + /// Initializes a new instance of the CSBK_CALL_ALRT class. + CSBK_CALL_ALRT(); + + /// Decode a control signalling block. + virtual bool decode(const uint8_t* data); + /// Encode a control signalling block. + virtual void encode(uint8_t* data); + }; + } // namespace csbk + } // namespace lc +} // namespace dmr + +#endif // __DMR_LC_CSBK__CSBK_CALL_ALRT_H__ diff --git a/dmr/lc/csbk/CSBK_DVM_GIT_HASH.cpp b/dmr/lc/csbk/CSBK_DVM_GIT_HASH.cpp new file mode 100644 index 00000000..bb72d534 --- /dev/null +++ b/dmr/lc/csbk/CSBK_DVM_GIT_HASH.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 "dmr/lc/csbk/CSBK_DVM_GIT_HASH.h" +#include "HostMain.h" +#include "Log.h" +#include "Utils.h" + +using namespace dmr::lc::csbk; +using namespace dmr::lc; +using namespace dmr; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the CSBK_DVM_GIT_HASH class. +/// +CSBK_DVM_GIT_HASH::CSBK_DVM_GIT_HASH() : CSBK() +{ + m_CSBKO = CSBKO_DVM_GIT_HASH; + m_FID = FID_DVM; +} + +/// +/// Decode a control signalling block. +/// +/// +/// True, if CSBK was decoded, otherwise false. +bool CSBK_DVM_GIT_HASH::decode(const uint8_t* data) +{ + assert(data != NULL); + + /* stub */ + + return true; +} + +/// +/// Encode a control signalling block. +/// +/// +void CSBK_DVM_GIT_HASH::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t csbkValue = 0U; + + csbkValue = g_gitHashBytes[0]; // ... + csbkValue = (csbkValue << 8) + (g_gitHashBytes[1U]); // ... + csbkValue = (csbkValue << 8) + (g_gitHashBytes[2U]); // ... + csbkValue = (csbkValue << 8) + (g_gitHashBytes[3U]); // ... + csbkValue = (csbkValue << 16) + 0U; + csbkValue = (csbkValue << 4) + m_siteIdenEntry.channelId(); // Channel ID + csbkValue = (csbkValue << 12) + m_logicalCh1; // Channel Number + + std::unique_ptr csbk = CSBK::fromValue(csbkValue); + CSBK::encode(data, csbk.get()); +} diff --git a/dmr/lc/csbk/CSBK_DVM_GIT_HASH.h b/dmr/lc/csbk/CSBK_DVM_GIT_HASH.h new file mode 100644 index 00000000..d1a4aab8 --- /dev/null +++ b/dmr/lc/csbk/CSBK_DVM_GIT_HASH.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(__DMR_LC_CSBK__CSBK_DVM_GIT_HASH_H__) +#define __DMR_LC_CSBK__CSBK_DVM_GIT_HASH_H__ + +#include "Defines.h" +#include "dmr/lc/CSBK.h" + +namespace dmr +{ + namespace lc + { + namespace csbk + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements DVM GIT Hash Identification + // --------------------------------------------------------------------------- + + class HOST_SW_API CSBK_DVM_GIT_HASH : public CSBK { + public: + /// Initializes a new instance of the CSBK_DVM_GIT_HASH class. + CSBK_DVM_GIT_HASH(); + + /// Decode a control signalling block. + virtual bool decode(const uint8_t* data); + /// Encode a control signalling block. + virtual void encode(uint8_t* data); + }; + } // namespace csbk + } // namespace lc +} // namespace dmr + +#endif // __DMR_LC_CSBK__CSBK_DVM_GIT_HASH_H__ diff --git a/dmr/lc/csbk/CSBK_EXT_FNCT.cpp b/dmr/lc/csbk/CSBK_EXT_FNCT.cpp new file mode 100644 index 00000000..6a5a86e1 --- /dev/null +++ b/dmr/lc/csbk/CSBK_EXT_FNCT.cpp @@ -0,0 +1,112 @@ +/** +* 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 "dmr/lc/csbk/CSBK_EXT_FNCT.h" +#include "Log.h" +#include "Utils.h" + +using namespace dmr::lc::csbk; +using namespace dmr::lc; +using namespace dmr; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the CSBK_EXT_FNCT class. +/// +CSBK_EXT_FNCT::CSBK_EXT_FNCT() : CSBK(), + m_extendedFunction(DMR_EXT_FNCT_CHECK) +{ + m_CSBKO = CSBKO_EXT_FNCT; + m_FID = FID_DMRA; +} + +/// +/// Decode a control signalling block. +/// +/// +/// True, if CSBK was decoded, otherwise false. +bool CSBK_EXT_FNCT::decode(const uint8_t* data) +{ + assert(data != NULL); + + uint8_t csbk[DMR_CSBK_LENGTH_BYTES]; + ::memset(csbk, 0x00U, DMR_CSBK_LENGTH_BYTES); + + bool ret = CSBK::decode(data, csbk); + if (!ret) + return false; + + ulong64_t csbkValue = CSBK::toValue(csbk); + + m_dataContent = (((csbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // + m_extendedFunction = (uint8_t)((csbkValue >> 48) & 0xFFU); // Function + m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFFFU); // Target Radio Address + m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address + + return true; +} + +/// +/// Encode a control signalling block. +/// +/// +void CSBK_EXT_FNCT::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t csbkValue = 0U; + + csbkValue = + (m_GI ? 0x40U : 0x00U) + // Group or Invididual + (m_dataContent ? 0x80U : 0x00U); + csbkValue = (csbkValue << 8) + m_extendedFunction; // Function + csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address + csbkValue = (csbkValue << 24) + m_dstId; // Target Radio Address + + std::unique_ptr csbk = CSBK::fromValue(csbkValue); + CSBK::encode(data, csbk.get()); +} + +// --------------------------------------------------------------------------- +// Private Class Members +// --------------------------------------------------------------------------- + +/// +/// Internal helper to copy the the class. +/// +/// +void CSBK_EXT_FNCT::copy(const CSBK_EXT_FNCT& data) +{ + CSBK::copy(data); + + m_extendedFunction = data.m_extendedFunction; +} diff --git a/dmr/lc/csbk/CSBK_EXT_FNCT.h b/dmr/lc/csbk/CSBK_EXT_FNCT.h new file mode 100644 index 00000000..561eea58 --- /dev/null +++ b/dmr/lc/csbk/CSBK_EXT_FNCT.h @@ -0,0 +1,63 @@ +/** +* 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(__DMR_LC_CSBK__CSBK_EXT_FNCT_H__) +#define __DMR_LC_CSBK__CSBK_EXT_FNCT_H__ + +#include "Defines.h" +#include "dmr/lc/CSBK.h" + +namespace dmr +{ + namespace lc + { + namespace csbk + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements EXT FNCT - Extended Function + // --------------------------------------------------------------------------- + + class HOST_SW_API CSBK_EXT_FNCT : public CSBK { + public: + /// Initializes a new instance of the CSBK_EXT_FNCT class. + CSBK_EXT_FNCT(); + + /// Decode a control signalling block. + virtual bool decode(const uint8_t* data); + /// Encode a control signalling block. + virtual void encode(uint8_t* data); + + public: + /// Extended function opcode. + __PROPERTY(uint8_t, extendedFunction, ExtendedFunction); + + __COPY(CSBK_EXT_FNCT); + }; + } // namespace csbk + } // namespace lc +} // namespace dmr + +#endif // __DMR_LC_CSBK__CSBK_EXT_FNCT_H__ diff --git a/dmr/lc/csbk/CSBK_NACK_RSP.cpp b/dmr/lc/csbk/CSBK_NACK_RSP.cpp new file mode 100644 index 00000000..355bb913 --- /dev/null +++ b/dmr/lc/csbk/CSBK_NACK_RSP.cpp @@ -0,0 +1,112 @@ +/** +* 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 "dmr/lc/csbk/CSBK_NACK_RSP.h" +#include "Log.h" +#include "Utils.h" + +using namespace dmr::lc::csbk; +using namespace dmr::lc; +using namespace dmr; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the CSBK_NACK_RSP class. +/// +CSBK_NACK_RSP::CSBK_NACK_RSP() : CSBK(), + m_serviceKind(0U) +{ + m_CSBKO = CSBKO_NACK_RSP; +} + +/// +/// Decode a control signalling block. +/// +/// +/// True, if CSBK was decoded, otherwise false. +bool CSBK_NACK_RSP::decode(const uint8_t* data) +{ + assert(data != NULL); + + uint8_t csbk[DMR_CSBK_LENGTH_BYTES]; + ::memset(csbk, 0x00U, DMR_CSBK_LENGTH_BYTES); + + bool ret = CSBK::decode(data, csbk); + if (!ret) + return false; + + ulong64_t csbkValue = CSBK::toValue(csbk); + + m_GI = (((csbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Group/Individual Flag + m_serviceKind = (((csbkValue >> 56) & 0xFFU) & 0x3FU); // Service Kind + m_reason = (uint8_t)((csbkValue >> 48) & 0xFFU); // Reason Code + m_srcId = (uint32_t)((csbkValue >> 24) & 0xFFFFFFU); // Source Radio Address + m_dstId = (uint32_t)(csbkValue & 0xFFFFFFU); // Target Radio Address + + return true; +} + +/// +/// Encode a control signalling block. +/// +/// +void CSBK_NACK_RSP::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t csbkValue = 0U; + + csbkValue = 0x80U + // Additional Information Field (always 1) + (m_GI ? 0x40U : 0x00U) + // Source Type + (m_serviceKind & 0x3FU); // Service Kind + csbkValue = (csbkValue << 8) + m_reason; // Reason Code + csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address + csbkValue = (csbkValue << 24) + m_dstId; // Target Radio Address + + std::unique_ptr csbk = CSBK::fromValue(csbkValue); + CSBK::encode(data, csbk.get()); +} + +// --------------------------------------------------------------------------- +// Private Class Members +// --------------------------------------------------------------------------- + +/// +/// Internal helper to copy the the class. +/// +/// +void CSBK_NACK_RSP::copy(const CSBK_NACK_RSP& data) +{ + CSBK::copy(data); + + m_serviceKind = data.m_serviceKind; +} diff --git a/dmr/lc/csbk/CSBK_NACK_RSP.h b/dmr/lc/csbk/CSBK_NACK_RSP.h new file mode 100644 index 00000000..7d629eca --- /dev/null +++ b/dmr/lc/csbk/CSBK_NACK_RSP.h @@ -0,0 +1,63 @@ +/** +* 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(__DMR_LC_CSBK__CSBK_NACK_RSP_H__) +#define __DMR_LC_CSBK__CSBK_NACK_RSP_H__ + +#include "Defines.h" +#include "dmr/lc/CSBK.h" + +namespace dmr +{ + namespace lc + { + namespace csbk + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements NACK RSP - Negative Acknowledgement Response + // --------------------------------------------------------------------------- + + class HOST_SW_API CSBK_NACK_RSP : public CSBK { + public: + /// Initializes a new instance of the CSBK_NACK_RSP class. + CSBK_NACK_RSP(); + + /// Decode a control signalling block. + virtual bool decode(const uint8_t* data); + /// Encode a control signalling block. + virtual void encode(uint8_t* data); + + public: + /// Service Kind. + __PROPERTY(uint8_t, serviceKind, ServiceKind); + + __COPY(CSBK_NACK_RSP); + }; + } // namespace csbk + } // namespace lc +} // namespace dmr + +#endif // __DMR_LC_CSBK__CSBK_NACK_RSP_H__ diff --git a/dmr/lc/csbk/CSBK_PD_GRANT.cpp b/dmr/lc/csbk/CSBK_PD_GRANT.cpp new file mode 100644 index 00000000..f7ca5a5a --- /dev/null +++ b/dmr/lc/csbk/CSBK_PD_GRANT.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 "dmr/lc/csbk/CSBK_PD_GRANT.h" +#include "Log.h" +#include "Utils.h" + +using namespace dmr::lc::csbk; +using namespace dmr::lc; +using namespace dmr; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the CSBK_PD_GRANT class. +/// +CSBK_PD_GRANT::CSBK_PD_GRANT() : CSBK() +{ + m_CSBKO = CSBKO_PD_GRANT; +} + +/// +/// Decode a control signalling block. +/// +/// +/// True, if CSBK was decoded, otherwise false. +bool CSBK_PD_GRANT::decode(const uint8_t* data) +{ + assert(data != NULL); + + /* stub */ + + return true; +} + +/// +/// Encode a control signalling block. +/// +/// +void CSBK_PD_GRANT::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t csbkValue = 0U; + + csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Physical Channel 1 + csbkValue = (csbkValue << 1) + (m_slotNo & 0x3U); // Logical Slot Number + csbkValue = (csbkValue << 1) + 0U; // High Rate Flag - Always Single Slot Data + csbkValue = (csbkValue << 1) + ((m_emergency) ? 1U : 0U); // Emergency + csbkValue = (csbkValue << 1) + ((m_siteOffsetTiming) ? 1U : 0U); // Site Timing: Aligned or Offset + csbkValue = (csbkValue << 24) + m_dstId; // Talkgroup ID + csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address + + std::unique_ptr csbk = CSBK::fromValue(csbkValue); + CSBK::encode(data, csbk.get()); +} diff --git a/dmr/lc/csbk/CSBK_PD_GRANT.h b/dmr/lc/csbk/CSBK_PD_GRANT.h new file mode 100644 index 00000000..588bc0c1 --- /dev/null +++ b/dmr/lc/csbk/CSBK_PD_GRANT.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(__DMR_LC_CSBK__CSBK_PD_GRANT_H__) +#define __DMR_LC_CSBK__CSBK_PD_GRANT_H__ + +#include "Defines.h" +#include "dmr/lc/CSBK.h" + +namespace dmr +{ + namespace lc + { + namespace csbk + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements PD_GRANT - Private Data Channel Grant + // --------------------------------------------------------------------------- + + class HOST_SW_API CSBK_PD_GRANT : public CSBK { + public: + /// Initializes a new instance of the CSBK_PD_GRANT class. + CSBK_PD_GRANT(); + + /// Decode a control signalling block. + virtual bool decode(const uint8_t* data); + /// Encode a control signalling block. + virtual void encode(uint8_t* data); + }; + } // namespace csbk + } // namespace lc +} // namespace dmr + +#endif // __DMR_LC_CSBK__CSBK_PD_GRANT_H__ diff --git a/dmr/lc/csbk/CSBK_PRECCSBK.cpp b/dmr/lc/csbk/CSBK_PRECCSBK.cpp new file mode 100644 index 00000000..2f574487 --- /dev/null +++ b/dmr/lc/csbk/CSBK_PRECCSBK.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 "dmr/lc/csbk/CSBK_PRECCSBK.h" +#include "Log.h" +#include "Utils.h" + +using namespace dmr::lc::csbk; +using namespace dmr::lc; +using namespace dmr; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the CSBK_PRECCSBK class. +/// +CSBK_PRECCSBK::CSBK_PRECCSBK() : CSBK() +{ + m_CSBKO = CSBKO_PRECCSBK; +} + +/// +/// Decode a control signalling block. +/// +/// +/// True, if CSBK was decoded, otherwise false. +bool CSBK_PRECCSBK::decode(const uint8_t* data) +{ + assert(data != NULL); + + uint8_t csbk[DMR_CSBK_LENGTH_BYTES]; + ::memset(csbk, 0x00U, DMR_CSBK_LENGTH_BYTES); + + bool ret = CSBK::decode(data, csbk); + if (!ret) + return false; + + ulong64_t csbkValue = CSBK::toValue(csbk); + + m_GI = (((csbkValue >> 56) & 0xFFU) & 0x40U) == 0x40U; // Group/Individual Flag + m_dataContent = (((csbkValue >> 56) & 0xFFU) & 0x80U) == 0x80U; // + m_CBF = (uint8_t)((csbkValue >> 48) & 0xFFU); // Blocks to Follow + m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFFFU); // Target Radio Address + m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address + + return true; +} + +/// +/// Encode a control signalling block. +/// +/// +void CSBK_PRECCSBK::encode(uint8_t* data) +{ + assert(data != NULL); + + /* stub */ +} diff --git a/dmr/lc/csbk/CSBK_PRECCSBK.h b/dmr/lc/csbk/CSBK_PRECCSBK.h new file mode 100644 index 00000000..59a31ced --- /dev/null +++ b/dmr/lc/csbk/CSBK_PRECCSBK.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(__DMR_LC_CSBK__CSBK_PRECCSBK_H__) +#define __DMR_LC_CSBK__CSBK_PRECCSBK_H__ + +#include "Defines.h" +#include "dmr/lc/CSBK.h" + +namespace dmr +{ + namespace lc + { + namespace csbk + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements PRE CSBK - Preamble CSBK + // --------------------------------------------------------------------------- + + class HOST_SW_API CSBK_PRECCSBK : public CSBK { + public: + /// Initializes a new instance of the CSBK_PRECCSBK class. + CSBK_PRECCSBK(); + + /// Decode a control signalling block. + virtual bool decode(const uint8_t* data); + /// Encode a control signalling block. + virtual void encode(uint8_t* data); + }; + } // namespace csbk + } // namespace lc +} // namespace dmr + +#endif // __DMR_LC_CSBK__CSBK_PRECCSBK_H__ diff --git a/dmr/lc/csbk/CSBK_PV_GRANT.cpp b/dmr/lc/csbk/CSBK_PV_GRANT.cpp new file mode 100644 index 00000000..2094cab4 --- /dev/null +++ b/dmr/lc/csbk/CSBK_PV_GRANT.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 "dmr/lc/csbk/CSBK_PV_GRANT.h" +#include "Log.h" +#include "Utils.h" + +using namespace dmr::lc::csbk; +using namespace dmr::lc; +using namespace dmr; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the CSBK_PV_GRANT class. +/// +CSBK_PV_GRANT::CSBK_PV_GRANT() : CSBK() +{ + m_CSBKO = CSBKO_PV_GRANT; +} + +/// +/// Decode a control signalling block. +/// +/// +/// True, if CSBK was decoded, otherwise false. +bool CSBK_PV_GRANT::decode(const uint8_t* data) +{ + assert(data != NULL); + + /* stub */ + + return true; +} + +/// +/// Encode a control signalling block. +/// +/// +void CSBK_PV_GRANT::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t csbkValue = 0U; + + csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Physical Channel 1 + csbkValue = (csbkValue << 1) + (m_slotNo & 0x3U); // Logical Slot Number + csbkValue = (csbkValue << 1) + 0U; // Reserved + csbkValue = (csbkValue << 1) + ((m_emergency) ? 1U : 0U); // Emergency + csbkValue = (csbkValue << 1) + ((m_siteOffsetTiming) ? 1U : 0U); // Site Timing: Aligned or Offset + csbkValue = (csbkValue << 24) + m_dstId; // Talkgroup ID + csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address + + std::unique_ptr csbk = CSBK::fromValue(csbkValue); + CSBK::encode(data, csbk.get()); +} diff --git a/dmr/lc/csbk/CSBK_PV_GRANT.h b/dmr/lc/csbk/CSBK_PV_GRANT.h new file mode 100644 index 00000000..e87f1328 --- /dev/null +++ b/dmr/lc/csbk/CSBK_PV_GRANT.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(__DMR_LC_CSBK__CSBK_PV_GRANT_H__) +#define __DMR_LC_CSBK__CSBK_PV_GRANT_H__ + +#include "Defines.h" +#include "dmr/lc/CSBK.h" + +namespace dmr +{ + namespace lc + { + namespace csbk + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements PV_GRANT - Private Voice Channel Grant + // --------------------------------------------------------------------------- + + class HOST_SW_API CSBK_PV_GRANT : public CSBK { + public: + /// Initializes a new instance of the CSBK_PV_GRANT class. + CSBK_PV_GRANT(); + + /// Decode a control signalling block. + virtual bool decode(const uint8_t* data); + /// Encode a control signalling block. + virtual void encode(uint8_t* data); + }; + } // namespace csbk + } // namespace lc +} // namespace dmr + +#endif // __DMR_LC_CSBK__CSBK_PV_GRANT_H__ diff --git a/dmr/lc/csbk/CSBK_RAND.cpp b/dmr/lc/csbk/CSBK_RAND.cpp new file mode 100644 index 00000000..0a0dd997 --- /dev/null +++ b/dmr/lc/csbk/CSBK_RAND.cpp @@ -0,0 +1,117 @@ +/** +* 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 "dmr/lc/csbk/CSBK_RAND.h" +#include "Log.h" +#include "Utils.h" + +using namespace dmr::lc::csbk; +using namespace dmr::lc; +using namespace dmr; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the CSBK_RAND class. +/// +CSBK_RAND::CSBK_RAND() : CSBK(), + m_serviceOptions(0U), + m_serviceExtra(0U), + m_serviceKind(0U) +{ + m_CSBKO = CSBKO_RAND; +} + +/// +/// Decode a control signalling block. +/// +/// +/// True, if CSBK was decoded, otherwise false. +bool CSBK_RAND::decode(const uint8_t* data) +{ + assert(data != NULL); + + uint8_t csbk[DMR_CSBK_LENGTH_BYTES]; + ::memset(csbk, 0x00U, DMR_CSBK_LENGTH_BYTES); + + bool ret = CSBK::decode(data, csbk); + if (!ret) + return false; + + ulong64_t csbkValue = CSBK::toValue(csbk); + + m_serviceOptions = (uint8_t)((csbkValue >> 57U) & 0x7FU); // Service Options + m_proxy = (((csbkValue >> 56U) & 0xFF) & 0x01U) == 0x01U; // Proxy Flag + m_serviceExtra = (uint8_t)((csbkValue >> 52U) & 0x0FU); // Service Extras (content dependant on service) + m_serviceKind = (uint8_t)((csbkValue >> 48U) & 0x0FU); // Service Kind + m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFFFU); // Target Radio Address + m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address + + return true; +} + +/// +/// Encode a control signalling block. +/// +/// +void CSBK_RAND::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t csbkValue = 0U; + + csbkValue = m_serviceOptions & 0x7FU; // Service Options + csbkValue = (csbkValue << 1) + (m_proxy ? 0x01U : 0x00); // Proxy Flag + csbkValue = (csbkValue << 4) + (m_serviceExtra & 0x0FU); // Service Extras + csbkValue = (csbkValue << 4) + (m_serviceKind & 0x0FU); // Service Kind + csbkValue = (csbkValue << 24) + m_dstId; // Target Radio Address + csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address + + std::unique_ptr csbk = CSBK::fromValue(csbkValue); + CSBK::encode(data, csbk.get()); +} + +// --------------------------------------------------------------------------- +// Private Class Members +// --------------------------------------------------------------------------- + +/// +/// Internal helper to copy the the class. +/// +/// +void CSBK_RAND::copy(const CSBK_RAND& data) +{ + CSBK::copy(data); + + m_serviceOptions = data.m_serviceOptions; + m_serviceExtra = data.m_serviceExtra; + m_serviceKind = data.m_serviceKind; +} diff --git a/dmr/lc/csbk/CSBK_RAND.h b/dmr/lc/csbk/CSBK_RAND.h new file mode 100644 index 00000000..0842b79f --- /dev/null +++ b/dmr/lc/csbk/CSBK_RAND.h @@ -0,0 +1,67 @@ +/** +* 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(__DMR_LC_CSBK__CSBK_RAND_H__) +#define __DMR_LC_CSBK__CSBK_RAND_H__ + +#include "Defines.h" +#include "dmr/lc/CSBK.h" + +namespace dmr +{ + namespace lc + { + namespace csbk + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements RAND - Random Access + // --------------------------------------------------------------------------- + + class HOST_SW_API CSBK_RAND : public CSBK { + public: + /// Initializes a new instance of the CSBK_RAND class. + CSBK_RAND(); + + /// Decode a control signalling block. + virtual bool decode(const uint8_t* data); + /// Encode a control signalling block. + virtual void encode(uint8_t* data); + + public: + /// Service Options. + __PROPERTY(uint8_t, serviceOptions, ServiceOptions); + /// Service Extra Options. + __PROPERTY(uint8_t, serviceExtra, ServiceExtra); + /// Service Kind. + __PROPERTY(uint8_t, serviceKind, ServiceKind); + + __COPY(CSBK_RAND); + }; + } // namespace csbk + } // namespace lc +} // namespace dmr + +#endif // __DMR_LC_CSBK__CSBK_RAND_H__ diff --git a/dmr/lc/csbk/CSBK_TD_GRANT.cpp b/dmr/lc/csbk/CSBK_TD_GRANT.cpp new file mode 100644 index 00000000..f29c450b --- /dev/null +++ b/dmr/lc/csbk/CSBK_TD_GRANT.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 "dmr/lc/csbk/CSBK_TD_GRANT.h" +#include "Log.h" +#include "Utils.h" + +using namespace dmr::lc::csbk; +using namespace dmr::lc; +using namespace dmr; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the CSBK_TD_GRANT class. +/// +CSBK_TD_GRANT::CSBK_TD_GRANT() : CSBK() +{ + m_CSBKO = CSBKO_TD_GRANT; +} + +/// +/// Decode a control signalling block. +/// +/// +/// True, if CSBK was decoded, otherwise false. +bool CSBK_TD_GRANT::decode(const uint8_t* data) +{ + assert(data != NULL); + + /* stub */ + + return true; +} + +/// +/// Encode a control signalling block. +/// +/// +void CSBK_TD_GRANT::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t csbkValue = 0U; + + csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Physical Channel 1 + csbkValue = (csbkValue << 1) + (m_slotNo & 0x3U); // Logical Slot Number + csbkValue = (csbkValue << 1) + 0U; // High Rate Flag - Always Single Slot Data + csbkValue = (csbkValue << 1) + ((m_emergency) ? 1U : 0U); // Emergency + csbkValue = (csbkValue << 1) + ((m_siteOffsetTiming) ? 1U : 0U); // Site Timing: Aligned or Offset + csbkValue = (csbkValue << 24) + m_dstId; // Talkgroup ID + csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address + + std::unique_ptr csbk = CSBK::fromValue(csbkValue); + CSBK::encode(data, csbk.get()); +} diff --git a/dmr/lc/csbk/CSBK_TD_GRANT.h b/dmr/lc/csbk/CSBK_TD_GRANT.h new file mode 100644 index 00000000..b1b109d4 --- /dev/null +++ b/dmr/lc/csbk/CSBK_TD_GRANT.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(__DMR_LC_CSBK__CSBK_TD_GRANT_H__) +#define __DMR_LC_CSBK__CSBK_TD_GRANT_H__ + +#include "Defines.h" +#include "dmr/lc/CSBK.h" + +namespace dmr +{ + namespace lc + { + namespace csbk + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements TD_GRANT - Talkgroup Data Channel Grant + // --------------------------------------------------------------------------- + + class HOST_SW_API CSBK_TD_GRANT : public CSBK { + public: + /// Initializes a new instance of the CSBK_TD_GRANT class. + CSBK_TD_GRANT(); + + /// Decode a control signalling block. + virtual bool decode(const uint8_t* data); + /// Encode a control signalling block. + virtual void encode(uint8_t* data); + }; + } // namespace csbk + } // namespace lc +} // namespace dmr + +#endif // __DMR_LC_CSBK__CSBK_TD_GRANT_H__ diff --git a/dmr/lc/csbk/CSBK_TV_GRANT.cpp b/dmr/lc/csbk/CSBK_TV_GRANT.cpp new file mode 100644 index 00000000..9ecc94a4 --- /dev/null +++ b/dmr/lc/csbk/CSBK_TV_GRANT.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 "dmr/lc/csbk/CSBK_TV_GRANT.h" +#include "Log.h" +#include "Utils.h" + +using namespace dmr::lc::csbk; +using namespace dmr::lc; +using namespace dmr; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the CSBK_TV_GRANT class. +/// +CSBK_TV_GRANT::CSBK_TV_GRANT() : CSBK() +{ + m_CSBKO = CSBKO_TV_GRANT; +} + +/// +/// Decode a control signalling block. +/// +/// +/// True, if CSBK was decoded, otherwise false. +bool CSBK_TV_GRANT::decode(const uint8_t* data) +{ + assert(data != NULL); + + /* stub */ + + return true; +} + +/// +/// Encode a control signalling block. +/// +/// +void CSBK_TV_GRANT::encode(uint8_t* data) +{ + assert(data != NULL); + + ulong64_t csbkValue = 0U; + + csbkValue = (csbkValue << 12) + (m_logicalCh1 & 0xFFFU); // Logical Physical Channel 1 + csbkValue = (csbkValue << 1) + (m_slotNo & 0x3U); // Logical Slot Number + csbkValue = (csbkValue << 1) + 0U; // Late Entry + csbkValue = (csbkValue << 1) + ((m_emergency) ? 1U : 0U); // Emergency + csbkValue = (csbkValue << 1) + ((m_siteOffsetTiming) ? 1U : 0U); // Site Timing: Aligned or Offset + csbkValue = (csbkValue << 24) + m_dstId; // Talkgroup ID + csbkValue = (csbkValue << 24) + m_srcId; // Source Radio Address + + std::unique_ptr csbk = CSBK::fromValue(csbkValue); + CSBK::encode(data, csbk.get()); +} diff --git a/dmr/lc/csbk/CSBK_TV_GRANT.h b/dmr/lc/csbk/CSBK_TV_GRANT.h new file mode 100644 index 00000000..2ae4f57e --- /dev/null +++ b/dmr/lc/csbk/CSBK_TV_GRANT.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(__DMR_LC_CSBK__CSBK_TV_GRANT_H__) +#define __DMR_LC_CSBK__CSBK_TV_GRANT_H__ + +#include "Defines.h" +#include "dmr/lc/CSBK.h" + +namespace dmr +{ + namespace lc + { + namespace csbk + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements TV_GRANT - Talkgroup Voice Channel Grant + // --------------------------------------------------------------------------- + + class HOST_SW_API CSBK_TV_GRANT : public CSBK { + public: + /// Initializes a new instance of the CSBK_TV_GRANT class. + CSBK_TV_GRANT(); + + /// Decode a control signalling block. + virtual bool decode(const uint8_t* data); + /// Encode a control signalling block. + virtual void encode(uint8_t* data); + }; + } // namespace csbk + } // namespace lc +} // namespace dmr + +#endif // __DMR_LC_CSBK__CSBK_TV_GRANT_H__ diff --git a/dmr/lc/csbk/CSBK_UU_ANS_RSP.cpp b/dmr/lc/csbk/CSBK_UU_ANS_RSP.cpp new file mode 100644 index 00000000..b401f15e --- /dev/null +++ b/dmr/lc/csbk/CSBK_UU_ANS_RSP.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 "dmr/lc/csbk/CSBK_UU_ANS_RSP.h" +#include "Log.h" +#include "Utils.h" + +using namespace dmr::lc::csbk; +using namespace dmr::lc; +using namespace dmr; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the CSBK_UU_ANS_RSP class. +/// +CSBK_UU_ANS_RSP::CSBK_UU_ANS_RSP() : CSBK() +{ + m_CSBKO = CSBKO_UU_ANS_RSP; +} + +/// +/// Decode a control signalling block. +/// +/// +/// True, if CSBK was decoded, otherwise false. +bool CSBK_UU_ANS_RSP::decode(const uint8_t* data) +{ + assert(data != NULL); + + uint8_t csbk[DMR_CSBK_LENGTH_BYTES]; + ::memset(csbk, 0x00U, DMR_CSBK_LENGTH_BYTES); + + bool ret = CSBK::decode(data, csbk); + if (!ret) + return false; + + ulong64_t csbkValue = CSBK::toValue(csbk); + + m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFFFU); // Target Radio Address + m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address + + return true; +} + +/// +/// Encode a control signalling block. +/// +/// +void CSBK_UU_ANS_RSP::encode(uint8_t* data) +{ + assert(data != NULL); + + /* stub */ +} diff --git a/dmr/lc/csbk/CSBK_UU_ANS_RSP.h b/dmr/lc/csbk/CSBK_UU_ANS_RSP.h new file mode 100644 index 00000000..1452db09 --- /dev/null +++ b/dmr/lc/csbk/CSBK_UU_ANS_RSP.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(__DMR_LC_CSBK__CSBK_UU_ANS_RSP_H__) +#define __DMR_LC_CSBK__CSBK_UU_ANS_RSP_H__ + +#include "Defines.h" +#include "dmr/lc/CSBK.h" + +namespace dmr +{ + namespace lc + { + namespace csbk + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements UU ANS RSP - Unit to Unit Answer Response + // --------------------------------------------------------------------------- + + class HOST_SW_API CSBK_UU_ANS_RSP : public CSBK { + public: + /// Initializes a new instance of the CSBK_UU_ANS_RSP class. + CSBK_UU_ANS_RSP(); + + /// Decode a control signalling block. + virtual bool decode(const uint8_t* data); + /// Encode a control signalling block. + virtual void encode(uint8_t* data); + }; + } // namespace csbk + } // namespace lc +} // namespace dmr + +#endif // __DMR_LC_CSBK__CSBK_UU_ANS_RSP_H__ diff --git a/dmr/lc/csbk/CSBK_UU_V_REQ.cpp b/dmr/lc/csbk/CSBK_UU_V_REQ.cpp new file mode 100644 index 00000000..8832a6a2 --- /dev/null +++ b/dmr/lc/csbk/CSBK_UU_V_REQ.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 "dmr/lc/csbk/CSBK_UU_V_REQ.h" +#include "Log.h" +#include "Utils.h" + +using namespace dmr::lc::csbk; +using namespace dmr::lc; +using namespace dmr; + +#include +#include + +// --------------------------------------------------------------------------- +// Public Class Members +// --------------------------------------------------------------------------- + +/// +/// Initializes a new instance of the CSBK_UU_V_REQ class. +/// +CSBK_UU_V_REQ::CSBK_UU_V_REQ() : CSBK() +{ + m_CSBKO = CSBKO_UU_V_REQ; +} + +/// +/// Decode a control signalling block. +/// +/// +/// True, if CSBK was decoded, otherwise false. +bool CSBK_UU_V_REQ::decode(const uint8_t* data) +{ + assert(data != NULL); + + uint8_t csbk[DMR_CSBK_LENGTH_BYTES]; + ::memset(csbk, 0x00U, DMR_CSBK_LENGTH_BYTES); + + bool ret = CSBK::decode(data, csbk); + if (!ret) + return false; + + ulong64_t csbkValue = CSBK::toValue(csbk); + + m_dstId = (uint32_t)((csbkValue >> 24) & 0xFFFFFFU); // Target Radio Address + m_srcId = (uint32_t)(csbkValue & 0xFFFFFFU); // Source Radio Address + + return true; +} + +/// +/// Encode a control signalling block. +/// +/// +void CSBK_UU_V_REQ::encode(uint8_t* data) +{ + assert(data != NULL); + + /* stub */ +} diff --git a/dmr/lc/csbk/CSBK_UU_V_REQ.h b/dmr/lc/csbk/CSBK_UU_V_REQ.h new file mode 100644 index 00000000..972d8e97 --- /dev/null +++ b/dmr/lc/csbk/CSBK_UU_V_REQ.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(__DMR_LC_CSBK__CSBK_UU_V_REQ_H__) +#define __DMR_LC_CSBK__CSBK_UU_V_REQ_H__ + +#include "Defines.h" +#include "dmr/lc/CSBK.h" + +namespace dmr +{ + namespace lc + { + namespace csbk + { + // --------------------------------------------------------------------------- + // Class Declaration + // Implements UU VCH REQ - Unit-to-Unit Voice Channel Request + // --------------------------------------------------------------------------- + + class HOST_SW_API CSBK_UU_V_REQ : public CSBK { + public: + /// Initializes a new instance of the CSBK_UU_V_REQ class. + CSBK_UU_V_REQ(); + + /// Decode a control signalling block. + virtual bool decode(const uint8_t* data); + /// Encode a control signalling block. + virtual void encode(uint8_t* data); + }; + } // namespace csbk + } // namespace lc +} // namespace dmr + +#endif // __DMR_LC_CSBK__CSBK_UU_V_REQ_H__ diff --git a/dmr/packet/ControlSignaling.cpp b/dmr/packet/ControlSignaling.cpp index 0558b96f..e8544ea2 100644 --- a/dmr/packet/ControlSignaling.cpp +++ b/dmr/packet/ControlSignaling.cpp @@ -32,6 +32,7 @@ #include "dmr/lc/ShortLC.h" #include "dmr/lc/FullLC.h" #include "dmr/lc/CSBK.h" +#include "dmr/lc/csbk/CSBKFactory.h" #include "dmr/Slot.h" #include "dmr/SlotType.h" #include "dmr/Sync.h" @@ -41,6 +42,7 @@ #include "Utils.h" using namespace dmr; +using namespace dmr::lc::csbk; using namespace dmr::packet; #include @@ -70,7 +72,7 @@ using namespace dmr::packet; #define IS_SUPPORT_CONTROL_CHECK(_PCKT_STR, _PCKT, _SRCID) \ if (!m_slot->m_dmr->getTSCCSlot()->m_enableTSCC) { \ LogWarning(LOG_RF, "DMR Slot %u, " _PCKT_STR " denial, unsupported service, srcId = %u", m_slot->m_slotNo, _SRCID); \ - writeRF_CSBK_ACK_RSP(TS_DENY_RSN_SYS_UNSUPPORTED_SVC, 0U); \ + writeRF_CSBK_ACK_RSP(_SRCID, TS_DENY_RSN_SYS_UNSUPPORTED_SVC, 0U); \ return false; \ } @@ -78,23 +80,23 @@ using namespace dmr::packet; #define VALID_SRCID(_PCKT_STR, _PCKT, _SRCID) \ if (!acl::AccessControl::validateSrcId(_SRCID)) { \ LogWarning(LOG_RF, "DMR Slot %u, " _PCKT_STR " denial, RID rejection, srcId = %u", m_slot->m_slotNo, _SRCID); \ - writeRF_CSBK_ACK_RSP(TS_DENY_RSN_PERM_USER_REFUSED, 0U); \ + writeRF_CSBK_ACK_RSP(_SRCID, TS_DENY_RSN_PERM_USER_REFUSED, 0U); \ return false; \ } // Validate the target RID. -#define VALID_DSTID(_PCKT_STR, _PCKT, _DSTID) \ +#define VALID_DSTID(_PCKT_STR, _PCKT, _SRCID, _DSTID) \ if (!acl::AccessControl::validateSrcId(_DSTID)) { \ LogWarning(LOG_RF, "DMR Slot %u, " _PCKT_STR " denial, RID rejection, dstId = %u", m_slot->m_slotNo, _DSTID); \ - writeRF_CSBK_ACK_RSP(TS_DENY_RSN_TEMP_USER_REFUSED, 0U); \ + writeRF_CSBK_ACK_RSP(_SRCID, TS_DENY_RSN_TEMP_USER_REFUSED, 0U); \ return false; \ } // Validate the talkgroup ID. -#define VALID_TGID(_PCKT_STR, _PCKT, _DSTID) \ +#define VALID_TGID(_PCKT_STR, _PCKT, _SRCID, _DSTID) \ if (!acl::AccessControl::validateTGId(0U, _DSTID)) { \ LogWarning(LOG_RF, "DMR Slot %u, " _PCKT_STR " denial, TGID rejection, dstId = %u", m_slot->m_slotNo, _DSTID); \ - writeRF_CSBK_ACK_RSP(TS_DENY_RSN_TGT_GROUP_NOT_VALID, 0U); \ + writeRF_CSBK_ACK_RSP(_SRCID, TS_DENY_RSN_TGT_GROUP_NOT_VALID, 0U); \ return false; \ } @@ -102,7 +104,7 @@ using namespace dmr::packet; #define VERIFY_SRCID_REG(_PCKT_STR, _PCKT, _SRCID) \ if (!m_slot->m_affiliations->isUnitReg(_SRCID) && m_slot->m_verifyReg) { \ LogWarning(LOG_RF, "DMR Slot %u, " _PCKT_STR " denial, RID not registered, srcId = %u", m_slot->m_slotNo, _SRCID); \ - writeRF_CSBK_ACK_RSP(TS_DENY_RSN_PERM_USER_REFUSED, 0U); \ + writeRF_CSBK_ACK_RSP(_SRCID, TS_DENY_RSN_PERM_USER_REFUSED, 0U); \ return false; \ } @@ -135,19 +137,17 @@ bool ControlSignaling::process(uint8_t* data, uint32_t len) if (dataType == DT_CSBK) { // generate a new CSBK and check validity - lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); - - bool valid = csbk.decode(data + 2U); - if (!valid) + std::unique_ptr csbk = CSBKFactory::createCSBK(data + 2U); + if (csbk == nullptr) return false; - uint8_t csbko = csbk.getCSBKO(); + uint8_t csbko = csbk->getCSBKO(); if (csbko == CSBKO_BSDWNACT) return false; - bool gi = csbk.getGI(); - uint32_t srcId = csbk.getSrcId(); - uint32_t dstId = csbk.getDstId(); + bool gi = csbk->getGI(); + uint32_t srcId = csbk->getSrcId(); + uint32_t dstId = csbk->getDstId(); if (srcId != 0U || dstId != 0U) { CHECK_TRAFFIC_COLLISION(dstId); @@ -184,7 +184,8 @@ bool ControlSignaling::process(uint8_t* data, uint32_t len) } break; case CSBKO_RAND: - if (csbk.getFID() == FID_DMRA) { + { + if (csbk->getFID() == FID_DMRA) { if (m_verbose) { LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_CALL_ALRT (Call Alert), src = %u, dst = %s%u", m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId); @@ -194,12 +195,13 @@ bool ControlSignaling::process(uint8_t* data, uint32_t len) } else { handled = true; + CSBK_RAND* isp = static_cast(csbk.get()); if (m_verbose) { LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), serviceKind = $%02X, serviceOptions = $%02X, serviceExtra = $%02X, srcId = %u, dstId = %u", - m_slot->m_slotNo, csbk.getServiceKind(), csbk.getServiceOptions(), csbk.getServiceExtra(), csbk.getSrcId(), csbk.getDstId()); + m_slot->m_slotNo, isp->getServiceKind(), isp->getServiceOptions(), isp->getServiceExtra(), isp->getSrcId(), isp->getDstId()); } - switch (csbk.getServiceKind()) { + switch (isp->getServiceKind()) { case SVC_KIND_IND_VOICE_CALL: // make sure control data is supported IS_SUPPORT_CONTROL_CHECK("DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_IND_VOICE_CALL (Individual Voice Call)", SVC_KIND_IND_VOICE_CALL, srcId); @@ -208,12 +210,12 @@ bool ControlSignaling::process(uint8_t* data, uint32_t len) VALID_SRCID("DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_IND_VOICE_CALL (Individual Voice Call)", SVC_KIND_IND_VOICE_CALL, srcId); // validate the target RID - VALID_DSTID("DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_IND_VOICE_CALL (Individual Voice Call)", SVC_KIND_IND_VOICE_CALL, dstId); + VALID_DSTID("DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_IND_VOICE_CALL (Individual Voice Call)", SVC_KIND_IND_VOICE_CALL, srcId, dstId); // verify the source RID is registered VERIFY_SRCID_REG("DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_IND_VOICE_CALL (Individual Voice Call)", SVC_KIND_IND_VOICE_CALL, srcId); - writeRF_CSBK_Grant(srcId, dstId, csbk.getServiceOptions(), false); + writeRF_CSBK_Grant(srcId, dstId, isp->getServiceOptions(), false); break; case SVC_KIND_GRP_VOICE_CALL: // make sure control data is supported @@ -223,9 +225,9 @@ bool ControlSignaling::process(uint8_t* data, uint32_t len) VALID_SRCID("DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_GRP_VOICE_CALL (Group Voice Call)", SVC_KIND_GRP_VOICE_CALL, srcId); // validate the talkgroup ID - VALID_TGID("DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_GRP_VOICE_CALL (Group Voice Call)", SVC_KIND_GRP_VOICE_CALL, dstId); + VALID_TGID("DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_GRP_VOICE_CALL (Group Voice Call)", SVC_KIND_GRP_VOICE_CALL, srcId, dstId); - writeRF_CSBK_Grant(srcId, dstId, csbk.getServiceOptions(), true); + writeRF_CSBK_Grant(srcId, dstId, isp->getServiceOptions(), true); break; case SVC_KIND_IND_DATA_CALL: case SVC_KIND_IND_UDT_DATA_CALL: @@ -236,12 +238,12 @@ bool ControlSignaling::process(uint8_t* data, uint32_t len) VALID_SRCID("DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_IND_VOICE_CALL (Individual Voice Call)", SVC_KIND_IND_VOICE_CALL, srcId); // validate the target RID - VALID_DSTID("DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_IND_VOICE_CALL (Individual Voice Call)", SVC_KIND_IND_VOICE_CALL, dstId); + VALID_DSTID("DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_IND_VOICE_CALL (Individual Voice Call)", SVC_KIND_IND_VOICE_CALL, srcId, dstId); // verify the source RID is registered VERIFY_SRCID_REG("DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_IND_VOICE_CALL (Individual Voice Call)", SVC_KIND_IND_VOICE_CALL, srcId); - writeRF_CSBK_Data_Grant(srcId, dstId, csbk.getServiceOptions(), false); + writeRF_CSBK_Data_Grant(srcId, dstId, isp->getServiceOptions(), false); break; case SVC_KIND_GRP_DATA_CALL: case SVC_KIND_GRP_UDT_DATA_CALL: @@ -252,39 +254,44 @@ bool ControlSignaling::process(uint8_t* data, uint32_t len) VALID_SRCID("DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_GRP_VOICE_CALL (Group Voice Call)", SVC_KIND_GRP_VOICE_CALL, srcId); // validate the talkgroup ID - VALID_TGID("DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_GRP_VOICE_CALL (Group Voice Call)", SVC_KIND_GRP_VOICE_CALL, dstId); + VALID_TGID("DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_GRP_VOICE_CALL (Group Voice Call)", SVC_KIND_GRP_VOICE_CALL, srcId, dstId); - writeRF_CSBK_Data_Grant(srcId, dstId, csbk.getServiceOptions(), true); + writeRF_CSBK_Data_Grant(srcId, dstId, isp->getServiceOptions(), true); break; case SVC_KIND_REG_SVC: // make sure control data is supported IS_SUPPORT_CONTROL_CHECK("DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_REG_SVC (Registration Service)", SVC_KIND_REG_SVC, srcId); - writeRF_CSBK_U_Reg_Rsp(srcId, csbk.getServiceOptions()); + writeRF_CSBK_U_Reg_Rsp(srcId, isp->getServiceOptions()); break; default: - LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), unhandled service, serviceKind = %02X", m_slot->m_slotNo, csbk.getServiceKind()); + LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), unhandled service, serviceKind = %02X", m_slot->m_slotNo, isp->getServiceKind()); // should we drop the CSBK and not repeat it? break; } } - break; + } + break; case CSBKO_ACK_RSP: + { if (m_verbose) { LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_ACK_RSP (Acknowledge Response), src = %u, dst = %s%u", m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId); } ::ActivityLog("DMR", true, "Slot %u ack response from %u to %u", m_slot->m_slotNo, srcId, dstId); - break; + } + break; case CSBKO_EXT_FNCT: + { + CSBK_EXT_FNCT* isp = static_cast(csbk.get()); if (m_verbose) { LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_EXT_FNCT (Extended Function), op = $%02X, arg = %u, tgt = %u", - m_slot->m_slotNo, csbk.getServiceKind(), dstId, srcId); + m_slot->m_slotNo, isp->getExtendedFunction(), dstId, srcId); } // generate activity log entry - switch (csbk.getServiceKind()) { + switch (isp->getExtendedFunction()) { case DMR_EXT_FNCT_CHECK: ::ActivityLog("DMR", true, "Slot %u radio check request from %u to %u", m_slot->m_slotNo, dstId, srcId); break; @@ -304,31 +311,36 @@ bool ControlSignaling::process(uint8_t* data, uint32_t len) ::ActivityLog("DMR", true, "Slot %u radio uninhibit response from %u to %u", m_slot->m_slotNo, dstId, srcId); break; default: - LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_EXT_FNCT (Extended Function), unhandled op, op = $%02X", m_slot->m_slotNo, csbk.getServiceKind()); + LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_EXT_FNCT (Extended Function), unhandled op, op = $%02X", m_slot->m_slotNo, isp->getExtendedFunction()); break; } - break; + } + break; case CSBKO_NACK_RSP: + { if (m_verbose) { LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_NACK_RSP (Negative Acknowledgment Response), src = %u, dst = %s%u", m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId); } - break; + } + break; case CSBKO_PRECCSBK: + { if (m_verbose) { LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_PRECCSBK (%s Preamble CSBK), toFollow = %u, src = %u, dst = %s%u", - m_slot->m_slotNo, csbk.getDataContent() ? "Data" : "CSBK", csbk.getCBF(), srcId, gi ? "TG " : "", dstId); + m_slot->m_slotNo, csbk->getDataContent() ? "Data" : "CSBK", csbk->getCBF(), srcId, gi ? "TG " : "", dstId); } - break; + } + break; default: - LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, unhandled CSBK, csbko = $%02X, fid = $%02X", m_slot->m_slotNo, csbko, csbk.getFID()); + LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, unhandled CSBK, csbko = $%02X, fid = $%02X", m_slot->m_slotNo, csbko, csbk->getFID()); // should we drop the CSBK and not repeat it? break; } if (!handled) { // regenerate the CSBK data - csbk.encode(data + 2U); + lc::CSBK::regenerate(data + 2U); // regenerate the Slot Type slotType.encode(data + 2U); @@ -365,41 +377,43 @@ void ControlSignaling::processNetwork(const data::Data & dmrData) dmrData.getData(data + 2U); if (dataType == DT_CSBK) { - lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); - csbk.setVerbose(m_dumpCSBKData); - - bool valid = csbk.decode(data + 2U); - if (!valid) { + std::unique_ptr csbk = CSBKFactory::createCSBK(data + 2U); + if (csbk == nullptr) { LogError(LOG_NET, "DMR Slot %u, DT_CSBK, unable to decode the network CSBK", m_slot->m_slotNo); return; } - uint8_t csbko = csbk.getCSBKO(); + uint8_t csbko = csbk->getCSBKO(); if (csbko == CSBKO_BSDWNACT) return; - bool gi = csbk.getGI(); - uint32_t srcId = csbk.getSrcId(); - uint32_t dstId = csbk.getDstId(); + bool gi = csbk->getGI(); + uint32_t srcId = csbk->getSrcId(); + uint32_t dstId = csbk->getDstId(); CHECK_TG_HANG(dstId); bool handled = false; switch (csbko) { case CSBKO_UU_V_REQ: + { if (m_verbose) { LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_UU_V_REQ (Unit to Unit Voice Service Request), src = %u, dst = %s%u", m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId); } - break; + } + break; case CSBKO_UU_ANS_RSP: + { if (m_verbose) { LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_UU_ANS_RSP (Unit to Unit Voice Service Answer Response), src = %u, dst = %s%u", m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId); } - break; + } + break; case CSBKO_RAND: - if (csbk.getFID() == FID_DMRA) { + { + if (csbk->getFID() == FID_DMRA) { if (m_verbose) { LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_CALL_ALRT (Call Alert), src = %u, dst = %s%u", m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId); @@ -407,28 +421,34 @@ void ControlSignaling::processNetwork(const data::Data & dmrData) ::ActivityLog("DMR", false, "Slot %u call alert request from %u to %u", m_slot->m_slotNo, srcId, dstId); } else { + CSBK_RAND* isp = static_cast(csbk.get()); if (m_verbose) { LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), serviceKind = $%02X, serviceOptions = $%02X, serviceExtra = $%02X, srcId = %u, dstId = %u", - m_slot->m_slotNo, csbk.getServiceKind(), csbk.getServiceOptions(), csbk.getServiceExtra(), csbk.getSrcId(), csbk.getDstId()); + m_slot->m_slotNo, isp->getServiceKind(), isp->getServiceOptions(), isp->getServiceExtra(), isp->getSrcId(), isp->getDstId()); } } - break; + } + break; case CSBKO_ACK_RSP: + { if (m_verbose) { LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_ACK_RSP (Acknowledge Response), src = %u, dst = %s%u", m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId); } ::ActivityLog("DMR", false, "Slot %u ack response from %u to %u", m_slot->m_slotNo, srcId, dstId); - break; + } + break; case CSBKO_EXT_FNCT: + { + CSBK_EXT_FNCT* isp = static_cast(csbk.get()); if (m_verbose) { LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_EXT_FNCT (Extended Function), op = $%02X, arg = %u, tgt = %u", - m_slot->m_slotNo, csbk.getServiceKind(), dstId, srcId); + m_slot->m_slotNo, isp->getExtendedFunction(), dstId, srcId); } // generate activity log entry - switch (csbk.getServiceKind()) { + switch (isp->getExtendedFunction()) { case DMR_EXT_FNCT_CHECK: ::ActivityLog("DMR", false, "Slot %u radio check request from %u to %u", m_slot->m_slotNo, dstId, srcId); break; @@ -448,31 +468,36 @@ void ControlSignaling::processNetwork(const data::Data & dmrData) ::ActivityLog("DMR", false, "Slot %u radio uninhibit response from %u to %u", m_slot->m_slotNo, dstId, srcId); break; default: - LogWarning(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_EXT_FNCT (Extended Function), unhandled op, op = $%02X", m_slot->m_slotNo, csbk.getServiceKind()); + LogWarning(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_EXT_FNCT (Extended Function), unhandled op, op = $%02X", m_slot->m_slotNo, isp->getExtendedFunction()); break; } - break; + } + break; case CSBKO_NACK_RSP: + { if (m_verbose) { LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_NACK_RSP (Negative Acknowledgment Response), src = %u, dst = %s%u", m_slot->m_slotNo, srcId, gi ? "TG " : "", dstId); } - break; + } + break; case CSBKO_PRECCSBK: + { if (m_verbose) { LogMessage(LOG_NET, "DMR Slot %u, DT_CSBK, CSBKO_PRECCSBK (%s Preamble CSBK), toFollow = %u, src = %u, dst = %s%u", - m_slot->m_slotNo, csbk.getDataContent() ? "Data" : "CSBK", csbk.getCBF(), srcId, gi ? "TG " : "", dstId); + m_slot->m_slotNo, csbk->getDataContent() ? "Data" : "CSBK", csbk->getCBF(), srcId, gi ? "TG " : "", dstId); } - break; + } + break; default: - LogWarning(LOG_NET, "DMR Slot %u, DT_CSBK, unhandled network CSBK, csbko = $%02X, fid = $%02X", m_slot->m_slotNo, csbko, csbk.getFID()); + LogWarning(LOG_NET, "DMR Slot %u, DT_CSBK, unhandled network CSBK, csbko = $%02X, fid = $%02X", m_slot->m_slotNo, csbko, csbk->getFID()); // should we drop the CSBK and not repeat it? break; } if (!handled) { // regenerate the CSBK data - csbk.encode(data + 2U); + lc::CSBK::regenerate(data + 2U); // regenerate the Slot Type SlotType slotType; @@ -486,14 +511,14 @@ void ControlSignaling::processNetwork(const data::Data & dmrData) data[0U] = modem::TAG_DATA; data[1U] = 0x00U; - if (csbko == CSBKO_PRECCSBK && csbk.getDataContent()) { - uint32_t cbf = NO_PREAMBLE_CSBK + csbk.getCBF() - 1U; + if (csbko == CSBKO_PRECCSBK && csbk->getDataContent()) { + uint32_t cbf = NO_PREAMBLE_CSBK + csbk->getCBF() - 1U; for (uint32_t i = 0U; i < NO_PREAMBLE_CSBK; i++, cbf--) { // change blocks to follow - csbk.setCBF(cbf); + csbk->setCBF(cbf); // regenerate the CSBK data - csbk.encode(data + 2U); + csbk->encode(data + 2U); // regenerate the Slot Type SlotType slotType; @@ -541,17 +566,13 @@ void ControlSignaling::writeRF_Ext_Func(uint32_t func, uint32_t arg, uint32_t ds ::ActivityLog("DMR", true, "Slot %u radio uninhibit request from %u to %u", m_slot->m_slotNo, arg, dstId); } - lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); - csbk.setVerbose(m_dumpCSBKData); - csbk.setCSBKO(CSBKO_EXT_FNCT); - csbk.setFID(FID_DMRA); + std::unique_ptr csbk = new_unique(CSBK_EXT_FNCT); + csbk->setGI(false); + csbk->setExtendedFunction(func); + csbk->setSrcId(arg); + csbk->setDstId(dstId); - csbk.setGI(false); - csbk.setCBF(func); - csbk.setSrcId(arg); - csbk.setDstId(dstId); - - writeRF_CSBK(csbk); + writeRF_CSBK(csbk.get()); } /// @@ -568,16 +589,12 @@ void ControlSignaling::writeRF_Call_Alrt(uint32_t srcId, uint32_t dstId) ::ActivityLog("DMR", true, "Slot %u call alert request from %u to %u", m_slot->m_slotNo, srcId, dstId); - lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); - csbk.setVerbose(m_dumpCSBKData); - csbk.setCSBKO(CSBKO_RAND); - csbk.setFID(FID_DMRA); - - csbk.setGI(false); - csbk.setSrcId(srcId); - csbk.setDstId(dstId); + std::unique_ptr csbk = new_unique(CSBK_CALL_ALRT); + csbk->setGI(false); + csbk->setSrcId(srcId); + csbk->setDstId(dstId); - writeRF_CSBK(csbk); + writeRF_CSBK(csbk.get()); } // --------------------------------------------------------------------------- @@ -614,7 +631,7 @@ ControlSignaling::~ControlSignaling() /// /// /// -void ControlSignaling::writeRF_CSBK(lc::CSBK csbk, bool clearBeforeWrite) +void ControlSignaling::writeRF_CSBK(lc::CSBK* csbk, bool clearBeforeWrite) { Slot *m_tscc = m_slot->m_dmr->getTSCCSlot(); if (m_tscc != nullptr) { @@ -636,7 +653,7 @@ void ControlSignaling::writeRF_CSBK(lc::CSBK csbk, bool clearBeforeWrite) slotType.setDataType(DT_CSBK); // Regenerate the CSBK data - csbk.encode(data + 2U); + csbk->encode(data + 2U); // Regenerate the Slot Type slotType.encode(data + 2U); @@ -665,37 +682,35 @@ void ControlSignaling::writeRF_CSBK(lc::CSBK csbk, bool clearBeforeWrite) /// /// Helper to write a deny packet. /// +/// /// /// -void ControlSignaling::writeRF_CSBK_ACK_RSP(uint8_t reason, uint8_t responseInfo) +void ControlSignaling::writeRF_CSBK_ACK_RSP(uint32_t dstId, uint8_t reason, uint8_t responseInfo) { - lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); - csbk.setVerbose(m_dumpCSBKData); - csbk.setCSBKO(CSBKO_ACK_RSP); - csbk.setFID(FID_ETSI); - - csbk.setResponse(responseInfo); - csbk.setReason(reason); + std::unique_ptr csbk = new_unique(CSBK_ACK_RSP); + csbk->setResponse(responseInfo); + csbk->setReason(reason); + csbk->setSrcId(DMR_WUID_ALL); // hmmm... + csbk->setDstId(dstId); - writeRF_CSBK(csbk); + writeRF_CSBK(csbk.get()); } /// /// Helper to write a deny packet. /// +/// /// /// -void ControlSignaling::writeRF_CSBK_NACK_RSP(uint8_t reason, uint8_t service) +void ControlSignaling::writeRF_CSBK_NACK_RSP(uint32_t dstId, uint8_t reason, uint8_t service) { - lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); - csbk.setVerbose(m_dumpCSBKData); - csbk.setCSBKO(CSBKO_NACK_RSP); - csbk.setFID(FID_ETSI); - - csbk.setServiceKind(service); - csbk.setReason(reason); + std::unique_ptr csbk = new_unique(CSBK_NACK_RSP); + csbk->setServiceKind(service); + csbk->setReason(reason); + csbk->setSrcId(DMR_WUID_ALL); // hmmm... + csbk->setDstId(dstId); - writeRF_CSBK(csbk); + writeRF_CSBK(csbk.get()); } /// @@ -706,10 +721,11 @@ void ControlSignaling::writeRF_CSBK_NACK_RSP(uint8_t reason, uint8_t service) /// /// /// +/// /// /// /// -bool ControlSignaling::writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_t serviceOptions, bool grp, bool skip, bool net, bool skipNetCheck) +bool ControlSignaling::writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_t serviceOptions, bool grp, bool skip, uint32_t chNo, bool net, bool skipNetCheck) { Slot *m_tscc = m_slot->m_dmr->getTSCCSlot(); @@ -718,10 +734,6 @@ bool ControlSignaling::writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_ bool broadcast = ((serviceOptions & 0xFFU) & 0x10U) == 0x10U; // Broadcast Flag uint8_t priority = ((serviceOptions & 0xFFU) & 0x03U); // Priority - lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); - csbk.setVerbose(m_dumpCSBKData); - csbk.setFID(FID_ETSI); - if (dstId == DMR_WUID_ALL) { return true; // do not generate grant packets for $FFFF (All Call) TGID } @@ -738,7 +750,7 @@ bool ControlSignaling::writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_ if (m_slot->m_rfState != RS_RF_LISTENING && m_slot->m_rfState != RS_RF_DATA) { if (!net) { LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_VOICE_CALL (Voice Call) denied, traffic in progress, dstId = %u", m_tscc->m_slotNo, dstId); - writeRF_CSBK_ACK_RSP(TS_DENY_RSN_TGT_BUSY, (grp) ? 1U : 0U); + writeRF_CSBK_ACK_RSP(srcId, TS_DENY_RSN_TGT_BUSY, (grp) ? 1U : 0U); ::ActivityLog("DMR", true, "Slot %u group grant request %u to TG %u denied", m_tscc->m_slotNo, srcId, dstId); m_slot->m_rfState = RS_RF_REJECTED; @@ -750,7 +762,7 @@ bool ControlSignaling::writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_ if (m_slot->m_netState != RS_NET_IDLE && dstId == m_slot->m_netLastDstId) { if (!net) { LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_VOICE_CALL (Voice Call) denied, traffic in progress, dstId = %u", m_tscc->m_slotNo, dstId); - writeRF_CSBK_ACK_RSP(TS_DENY_RSN_TGT_BUSY, (grp) ? 1U : 0U); + writeRF_CSBK_ACK_RSP(srcId, TS_DENY_RSN_TGT_BUSY, (grp) ? 1U : 0U); ::ActivityLog("DMR", true, "Slot %u group grant request %u to TG %u denied", m_tscc->m_slotNo, srcId, dstId); m_slot->m_rfState = RS_RF_REJECTED; @@ -763,7 +775,7 @@ bool ControlSignaling::writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_ if (m_slot->m_rfLastDstId != 0U) { if (m_slot->m_rfLastDstId != dstId && (m_slot->m_rfTGHang.isRunning() && !m_slot->m_rfTGHang.hasExpired())) { if (!net) { - writeRF_CSBK_ACK_RSP(TS_DENY_RSN_TGT_BUSY, (grp) ? 1U : 0U); + writeRF_CSBK_ACK_RSP(srcId, TS_DENY_RSN_TGT_BUSY, (grp) ? 1U : 0U); m_slot->m_rfState = RS_RF_REJECTED; } @@ -776,7 +788,7 @@ bool ControlSignaling::writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_ if (grp) { if (!net) { LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_GRP_VOICE_CALL (Group Voice Call) queued, no channels available, dstId = %u", m_tscc->m_slotNo, dstId); - writeRF_CSBK_ACK_RSP(TS_DENY_RSN_SYS_BUSY, (grp) ? 1U : 0U); + writeRF_CSBK_ACK_RSP(srcId, TS_DENY_RSN_SYS_BUSY, (grp) ? 1U : 0U); ::ActivityLog("DMR", true, "Slot %u group grant request %u to TG %u queued", m_tscc->m_slotNo, srcId, dstId); m_slot->m_rfState = RS_RF_REJECTED; @@ -787,7 +799,7 @@ bool ControlSignaling::writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_ else { if (!net) { LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_IND_VOICE_CALL (Individual Voice Call) queued, no channels available, dstId = %u", m_tscc->m_slotNo, dstId); - writeRF_CSBK_ACK_RSP(TS_DENY_RSN_SYS_BUSY, (grp) ? 1U : 0U); + writeRF_CSBK_ACK_RSP(srcId, TS_DENY_RSN_SYS_BUSY, (grp) ? 1U : 0U); ::ActivityLog("DMR", true, "Slot %u group grant request %u to TG %u queued", m_tscc->m_slotNo, srcId, dstId); m_slot->m_rfState = RS_RF_REJECTED; @@ -798,18 +810,14 @@ bool ControlSignaling::writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_ } else { if (m_tscc->m_affiliations->grantCh(dstId, GRANT_TIMER_TIMEOUT)) { - uint32_t chNo = m_tscc->m_affiliations->getGrantedCh(dstId); - csbk.setLogicalCh1(chNo); - csbk.setSlotNo(0U); + chNo = m_tscc->m_affiliations->getGrantedCh(dstId); //m_tscc->m_siteData.setChCnt(m_tscc->m_affiliations->getRFChCnt() + m_tscc->m_affiliations->getGrantedRFChCnt()); } } } else { - uint32_t chNo = m_tscc->m_affiliations->getGrantedCh(dstId); - csbk.setLogicalCh1(chNo); - csbk.setSlotNo(0U); + chNo = m_tscc->m_affiliations->getGrantedCh(dstId); m_tscc->m_affiliations->touchGrant(dstId); } @@ -820,38 +828,44 @@ bool ControlSignaling::writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_ ::ActivityLog("DMR", true, "Slot %u group grant request from %u to TG %u", m_tscc->m_slotNo, srcId, dstId); } + std::unique_ptr csbk = new_unique(CSBK_TV_GRANT); + if (broadcast) + csbk->setCSBKO(CSBKO_BTV_GRANT); + csbk->setLogicalCh1(chNo); + csbk->setSlotNo(1U); // eah? this can't be okay... + if (m_verbose) { LogMessage((net) ? LOG_NET : LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_GRP_VOICE_CALL (Group Voice Call), emerg = %u, privacy = %u, broadcast = %u, prio = %u, chNo = %u, slot = %u, srcId = %u, dstId = %u", - m_tscc->m_slotNo, emergency, privacy, broadcast, priority, csbk.getLogicalCh1(), csbk.getSlotNo(), srcId, dstId); + m_tscc->m_slotNo, emergency, privacy, broadcast, priority, csbk->getLogicalCh1(), csbk->getSlotNo(), srcId, dstId); } - // transmit group grant - csbk.setCSBKO(CSBKO_TV_GRANT); - if (broadcast) - csbk.setCSBKO(CSBKO_BTV_GRANT); - csbk.setSrcId(srcId); - csbk.setDstId(dstId); - csbk.setEmergency(emergency); + csbk->setEmergency(emergency); + csbk->setSrcId(srcId); + csbk->setDstId(dstId); - writeRF_CSBK(csbk); + // transmit group grant + writeRF_CSBK(csbk.get()); } else { if (!net) { ::ActivityLog("DMR", true, "Slot %u individual grant request from %u to TG %u", m_tscc->m_slotNo, srcId, dstId); } + std::unique_ptr csbk = new_unique(CSBK_PV_GRANT); + csbk->setLogicalCh1(chNo); + csbk->setSlotNo(1U); // eah? this can't be okay... + if (m_verbose) { LogMessage((net) ? LOG_NET : LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_IND_VOICE_CALL (Individual Voice Call), emerg = %u, privacy = %u, broadcast = %u, prio = %u, chNo = %u, slot = %u, srcId = %u, dstId = %u", - m_tscc->m_slotNo, emergency, privacy, broadcast, priority, csbk.getLogicalCh1(), csbk.getSlotNo(), srcId, dstId); + m_tscc->m_slotNo, emergency, privacy, broadcast, priority, csbk->getLogicalCh1(), csbk->getSlotNo(), srcId, dstId); } - // transmit private grant - csbk.setCSBKO(CSBKO_PV_GRANT); - csbk.setSrcId(srcId); - csbk.setDstId(dstId); - csbk.setEmergency(emergency); + csbk->setEmergency(emergency); + csbk->setSrcId(srcId); + csbk->setDstId(dstId); - writeRF_CSBK(csbk); + // transmit private grant + writeRF_CSBK(csbk.get()); } return true; @@ -865,9 +879,10 @@ bool ControlSignaling::writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_ /// /// /// +/// /// /// -bool ControlSignaling::writeRF_CSBK_Data_Grant(uint32_t srcId, uint32_t dstId, uint8_t serviceOptions, bool grp, bool skip, bool net) +bool ControlSignaling::writeRF_CSBK_Data_Grant(uint32_t srcId, uint32_t dstId, uint8_t serviceOptions, bool grp, bool skip, uint32_t chNo, bool net) { Slot *m_tscc = m_slot->m_dmr->getTSCCSlot(); @@ -876,10 +891,6 @@ bool ControlSignaling::writeRF_CSBK_Data_Grant(uint32_t srcId, uint32_t dstId, u bool broadcast = ((serviceOptions & 0xFFU) & 0x10U) == 0x10U; // Broadcast Flag uint8_t priority = ((serviceOptions & 0xFFU) & 0x03U); // Priority - lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); - csbk.setVerbose(m_dumpCSBKData); - csbk.setFID(FID_ETSI); - if (dstId == DMR_WUID_ALL) { return true; // do not generate grant packets for $FFFF (All Call) TGID } @@ -889,7 +900,7 @@ bool ControlSignaling::writeRF_CSBK_Data_Grant(uint32_t srcId, uint32_t dstId, u if (m_slot->m_rfState != RS_RF_LISTENING && m_slot->m_rfState != RS_RF_DATA) { if (!net) { LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_DATA_CALL (Data Call) denied, traffic in progress, dstId = %u", m_tscc->m_slotNo, dstId); - writeRF_CSBK_ACK_RSP(TS_DENY_RSN_TGT_BUSY, (grp) ? 1U : 0U); + writeRF_CSBK_ACK_RSP(srcId, TS_DENY_RSN_TGT_BUSY, (grp) ? 1U : 0U); ::ActivityLog("DMR", true, "Slot %u group grant request %u to TG %u denied", m_tscc->m_slotNo, srcId, dstId); m_slot->m_rfState = RS_RF_REJECTED; @@ -901,7 +912,7 @@ bool ControlSignaling::writeRF_CSBK_Data_Grant(uint32_t srcId, uint32_t dstId, u if (m_slot->m_netState != RS_NET_IDLE && dstId == m_slot->m_netLastDstId) { if (!net) { LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_DATA_CALL (Data Call) denied, traffic in progress, dstId = %u", m_tscc->m_slotNo, dstId); - writeRF_CSBK_ACK_RSP(TS_DENY_RSN_TGT_BUSY, (grp) ? 1U : 0U); + writeRF_CSBK_ACK_RSP(srcId, TS_DENY_RSN_TGT_BUSY, (grp) ? 1U : 0U); ::ActivityLog("DMR", true, "Slot %u group grant request %u to TG %u denied", m_tscc->m_slotNo, srcId, dstId); m_slot->m_rfState = RS_RF_REJECTED; @@ -914,7 +925,7 @@ bool ControlSignaling::writeRF_CSBK_Data_Grant(uint32_t srcId, uint32_t dstId, u if (m_slot->m_rfLastDstId != 0U) { if (m_slot->m_rfLastDstId != dstId && (m_slot->m_rfTGHang.isRunning() && !m_slot->m_rfTGHang.hasExpired())) { if (!net) { - writeRF_CSBK_ACK_RSP(TS_DENY_RSN_TGT_BUSY, (grp) ? 1U : 0U); + writeRF_CSBK_ACK_RSP(srcId, TS_DENY_RSN_TGT_BUSY, (grp) ? 1U : 0U); m_slot->m_rfState = RS_RF_REJECTED; } @@ -927,7 +938,7 @@ bool ControlSignaling::writeRF_CSBK_Data_Grant(uint32_t srcId, uint32_t dstId, u if (grp) { if (!net) { LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_GRP_DATA_CALL (Group Data Call) queued, no channels available, dstId = %u", m_tscc->m_slotNo, dstId); - writeRF_CSBK_ACK_RSP(TS_DENY_RSN_SYS_BUSY, (grp) ? 1U : 0U); + writeRF_CSBK_ACK_RSP(srcId, TS_DENY_RSN_SYS_BUSY, (grp) ? 1U : 0U); ::ActivityLog("DMR", true, "Slot %u group grant request %u to TG %u queued", m_tscc->m_slotNo, srcId, dstId); m_slot->m_rfState = RS_RF_REJECTED; @@ -938,7 +949,7 @@ bool ControlSignaling::writeRF_CSBK_Data_Grant(uint32_t srcId, uint32_t dstId, u else { if (!net) { LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_IND_DATA_CALL (Individual Data Call) queued, no channels available, dstId = %u", m_tscc->m_slotNo, dstId); - writeRF_CSBK_ACK_RSP(TS_DENY_RSN_SYS_BUSY, (grp) ? 1U : 0U); + writeRF_CSBK_ACK_RSP(srcId, TS_DENY_RSN_SYS_BUSY, (grp) ? 1U : 0U); ::ActivityLog("DMR", true, "Slot %u group grant request %u to TG %u queued", m_tscc->m_slotNo, srcId, dstId); m_slot->m_rfState = RS_RF_REJECTED; @@ -949,58 +960,61 @@ bool ControlSignaling::writeRF_CSBK_Data_Grant(uint32_t srcId, uint32_t dstId, u } else { if (m_tscc->m_affiliations->grantCh(dstId, GRANT_TIMER_TIMEOUT)) { - uint32_t chNo = m_tscc->m_affiliations->getGrantedCh(dstId); - csbk.setLogicalCh1(chNo); - csbk.setSlotNo(0U); + chNo = m_tscc->m_affiliations->getGrantedCh(dstId); //m_tscc->m_siteData.setChCnt(m_tscc->m_affiliations->getRFChCnt() + m_tscc->m_affiliations->getGrantedRFChCnt()); } } } else { - uint32_t chNo = m_tscc->m_affiliations->getGrantedCh(dstId); - csbk.setLogicalCh1(chNo); - csbk.setSlotNo(0U); + chNo = m_tscc->m_affiliations->getGrantedCh(dstId); m_tscc->m_affiliations->touchGrant(dstId); } } + if (grp) { if (!net) { ::ActivityLog("DMR", true, "Slot %u group grant request from %u to TG %u", m_tscc->m_slotNo, srcId, dstId); } + std::unique_ptr csbk = new_unique(CSBK_TD_GRANT); + csbk->setLogicalCh1(chNo); + csbk->setSlotNo(1U); // eah? this can't be okay... + if (m_verbose) { LogMessage((net) ? LOG_NET : LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_GRP_DATA_CALL (Group Data Call), emerg = %u, privacy = %u, broadcast = %u, prio = %u, chNo = %u, slot = %u, srcId = %u, dstId = %u", - m_tscc->m_slotNo, emergency, privacy, broadcast, priority, csbk.getLogicalCh1(), csbk.getSlotNo(), srcId, dstId); + m_tscc->m_slotNo, emergency, privacy, broadcast, priority, csbk->getLogicalCh1(), csbk->getSlotNo(), srcId, dstId); } - // transmit group grant - csbk.setCSBKO(CSBKO_TD_GRANT); - csbk.setSrcId(srcId); - csbk.setDstId(dstId); - csbk.setEmergency(emergency); + csbk->setEmergency(emergency); + csbk->setSrcId(srcId); + csbk->setDstId(dstId); - writeRF_CSBK(csbk); + // transmit group grant + writeRF_CSBK(csbk.get()); } else { if (!net) { ::ActivityLog("DMR", true, "Slot %u individual grant request from %u to TG %u", m_tscc->m_slotNo, srcId, dstId); } + std::unique_ptr csbk = new_unique(CSBK_PD_GRANT); + csbk->setLogicalCh1(chNo); + csbk->setSlotNo(1U); // eah? this can't be okay... + if (m_verbose) { LogMessage((net) ? LOG_NET : LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_IND_DATA_CALL (Individual Data Call), emerg = %u, privacy = %u, broadcast = %u, prio = %u, chNo = %u, slot = %u, srcId = %u, dstId = %u", - m_tscc->m_slotNo, emergency, privacy, broadcast, priority, csbk.getLogicalCh1(), csbk.getSlotNo(), srcId, dstId); + m_tscc->m_slotNo, emergency, privacy, broadcast, priority, csbk->getLogicalCh1(), csbk->getSlotNo(), srcId, dstId); } - // transmit private grant - csbk.setCSBKO(CSBKO_PD_GRANT); - csbk.setSrcId(srcId); - csbk.setDstId(dstId); - csbk.setEmergency(emergency); + csbk->setEmergency(emergency); + csbk->setSrcId(srcId); + csbk->setDstId(dstId); - writeRF_CSBK(csbk); + // transmit private grant + writeRF_CSBK(csbk.get()); } return true; @@ -1017,10 +1031,7 @@ void ControlSignaling::writeRF_CSBK_U_Reg_Rsp(uint32_t srcId, uint8_t serviceOpt bool dereg = (serviceOptions & 0x01U) == 0x01U; - lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, m_slot->m_dumpCSBKData); - csbk.setVerbose(m_dumpCSBKData); - csbk.setCSBKO(CSBKO_ACK_RSP); - csbk.setFID(FID_ETSI); + std::unique_ptr csbk = new_unique(CSBK_ACK_RSP); if (!dereg) { if (m_verbose) { @@ -1030,20 +1041,20 @@ void ControlSignaling::writeRF_CSBK_U_Reg_Rsp(uint32_t srcId, uint8_t serviceOpt // remove dynamic unit registration table entry m_slot->m_affiliations->unitDereg(srcId); - csbk.setReason(TS_ACK_RSN_REG); + csbk->setReason(TS_ACK_RSN_REG); } else { - csbk.setReason(TS_ACK_RSN_REG); + csbk->setReason(TS_ACK_RSN_REG); // validate the source RID if (!acl::AccessControl::validateSrcId(srcId)) { LogWarning(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_REG_SVC (Registration Service), denial, RID rejection, srcId = %u", m_tscc->m_slotNo, srcId); ::ActivityLog("DMR", true, "unit registration request from %u denied", srcId); - csbk.setReason(TS_DENY_RSN_REG_DENIED); + csbk->setReason(TS_DENY_RSN_REG_DENIED); } - if (csbk.getReason() == TS_ACK_RSN_REG) { + if (csbk->getReason() == TS_ACK_RSN_REG) { if (m_verbose) { LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_RAND (Random Access), SVC_KIND_REG_SVC (Registration Service), srcId = %u, serviceOptions = $%02X", m_tscc->m_slotNo, srcId, serviceOptions); } @@ -1057,10 +1068,10 @@ void ControlSignaling::writeRF_CSBK_U_Reg_Rsp(uint32_t srcId, uint8_t serviceOpt } } - csbk.setSrcId(DMR_WUID_REGI); - csbk.setDstId(srcId); + csbk->setSrcId(DMR_WUID_REGI); + csbk->setDstId(srcId); - writeRF_CSBK(csbk); + writeRF_CSBK(csbk.get()); } /// @@ -1072,14 +1083,11 @@ void ControlSignaling::writeRF_TSCC_Aloha() LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_ALOHA (Aloha)", m_slot->m_slotNo); } - lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, false/*m_slot->m_dumpCSBKData*/); - csbk.setCSBKO(CSBKO_ALOHA); - csbk.setFID(FID_ETSI); + std::unique_ptr csbk = new_unique(CSBK_ALOHA); + csbk->setNRandWait(m_slot->m_alohaNRandWait); + csbk->setBackoffNo(m_slot->m_alohaBackOff); - csbk.setNRandWait(m_slot->m_alohaNRandWait); - csbk.setBackoffNo(m_slot->m_alohaBackOff); - - writeRF_CSBK(csbk); + writeRF_CSBK(csbk.get()); } /// @@ -1096,16 +1104,13 @@ void ControlSignaling::writeRF_TSCC_Bcast_Ann_Wd(uint32_t channelNo, bool annWd) m_slot->m_rfSeqNo = 0U; - lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, false/*m_slot->m_dumpCSBKData*/); - csbk.setCdef(false); - csbk.setCSBKO(CSBKO_BROADCAST); - csbk.setFID(FID_ETSI); - - csbk.setAnncType(BCAST_ANNC_ANN_WD_TSCC); - csbk.setLogicalCh1(channelNo); - csbk.setAnnWdCh1(annWd); + std::unique_ptr csbk = new_unique(CSBK_BROADCAST); + csbk->setCdef(false); + csbk->setAnncType(BCAST_ANNC_ANN_WD_TSCC); + csbk->setLogicalCh1(channelNo); + csbk->setAnnWdCh1(annWd); - writeRF_CSBK(csbk); + writeRF_CSBK(csbk.get()); } /// @@ -1117,13 +1122,10 @@ void ControlSignaling::writeRF_TSCC_Bcast_Sys_Parm() LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_BROADCAST (Broadcast), BCAST_ANNC_SITE_PARMS (Announce Site Parms)", m_slot->m_slotNo); } - lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, false/*m_slot->m_dumpCSBKData*/); - csbk.setCSBKO(CSBKO_BROADCAST); - csbk.setFID(FID_ETSI); - - csbk.setAnncType(BCAST_ANNC_SITE_PARMS); + std::unique_ptr csbk = new_unique(CSBK_BROADCAST); + csbk->setAnncType(BCAST_ANNC_SITE_PARMS); - writeRF_CSBK(csbk); + writeRF_CSBK(csbk.get()); } /// @@ -1135,9 +1137,7 @@ void ControlSignaling::writeRF_TSCC_Git_Hash() LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_DVM_GIT_HASH (DVM Git Hash)", m_slot->m_slotNo); } - lc::CSBK csbk = lc::CSBK(m_slot->m_siteData, m_slot->m_idenEntry, false/*m_slot->m_dumpCSBKData*/); - csbk.setCSBKO(CSBKO_DVM_GIT_HASH); - csbk.setFID(FID_DVM); + std::unique_ptr csbk = new_unique(CSBK_DVM_GIT_HASH); - writeRF_CSBK(csbk); + writeRF_CSBK(csbk.get()); } diff --git a/dmr/packet/ControlSignaling.h b/dmr/packet/ControlSignaling.h index a7dc4968..88c99010 100644 --- a/dmr/packet/ControlSignaling.h +++ b/dmr/packet/ControlSignaling.h @@ -88,16 +88,16 @@ namespace dmr ~ControlSignaling(); /// Helper to write a CSBK packet. - void writeRF_CSBK(lc::CSBK csbk, bool clearBeforeWrite = false); + void writeRF_CSBK(lc::CSBK* csbk, bool clearBeforeWrite = false); /// Helper to write a ACK RSP packet. - void writeRF_CSBK_ACK_RSP(uint8_t reason, uint8_t responseInfo); + void writeRF_CSBK_ACK_RSP(uint32_t dstId, uint8_t reason, uint8_t responseInfo); /// Helper to write a NACK RSP packet. - void writeRF_CSBK_NACK_RSP(uint8_t reason, uint8_t service); + void writeRF_CSBK_NACK_RSP(uint32_t dstId, uint8_t reason, uint8_t service); /// Helper to write a grant packet. - bool writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_t serviceOptions, bool grp, bool skip = false, bool net = false, bool skipNetCheck = false); + bool writeRF_CSBK_Grant(uint32_t srcId, uint32_t dstId, uint8_t serviceOptions, bool grp, bool skip = false, uint32_t chNo = 0U, bool net = false, bool skipNetCheck = false); /// Helper to write a data grant packet. - bool writeRF_CSBK_Data_Grant(uint32_t srcId, uint32_t dstId, uint8_t serviceOptions, bool grp, bool skip = false, bool net = false); + bool writeRF_CSBK_Data_Grant(uint32_t srcId, uint32_t dstId, uint8_t serviceOptions, bool grp, bool skip = false, uint32_t chNo = 0U, bool net = false); /// Helper to write a unit registration response packet. void writeRF_CSBK_U_Reg_Rsp(uint32_t srcId, uint8_t serviceOptions); diff --git a/p25/lc/TSBK.cpp b/p25/lc/TSBK.cpp index 5c0efbd1..a117ac7f 100644 --- a/p25/lc/TSBK.cpp +++ b/p25/lc/TSBK.cpp @@ -104,6 +104,7 @@ TSBK::TSBK() : m_encrypted(false), m_priority(4U), m_group(true), + m_siteIdenEntry(lookups::IdenTable()), m_rs(), m_trellis() { @@ -148,7 +149,7 @@ void TSBK::setCallsign(std::string callsign) } // --------------------------------------------------------------------------- -// Private Class Members +// Protected Class Members // --------------------------------------------------------------------------- /// @@ -267,7 +268,7 @@ bool TSBK::decode(const uint8_t* data, uint8_t* tsbk, bool rawTSBK) } /// -/// Encode a trunking signalling block. +/// Internal helper to eecode a trunking signalling block. /// /// /// @@ -325,8 +326,6 @@ void TSBK::encode(uint8_t* data, const uint8_t* tsbk, bool rawTSBK, bool noTrell /// void TSBK::copy(const TSBK& data) { - m_verbose = data.m_verbose; - m_warnCRC = data.m_warnCRC; m_protect = data.m_protect; m_lco = data.m_lco; m_mfId = data.m_mfId; @@ -351,4 +350,6 @@ void TSBK::copy(const TSBK& data) m_priority = data.m_priority; m_group = data.m_group; + + m_siteIdenEntry = data.m_siteIdenEntry; }