correct P25 secondary control channel and adjacent site status broadcasts, preserve per-channel service classes, properly encode and decode advertised site data and retain multiple secondary control channels;

pull/134/head
Bryan Biedenkapp 4 days ago
parent d2ac635b9d
commit 6911c69170

@ -161,6 +161,7 @@ namespace p25
/**
* @brief Helper to set adjacent site data.
* @param lra Location Registration Area.
* @param sysId P25 System ID.
* @param rfssId P25 RFSS ID.
* @param siteId P25 Site ID.
@ -168,7 +169,7 @@ namespace p25
* @param channelNo Channel Number.
* @param serviceClass Service class.
*/
void setAdjSite(uint32_t sysId, uint8_t rfssId, uint8_t siteId, uint8_t channelId, uint32_t channelNo, uint8_t serviceClass)
void setAdjSite(uint8_t lra, uint32_t sysId, uint8_t rfssId, uint8_t siteId, uint8_t channelId, uint32_t channelNo, uint8_t serviceClass)
{
// sysId clamping
sysId = P25Utils::sysId(sysId);
@ -191,7 +192,7 @@ namespace p25
channelNo = 4095U;
}
m_lra = 0U;
m_lra = lra;
m_netId = 0U;
m_sysId = sysId;
@ -213,6 +214,20 @@ namespace p25
m_lto = 0;
}
/**
* @brief Helper to set adjacent site data when the Location Registration Area is unavailable.
* @param sysId P25 System ID.
* @param rfssId P25 RFSS ID.
* @param siteId P25 Site ID.
* @param channelId Channel ID.
* @param channelNo Channel Number.
* @param serviceClass Service class.
*/
void setAdjSite(uint32_t sysId, uint8_t rfssId, uint8_t siteId, uint8_t channelId, uint32_t channelNo, uint8_t serviceClass)
{
setAdjSite(0U, sysId, rfssId, siteId, channelId, channelNo, serviceClass);
}
/**
* @brief Equals operator.
* @param data Instance of SiteData to copy.

@ -24,6 +24,7 @@ using namespace p25::lc::tsbk;
/* Initializes a new instance of the OSP_ADJ_STS_BCAST class. */
OSP_ADJ_STS_BCAST::OSP_ADJ_STS_BCAST() : TSBK(),
m_adjLRA(s_siteData.lra()),
m_adjCFVA(CFVA::FAILURE),
m_adjSysId(0U),
m_adjRfssId(0U),
@ -50,6 +51,8 @@ bool OSP_ADJ_STS_BCAST::decode(const uint8_t* data, bool rawTSBK)
ulong64_t tsbkValue = TSBK::toValue(tsbk);
m_adjLRA = (uint8_t)((tsbkValue >> 56) & 0xFFU); // Location Registration Area
m_adjCFVA = (uint8_t)((tsbkValue >> 52) & 0x0FU); // CFVA
m_adjSysId = (uint32_t)((tsbkValue >> 40) & 0xFFFU); // Site System ID
m_adjRfssId = (uint8_t)((tsbkValue >> 32) & 0xFFU); // Site RFSS ID
m_adjSiteId = (uint8_t)((tsbkValue >> 24) & 0xFFU); // Site ID
@ -68,9 +71,9 @@ void OSP_ADJ_STS_BCAST::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
ulong64_t tsbkValue = 0U;
tsbkValue = s_siteData.lra(); // Location Registration Area
tsbkValue = m_adjLRA; // Location Registration Area
tsbkValue = (tsbkValue << 4) + m_adjCFVA; // CFVA
tsbkValue = (tsbkValue << 12) + s_siteData.sysId(); // System ID
tsbkValue = (tsbkValue << 12) + m_adjSysId; // System ID
tsbkValue = (tsbkValue << 8) + m_adjRfssId; // RF Sub-System ID
tsbkValue = (tsbkValue << 8) + m_adjSiteId; // Site ID
tsbkValue = (tsbkValue << 4) + m_adjChannelId; // Channel ID
@ -98,6 +101,7 @@ void OSP_ADJ_STS_BCAST::copy(const OSP_ADJ_STS_BCAST& data)
{
TSBK::copy(data);
m_adjLRA = data.m_adjLRA;
m_adjCFVA = data.m_adjCFVA;
m_adjSysId = data.m_adjSysId;
m_adjRfssId = data.m_adjRfssId;

@ -63,6 +63,10 @@ namespace p25
public:
// Adjacent Site Data
/**
* @brief Adjacent site location registration area.
*/
DECLARE_PROPERTY(uint8_t, adjLRA, AdjSiteLRA);
/**
* @brief Adjacent site CFVA flags.
*/

@ -24,8 +24,12 @@ using namespace p25::lc::tsbk;
/* Initializes a new instance of the OSP_SCCB class. */
OSP_SCCB::OSP_SCCB() : TSBK(),
m_sccbRfssId(s_siteData.rfssId()),
m_sccbSiteId(s_siteData.siteId()),
m_sccbChannelId1(0U),
m_sccbChannelId2(0U)
m_sccbServiceClass1(ServiceClass::INVALID),
m_sccbChannelId2(0U),
m_sccbServiceClass2(ServiceClass::INVALID)
{
m_lco = TSBKO::OSP_SCCB;
}
@ -36,7 +40,20 @@ bool OSP_SCCB::decode(const uint8_t* data, bool rawTSBK)
{
assert(data != nullptr);
/* stub */
uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
if (!TSBK::decode(data, tsbk, rawTSBK))
return false;
const ulong64_t tsbkValue = TSBK::toValue(tsbk);
m_sccbRfssId = (uint8_t)((tsbkValue >> 56) & 0xFFU);
m_sccbSiteId = (uint8_t)((tsbkValue >> 48) & 0xFFU);
m_sccbChannelId1 = (uint16_t)((tsbkValue >> 32) & 0xFFFFU);
m_sccbServiceClass1 = (uint8_t)((tsbkValue >> 24) & 0xFFU);
m_sccbChannelId2 = (uint16_t)((tsbkValue >> 8) & 0xFFFFU);
m_sccbServiceClass2 = (uint8_t)(tsbkValue & 0xFFU);
return true;
}
@ -49,22 +66,12 @@ void OSP_SCCB::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
ulong64_t tsbkValue = 0U;
tsbkValue = s_siteData.rfssId(); // RF Sub-System ID
tsbkValue = (tsbkValue << 8) + s_siteData.siteId(); // Site ID
tsbkValue = m_sccbRfssId; // RF Sub-System ID
tsbkValue = (tsbkValue << 8) + m_sccbSiteId; // Site ID
tsbkValue = (tsbkValue << 16) + m_sccbChannelId1; // SCCB Channel ID 1
if (m_sccbChannelId1 > 0) {
tsbkValue = (tsbkValue << 8) + s_siteData.serviceClass(); // System Service Class
}
else {
tsbkValue = (tsbkValue << 8) + (ServiceClass::INVALID); // System Service Class
}
tsbkValue = (tsbkValue << 8) + m_sccbServiceClass1; // System Service Class
tsbkValue = (tsbkValue << 16) + m_sccbChannelId2; // SCCB Channel ID 2
if (m_sccbChannelId2 > 0) {
tsbkValue = (tsbkValue << 8) + s_siteData.serviceClass(); // System Service Class
}
else {
tsbkValue = (tsbkValue << 8) + (ServiceClass::INVALID); // System Service Class
}
tsbkValue = (tsbkValue << 8) + m_sccbServiceClass2; // System Service Class
std::unique_ptr<uint8_t[]> tsbk = TSBK::fromValue(tsbkValue);
TSBK::encode(data, tsbk.get(), rawTSBK, noTrellis);
@ -87,6 +94,10 @@ void OSP_SCCB::copy(const OSP_SCCB& data)
{
TSBK::copy(data);
m_sccbRfssId = data.m_sccbRfssId;
m_sccbSiteId = data.m_sccbSiteId;
m_sccbChannelId1 = data.m_sccbChannelId1;
m_sccbServiceClass1 = data.m_sccbServiceClass1;
m_sccbChannelId2 = data.m_sccbChannelId2;
m_sccbServiceClass2 = data.m_sccbServiceClass2;
}

@ -63,13 +63,29 @@ namespace p25
public:
/**
* @brief SCCB channel ID 1.
* @brief RF Sub-System ID containing the secondary control channels.
*/
DECLARE_PROPERTY(uint8_t, sccbChannelId1, SCCBChnId1);
DECLARE_PROPERTY(uint8_t, sccbRfssId, SCCBRFSSId);
/**
* @brief SCCB channel ID 2.
* @brief Site ID containing the secondary control channels.
*/
DECLARE_PROPERTY(uint8_t, sccbChannelId2, SCCBChnId2);
DECLARE_PROPERTY(uint8_t, sccbSiteId, SCCBSiteId);
/**
* @brief Complete implicit SCCB channel value A.
*/
DECLARE_PROPERTY(uint16_t, sccbChannelId1, SCCBChnId1);
/**
* @brief System service class for SCCB channel A.
*/
DECLARE_PROPERTY(uint8_t, sccbServiceClass1, SCCBSvcClass1);
/**
* @brief Complete implicit SCCB channel value B.
*/
DECLARE_PROPERTY(uint16_t, sccbChannelId2, SCCBChnId2);
/**
* @brief System service class for SCCB channel B.
*/
DECLARE_PROPERTY(uint8_t, sccbServiceClass2, SCCBSvcClass2);
DECLARE_COPY(OSP_SCCB);
};

