convert DMR to follow the factory code pattern for CSBKs;

3.0-rcon_maint
Bryan Biedenkapp 3 years ago
parent daf09bd562
commit d89c90118d

@ -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"

@ -241,7 +241,7 @@ inline std::string __IP_FROM_ULONG(const ulong64_t& value) {
/// <summary>Creates a private copy implementation.</summary>
/// <remarks>This requires the copy(const type& data) to be declared in the class definition.</remarks>
#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) {
/// <summary>Creates a protected copy implementation.</summary>
/// <remarks>This requires the copy(const type& data) to be declared in the class definition.</remarks>
#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); \

@ -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<lc::CSBK> 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);
}

@ -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;
}
/// <summary>
/// Helper to change the CSBK verbose state.
/// </summary>
/// <param name="verbose">Flag indicating whether CSBK dumping is enabled.</param>
void Slot::setCSBKVerbose(bool verbose)
{
m_dumpCSBKData = verbose;
}
/// <summary>
/// Helper to enable and configure TSCC support for this slot.
/// </summary>

@ -99,8 +99,6 @@ namespace dmr
/// <summary>Helper to change the debug and verbose state.</summary>
void setDebugVerbose(bool debug, bool verbose);
/// <summary>Helper to change the CSBK verbose state.</summary>
void setCSBKVerbose(bool verbose);
/// <summary>Helper to enable and configure TSCC support for this slot.</summary>
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;

@ -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 <cstdio>
#include <cassert>
// ---------------------------------------------------------------------------
// Static Class Members
// ---------------------------------------------------------------------------
bool CSBK::m_verbose = false;
SiteData CSBK::m_siteData = SiteData();
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CSBK class.
/// Initializes a copy instance of the CSBK class.
/// </summary>
/// <param name="siteData"></param>
/// <param name="entry"></param>
CSBK::CSBK(SiteData siteData, lookups::IdenTable entry) : CSBK(siteData)
/// <param name="data"></param>
CSBK::CSBK(const CSBK& data) : CSBK()
{
m_siteIdenEntry = entry;
copy(data);
}
/// <summary>
/// Initializes a new instance of the CSBK class.
/// </summary>
/// <param name="siteData"></param>
/// <param name="entry"></param>
/// <param name="verbose"></param>
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 */
}
/// <summary>
@ -77,15 +102,14 @@ CSBK::~CSBK()
}
/// <summary>
/// Decodes a DMR CSBK.
/// Regenerate a DMR CSBK without decoding.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if DMR CSBK was decoded, otherwise false.</returns>
bool CSBK::decode(const uint8_t* data)
/// <returns>True, if TSBK was decoded, otherwise false.</returns>
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
// ---------------------------------------------------------------------------
/// <summary>
/// Internal helper to convert CSBK bytes to a 64-bit long value.
/// </summary>
/// <param name="tsbk"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Encodes a DMR CSBK.
/// Internal helper to convert a 64-bit long value to CSBK bytes.
/// </summary>
/// <param name="data"></param>
void CSBK::encode(uint8_t* data)
/// <param name="csbkValue"></param>
/// <returns></returns>
std::unique_ptr<uint8_t[]> 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;
}
/// <summary>
/// Internal helper to decode a control signalling block.
/// </summary>
/// <param name="data"></param>
/// <param name="tsbk"></param>
/// <returns>True, if TSBK was decoded, otherwise false.</returns>
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;
}
/// <summary>
/// Internal helper to encode a control signalling block.
/// </summary>
/// <param name="data"></param>
/// <param name="tsbk"></param>
/// <param name="rawTSBK"></param>
/// <param name="noTrellis"></param>
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
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CSBK class.
/// Internal helper to copy the the class.
/// </summary>
/// <param name="siteData"></param>
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())
/// <param name="data"></param>
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;
}

