fix buffer overflow error in HostMain; implement some of the basis for DMR Tier III;

pull/1/head
Bryan Biedenkapp 5 years ago
parent 4d65c635e4
commit cfc8604c8e

@ -162,6 +162,7 @@
<ClInclude Include="dmr\Control.h" /> <ClInclude Include="dmr\Control.h" />
<ClInclude Include="dmr\DataPacket.h" /> <ClInclude Include="dmr\DataPacket.h" />
<ClInclude Include="dmr\DMRDefines.h" /> <ClInclude Include="dmr\DMRDefines.h" />
<ClInclude Include="dmr\SiteData.h" />
<ClInclude Include="dmr\Slot.h" /> <ClInclude Include="dmr\Slot.h" />
<ClInclude Include="dmr\SlotType.h" /> <ClInclude Include="dmr\SlotType.h" />
<ClInclude Include="dmr\Sync.h" /> <ClInclude Include="dmr\Sync.h" />

@ -329,6 +329,9 @@
<ClInclude Include="p25\data\DataRspHeader.h"> <ClInclude Include="p25\data\DataRspHeader.h">
<Filter>Header Files\p25\data</Filter> <Filter>Header Files\p25\data</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="dmr\SiteData.h">
<Filter>Header Files\dmr</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="Log.cpp"> <ClCompile Include="Log.cpp">