@ -24,8 +24,13 @@ using namespace p25::lc::tsbk;
/* Initializes a new instance of the OSP_SCCB_EXP class. */
OSP_SCCB_EXP::OSP_SCCB_EXP() : TSBK(),
m_sccbRfssId(s_siteData.rfssId()),
m_sccbSiteId(s_siteData.siteId()),
m_sccbChannelId1(0U),
m_sccbChannelNo(0U)
m_sccbChannelNo(0U),
m_sccbChannelId2(0U),
m_sccbChannelNo2(0U),
m_sccbServiceClass(ServiceClass::INVALID)
{
m_lco = TSBKO::OSP_SCCB_EXP;
}
@ -36,7 +41,21 @@ bool OSP_SCCB_EXP::decode(const uint8_t* data, bool rawTSBK)
{
assert(data != nullptr);
/* stub */
uint8_t tsbk[P25_TSBK_LENGTH_BYTES + 1U];
::memset(tsbk, 0x00U, P25_TSBK_LENGTH_BYTES);
if (!TSBK::decode(data, tsbk, rawTSBK))
return false;
const ulong64_t tsbkValue = TSBK::toValue(tsbk);
m_sccbRfssId = (uint8_t)((tsbkValue >> 56) & 0xFFU);
m_sccbSiteId = (uint8_t)((tsbkValue >> 48) & 0xFFU);
m_sccbChannelId1 = (uint8_t)((tsbkValue >> 44) & 0x0FU);
m_sccbChannelNo = (uint32_t)((tsbkValue >> 32) & 0x0FFFU);
m_sccbChannelId2 = (uint8_t)((tsbkValue >> 20) & 0x0FU);
m_sccbChannelNo2 = (uint32_t)((tsbkValue >> 8) & 0x0FFFU);
m_sccbServiceClass = (uint8_t)(tsbkValue & 0xFFU);
return true;
}
@ -49,20 +68,15 @@ void OSP_SCCB_EXP::encode(uint8_t* data, bool rawTSBK, bool noTrellis)
ulong64_t tsbkValue = 0U;
tsbkValue = s_siteData.rfssId(); // RF Sub-System ID
tsbkValue = (tsbkValue << 8) + s_siteData.siteId(); // Site ID
tsbkValue = m_sccbRfssId; // RF Sub-System ID
tsbkValue = (tsbkValue << 8) + m_sccbSiteId; // Site ID
tsbkValue = (tsbkValue << 4) + m_sccbChannelId1; // Channel (T) ID
tsbkValue = (tsbkValue << 12) + m_sccbChannelNo; // Channel (T) Number
tsbkValue = (tsbkValue << 12) + m_sccbChannelId1; // Channel (R) ID
tsbkValue = (tsbkValue << 12) + m_sccbChannelNo; // Channel (R) Number
tsbkValue = (tsbkValue << 12) + m_sccbChannelId2; // Channel (R) ID
tsbkValue = (tsbkValue << 12) + m_sccbChannelNo2; // Channel (R) Number
if (m_sccbChannelId1 > 0) {
tsbkValue = (tsbkValue << 8) + s_siteData.serviceClass(); // System Service Class
}
else {
tsbkValue = (tsbkValue << 8) + (ServiceClass::INVALID); // System Service Class
}
tsbkValue = (tsbkValue << 8) + m_sccbServiceClass; // System Service Class
std::unique_ptr<uint8_t[]> tsbk = TSBK::fromValue(tsbkValue);
TSBK::encode(data, tsbk.get(), rawTSBK, noTrellis);
@ -85,6 +99,11 @@ void OSP_SCCB_EXP::copy(const OSP_SCCB_EXP& data)
{
TSBK::copy(data);
m_sccbRfssId = data.m_sccbRfssId;
m_sccbSiteId = data.m_sccbSiteId;
m_sccbChannelId1 = data.m_sccbChannelId1;
m_sccbChannelNo = data.m_sccbChannelNo;
m_sccbChannelId2 = data.m_sccbChannelId2;
m_sccbChannelNo2 = data.m_sccbChannelNo2;
m_sccbServiceClass = data.m_sccbServiceClass;
}