@ -47,120 +47,111 @@ namespace dmr
class HOST_SW_API CSBK {
public:
/// <summary>Initializes a copy instance of the CSBK class.</summary>
CSBK(const CSBK& data);
/// <summary>Initializes a new instance of the CSBK class.</summary>
CSBK(SiteData siteData, lookups::IdenTable entry);
/// <summary>Initializes a new instance of the CSBK class.</summary>
CSBK(SiteData siteData, lookups::IdenTable entry, bool verbose);
CSBK();
/// <summary>Finalizes a instance of the CSBK class.</summary>
~CSBK();
virtual ~CSBK();
/// <summary>Decodes a DMR CSBK.</summary>
bool decode(const uint8_t* data);
virtual bool decode(const uint8_t* data) = 0;
/// <summary>Encodes a DMR CSBK.</summary>
void encode(uint8_t* data);
virtual void encode(uint8_t* data) = 0;
public:
/// <summary>Flag indicating verbose log output.</summary>
__PROPERTY(bool, verbose, Verbose);
/// <summary>Regenerate a DMR CSBK without decoding.</summary>
/// <remarks>This is because the DMR archeticture allows fall-thru of unsupported CSBKs.</remarks>
static bool regenerate(uint8_t* data);
/// <summary>DMR access color code.</summary>
__PROPERTY(uint8_t, colorCode, ColorCode);
/// <summary>Sets the flag indicating verbose log output.</summary>
static void setVerbose(bool verbose) { m_verbose = verbose; }
/** Local Site data */
/// <summary>Gets the local site data.</summary>
static SiteData getSiteData() { return m_siteData; }
/// <summary>Sets the local site data.</summary>
static void setSiteData(SiteData siteData) { m_siteData = siteData; }
public:
/** Common Data */
/// <summary>DMR access color code.</summary>
__PROTECTED_PROPERTY(uint8_t, colorCode, ColorCode);
/// <summary>Flag indicating this is the last TSBK in a sequence of TSBKs.</summary>
__PROPERTY(bool, lastBlock, LastBlock);
__PROTECTED_PROPERTY(bool, lastBlock, LastBlock);
/// <summary>Flag indicating whether the CSBK is a Cdef block.</summary>
__PROPERTY(bool, Cdef, Cdef);
__PROTECTED_PROPERTY(bool, Cdef, Cdef);
/// <summary>CSBK opcode.</summary>
__PROPERTY(uint8_t, CSBKO, CSBKO);
__PROTECTED_PROPERTY(uint8_t, CSBKO, CSBKO);
/// <summary>CSBK feature ID.</summayr>
__PROPERTY(uint8_t, FID, FID);
__PROTECTED_PROPERTY(uint8_t, FID, FID);
/// <summary>Flag indicating whether the CSBK is group or individual.</summary>
__PROPERTY(bool, GI, GI);
__PROTECTED_PROPERTY(bool, GI, GI);
/// <summary>Base Station ID.</summary>
__READONLY_PROPERTY(uint32_t, bsId, BSId);
/// <summary>Source ID.</summary>
__PROPERTY(uint32_t, srcId, SrcId);
__PROTECTED_PROPERTY(uint32_t, srcId, SrcId);
/// <summary>Destination ID.</summary>
__PROPERTY(uint32_t, dstId, DstId);
__PROTECTED_PROPERTY(uint32_t, dstId, DstId);
/// <summary></summary>
__READONLY_PROPERTY(bool, dataContent, DataContent);
__PROTECTED_READONLY_PROPERTY(bool, dataContent, DataContent);
/// <summary>Number of blocks to follow.</summary>
__PROPERTY(uint8_t, CBF, CBF);
__PROTECTED_PROPERTY(uint8_t, CBF, CBF);
/** Service Options */
/** Common Service Options */
/// <summary>Flag indicating the emergency bits are set.</summary>
__PROPERTY(bool, emergency, Emergency);
__PROTECTED_PROPERTY(bool, emergency, Emergency);
/// <summary>Flag indicating that privacy is enabled.</summary>
__PROPERTY(bool, privacy, Privacy);
__PROTECTED_PROPERTY(bool, privacy, Privacy);
/// <summary>Flag indicating that supplementary data is required.</summary>
__PROPERTY(bool, supplementData, SupplementData);
__PROTECTED_PROPERTY(bool, supplementData, SupplementData);
/// <summary>Priority level for the traffic.</summary>
__PROPERTY(uint8_t, priority, Priority);
__PROTECTED_PROPERTY(uint8_t, priority, Priority);
/// <summary>Flag indicating a broadcast service.</summary>
__PROPERTY(bool, broadcast, Broadcast);
__PROTECTED_PROPERTY(bool, broadcast, Broadcast);
/// <summary>Flag indicating a proxy.</summary>
__PROPERTY(bool, proxy, Proxy);
/** Tier III */
/// <summary>Backoff Number.</summary>
__PROPERTY(uint8_t, backoffNo, BackoffNo);
/// <summary>Random Access Wait Delay.</summary>
__PROPERTY(uint8_t, nRandWait, NRandWait);
/// <summary>Service Options.</summary>
__PROPERTY(uint8_t, serviceOptions, ServiceOptions);
/// <summary>Service Extra Options.</summary>
__PROPERTY(uint8_t, serviceExtra, ServiceExtra);
/// <summary>Service Kind.</summary>
__PROPERTY(uint8_t, serviceKind, ServiceKind);
/// <summary>Destination/Target address type.</summary>
__PROPERTY(uint8_t, targetAddress, TargetAddress);
__PROTECTED_PROPERTY(bool, proxy, Proxy);
/// <summary>Response information.</summary>
__PROPERTY(uint8_t, response, Response);
__PROTECTED_PROPERTY(uint8_t, response, Response);
/// <summary>Reason type.</summary>
__PROPERTY(uint8_t, reason, Reason);
__PROTECTED_PROPERTY(uint8_t, reason, Reason);
/// <summary>Broadcast Announcment Type.</summary>
__PROPERTY(uint8_t, anncType, AnncType);
/// <summary>Broadcast Hibernation Flag.</summary>
__PROPERTY(bool, hibernating, Hibernating);
/** Tier 3 */
/// <summary>Site offset timing.</summary>
__PROTECTED_PROPERTY(bool, siteOffsetTiming, SiteOffsetTiming);
/// <summary>Broadcast Announce/Withdraw Channel 1 Flag.</summary>
__PROPERTY(bool, annWdCh1, AnnWdCh1);
/// <summary>Broadcast Logical Channel ID 1.</summary>
__PROPERTY(uint16_t, logicalCh1, LogicalCh1);
/// <summary>Broadcast Announce/Withdraw Channel 2 Flag.</summary>
__PROPERTY(bool, annWdCh2, AnnWdCh2);
__PROTECTED_PROPERTY(uint16_t, logicalCh1, LogicalCh1);
/// <summary>Broadcast Logical Channel ID 2.</summary>
__PROPERTY(uint16_t, logicalCh2, LogicalCh2);
__PROTECTED_PROPERTY(uint16_t, logicalCh2, LogicalCh2);
/// <summary>Logical Channel Slot Number.</summary>
__PROPERTY(uint8_t, slotNo, SlotNo);
/// <summary>Aloha Site Time Slot Synchronization.</summary>
__PROPERTY(bool, siteTSSync, SiteTSSync);
/// <summary>Aloha site users offset timing.</summary>
__PROPERTY(bool, siteOffsetTiming, SiteOffsetTiming);
/// <summary>Aloha MS mask.</summary>
__PROPERTY(uint8_t, alohaMask, AlohaMask);
__PROTECTED_PROPERTY(uint8_t, slotNo, SlotNo);
/** Local Site data */
/// <summary>Local Site Data.</summary>
__PROPERTY_PLAIN(SiteData, siteData, siteData);
/// <summary>Local Site Identity Entry.</summary>
__PROPERTY_PLAIN(lookups::IdenTable, siteIdenEntry, siteIdenEntry);
__PROTECTED_PROPERTY_PLAIN(lookups::IdenTable, siteIdenEntry, siteIdenEntry);
private:
/// <summary>Initializes a new instance of the CSBK class.</summary>
CSBK(SiteData siteData);
protected:
static bool m_verbose;
/** Local Site data */
static SiteData m_siteData;
/// <summary>Internal helper to convert CSBK bytes to a 64-bit long value.</summary>
static ulong64_t toValue(const uint8_t* Csbk);
/// <summary>Internal helper to convert a 64-bit long value to CSBK bytes.</summary>
static std::unique_ptr<uint8_t[]> fromValue(const ulong64_t csbkValue);
/// <summary>Internal helper to decode a control signalling block.</summary>
bool decode(const uint8_t* data, uint8_t* csbk);
/// <summary>Internal helper to encode a control signalling block.</summary>
void encode(uint8_t* data, const uint8_t* csbk);
__PROTECTED_COPY(CSBK);
};
} // namespace lc
} // namespace dmr