@ -87,11 +87,12 @@ static void sigHandler(int signum)
void fatal(const char* msg, ...) void fatal(const char* msg, ...)
{ {
char buffer[400U]; char buffer[400U];
::memset(buffer, 0x20U, 400U);
va_list vl; va_list vl;
va_start(vl, msg); va_start(vl, msg);
::vsprintf(buffer + ::strlen(buffer), msg, vl); ::vsprintf(buffer, msg, vl);
va_end(vl); va_end(vl);

@ -81,7 +81,7 @@ Control::Control(uint32_t colorCode, uint32_t callHang, uint32_t queueSize, bool
assert(rssi != NULL); assert(rssi != NULL);
acl::AccessControl::init(m_ridLookup, m_tidLookup); acl::AccessControl::init(m_ridLookup, m_tidLookup);
Slot::init(colorCode, embeddedLCOnly, dumpTAData, callHang, modem, network, duplex, m_ridLookup, m_tidLookup, rssi, jitter); Slot::init(colorCode, SiteData(), embeddedLCOnly, dumpTAData, callHang, modem, network, duplex, m_ridLookup, m_tidLookup, rssi, jitter);
m_slot1 = new Slot(1U, timeout, tgHang, queueSize, dumpDataPacket, repeatDataPacket, dumpCSBKData, debug, verbose); m_slot1 = new Slot(1U, timeout, tgHang, queueSize, dumpDataPacket, repeatDataPacket, dumpCSBKData, debug, verbose);
m_slot2 = new Slot(2U, timeout, tgHang, queueSize, dumpDataPacket, repeatDataPacket, dumpCSBKData, debug, verbose); m_slot2 = new Slot(2U, timeout, tgHang, queueSize, dumpDataPacket, repeatDataPacket, dumpCSBKData, debug, verbose);

@ -12,7 +12,7 @@
// //
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2019 by Bryan Biedenkapp N2PLL * Copyright (C) 2019-2021 by Bryan Biedenkapp N2PLL
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -130,6 +130,8 @@ namespace dmr
const uint32_t DMR_EXT_FNCT_UNINHIBIT_ACK = 0x00FEU; // Radio Uninhibit Ack const uint32_t DMR_EXT_FNCT_UNINHIBIT_ACK = 0x00FEU; // Radio Uninhibit Ack
const uint32_t DMR_EXT_FNCT_INHIBIT_ACK = 0x00FFU; // Radio Inhibit Ack const uint32_t DMR_EXT_FNCT_INHIBIT_ACK = 0x00FFU; // Radio Inhibit Ack
const uint8_t DMR_ALOHA_VER_151 = 0x00U;
// Data Type(s) // Data Type(s)
const uint8_t DT_VOICE_PI_HEADER = 0x00U; const uint8_t DT_VOICE_PI_HEADER = 0x00U;
const uint8_t DT_VOICE_LC_HEADER = 0x01U; const uint8_t DT_VOICE_LC_HEADER = 0x01U;
@ -145,6 +147,31 @@ namespace dmr
const uint8_t DT_VOICE_SYNC = 0xF0U; const uint8_t DT_VOICE_SYNC = 0xF0U;
const uint8_t DT_VOICE = 0xF1U; const uint8_t DT_VOICE = 0xF1U;
// Site Models
const uint8_t SITE_MODEL_TINY = 0x00U;
const uint8_t SITE_MODEL_SMALL = 0x01U;
const uint8_t SITE_MODEL_LARGE = 0x02U;
const uint8_t SITE_MODEL_HUGE = 0x03U;
// Target Address
const uint8_t TGT_ADRS_SYSCODE = 0x00U;
const uint8_t TGT_ADRS_TGID = 0x01U;
// Short-Link Control Opcode(s)
const uint8_t SLCO_NULL = 0x00U;
const uint8_t SLCO_ACT = 0x01U;
const uint8_t SLCO_TSCC = 0x02U;
// Broadcast Announcement Type(s)
const uint8_t BCAST_ANNC_ANN_WD_TSCC = 0x00U; // Announce/Withdraw TSCC
const uint8_t BCAST_ANNC_CALL_TIMER_PARMS = 0x01U; // Specify Call Timer Parameters
const uint8_t BCAST_ANNC_VOTE_NOW = 0x02U; // Vote Now Advice
const uint8_t BCAST_ANNC_LOCAL_TIME = 0x03U; // Broadcast Local Time
const uint8_t BCAST_ANNC_MASS_REG = 0x04U; // Mass Registration
const uint8_t BCAST_ANNC_CHAN_FREQ = 0x05U; // Announce a logical channel/frequency relationship
const uint8_t BCAST_ANNC_ADJ_SITE = 0x06U; // Adjacent Site information
const uint8_t BCAST_ANNC_SITE_PARMS = 0x07U; // General Site Parameters information
// Full-Link Control Opcode(s) // Full-Link Control Opcode(s)
const uint8_t FLCO_GROUP = 0x00U; // GRP VCH USER - Group Voice Channel User const uint8_t FLCO_GROUP = 0x00U; // GRP VCH USER - Group Voice Channel User
const uint8_t FLCO_PRIVATE = 0x03U; // UU VCH USER - Unit-to-Unit Voice Channel User const uint8_t FLCO_PRIVATE = 0x03U; // UU VCH USER - Unit-to-Unit Voice Channel User
@ -159,12 +186,15 @@ namespace dmr
const uint8_t CSBKO_UU_V_REQ = 0x04U; // UU VCH REQ - Unit-to-Unit Voice Channel Request const uint8_t CSBKO_UU_V_REQ = 0x04U; // UU VCH REQ - Unit-to-Unit Voice Channel Request
const uint8_t CSBKO_UU_ANS_RSP = 0x05U; // UU ANS RSP - Unit to Unit Answer Response const uint8_t CSBKO_UU_ANS_RSP = 0x05U; // UU ANS RSP - Unit to Unit Answer Response
const uint8_t CSBKO_CTCSBK = 0x07U; // CT CSBK - Channel Timing CSBK const uint8_t CSBKO_CTCSBK = 0x07U; // CT CSBK - Channel Timing CSBK
const uint8_t CSBKO_CALL_ALRT = 0x1FU; // CALL ALRT - Call Alert const uint8_t CSBKO_ALOHA = 0x19U; // ALOHA - Aloha PDUs for the random access protocol
const uint8_t CSBKO_RAND = 0x1FU; // (ETSI) RAND - Random Access / (DMRA) CALL ALRT - Call Alert
const uint8_t CSBKO_CALL_ALRT = 0x1FU; // (ETSI) RAND - Random Access / (DMRA) CALL ALRT - Call Alert
const uint8_t CSBKO_ACK_RSP = 0x20U; // ACK RSP - Acknowledge Response const uint8_t CSBKO_ACK_RSP = 0x20U; // ACK RSP - Acknowledge Response
const uint8_t CSBKO_EXT_FNCT = 0x24U; // EXT FNCT - Extended Function const uint8_t CSBKO_EXT_FNCT = 0x24U; // (DMRA) EXT FNCT - Extended Function
const uint8_t CSBKO_NACK_RSP = 0x26U; // NACK RSP - Negative Acknowledgement Response const uint8_t CSBKO_NACK_RSP = 0x26U; // NACK RSP - Negative Acknowledgement Response
const uint8_t CSBKO_BSDWNACT = 0x38U; // BS DWN ACT - BS Outbound Activation const uint8_t CSBKO_BSDWNACT = 0x38U; // BS DWN ACT - BS Outbound Activation
const uint8_t CSBKO_PRECCSBK = 0x3DU; // PRE CSBK - Preamble CSBK const uint8_t CSBKO_PRECCSBK = 0x3DU; // PRE CSBK - Preamble CSBK
const uint8_t CSBKO_BROADCAST = 0x40U; // BCAST - Announcement PDUs
const uint8_t TALKER_ID_NONE = 0x00U; const uint8_t TALKER_ID_NONE = 0x00U;
const uint8_t TALKER_ID_HEADER = 0x01U; const uint8_t TALKER_ID_HEADER = 0x01U;

@ -0,0 +1,219 @@
/**
* 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 Server
*
*/
//
// Based on code from the MMDVMHost project. (https://github.com/g4klx/MMDVMHost)
// Licensed under the GPLv2 License (https://opensource.org/licenses/GPL-2.0)
//
/*
* Copyright (C) 2021 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_SITE_DATA_H__)
#define __DMR_SITE_DATA_H__
#include "Defines.h"
#include "dmr/DMRDefines.h"
namespace dmr
{
// ---------------------------------------------------------------------------
// Class Declaration
// Represents site data for DMR.
// ---------------------------------------------------------------------------
class HOST_SW_API SiteData {
public:
/// <summary>Initializes a new instance of the SiteData class.</summary>
SiteData() :
m_siteModel(SITE_MODEL_SMALL),
m_netId(1U),
m_siteId(1U),
m_parId(3U),
m_requireReg(false)
{
/* stub */
}
/// <summary>Initializes a new instance of the SiteData class.</summary>
/// <param name="siteModel">DMR site model.</param>
/// <param name="netId">DMR Network ID.</param>
/// <param name="siteId">DMR Site ID.</param>
/// <param name="parId">DMR partition ID.</param>
/// <param name="requireReg"></param>
SiteData(uint8_t siteModel, uint16_t netId, uint16_t siteId, uint8_t parId, bool requireReq) :
m_siteModel(siteModel),
m_netId(netId),
m_siteId(siteId),
m_parId(parId),
m_requireReg(requireReq)
{
// siteModel clamping
if (siteModel > SITE_MODEL_HUGE)
siteModel = SITE_MODEL_SMALL;
// netId clamping
if (netId == 0U) // clamp to 1
netId = 1U;
switch (siteModel) {
case SITE_MODEL_TINY:
{
if (netId > 0x1FFU) // clamp to $1FF
netId = 0x1FFU;
}
break;
case SITE_MODEL_SMALL:
{
if (netId > 0x7FU) // clamp to $7F
netId = 0x7FU;
}
break;
case SITE_MODEL_LARGE:
{
if (netId > 0x1FU) // clamp to $1F
netId = 0x1FU;
}
break;
case SITE_MODEL_HUGE:
{
if (netId > 0x03U) // clamp to $3
netId = 0x03U;
}
break;
}
m_netId = netId;
// siteId clamping
if (siteId == 0U) // clamp to 1
siteId = 1U;
switch (siteModel)
{
case SITE_MODEL_TINY:
{
if (siteId > 0x07U) // clamp to $7
siteId = 0x07U;
}
break;
case SITE_MODEL_SMALL:
{
if (siteId > 0x1FU) // clamp to $1F
siteId = 0x1FU;
}
break;
case SITE_MODEL_LARGE:
{
if (siteId > 0xFFU) // clamp to $FF
siteId = 0xFFU;
}
break;
case SITE_MODEL_HUGE:
{
if (siteId > 0x7FFU) // clamp to $7FF
siteId = 0x7FFU;
}
break;
}
m_siteId = siteId;
// parId clamping
if (parId == 0U)
parId = 3U;
if (parId > 3U)
parId = 3U;
}
/// <summary>Returns the DMR system identity value.</summary>
/// <param name="msb"></param>
/// <returns></returns>
const uint32_t systemIdentity(bool msb = false)
{
uint32_t value = m_siteModel;
switch (m_siteModel)
{
case SITE_MODEL_TINY:
{
value = (value << 9) + m_netId;
value = (value << 3) + m_siteId;
}
break;
case SITE_MODEL_SMALL:
{
value = (value << 7) + m_netId;
value = (value << 5) + m_siteId;
}
break;
case SITE_MODEL_LARGE:
{
value = (value << 5) + m_netId;
value = (value << 7) + m_siteId;
}
break;
case SITE_MODEL_HUGE:
{
value = (value << 2) + m_netId;
value = (value << 10) + m_siteId;
}
break;
}
if (!msb) {
value = (value << 2) + m_parId;
}
return value & 0xFFFFU;
}
/// <summary>Equals operator.</summary>
/// <param name="data"></param>
/// <returns></returns>
SiteData & operator=(const SiteData & data)
{
if (this != &data) {
m_siteModel = data.m_siteModel;
m_netId = data.m_netId;
m_siteId = data.m_siteId;
m_requireReg = data.m_requireReg;
}
return *this;
}
public:
/// <summary>DMR site model type.</summary>
__READONLY_PROPERTY_PLAIN(uint8_t, siteModel, siteModel);
/// <summary>DMR site network ID.</summary>
__READONLY_PROPERTY_PLAIN(uint16_t, netId, netId);
/// <summary>DMR site ID.</summary>
__READONLY_PROPERTY_PLAIN(uint16_t, siteId, siteId);
/// <summary>DMR partition ID.</summary>
__READONLY_PROPERTY_PLAIN(uint8_t, parId, parId);
/// <summary>DMR require registration.</summary>
__READONLY_PROPERTY_PLAIN(bool, requireReg, requireReg);
};
} // namespace dmr
#endif // __DMR_SITE_DATA_H__