@ -63,13 +63,33 @@ namespace p25
public:
/**
* @brief SCCB channel ID 1.
* @brief RF Sub-System ID containing the secondary control channel.
*/
DECLARE_PROPERTY(uint8_t, sccbRfssId, SCCBRFSSId);
/**
* @brief Site ID containing the secondary control channel.
*/
DECLARE_PROPERTY(uint8_t, sccbSiteId, SCCBSiteId);
/**
* @brief Explicit SCCB transmit channel ID.
*/
DECLARE_PROPERTY(uint8_t, sccbChannelId1, SCCBChnId1);
/**
* @brief Explicit SCCB channel number.
* @brief Explicit SCCB transmit channel number.
*/
DECLARE_PROPERTY(uint32_t, sccbChannelNo, SCCBChnNo);
/**
* @brief Explicit SCCB receive channel ID.
*/
DECLARE_PROPERTY(uint8_t, sccbChannelId2, SCCBChnId2);
/**
* @brief Explicit SCCB receive channel number.
*/
DECLARE_PROPERTY(uint32_t, sccbChannelNo2, SCCBChnNo2);
/**
* @brief System service class for the secondary control channel.
*/
DECLARE_PROPERTY(uint8_t, sccbServiceClass, SCCBSvcClass);
DECLARE_COPY(OSP_SCCB_EXP);
};