@ -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 <cassert>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CSBKFactory class.
/// </summary>
CSBKFactory::CSBKFactory()
{
/* stub */
}
/// <summary>
/// Finalizes a instance of CSBKFactory class.
/// </summary>
CSBKFactory::~CSBKFactory()
{
/* stub */
}
/// <summary>
/// Create an instance of a CSBK.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if CSBK was decoded, otherwise false.</returns>
std::unique_ptr<CSBK> 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
// ---------------------------------------------------------------------------
/// <summary>
///
/// </summary>
/// <param name="csbk"></param>
/// <param name="data"></param>
/// <returns></returns>
std::unique_ptr<CSBK> 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>(csbk);
}

@ -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:
/// <summary>Initializes a new instance of the CSBKFactory class.</summary>
CSBKFactory();
/// <summary>Finalizes a instance of the CSBKFactory class.</summary>
~CSBKFactory();
/// <summary>Create an instance of a CSBK.</summary>
static std::unique_ptr<CSBK> createCSBK(const uint8_t* data);
private:
/// <summary></summary>
static std::unique_ptr<CSBK> decode(CSBK* tsbk, const uint8_t* data);
};
} // namespace csbk
} // namespace lc
} // namespace dmr
#endif // __DMR_LC__CSBK_FACTORY_H__