@ -12,7 +12,7 @@
// //
/* /*
* Copyright (C) 2015,2016,2017,2018 Jonathan Naylor, G4KLX * Copyright (C) 2015,2016,2017,2018 Jonathan Naylor, G4KLX
* Copyright (C) 2017-2020 by Bryan Biedenkapp N2PLL * Copyright (C) 2017-2021 by Bryan Biedenkapp N2PLL
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -49,6 +49,8 @@ using namespace dmr;
uint32_t Slot::m_colorCode = 0U; uint32_t Slot::m_colorCode = 0U;
SiteData Slot::m_siteData = SiteData();
bool Slot::m_embeddedLCOnly = false; bool Slot::m_embeddedLCOnly = false;
bool Slot::m_dumpTAData = true; bool Slot::m_dumpTAData = true;
@ -385,6 +387,7 @@ void Slot::clock()
/// Helper to initialize the DMR slot processor. /// Helper to initialize the DMR slot processor.
/// </summary> /// </summary>
/// <param name="colorCode">DMR access color code.</param> /// <param name="colorCode">DMR access color code.</param>
/// <param name="siteData">DMR site data.</param>
/// <param name="embeddedLCOnly"></param> /// <param name="embeddedLCOnly"></param>
/// <param name="dumpTAData"></param> /// <param name="dumpTAData"></param>
/// <param name="callHang">Amount of hangtime for a DMR call.</param> /// <param name="callHang">Amount of hangtime for a DMR call.</param>
@ -395,7 +398,7 @@ void Slot::clock()
/// <param name="tidLookup">Instance of the TalkgroupIdLookup class.</param> /// <param name="tidLookup">Instance of the TalkgroupIdLookup class.</param>
/// <param name="rssi">Instance of the CRSSIInterpolator class.</param> /// <param name="rssi">Instance of the CRSSIInterpolator class.</param>
/// <param name="jitter"></param> /// <param name="jitter"></param>
void Slot::init(uint32_t colorCode, bool embeddedLCOnly, bool dumpTAData, uint32_t callHang, modem::Modem* modem, void Slot::init(uint32_t colorCode, SiteData siteData, bool embeddedLCOnly, bool dumpTAData, uint32_t callHang, modem::Modem* modem,
network::BaseNetwork* network, bool duplex, lookups::RadioIdLookup* ridLookup, lookups::TalkgroupIdLookup* tidLookup, network::BaseNetwork* network, bool duplex, lookups::RadioIdLookup* ridLookup, lookups::TalkgroupIdLookup* tidLookup,
lookups::RSSIInterpolator* rssiMapper, uint32_t jitter) lookups::RSSIInterpolator* rssiMapper, uint32_t jitter)
{ {
@ -405,6 +408,7 @@ void Slot::init(uint32_t colorCode, bool embeddedLCOnly, bool dumpTAData, uint32
assert(rssiMapper != NULL); assert(rssiMapper != NULL);
m_colorCode = colorCode; m_colorCode = colorCode;
m_siteData = siteData;
m_embeddedLCOnly = embeddedLCOnly; m_embeddedLCOnly = embeddedLCOnly;
m_dumpTAData = dumpTAData; m_dumpTAData = dumpTAData;
m_modem = modem; m_modem = modem;
@ -650,6 +654,50 @@ void Slot::writeRF_Call_Alrt(uint32_t srcId, uint32_t dstId)
writeQueueRF(data); writeQueueRF(data);
} }
/// <summary>
/// Helper to write a TSCC broadcast packet on the RF interface.
/// </summary>
/// <param name="anncType">Broadcast announcement type.</param>
void Slot::writeRF_TSCC_Broadcast(uint8_t anncType)
{
if (m_verbose) {
LogMessage(LOG_RF, "DMR Slot %u, DT_CSBK, CSBKO_BROADCAST (Broadcast), anncType = %u",
m_slotNo, anncType);
}
uint8_t data[DMR_FRAME_LENGTH_BYTES + 2U];
::memset(data + 2U, 0x00U, DMR_FRAME_LENGTH_BYTES);
SlotType slotType;
slotType.setColorCode(m_colorCode);
slotType.setDataType(DT_CSBK);
lc::CSBK csbk = lc::CSBK();
csbk.setVerbose(m_dumpCSBKData);
csbk.setCSBKO(CSBKO_BROADCAST);
csbk.setFID(FID_ETSI);
csbk.setAnncType(anncType);
csbk.setSiteData(m_siteData);
// Regenerate the CSBK data
csbk.encode(data + 2U);
// Regenerate the Slot Type
slotType.encode(data + 2U);
// Convert the Data Sync to be from the BS or MS as needed
Sync::addDMRDataSync(data + 2U, m_duplex);
m_rfSeqNo = 0U;
data[0U] = TAG_DATA;
data[1U] = 0x00U;
if (m_duplex)
writeQueueRF(data);
}
/// <summary> /// <summary>
/// ///
/// </summary> /// </summary>
@ -696,7 +744,7 @@ void Slot::setShortLC(uint32_t slotNo, uint32_t id, uint8_t flco, bool voice)
return; return;
uint8_t lc[5U]; uint8_t lc[5U];
lc[0U] = 0x01U; lc[0U] = SLCO_ACT;
lc[1U] = 0x00U; lc[1U] = 0x00U;
lc[2U] = 0x00U; lc[2U] = 0x00U;
lc[3U] = 0x00U; lc[3U] = 0x00U;
@ -742,3 +790,64 @@ void Slot::setShortLC(uint32_t slotNo, uint32_t id, uint8_t flco, bool voice)
m_modem->writeDMRShortLC(sLC); m_modem->writeDMRShortLC(sLC);
} }
/// <summary>
///
/// </summary>
/// <param name="slotNo"></param>
/// <param name="siteData"></param>
/// <param name="counter"></param>
void Slot::setShortLC_TSCC(SiteData siteData, uint16_t counter)
{
assert(m_modem != NULL);
uint8_t lc[5U];
uint32_t lcValue = 0U;
lcValue = SLCO_TSCC;
lcValue = (lcValue << 2) + siteData.siteModel();
switch (siteData.siteModel())
{
case SITE_MODEL_TINY:
{
lcValue = (lcValue << 9) + siteData.netId();
lcValue = (lcValue << 3) + siteData.siteId();
}
break;
case SITE_MODEL_SMALL:
{
lcValue = (lcValue << 7) + siteData.netId();
lcValue = (lcValue << 5) + siteData.siteId();
}
break;
case SITE_MODEL_LARGE:
{
lcValue = (lcValue << 5) + siteData.netId();
lcValue = (lcValue << 7) + siteData.siteId();
}
break;
case SITE_MODEL_HUGE:
{
lcValue = (lcValue << 2) + siteData.netId();
lcValue = (lcValue << 10) + siteData.siteId();
}
break;
}
lcValue = (lcValue << 1) + ((siteData.requireReg()) ? 1U : 0U);
lcValue = (lcValue << 9) + (counter & 0x1FFU);
// split value into bytes
lc[0U] = (uint8_t)((lcValue >> 24) & 0xFFU);
lc[1U] = (uint8_t)((lcValue >> 16) & 0xFFU);
lc[2U] = (uint8_t)((lcValue >> 8) & 0xFFU);
lc[3U] = (uint8_t)((lcValue >> 0) & 0xFFU);
lc[4U] = edac::CRC::crc8(lc, 4U);
uint8_t sLC[9U];
lc::ShortLC shortLC;
shortLC.encode(lc, sLC);
m_modem->writeDMRShortLC(sLC);
}

@ -33,6 +33,7 @@
#include "Defines.h" #include "Defines.h"
#include "dmr/Control.h" #include "dmr/Control.h"
#include "dmr/SiteData.h"
#include "dmr/DataPacket.h" #include "dmr/DataPacket.h"
#include "dmr/VoicePacket.h" #include "dmr/VoicePacket.h"
#include "modem/Modem.h" #include "modem/Modem.h"
@ -80,7 +81,7 @@ namespace dmr
void clock(); void clock();
/// <summary>Helper to initialize the slot processor.</summary> /// <summary>Helper to initialize the slot processor.</summary>
static void init(uint32_t colorCode, bool embeddedLCOnly, bool dumpTAData, uint32_t callHang, modem::Modem* modem, static void init(uint32_t colorCode, SiteData siteData, bool embeddedLCOnly, bool dumpTAData, uint32_t callHang, modem::Modem* modem,
network::BaseNetwork* network, bool duplex, lookups::RadioIdLookup* ridLookup, lookups::TalkgroupIdLookup* tidLookup, network::BaseNetwork* network, bool duplex, lookups::RadioIdLookup* ridLookup, lookups::TalkgroupIdLookup* tidLookup,
lookups::RSSIInterpolator* rssiMapper, uint32_t jitter); lookups::RSSIInterpolator* rssiMapper, uint32_t jitter);
@ -136,6 +137,8 @@ namespace dmr
static uint32_t m_colorCode; static uint32_t m_colorCode;
static SiteData m_siteData;
static bool m_embeddedLCOnly; static bool m_embeddedLCOnly;
static bool m_dumpTAData; static bool m_dumpTAData;
@ -181,9 +184,13 @@ namespace dmr
void writeRF_Ext_Func(uint32_t func, uint32_t arg, uint32_t dstId); void writeRF_Ext_Func(uint32_t func, uint32_t arg, uint32_t dstId);
/// <summary>Helper to write a call alert packet on the RF interface.</summary> /// <summary>Helper to write a call alert packet on the RF interface.</summary>
void writeRF_Call_Alrt(uint32_t srcId, uint32_t dstId); void writeRF_Call_Alrt(uint32_t srcId, uint32_t dstId);
/// <summary>Helper to write a TSCC broadcast packet on the RF interface.</summary>
void writeRF_TSCC_Broadcast(uint8_t anncType);
/// <summary></summary> /// <summary></summary>
static void setShortLC(uint32_t slotNo, uint32_t id, uint8_t flco = FLCO_GROUP, bool voice = true); static void setShortLC(uint32_t slotNo, uint32_t id, uint8_t flco = FLCO_GROUP, bool voice = true);
/// <summary></summary>
static void setShortLC_TSCC(SiteData siteData, uint16_t counter);
}; };
} // namespace dmr } // namespace dmr

@ -12,7 +12,7 @@
// //
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2019 by Bryan Biedenkapp N2PLL * Copyright (C) 2019-2021 by Bryan Biedenkapp N2PLL
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -51,15 +51,20 @@ CSBK::CSBK() :
m_verbose(false), m_verbose(false),
m_CSBKO(CSBKO_NONE), m_CSBKO(CSBKO_NONE),
m_FID(0x00U), m_FID(0x00U),
m_lastBlock(true),
m_bsId(0U), m_bsId(0U),
m_GI(false), m_GI(false),
m_srcId(0U), m_srcId(0U),
m_dstId(0U), m_dstId(0U),
m_dataContent(false), m_dataContent(false),
m_CBF(0U), m_CBF(0U),
m_data(NULL) m_data(NULL),
m_siteData(),
m_siteNetActive(false)
{ {
m_data = new uint8_t[12U]; m_data = new uint8_t[12U];
reset();
} }
/// <summary> /// <summary>
@ -99,72 +104,86 @@ bool CSBK::decode(const uint8_t* bytes)
Utils::dump(2U, "Decoded CSBK", m_data, DMR_LC_HEADER_LENGTH_BYTES); Utils::dump(2U, "Decoded CSBK", m_data, DMR_LC_HEADER_LENGTH_BYTES);
} }
m_CSBKO = m_data[0U] & 0x3FU; m_CSBKO = m_data[0U] & 0x3FU; // CSBKO
m_FID = m_data[1U]; m_lastBlock = (m_data[0U] & 0x80U) == 0x80U; // Last Block Marker
m_FID = m_data[1U]; // Feature ID
switch (m_CSBKO) { switch (m_CSBKO) {
case CSBKO_BSDWNACT: case CSBKO_BSDWNACT:
m_GI = false; m_GI = false;
m_bsId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; m_bsId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; // Base Station ID
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; // Source ID
m_dataContent = false; m_dataContent = false;
m_CBF = 0U; m_CBF = 0U;
break; break;
case CSBKO_UU_V_REQ: case CSBKO_UU_V_REQ:
m_GI = false; m_GI = false;
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; // Destination ID
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; // Source ID
m_dataContent = false; m_dataContent = false;
m_CBF = 0U; m_CBF = 0U;
break; break;
case CSBKO_UU_ANS_RSP: case CSBKO_UU_ANS_RSP:
m_GI = false; m_GI = false;
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; // Destination ID
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; // Source ID
m_dataContent = false; m_dataContent = false;
m_CBF = 0U; m_CBF = 0U;
break; break;
case CSBKO_PRECCSBK: case CSBKO_PRECCSBK:
m_GI = (m_data[2U] & 0x40U) == 0x40U; m_GI = (m_data[2U] & 0x40U) == 0x40U;
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; // Destination ID
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; // Source ID
m_dataContent = (m_data[2U] & 0x80U) == 0x80U; m_dataContent = (m_data[2U] & 0x80U) == 0x80U;
m_CBF = m_data[3U]; m_CBF = m_data[3U];
break; break;
case CSBKO_CALL_ALRT: case CSBKO_RAND: // CSBKO_CALL_ALRT when FID == FID_DMRA
m_GI = (m_data[2U] & 0x40U) == 0x40U; switch (m_FID)
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; {
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; case FID_DMRA:
m_dataContent = (m_data[2U] & 0x80U) == 0x80U; m_GI = (m_data[2U] & 0x40U) == 0x40U; // Group or Individual
m_CBF = m_data[3U]; m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; // Destination ID
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; // Source ID
m_dataContent = (m_data[2U] & 0x80U) == 0x80U; //
m_CBF = m_data[3U]; //
break; break;
/* Tier III */
case FID_ETSI:
default:
m_serviceOptions = m_data[2U]; // Service Options
m_targetAddress = (m_data[3U] >> 6 & 0x03U); // Target Address
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; // Destination ID
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; // Source ID
break;
}
case CSBKO_ACK_RSP: case CSBKO_ACK_RSP:
m_GI = (m_data[2U] & 0x40U) == 0x40U; m_GI = (m_data[2U] & 0x40U) == 0x40U;
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; // Destination ID
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; // Source ID
m_dataContent = (m_data[2U] & 0x80U) == 0x80U; m_response = m_data[3U]; // Response
m_CBF = m_data[3U]; m_dataContent = false;
break; break;
case CSBKO_EXT_FNCT: case CSBKO_EXT_FNCT:
m_GI = false; m_GI = false;
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; // Destination ID
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; // Source ID
m_dataContent = (m_data[2U] & 0x80U) == 0x80U; m_dataContent = (m_data[2U] & 0x80U) == 0x80U; //
m_CBF = m_data[3U]; m_CBF = m_data[3U]; //
break; break;
case CSBKO_NACK_RSP: case CSBKO_NACK_RSP:
m_GI = false; m_GI = false;
m_srcId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; m_srcId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U]; // Source ID
m_dstId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; m_dstId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U]; // Destination ID
m_response = m_data[3U]; // Response
m_dataContent = false; m_dataContent = false;
m_CBF = 0U;
break; break;
default: default:
@ -184,40 +203,146 @@ bool CSBK::decode(const uint8_t* bytes)
/// Encodes a DMR CSBK. /// Encodes a DMR CSBK.
/// </summary> /// </summary>
/// <param name="bytes"></param> /// <param name="bytes"></param>
void CSBK::encode(uint8_t* bytes) const void CSBK::encode(uint8_t* bytes)
{ {
assert(bytes != NULL); assert(bytes != NULL);
m_data[0U] = m_CSBKO; m_data[0U] = m_CSBKO; // CSBKO
m_data[1U] = m_FID; m_data[0U] |= (m_lastBlock) ? 0x80U : 0x00U; // Last Block Marker
m_data[1U] = m_FID; // Feature ID
switch (m_CSBKO) {
case CSBKO_ACK_RSP:
m_data[2U] = (uint8_t)(m_serviceType & 0x3FU); // Service Type
m_data[2U] |= 0x80U; // Additional Information Field (always 1)
if (m_GI) {
m_data[2U] |= 0x40U; // Source Type
}
m_data[3U] = m_response; // Reason Code
m_data[4U] = (m_srcId >> 16) & 0xFFU; // Source ID
m_data[5U] = (m_srcId >> 8) & 0xFFU;
m_data[6U] = (m_srcId >> 0) & 0xFFU;
m_data[7U] = (m_dstId >> 16) & 0xFFU; // Destination ID
m_data[8U] = (m_dstId >> 8) & 0xFFU;
m_data[9U] = (m_dstId >> 0) & 0xFFU;
break;
case CSBKO_EXT_FNCT:
if (m_GI) { if (m_GI) {
m_data[2U] |= 0x40U; m_data[2U] |= 0x40U; // Group or Individual
} }
if (m_dataContent) { if (m_dataContent) {
m_data[2U] |= 0x80U; m_data[2U] |= 0x80U; //
} }
m_data[3U] = m_CBF; m_data[3U] = m_CBF; //
if (m_CSBKO == CSBKO_EXT_FNCT) { m_data[4U] = (m_srcId >> 16) & 0xFFU; // Source ID
m_data[4U] = (m_srcId >> 16) & 0xFFU;
m_data[5U] = (m_srcId >> 8) & 0xFFU; m_data[5U] = (m_srcId >> 8) & 0xFFU;
m_data[6U] = (m_srcId >> 0) & 0xFFU; m_data[6U] = (m_srcId >> 0) & 0xFFU;
m_data[7U] = (m_dstId >> 16) & 0xFFU; m_data[7U] = (m_dstId >> 16) & 0xFFU; // Destination ID
m_data[8U] = (m_dstId >> 8) & 0xFFU; m_data[8U] = (m_dstId >> 8) & 0xFFU;
m_data[9U] = (m_dstId >> 0) & 0xFFU; m_data[9U] = (m_dstId >> 0) & 0xFFU;
break;
case CSBKO_NACK_RSP:
m_data[2U] = (uint8_t)(m_serviceType & 0x3FU); // Service Type
m_data[2U] |= 0x80U; // Additional Information Field (always 1)
if (m_GI) {
m_data[2U] |= 0x40U; // Source Type
} }
else { m_data[3U] = m_response; // Reason Code
m_data[4U] = (m_dstId >> 16) & 0xFFU;
m_data[4U] = (m_srcId >> 16) & 0xFFU; // Source ID
m_data[5U] = (m_srcId >> 8) & 0xFFU;
m_data[6U] = (m_srcId >> 0) & 0xFFU;
m_data[7U] = (m_dstId >> 16) & 0xFFU; // Destination ID
m_data[8U] = (m_dstId >> 8) & 0xFFU;
m_data[9U] = (m_dstId >> 0) & 0xFFU;
break;
default:
if (m_GI) {
m_data[2U] |= 0x40U; // Group or Individual
}
if (m_dataContent) {
m_data[2U] |= 0x80U; //
}
m_data[3U] = m_CBF; //
m_data[4U] = (m_dstId >> 16) & 0xFFU; // Destination ID
m_data[5U] = (m_dstId >> 8) & 0xFFU; m_data[5U] = (m_dstId >> 8) & 0xFFU;
m_data[6U] = (m_dstId >> 0) & 0xFFU; m_data[6U] = (m_dstId >> 0) & 0xFFU;
m_data[7U] = (m_srcId >> 16) & 0xFFU; m_data[7U] = (m_srcId >> 16) & 0xFFU; // Source ID
m_data[8U] = (m_srcId >> 8) & 0xFFU; m_data[8U] = (m_srcId >> 8) & 0xFFU;
m_data[9U] = (m_srcId >> 0) & 0xFFU; m_data[9U] = (m_srcId >> 0) & 0xFFU;
break;
/* Tier III */
case CSBKO_ALOHA:
{
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_siteNetActive) ? 1U : 0U); // Site Networked
csbkValue = (csbkValue << 5) + (m_alohaMask & 0x1FU); // MS Mask
csbkValue = (csbkValue << 2) + 0U; // Service Function
csbkValue = (csbkValue << 4) + 0U; //
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 ID
// split value into bytes
m_data[2U] = (uint8_t)((csbkValue >> 56) & 0xFFU);
m_data[3U] = (uint8_t)((csbkValue >> 48) & 0xFFU);
m_data[4U] = (uint8_t)((csbkValue >> 40) & 0xFFU);
m_data[5U] = (uint8_t)((csbkValue >> 32) & 0xFFU);
m_data[6U] = (uint8_t)((csbkValue >> 24) & 0xFFU);
m_data[7U] = (uint8_t)((csbkValue >> 16) & 0xFFU);
m_data[8U] = (uint8_t)((csbkValue >> 8) & 0xFFU);
m_data[9U] = (uint8_t)((csbkValue >> 0) & 0xFFU);
break;
}
break;
case CSBKO_BROADCAST:
{
ulong64_t csbkValue = 0U;
csbkValue = m_anncType; // Announcement Type
switch (m_anncType)
{
case BCAST_ANNC_SITE_PARMS:
csbkValue = (csbkValue << 14) + m_siteData.systemIdentity(true); // Site Identity (Broadcast Parms 1)
csbkValue = (csbkValue << 4) + (m_backoffNo & 0x0FU); // Backoff Number
csbkValue = (csbkValue << 16) + m_siteData.systemIdentity(); // Site Identity
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;
}
// split value into bytes
m_data[2U] = (uint8_t)((csbkValue >> 56) & 0xFFU);
m_data[3U] = (uint8_t)((csbkValue >> 48) & 0xFFU);
m_data[4U] = (uint8_t)((csbkValue >> 40) & 0xFFU);
m_data[5U] = (uint8_t)((csbkValue >> 32) & 0xFFU);
m_data[6U] = (uint8_t)((csbkValue >> 24) & 0xFFU);
m_data[7U] = (uint8_t)((csbkValue >> 16) & 0xFFU);
m_data[8U] = (uint8_t)((csbkValue >> 8) & 0xFFU);
m_data[9U] = (uint8_t)((csbkValue >> 0) & 0xFFU);
}
break;
} }
m_data[10U] ^= CSBK_CRC_MASK[0U]; m_data[10U] ^= CSBK_CRC_MASK[0U];
@ -236,3 +361,39 @@ void CSBK::encode(uint8_t* bytes) const
edac::BPTC19696 bptc; edac::BPTC19696 bptc;
bptc.encode(m_data, bytes); bptc.encode(m_data, bytes);
} }
/// <summary>
/// Helper to reset data values to defaults.
/// </summary>
void CSBK::reset()
{
m_backoffNo = 1U;
m_serviceType = 0U;
m_serviceOptions = 0U;
m_targetAddress = TGT_ADRS_TGID;
m_response = 0U;
/* Broadcast */
m_anncType = BCAST_ANNC_SITE_PARMS;
m_hibernating = false;
/* Aloha */
m_siteTSSync = false;
m_siteOffsetTiming = false;
}
/** Local Site data */
/// <summary>Sets local configured site data.</summary>
/// <param name="siteData"></param>
void CSBK::setSiteData(SiteData siteData)
{
m_siteData = siteData;
}
/// <summary>Sets a flag indicating whether or not networking is active.</summary>
/// <param name="netActive"></param>
void CSBK::setNetActive(bool netActive)
{
m_siteNetActive = netActive;
}