@ -232,6 +232,8 @@ std::unique_ptr<TSBK> TSBKFactory::createTSBK(const uint8_t* data, bool rawTSBK)
return decode(new ISP_AUTH_SU_DMD(), data, rawTSBK);
case TSBKO::OSP_ADJ_STS_BCAST:
return decode(new OSP_ADJ_STS_BCAST(), data, rawTSBK);
case TSBKO::OSP_SCCB:
return decode(new OSP_SCCB(), data, rawTSBK);
default:
LogError(LOG_P25, "TSBKFactory::create(), unknown TSBK LCO value, mfId = $%02X, lco = $%02X", mfId, lco);
break;

@ -1170,14 +1170,14 @@ void Control::clockSiteData(uint32_t ms)
if (m_control->m_sccbUpdateCnt.size() > 0) {
// update SCCB data
for (auto& entry : m_control->m_sccbUpdateCnt) {
uint8_t rfssId = entry.first;
uint16_t channel = entry.first;
uint8_t updateCnt = entry.second;
if (updateCnt > 0U) {
updateCnt--;
}
if (updateCnt == 0U) {
SiteData siteData = m_control->m_sccbTable[rfssId];
SiteData siteData = m_control->m_sccbTable[channel];
LogWarning(LOG_NET, "P25, Secondary Control Channel Expired, no data [FAILED], sysId = $%03X, rfss = $%02X, site = $%02X, chNo = %u-%u, svcClass = $%02X",
siteData.sysId(), siteData.rfssId(), siteData.siteId(), siteData.channelId(), siteData.channelNo(), siteData.serviceClass());
}

@ -1019,7 +1019,9 @@ bool ControlSignaling::processNetwork(uint8_t* data, uint32_t len, lc::LC& contr
}
OSP_ADJ_STS_BCAST* osp = static_cast<OSP_ADJ_STS_BCAST*>(tsbk.get());
if (osp->getAdjSiteId() != m_p25->m_siteData.siteId()) {
if (osp->getAdjSiteSysId() != m_p25->m_siteData.sysId() ||
osp->getAdjSiteRFSSId() != m_p25->m_siteData.rfssId() ||
osp->getAdjSiteId() != m_p25->m_siteData.siteId()) {
// update site table data
SiteData site;
try {
@ -1033,7 +1035,7 @@ bool ControlSignaling::processNetwork(uint8_t* data, uint32_t len, lc::LC& contr
osp->getAdjSiteSysId(), osp->getAdjSiteRFSSId(), osp->getAdjSiteId(), osp->getAdjSiteChnId(), osp->getAdjSiteChnNo(), osp->getAdjSiteSvcClass());
}
site.setAdjSite(osp->getAdjSiteSysId(), osp->getAdjSiteRFSSId(), osp->getAdjSiteId(), osp->getAdjSiteChnId(), osp->getAdjSiteChnNo(), osp->getAdjSiteSvcClass());
site.setAdjSite(osp->getAdjSiteLRA(), osp->getAdjSiteSysId(), osp->getAdjSiteRFSSId(), osp->getAdjSiteId(), osp->getAdjSiteChnId(), osp->getAdjSiteChnNo(), osp->getAdjSiteSvcClass());
m_adjSiteTable[site.siteId()] = site;
m_adjSiteUpdateCnt[site.siteId()] = ADJ_SITE_UPDATE_CNT;
@ -1044,7 +1046,8 @@ bool ControlSignaling::processNetwork(uint8_t* data, uint32_t len, lc::LC& contr
// update site table data
SiteData site;
try {
site = m_sccbTable.at(osp->getAdjSiteRFSSId());
const uint16_t channel = (uint16_t)((osp->getAdjSiteChnId() << 12) | osp->getAdjSiteChnNo());
site = m_sccbTable.at(channel);
}
catch (...) {
site = SiteData();
@ -1055,10 +1058,11 @@ bool ControlSignaling::processNetwork(uint8_t* data, uint32_t len, lc::LC& contr
osp->getAdjSiteSysId(), osp->getAdjSiteRFSSId(), osp->getAdjSiteId(), osp->getAdjSiteChnId(), osp->getAdjSiteChnNo(), osp->getAdjSiteSvcClass());
}
site.setAdjSite(osp->getAdjSiteSysId(), osp->getAdjSiteRFSSId(), osp->getAdjSiteId(), osp->getAdjSiteChnId(), osp->getAdjSiteChnNo(), osp->getAdjSiteSvcClass());
site.setAdjSite(osp->getAdjSiteLRA(), osp->getAdjSiteSysId(), osp->getAdjSiteRFSSId(), osp->getAdjSiteId(), osp->getAdjSiteChnId(), osp->getAdjSiteChnNo(), osp->getAdjSiteSvcClass());
m_sccbTable[site.rfssId()] = site;
m_sccbUpdateCnt[site.rfssId()] = ADJ_SITE_UPDATE_CNT;
const uint16_t channel = (uint16_t)((site.channelId() << 12) | site.channelNo());
m_sccbTable[channel] = site;
m_sccbUpdateCnt[channel] = ADJ_SITE_UPDATE_CNT;
}
return true;
@ -1415,6 +1419,7 @@ void ControlSignaling::writeAdjSSNetwork()
// transmit adjacent site broadcast
std::unique_ptr<OSP_ADJ_STS_BCAST> osp = std::make_unique<OSP_ADJ_STS_BCAST>();
osp->setSrcId(WUID_FNE);
osp->setAdjSiteLRA(m_p25->m_siteData.lra());
osp->setAdjSiteCFVA(cfva);
osp->setAdjSiteSysId(m_p25->m_siteData.sysId());
osp->setAdjSiteRFSSId(m_p25->m_siteData.rfssId());
@ -2462,6 +2467,7 @@ void ControlSignaling::queueRF_TSBK_Ctrl(uint8_t lco)
}
// transmit adjacent site broadcast
osp->setAdjSiteLRA(site.lra());
osp->setAdjSiteCFVA(cfva);
osp->setAdjSiteSysId(site.sysId());
osp->setAdjSiteRFSSId(site.rfssId());
@ -2501,8 +2507,13 @@ void ControlSignaling::queueRF_TSBK_Ctrl(uint8_t lco)
// transmit SCCB broadcast
osp->setLCO(TSBKO::OSP_SCCB_EXP);
osp->setSCCBRFSSId(site.rfssId());
osp->setSCCBSiteId(site.siteId());
osp->setSCCBChnId1(site.channelId());
osp->setSCCBChnNo(site.channelNo());
osp->setSCCBChnId2(site.channelId());
osp->setSCCBChnNo2(site.channelNo());
osp->setSCCBSvcClass(site.serviceClass());
tsbk = std::move(osp);
m_mbfSCCBCnt++;

@ -249,8 +249,8 @@ namespace p25
std::unordered_map<uint8_t, SiteData> m_adjSiteTable;
std::unordered_map<uint8_t, uint8_t> m_adjSiteUpdateCnt;
std::unordered_map<uint8_t, SiteData> m_sccbTable;
std::unordered_map<uint8_t, uint8_t> m_sccbUpdateCnt;
std::unordered_map<uint16_t, SiteData> m_sccbTable;
std::unordered_map<uint16_t, uint8_t> m_sccbUpdateCnt;
std::unordered_map<uint32_t, ulong64_t> m_llaDemandTable;
std::vector<uint32_t> m_llaDeferredAuthList;

@ -9,6 +9,8 @@
*/
#include "host/Defines.h"
#include "common/p25/lc/tsbk/OSP_SCCB.h"
#include "common/p25/lc/tsbk/OSP_SCCB_EXP.h"
#include "common/p25/lc/tsbk/OSP_ADJ_STS_BCAST.h"
#include "common/p25/lc/tsbk/OSP_SYS_SRV_BCAST.h"
#include "common/p25/lc/tsbk/OSP_GRP_AFF_Q.h"
#include "common/p25/lc/tsbk/ISP_GRP_AFF_Q_RSP.h"
@ -66,6 +68,87 @@ TEST_CASE("TSBK", "[p25][tsbk]") {
TSBK::setSiteData(previousSiteData);
}
SECTION("Secondary_Control_Channel_Broadcast_Known_Bytes") {
OSP_SCCB source;
source.setSCCBRFSSId(0x21U);
source.setSCCBSiteId(0x43U);
source.setSCCBChnId1(0x1567U);
source.setSCCBSvcClass1(0xA5U);
source.setSCCBChnId2(0x2ABCU);
source.setSCCBSvcClass2(0x5AU);
uint8_t raw[P25_TSBK_LENGTH_BYTES] = { 0U };
source.encode(raw, true, true);
const uint8_t expected[] = { 0x21U, 0x43U, 0x15U, 0x67U, 0xA5U, 0x2AU, 0xBCU, 0x5AU };
CHECK(::memcmp(raw + 2U, expected, sizeof(expected)) == 0);
OSP_SCCB decoded;
REQUIRE(decoded.decode(raw, true));
CHECK(decoded.getSCCBRFSSId() == 0x21U);
CHECK(decoded.getSCCBSiteId() == 0x43U);
CHECK(decoded.getSCCBChnId1() == 0x1567U);
CHECK(decoded.getSCCBSvcClass1() == 0xA5U);
CHECK(decoded.getSCCBChnId2() == 0x2ABCU);
CHECK(decoded.getSCCBSvcClass2() == 0x5AU);
}
SECTION("Secondary_Control_Channel_Broadcast_Explicit_Known_Bytes") {
OSP_SCCB_EXP source;
source.setSCCBRFSSId(0x21U);
source.setSCCBSiteId(0x43U);
source.setSCCBChnId1(0x01U);
source.setSCCBChnNo(0x567U);
source.setSCCBChnId2(0x02U);
source.setSCCBChnNo2(0xABCU);
source.setSCCBSvcClass(0xA5U);
uint8_t raw[P25_TSBK_LENGTH_BYTES] = { 0U };
source.encode(raw, true, true);
const uint8_t expected[] = { 0x21U, 0x43U, 0x15U, 0x67U, 0x00U, 0x2AU, 0xBCU, 0xA5U };
CHECK(::memcmp(raw + 2U, expected, sizeof(expected)) == 0);
OSP_SCCB_EXP decoded;
REQUIRE(decoded.decode(raw, true));
CHECK(decoded.getSCCBRFSSId() == 0x21U);
CHECK(decoded.getSCCBSiteId() == 0x43U);
CHECK(decoded.getSCCBChnId1() == 0x01U);
CHECK(decoded.getSCCBChnNo() == 0x567U);
CHECK(decoded.getSCCBChnId2() == 0x02U);
CHECK(decoded.getSCCBChnNo2() == 0xABCU);
CHECK(decoded.getSCCBSvcClass() == 0xA5U);
}
SECTION("Adjacent_Status_Broadcast_Known_Bytes") {
OSP_ADJ_STS_BCAST source;
source.setAdjSiteLRA(0x12U);
source.setAdjSiteCFVA(0x0BU);
source.setAdjSiteSysId(0x345U);
source.setAdjSiteRFSSId(0x67U);
source.setAdjSiteId(0x89U);
source.setAdjSiteChnId(0x0AU);
source.setAdjSiteChnNo(0xBCDU);
source.setAdjSiteSvcClass(0x5AU);
uint8_t raw[P25_TSBK_LENGTH_BYTES] = { 0U };
source.encode(raw, true, true);
const uint8_t expected[] = { 0x12U, 0xB3U, 0x45U, 0x67U, 0x89U, 0xABU, 0xCDU, 0x5AU };
CHECK(::memcmp(raw + 2U, expected, sizeof(expected)) == 0);
OSP_ADJ_STS_BCAST decoded;
REQUIRE(decoded.decode(raw, true));
CHECK(decoded.getAdjSiteLRA() == 0x12U);
CHECK(decoded.getAdjSiteCFVA() == 0x0BU);
CHECK(decoded.getAdjSiteSysId() == 0x345U);
CHECK(decoded.getAdjSiteRFSSId() == 0x67U);
CHECK(decoded.getAdjSiteId() == 0x89U);
CHECK(decoded.getAdjSiteChnId() == 0x0AU);
CHECK(decoded.getAdjSiteChnNo() == 0xBCDU);
CHECK(decoded.getAdjSiteSvcClass() == 0x5AU);
}
SECTION("Group_Affiliation_Query_Known_Bytes") {
OSP_GRP_AFF_Q query;
query.setDstId(0x123456U);

Loading…
Cancel
Save

Powered by TurnKey Linux.