@ -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 <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CSBK_ACK_RSP class.
/// </summary>
CSBK_ACK_RSP::CSBK_ACK_RSP() : CSBK()
{
m_CSBKO = CSBKO_ACK_RSP;
}
/// <summary>
/// Decode a control signalling block.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if CSBK was decoded, otherwise false.</returns>
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;
}
/// <summary>
/// Encode a control signalling block.
/// </summary>
/// <param name="data"></param>
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<uint8_t[]> csbk = CSBK::fromValue(csbkValue);
CSBK::encode(data, csbk.get());
}

@ -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:
/// <summary>Initializes a new instance of the CSBK_ACK_RSP class.</summary>
CSBK_ACK_RSP();
/// <summary>Decode a control signalling block.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a control signalling block.</summary>
virtual void encode(uint8_t* data);
};
} // namespace csbk
} // namespace lc
} // namespace dmr
#endif // __DMR_LC_CSBK__CSBK_ACK_RSP_H__

@ -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 <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CSBK_ALOHA class.
/// </summary>
CSBK_ALOHA::CSBK_ALOHA() : CSBK(),
m_siteTSSync(false),
m_alohaMask(0U),
m_backoffNo(1U),
m_nRandWait(DEFAULT_NRAND_WAIT)
{
m_CSBKO = CSBKO_ALOHA;
}
/// <summary>
/// Decode a control signalling block.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if CSBK was decoded, otherwise false.</returns>
bool CSBK_ALOHA::decode(const uint8_t* data)
{
assert(data != NULL);
/* stub */
return true;
}
/// <summary>
/// Encode a control signalling block.
/// </summary>
/// <param name="data"></param>
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<uint8_t[]> csbk = CSBK::fromValue(csbkValue);
CSBK::encode(data, csbk.get());
}
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Internal helper to copy the the class.
/// </summary>
/// <param name="data"></param>
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;
}

@ -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:
/// <summary>Initializes a new instance of the CSBK_ALOHA class.</summary>
CSBK_ALOHA();
/// <summary>Decode a control signalling block.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a control signalling block.</summary>
virtual void encode(uint8_t* data);
public:
/// <summary>Aloha Site Time Slot Synchronization.</summary>
__PROPERTY(bool, siteTSSync, SiteTSSync);
/// <summary>Aloha MS mask.</summary>
__PROPERTY(uint8_t, alohaMask, AlohaMask);
/// <summary>Backoff Number.</summary>
__PROPERTY(uint8_t, backoffNo, BackoffNo);
/// <summary>Random Access Wait Delay.</summary>
__PROPERTY(uint8_t, nRandWait, NRandWait);
__COPY(CSBK_ALOHA);
};
} // namespace csbk
} // namespace lc
} // namespace dmr
#endif // __DMR_LC_CSBK__CSBK_ALOHA_H__

@ -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 <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CSBK_BROADCAST class.
/// </summary>
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;
}
/// <summary>
/// Decode a control signalling block.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if CSBK was decoded, otherwise false.</returns>
bool CSBK_BROADCAST::decode(const uint8_t* data)
{
assert(data != NULL);
/* stub */
return true;
}
/// <summary>
/// Encode a control signalling block.
/// </summary>
/// <param name="data"></param>
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<uint8_t[]> csbk = CSBK::fromValue(csbkValue);
CSBK::encode(data, csbk.get());
}
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Internal helper to copy the the class.
/// </summary>
/// <param name="data"></param>
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;
}

@ -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:
/// <summary>Initializes a new instance of the CSBK_BROADCAST class.</summary>
CSBK_BROADCAST();
/// <summary>Decode a control signalling block.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a control signalling block.</summary>
virtual void encode(uint8_t* data);
public:
/// <summary>Broadcast Announcment Type.</summary>
__PROPERTY(uint8_t, anncType, AnncType);
/// <summary>Broadcast Hibernation Flag.</summary>
__PROPERTY(bool, hibernating, Hibernating);
/// <summary>Broadcast Announce/Withdraw Channel 1 Flag.</summary>
__PROPERTY(bool, annWdCh1, AnnWdCh1);
/// <summary>Broadcast Announce/Withdraw Channel 2 Flag.</summary>
__PROPERTY(bool, annWdCh2, AnnWdCh2);
/// <summary>Backoff Number.</summary>
__PROPERTY(uint8_t, backoffNo, BackoffNo);
__COPY(CSBK_BROADCAST);
};
} // namespace csbk
} // namespace lc
} // namespace dmr
#endif // __DMR_LC_CSBK__CSBK_BROADCAST_H__