@ -12,7 +12,7 @@
// //
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* Copyright (C) 2019 by Bryan Biedenkapp N2PLL * Copyright (C) 2019-2021 by Bryan Biedenkapp N2PLL
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -33,6 +33,7 @@
#include "Defines.h" #include "Defines.h"
#include "dmr/DMRDefines.h" #include "dmr/DMRDefines.h"
#include "dmr/SiteData.h"
namespace dmr namespace dmr
{ {
@ -53,7 +54,16 @@ namespace dmr
/// <summary>Decodes a DMR CSBK.</summary> /// <summary>Decodes a DMR CSBK.</summary>
bool decode(const uint8_t* bytes); bool decode(const uint8_t* bytes);
/// <summary>Encodes a DMR CSBK.</summary> /// <summary>Encodes a DMR CSBK.</summary>
void encode(uint8_t* bytes) const; void encode(uint8_t* bytes);
/// <summary>Helper to reset data values to defaults.</summary>
void reset();
/** Local Site data */
/// <summary>Sets local configured site data.</summary>
void setSiteData(SiteData siteData);
/// <summary>Sets a flag indicating whether or not networking is active.</summary>
void setNetActive(bool netActive);
public: public:
/// <summary></summary> /// <summary></summary>
@ -65,6 +75,9 @@ namespace dmr
/// <summary>CSBK feature ID.</summayr> /// <summary>CSBK feature ID.</summayr>
__PROPERTY(uint8_t, FID, FID); __PROPERTY(uint8_t, FID, FID);
/// <summary>Flag indicating this is the last TSBK in a sequence of TSBKs.</summary>
__PROPERTY(bool, lastBlock, LastBlock);
// For BS Dwn Act // For BS Dwn Act
__READONLY_PROPERTY(uint32_t, bsId, BSId); __READONLY_PROPERTY(uint32_t, bsId, BSId);
@ -83,8 +96,38 @@ namespace dmr
/// <summary>Sets the number of blocks to follow.</summary> /// <summary>Sets the number of blocks to follow.</summary>
__PROPERTY(uint8_t, CBF, CBF); __PROPERTY(uint8_t, CBF, CBF);
// Tier III
/// <summary>Backoff Number.</summary>
__PROPERTY(uint8_t, backoffNo, BackoffNo);
/// <summary>Service Type.</summary>
__PROPERTY(uint8_t, serviceType, serviceType);
/// <summary>Service type.</summary>
__PROPERTY(uint8_t, serviceOptions, ServiceOptions);
/// <summary>Destination/Target address type.</summary>
__PROPERTY(uint8_t, targetAddress, TargetAddress);
/// <summary>Response type.</summary>
__PROPERTY(uint8_t, response, Response);
/// <summary>Broadcast Announcment Type.</summary>
__PROPERTY(uint8_t, anncType, AnncType);
/// <summary>Broadcast Hibernation Flag.</summary>
__PROPERTY(bool, hibernating, Hibernating);
/// <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);
private: private:
uint8_t* m_data; uint8_t* m_data;
/** Local Site data */
SiteData m_siteData;
bool m_siteNetActive;
}; };
} // namespace lc } // namespace lc
} // namespace dmr } // namespace dmr

@ -130,7 +130,7 @@ bool TSBK::decode(const uint8_t* data)
} }
m_lco = tsbk[0U] & 0x3F; // LCO m_lco = tsbk[0U] & 0x3F; // LCO
m_lastBlock = (tsbk[0U] & 0x80U) == 0x80U; // Protect Flag m_lastBlock = (tsbk[0U] & 0x80U) == 0x80U; // Last Block Marker
m_mfId = tsbk[1U]; // Mfg Id. m_mfId = tsbk[1U]; // Mfg Id.
ulong64_t tsbkValue = 0U; ulong64_t tsbkValue = 0U;

Loading…
Cancel
Save

Powered by TurnKey Linux.