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;
}