@ -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 <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CSBK_BSDWNACT class.
/// </summary>
CSBK_BSDWNACT::CSBK_BSDWNACT() : CSBK(),
m_bsId(0U)
{
m_CSBKO = CSBKO_BSDWNACT;
}
/// <summary>
/// Decode a control signalling block.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if CSBK was decoded, otherwise false.</returns>
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;
}
/// <summary>
/// Encode a control signalling block.
/// </summary>
/// <param name="data"></param>
void CSBK_BSDWNACT::encode(uint8_t* data)
{
assert(data != NULL);
/* stub */
}
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Internal helper to copy the the class.
/// </summary>
/// <param name="data"></param>
void CSBK_BSDWNACT::copy(const CSBK_BSDWNACT& data)
{
CSBK::copy(data);
m_bsId = data.m_bsId;
}

@ -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:
/// <summary>Initializes a new instance of the CSBK_BSDWNACT class.</summary>
CSBK_BSDWNACT();
/// <summary>Decode a control signalling block.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a control signalling block.</summary>
virtual void encode(uint8_t* data);
public:
/// <summary>Base Station ID.</summary>
__READONLY_PROPERTY(uint32_t, bsId, BSId);
__COPY(CSBK_BSDWNACT);
};
} // namespace csbk
} // namespace lc
} // namespace dmr
#endif // __DMR_LC_CSBK__CSBK_BSDWNACT_H__

@ -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 <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CSBK_CALL_ALRT class.
/// </summary>
CSBK_CALL_ALRT::CSBK_CALL_ALRT() : CSBK()
{
m_CSBKO = CSBKO_RAND;
m_FID = FID_DMRA;
}
/// <summary>
/// Decode a control signalling block.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if CSBK was decoded, otherwise false.</returns>
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;
}
/// <summary>
/// Encode a control signalling block.
/// </summary>
/// <param name="data"></param>
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<uint8_t[]> csbk = CSBK::fromValue(csbkValue);
CSBK::encode(data, csbk.get());
}

@ -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:
/// <summary>Initializes a new instance of the CSBK_CALL_ALRT class.</summary>
CSBK_CALL_ALRT();
/// <summary>Decode a control signalling block.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a control signalling block.</summary>
virtual void encode(uint8_t* data);
};
} // namespace csbk
} // namespace lc
} // namespace dmr
#endif // __DMR_LC_CSBK__CSBK_CALL_ALRT_H__

@ -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 <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CSBK_DVM_GIT_HASH class.
/// </summary>
CSBK_DVM_GIT_HASH::CSBK_DVM_GIT_HASH() : CSBK()
{
m_CSBKO = CSBKO_DVM_GIT_HASH;
m_FID = FID_DVM;
}
/// <summary>
/// Decode a control signalling block.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if CSBK was decoded, otherwise false.</returns>
bool CSBK_DVM_GIT_HASH::decode(const uint8_t* data)
{
assert(data != NULL);
/* stub */
return true;
}
/// <summary>
/// Encode a control signalling block.
/// </summary>
/// <param name="data"></param>
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<uint8_t[]> csbk = CSBK::fromValue(csbkValue);
CSBK::encode(data, csbk.get());
}

@ -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:
/// <summary>Initializes a new instance of the CSBK_DVM_GIT_HASH class.</summary>
CSBK_DVM_GIT_HASH();
/// <summary>Decode a control signalling block.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a control signalling block.</summary>
virtual void encode(uint8_t* data);
};
} // namespace csbk
} // namespace lc
} // namespace dmr
#endif // __DMR_LC_CSBK__CSBK_DVM_GIT_HASH_H__

@ -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 <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CSBK_EXT_FNCT class.
/// </summary>
CSBK_EXT_FNCT::CSBK_EXT_FNCT() : CSBK(),
m_extendedFunction(DMR_EXT_FNCT_CHECK)
{
m_CSBKO = CSBKO_EXT_FNCT;
m_FID = FID_DMRA;
}
/// <summary>
/// Decode a control signalling block.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if CSBK was decoded, otherwise false.</returns>
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;
}
/// <summary>
/// Encode a control signalling block.
/// </summary>
/// <param name="data"></param>
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<uint8_t[]> csbk = CSBK::fromValue(csbkValue);
CSBK::encode(data, csbk.get());
}
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Internal helper to copy the the class.
/// </summary>
/// <param name="data"></param>
void CSBK_EXT_FNCT::copy(const CSBK_EXT_FNCT& data)
{
CSBK::copy(data);
m_extendedFunction = data.m_extendedFunction;
}

@ -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:
/// <summary>Initializes a new instance of the CSBK_EXT_FNCT class.</summary>
CSBK_EXT_FNCT();
/// <summary>Decode a control signalling block.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a control signalling block.</summary>
virtual void encode(uint8_t* data);
public:
/// <summary>Extended function opcode.</summary>
__PROPERTY(uint8_t, extendedFunction, ExtendedFunction);
__COPY(CSBK_EXT_FNCT);
};
} // namespace csbk
} // namespace lc
} // namespace dmr
#endif // __DMR_LC_CSBK__CSBK_EXT_FNCT_H__

@ -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 <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CSBK_NACK_RSP class.
/// </summary>
CSBK_NACK_RSP::CSBK_NACK_RSP() : CSBK(),
m_serviceKind(0U)
{
m_CSBKO = CSBKO_NACK_RSP;
}
/// <summary>
/// Decode a control signalling block.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if CSBK was decoded, otherwise false.</returns>
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;
}
/// <summary>
/// Encode a control signalling block.
/// </summary>
/// <param name="data"></param>
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<uint8_t[]> csbk = CSBK::fromValue(csbkValue);
CSBK::encode(data, csbk.get());
}
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Internal helper to copy the the class.
/// </summary>
/// <param name="data"></param>
void CSBK_NACK_RSP::copy(const CSBK_NACK_RSP& data)
{
CSBK::copy(data);
m_serviceKind = data.m_serviceKind;
}

@ -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:
/// <summary>Initializes a new instance of the CSBK_NACK_RSP class.</summary>
CSBK_NACK_RSP();
/// <summary>Decode a control signalling block.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a control signalling block.</summary>
virtual void encode(uint8_t* data);
public:
/// <summary>Service Kind.</summary>
__PROPERTY(uint8_t, serviceKind, ServiceKind);
__COPY(CSBK_NACK_RSP);
};
} // namespace csbk
} // namespace lc
} // namespace dmr
#endif // __DMR_LC_CSBK__CSBK_NACK_RSP_H__

@ -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 <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CSBK_PD_GRANT class.
/// </summary>
CSBK_PD_GRANT::CSBK_PD_GRANT() : CSBK()
{
m_CSBKO = CSBKO_PD_GRANT;
}
/// <summary>
/// Decode a control signalling block.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if CSBK was decoded, otherwise false.</returns>
bool CSBK_PD_GRANT::decode(const uint8_t* data)
{
assert(data != NULL);
/* stub */
return true;
}
/// <summary>
/// Encode a control signalling block.
/// </summary>
/// <param name="data"></param>
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<uint8_t[]> csbk = CSBK::fromValue(csbkValue);
CSBK::encode(data, csbk.get());
}

@ -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:
/// <summary>Initializes a new instance of the CSBK_PD_GRANT class.</summary>
CSBK_PD_GRANT();
/// <summary>Decode a control signalling block.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a control signalling block.</summary>
virtual void encode(uint8_t* data);
};
} // namespace csbk
} // namespace lc
} // namespace dmr
#endif // __DMR_LC_CSBK__CSBK_PD_GRANT_H__

@ -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 <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CSBK_PRECCSBK class.
/// </summary>
CSBK_PRECCSBK::CSBK_PRECCSBK() : CSBK()
{
m_CSBKO = CSBKO_PRECCSBK;
}
/// <summary>
/// Decode a control signalling block.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if CSBK was decoded, otherwise false.</returns>
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;
}
/// <summary>
/// Encode a control signalling block.
/// </summary>
/// <param name="data"></param>
void CSBK_PRECCSBK::encode(uint8_t* data)
{
assert(data != NULL);
/* stub */
}

@ -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:
/// <summary>Initializes a new instance of the CSBK_PRECCSBK class.</summary>
CSBK_PRECCSBK();
/// <summary>Decode a control signalling block.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a control signalling block.</summary>
virtual void encode(uint8_t* data);
};
} // namespace csbk
} // namespace lc
} // namespace dmr
#endif // __DMR_LC_CSBK__CSBK_PRECCSBK_H__

@ -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 <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CSBK_PV_GRANT class.
/// </summary>
CSBK_PV_GRANT::CSBK_PV_GRANT() : CSBK()
{
m_CSBKO = CSBKO_PV_GRANT;
}
/// <summary>
/// Decode a control signalling block.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if CSBK was decoded, otherwise false.</returns>
bool CSBK_PV_GRANT::decode(const uint8_t* data)
{
assert(data != NULL);
/* stub */
return true;
}
/// <summary>
/// Encode a control signalling block.
/// </summary>
/// <param name="data"></param>
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<uint8_t[]> csbk = CSBK::fromValue(csbkValue);
CSBK::encode(data, csbk.get());
}

@ -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:
/// <summary>Initializes a new instance of the CSBK_PV_GRANT class.</summary>
CSBK_PV_GRANT();
/// <summary>Decode a control signalling block.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a control signalling block.</summary>
virtual void encode(uint8_t* data);
};
} // namespace csbk
} // namespace lc
} // namespace dmr
#endif // __DMR_LC_CSBK__CSBK_PV_GRANT_H__

@ -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 <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CSBK_RAND class.
/// </summary>
CSBK_RAND::CSBK_RAND() : CSBK(),
m_serviceOptions(0U),
m_serviceExtra(0U),
m_serviceKind(0U)
{
m_CSBKO = CSBKO_RAND;
}
/// <summary>
/// Decode a control signalling block.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if CSBK was decoded, otherwise false.</returns>
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;
}
/// <summary>
/// Encode a control signalling block.
/// </summary>
/// <param name="data"></param>
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<uint8_t[]> csbk = CSBK::fromValue(csbkValue);
CSBK::encode(data, csbk.get());
}
// ---------------------------------------------------------------------------
// Private Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Internal helper to copy the the class.
/// </summary>
/// <param name="data"></param>
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;
}

@ -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:
/// <summary>Initializes a new instance of the CSBK_RAND class.</summary>
CSBK_RAND();
/// <summary>Decode a control signalling block.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a control signalling block.</summary>
virtual void encode(uint8_t* data);
public:
/// <summary>Service Options.</summary>
__PROPERTY(uint8_t, serviceOptions, ServiceOptions);
/// <summary>Service Extra Options.</summary>
__PROPERTY(uint8_t, serviceExtra, ServiceExtra);
/// <summary>Service Kind.</summary>
__PROPERTY(uint8_t, serviceKind, ServiceKind);
__COPY(CSBK_RAND);
};
} // namespace csbk
} // namespace lc
} // namespace dmr
#endif // __DMR_LC_CSBK__CSBK_RAND_H__

@ -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 <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CSBK_TD_GRANT class.
/// </summary>
CSBK_TD_GRANT::CSBK_TD_GRANT() : CSBK()
{
m_CSBKO = CSBKO_TD_GRANT;
}
/// <summary>
/// Decode a control signalling block.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if CSBK was decoded, otherwise false.</returns>
bool CSBK_TD_GRANT::decode(const uint8_t* data)
{
assert(data != NULL);
/* stub */
return true;
}
/// <summary>
/// Encode a control signalling block.
/// </summary>
/// <param name="data"></param>
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<uint8_t[]> csbk = CSBK::fromValue(csbkValue);
CSBK::encode(data, csbk.get());
}

@ -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:
/// <summary>Initializes a new instance of the CSBK_TD_GRANT class.</summary>
CSBK_TD_GRANT();
/// <summary>Decode a control signalling block.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a control signalling block.</summary>
virtual void encode(uint8_t* data);
};
} // namespace csbk
} // namespace lc
} // namespace dmr
#endif // __DMR_LC_CSBK__CSBK_TD_GRANT_H__

@ -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 <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CSBK_TV_GRANT class.
/// </summary>
CSBK_TV_GRANT::CSBK_TV_GRANT() : CSBK()
{
m_CSBKO = CSBKO_TV_GRANT;
}
/// <summary>
/// Decode a control signalling block.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if CSBK was decoded, otherwise false.</returns>
bool CSBK_TV_GRANT::decode(const uint8_t* data)
{
assert(data != NULL);
/* stub */
return true;
}
/// <summary>
/// Encode a control signalling block.
/// </summary>
/// <param name="data"></param>
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<uint8_t[]> csbk = CSBK::fromValue(csbkValue);
CSBK::encode(data, csbk.get());
}

@ -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:
/// <summary>Initializes a new instance of the CSBK_TV_GRANT class.</summary>
CSBK_TV_GRANT();
/// <summary>Decode a control signalling block.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a control signalling block.</summary>
virtual void encode(uint8_t* data);
};
} // namespace csbk
} // namespace lc
} // namespace dmr
#endif // __DMR_LC_CSBK__CSBK_TV_GRANT_H__

@ -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 <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CSBK_UU_ANS_RSP class.
/// </summary>
CSBK_UU_ANS_RSP::CSBK_UU_ANS_RSP() : CSBK()
{
m_CSBKO = CSBKO_UU_ANS_RSP;
}
/// <summary>
/// Decode a control signalling block.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if CSBK was decoded, otherwise false.</returns>
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;
}
/// <summary>
/// Encode a control signalling block.
/// </summary>
/// <param name="data"></param>
void CSBK_UU_ANS_RSP::encode(uint8_t* data)
{
assert(data != NULL);
/* stub */
}

@ -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:
/// <summary>Initializes a new instance of the CSBK_UU_ANS_RSP class.</summary>
CSBK_UU_ANS_RSP();
/// <summary>Decode a control signalling block.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a control signalling block.</summary>
virtual void encode(uint8_t* data);
};
} // namespace csbk
} // namespace lc
} // namespace dmr
#endif // __DMR_LC_CSBK__CSBK_UU_ANS_RSP_H__

@ -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 <cassert>
#include <cmath>
// ---------------------------------------------------------------------------
// Public Class Members
// ---------------------------------------------------------------------------
/// <summary>
/// Initializes a new instance of the CSBK_UU_V_REQ class.
/// </summary>
CSBK_UU_V_REQ::CSBK_UU_V_REQ() : CSBK()
{
m_CSBKO = CSBKO_UU_V_REQ;
}
/// <summary>
/// Decode a control signalling block.
/// </summary>
/// <param name="data"></param>
/// <returns>True, if CSBK was decoded, otherwise false.</returns>
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;
}
/// <summary>
/// Encode a control signalling block.
/// </summary>
/// <param name="data"></param>
void CSBK_UU_V_REQ::encode(uint8_t* data)
{
assert(data != NULL);
/* stub */
}

@ -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:
/// <summary>Initializes a new instance of the CSBK_UU_V_REQ class.</summary>
CSBK_UU_V_REQ();
/// <summary>Decode a control signalling block.</summary>
virtual bool decode(const uint8_t* data);
/// <summary>Encode a control signalling block.</summary>
virtual void encode(uint8_t* data);
};
} // namespace csbk
} // namespace lc
} // namespace dmr
#endif // __DMR_LC_CSBK__CSBK_UU_V_REQ_H__

@ -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 <cassert>
@ -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<lc::CSBK> 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_RAND*>(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_EXT_FNCT*>(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<lc::CSBK> 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_RAND*>(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_EXT_FNCT*>(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_EXT_FNCT> 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());
}
/// <summary>
@ -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_CALL_ALRT> 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()
/// </summary>
/// <param name="csbk"></param>
/// <param name="clearBeforeWrite"></param>
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)
/// <summary>
/// Helper to write a deny packet.
/// </summary>
/// <param name="dstId"></param>
/// <param name="reason"></param>
/// <param name="responseInfo"></param>
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_ACK_RSP> 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());
}
/// <summary>
/// Helper to write a deny packet.
/// </summary>
/// <param name="dstId"></param>
/// <param name="reason"></param>
/// <param name="service"></param>
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_NACK_RSP> 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());
}
/// <summary>
@ -706,10 +721,11 @@ void ControlSignaling::writeRF_CSBK_NACK_RSP(uint8_t reason, uint8_t service)
/// <param name="serviceOptions"></param>
/// <param name="grp"></param>
/// <param name="skip"></param>
/// <param name="chNo"></param>
/// <param name="net"></param>
/// <param name="skipNetCheck"></param>
/// <returns></returns>
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_TV_GRANT> 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_PV_GRANT> 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_
/// <param name="serviceOptions"></param>
/// <param name="grp"></param>
/// <param name="skip"></param>
/// <param name="chNo"></param>
/// <param name="net"></param>
/// <returns></returns>
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_TD_GRANT> 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_PD_GRANT> 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_ACK_RSP> 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());
}
/// <summary>
@ -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_ALOHA> 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());
}
/// <summary>
@ -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_BROADCAST> 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());
}
/// <summary>
@ -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_BROADCAST> csbk = new_unique(CSBK_BROADCAST);
csbk->setAnncType(BCAST_ANNC_SITE_PARMS);
writeRF_CSBK(csbk);
writeRF_CSBK(csbk.get());
}
/// <summary>
@ -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_DVM_GIT_HASH> csbk = new_unique(CSBK_DVM_GIT_HASH);
writeRF_CSBK(csbk);
writeRF_CSBK(csbk.get());
}

@ -88,16 +88,16 @@ namespace dmr
~ControlSignaling();
/// <summary>Helper to write a CSBK packet.</summary>
void writeRF_CSBK(lc::CSBK csbk, bool clearBeforeWrite = false);
void writeRF_CSBK(lc::CSBK* csbk, bool clearBeforeWrite = false);
/// <summary>Helper to write a ACK RSP packet.</summary>
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);
/// <summary>Helper to write a NACK RSP packet.</summary>
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);
/// <summary>Helper to write a grant packet.</summary>
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);
/// <summary>Helper to write a data grant packet.</summary>
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);
/// <summary>Helper to write a unit registration response packet.</summary>
void writeRF_CSBK_U_Reg_Rsp(uint32_t srcId, uint8_t serviceOptions);

@ -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
// ---------------------------------------------------------------------------
/// <summary>
@ -267,7 +268,7 @@ bool TSBK::decode(const uint8_t* data, uint8_t* tsbk, bool rawTSBK)
}
/// <summary>
/// Encode a trunking signalling block.
/// Internal helper to eecode a trunking signalling block.
/// </summary>
/// <param name="data"></param>
/// <param name="tsbk"></param>
@ -325,8 +326,6 @@ void TSBK::encode(uint8_t* data, const uint8_t* tsbk, bool rawTSBK, bool noTrell
/// <param name="data"></param>
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;
}

Loading…
Cancel
Save

Powered by TurnKey Linux.